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