layer/mounted_layer.go
500e77ba
 package layer
 
d04fa49a
 import (
 	"io"
 	"sync"
 
 	"github.com/docker/docker/pkg/archive"
 )
500e77ba
 
 type mountedLayer struct {
d04fa49a
 	name       string
 	mountID    string
 	initID     string
 	parent     *roLayer
6558158d
 	path       string
d04fa49a
 	layerStore *layerStore
 
 	references map[RWLayer]*referencedRWLayer
500e77ba
 }
 
 func (ml *mountedLayer) cacheParent() string {
 	if ml.initID != "" {
 		return ml.initID
 	}
 	if ml.parent != nil {
 		return ml.parent.cacheID
 	}
 	return ""
 }
 
21278efa
 func (ml *mountedLayer) TarStream() (io.ReadCloser, error) {
500e77ba
 	archiver, err := ml.layerStore.driver.Diff(ml.mountID, ml.cacheParent())
 	if err != nil {
 		return nil, err
 	}
21278efa
 	return archiver, nil
500e77ba
 }
 
d04fa49a
 func (ml *mountedLayer) Name() string {
 	return ml.name
500e77ba
 }
 
 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
 }
 
d04fa49a
 func (ml *mountedLayer) Mount(mountLabel string) (string, error) {
 	return ml.layerStore.driver.Get(ml.mountID, mountLabel)
 }
 
 func (ml *mountedLayer) Unmount() error {
 	return ml.layerStore.driver.Put(ml.mountID)
 }
 
500e77ba
 func (ml *mountedLayer) Size() (int64, error) {
 	return ml.layerStore.driver.DiffSize(ml.mountID, ml.cacheParent())
 }
d04fa49a
 
 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.references[ref] = ref
 
 	return ref
 }
 
 func (ml *mountedLayer) hasReferences() bool {
 	return len(ml.references) > 0
 }
 
1818ca9d
 func (ml *mountedLayer) incActivityCount(ref RWLayer) error {
 	rl, ok := ml.references[ref]
 	if !ok {
 		return ErrLayerNotRetained
 	}
 
 	if err := rl.acquire(); err != nil {
 		return err
 	}
 	return nil
 }
 
d04fa49a
 func (ml *mountedLayer) deleteReference(ref RWLayer) error {
 	rl, ok := ml.references[ref]
 	if !ok {
 		return ErrLayerNotRetained
 	}
 
 	if err := rl.release(); err != nil {
 		return err
 	}
 	delete(ml.references, ref)
 
 	return nil
 }
 
64530c8e
 func (ml *mountedLayer) retakeReference(r RWLayer) {
 	if ref, ok := r.(*referencedRWLayer); ok {
 		ref.activityCount = 0
 		ml.references[ref] = ref
 	}
 }
 
d04fa49a
 type referencedRWLayer struct {
 	*mountedLayer
 
 	activityL     sync.Mutex
 	activityCount int
 }
 
1818ca9d
 func (rl *referencedRWLayer) acquire() error {
 	rl.activityL.Lock()
 	defer rl.activityL.Unlock()
 
 	rl.activityCount++
 
 	return nil
 }
 
d04fa49a
 func (rl *referencedRWLayer) release() error {
 	rl.activityL.Lock()
 	defer rl.activityL.Unlock()
 
 	if rl.activityCount > 0 {
 		return ErrActiveMount
 	}
 
 	rl.activityCount = -1
 
 	return nil
 }
 
 func (rl *referencedRWLayer) Mount(mountLabel string) (string, error) {
 	rl.activityL.Lock()
 	defer rl.activityL.Unlock()
 
 	if rl.activityCount == -1 {
 		return "", ErrLayerNotRetained
 	}
 
6558158d
 	if rl.activityCount > 0 {
 		rl.activityCount++
 		return rl.path, nil
 	}
 
 	m, err := rl.mountedLayer.Mount(mountLabel)
 	if err == nil {
 		rl.activityCount++
 		rl.path = m
 	}
 	return m, err
d04fa49a
 }
 
6558158d
 // Unmount decrements the activity count and unmounts the underlying layer
 // Callers should only call `Unmount` once per call to `Mount`, even on error.
d04fa49a
 func (rl *referencedRWLayer) Unmount() error {
 	rl.activityL.Lock()
 	defer rl.activityL.Unlock()
 
 	if rl.activityCount == 0 {
 		return ErrNotMounted
 	}
 	if rl.activityCount == -1 {
 		return ErrLayerNotRetained
 	}
6558158d
 
d04fa49a
 	rl.activityCount--
6558158d
 	if rl.activityCount > 0 {
 		return nil
 	}
d04fa49a
 
 	return rl.mountedLayer.Unmount()
 }