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) }