d04fa49a0d
RWLayer will now have more operations and be protected through a referenced type rather than always looked up by string in the layer store. Separates creation of RWLayer (write capture layer) from mounting of the layer. This allows mount labels to be applied after creation and allowing RWLayer objects to have the same lifespan as a container without performance regressions from requiring mount. Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
144 lines
2.6 KiB
Go
144 lines
2.6 KiB
Go
package layer
|
|
|
|
import (
|
|
"io"
|
|
"sync"
|
|
|
|
"github.com/docker/docker/pkg/archive"
|
|
)
|
|
|
|
type mountedLayer struct {
|
|
name string
|
|
mountID string
|
|
initID string
|
|
parent *roLayer
|
|
layerStore *layerStore
|
|
|
|
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) {
|
|
archiver, err := ml.layerStore.driver.Diff(ml.mountID, ml.cacheParent())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return archiver, nil
|
|
}
|
|
|
|
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) 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)
|
|
}
|
|
|
|
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.references[ref] = ref
|
|
|
|
return ref
|
|
}
|
|
|
|
func (ml *mountedLayer) hasReferences() bool {
|
|
return len(ml.references) > 0
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
type referencedRWLayer struct {
|
|
*mountedLayer
|
|
|
|
activityL sync.Mutex
|
|
activityCount int
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
rl.activityCount++
|
|
return rl.mountedLayer.Mount(mountLabel)
|
|
}
|
|
|
|
func (rl *referencedRWLayer) Unmount() error {
|
|
rl.activityL.Lock()
|
|
defer rl.activityL.Unlock()
|
|
|
|
if rl.activityCount == 0 {
|
|
return ErrNotMounted
|
|
}
|
|
if rl.activityCount == -1 {
|
|
return ErrLayerNotRetained
|
|
}
|
|
rl.activityCount--
|
|
|
|
return rl.mountedLayer.Unmount()
|
|
}
|