1package layer // import "github.com/docker/docker/layer" 2 3import ( 4 "io" 5 "sync" 6 7 "github.com/docker/docker/pkg/archive" 8 "github.com/docker/docker/pkg/containerfs" 9) 10 11type mountedLayer struct { 12 name string 13 mountID string 14 initID string 15 parent *roLayer 16 layerStore *layerStore 17 18 sync.Mutex 19 references map[RWLayer]*referencedRWLayer 20} 21 22func (ml *mountedLayer) cacheParent() string { 23 if ml.initID != "" { 24 return ml.initID 25 } 26 if ml.parent != nil { 27 return ml.parent.cacheID 28 } 29 return "" 30} 31 32func (ml *mountedLayer) TarStream() (io.ReadCloser, error) { 33 return ml.layerStore.driver.Diff(ml.mountID, ml.cacheParent()) 34} 35 36func (ml *mountedLayer) Name() string { 37 return ml.name 38} 39 40func (ml *mountedLayer) Parent() Layer { 41 if ml.parent != nil { 42 return ml.parent 43 } 44 45 // Return a nil interface instead of an interface wrapping a nil 46 // pointer. 47 return nil 48} 49 50func (ml *mountedLayer) Size() (int64, error) { 51 return ml.layerStore.driver.DiffSize(ml.mountID, ml.cacheParent()) 52} 53 54func (ml *mountedLayer) Changes() ([]archive.Change, error) { 55 return ml.layerStore.driver.Changes(ml.mountID, ml.cacheParent()) 56} 57 58func (ml *mountedLayer) Metadata() (map[string]string, error) { 59 return ml.layerStore.driver.GetMetadata(ml.mountID) 60} 61 62func (ml *mountedLayer) getReference() RWLayer { 63 ref := &referencedRWLayer{ 64 mountedLayer: ml, 65 } 66 ml.Lock() 67 ml.references[ref] = ref 68 ml.Unlock() 69 70 return ref 71} 72 73func (ml *mountedLayer) hasReferences() bool { 74 ml.Lock() 75 ret := len(ml.references) > 0 76 ml.Unlock() 77 78 return ret 79} 80 81func (ml *mountedLayer) deleteReference(ref RWLayer) error { 82 ml.Lock() 83 defer ml.Unlock() 84 if _, ok := ml.references[ref]; !ok { 85 return ErrLayerNotRetained 86 } 87 delete(ml.references, ref) 88 return nil 89} 90 91func (ml *mountedLayer) retakeReference(r RWLayer) { 92 if ref, ok := r.(*referencedRWLayer); ok { 93 ml.Lock() 94 ml.references[ref] = ref 95 ml.Unlock() 96 } 97} 98 99type referencedRWLayer struct { 100 *mountedLayer 101} 102 103func (rl *referencedRWLayer) Mount(mountLabel string) (containerfs.ContainerFS, error) { 104 return rl.layerStore.driver.Get(rl.mountedLayer.mountID, mountLabel) 105} 106 107// Unmount decrements the activity count and unmounts the underlying layer 108// Callers should only call `Unmount` once per call to `Mount`, even on error. 109func (rl *referencedRWLayer) Unmount() error { 110 return rl.layerStore.driver.Put(rl.mountedLayer.mountID) 111} 112 113// ApplyDiff applies specified diff to the layer 114func (rl *referencedRWLayer) ApplyDiff(diff io.Reader) (int64, error) { 115 return rl.layerStore.driver.ApplyDiff(rl.mountID, rl.cacheParent(), diff) 116} 117