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) Upstream-commit: d04fa49a0dec89d2f71a813ce8eaa182184139c5 Component: engine
145 lines
2.6 KiB
Go
145 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()
|
|
}
|