dotcloud/docker

View on GitHub
layer/mounted_layer.go

Summary

Maintainability
A
0 mins
Test Coverage
package layer // import "github.com/docker/docker/layer"

import (
    "io"
    "sync"

    "github.com/docker/docker/pkg/archive"
)

type mountedLayer struct {
    name       string
    mountID    string
    initID     string
    parent     *roLayer
    layerStore *layerStore

    sync.Mutex
    references map[RWLayer]*referencedRWLayer
}

func (ml *mountedLayer) cacheParent() string {
    if ml.initID != "" {
        return ml.initID
    }
    if ml.parent != nil {
        return ml.parent.cacheID
    }
    return ""
}

func (ml *mountedLayer) TarStream() (io.ReadCloser, error) {
    return ml.layerStore.driver.Diff(ml.mountID, ml.cacheParent())
}

func (ml *mountedLayer) Name() string {
    return ml.name
}

func (ml *mountedLayer) Parent() Layer {
    if ml.parent != nil {
        return ml.parent
    }

    // Return a nil interface instead of an interface wrapping a nil
    // pointer.
    return nil
}

func (ml *mountedLayer) Size() (int64, error) {
    return ml.layerStore.driver.DiffSize(ml.mountID, ml.cacheParent())
}

func (ml *mountedLayer) Changes() ([]archive.Change, error) {
    return ml.layerStore.driver.Changes(ml.mountID, ml.cacheParent())
}

func (ml *mountedLayer) Metadata() (map[string]string, error) {
    return ml.layerStore.driver.GetMetadata(ml.mountID)
}

func (ml *mountedLayer) getReference() RWLayer {
    ref := &referencedRWLayer{
        mountedLayer: ml,
    }
    ml.Lock()
    ml.references[ref] = ref
    ml.Unlock()

    return ref
}

func (ml *mountedLayer) hasReferences() bool {
    ml.Lock()
    ret := len(ml.references) > 0
    ml.Unlock()

    return ret
}

func (ml *mountedLayer) deleteReference(ref RWLayer) error {
    ml.Lock()
    defer ml.Unlock()
    if _, ok := ml.references[ref]; !ok {
        return ErrLayerNotRetained
    }
    delete(ml.references, ref)
    return nil
}

func (ml *mountedLayer) retakeReference(r RWLayer) {
    if ref, ok := r.(*referencedRWLayer); ok {
        ml.Lock()
        ml.references[ref] = ref
        ml.Unlock()
    }
}

type referencedRWLayer struct {
    *mountedLayer
}

func (rl *referencedRWLayer) Mount(mountLabel string) (string, error) {
    return rl.layerStore.driver.Get(rl.mountedLayer.mountID, mountLabel)
}

// Unmount decrements the activity count and unmounts the underlying layer
// Callers should only call `Unmount` once per call to `Mount`, even on error.
func (rl *referencedRWLayer) Unmount() error {
    return rl.layerStore.driver.Put(rl.mountedLayer.mountID)
}

// ApplyDiff applies specified diff to the layer
func (rl *referencedRWLayer) ApplyDiff(diff io.Reader) (int64, error) {
    return rl.layerStore.driver.ApplyDiff(rl.mountID, rl.cacheParent(), diff)
}