mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
21278efaee
Currently, the resources associated with the io.Reader returned by TarStream are only freed when it is read until EOF. This means that partial uploads or exports (for example, in the case of a full disk or severed connection) can leak a goroutine and open file. This commit changes TarStream to return an io.ReadCloser. Resources are freed when Close is called. Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
110 lines
1.9 KiB
Go
110 lines
1.9 KiB
Go
package layer
|
|
|
|
import "io"
|
|
|
|
type roLayer struct {
|
|
chainID ChainID
|
|
diffID DiffID
|
|
parent *roLayer
|
|
cacheID string
|
|
size int64
|
|
layerStore *layerStore
|
|
|
|
referenceCount int
|
|
references map[Layer]struct{}
|
|
}
|
|
|
|
func (rl *roLayer) TarStream() (io.ReadCloser, error) {
|
|
r, err := rl.layerStore.store.TarSplitReader(rl.chainID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return rl.layerStore.assembleTar(rl.cacheID, r, nil)
|
|
}
|
|
|
|
func (rl *roLayer) ChainID() ChainID {
|
|
return rl.chainID
|
|
}
|
|
|
|
func (rl *roLayer) DiffID() DiffID {
|
|
return rl.diffID
|
|
}
|
|
|
|
func (rl *roLayer) Parent() Layer {
|
|
if rl.parent == nil {
|
|
return nil
|
|
}
|
|
return rl.parent
|
|
}
|
|
|
|
func (rl *roLayer) Size() (size int64, err error) {
|
|
if rl.parent != nil {
|
|
size, err = rl.parent.Size()
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
|
|
return size + rl.size, nil
|
|
}
|
|
|
|
func (rl *roLayer) DiffSize() (size int64, err error) {
|
|
return rl.size, nil
|
|
}
|
|
|
|
func (rl *roLayer) Metadata() (map[string]string, error) {
|
|
return rl.layerStore.driver.GetMetadata(rl.cacheID)
|
|
}
|
|
|
|
type referencedCacheLayer struct {
|
|
*roLayer
|
|
}
|
|
|
|
func (rl *roLayer) getReference() Layer {
|
|
ref := &referencedCacheLayer{
|
|
roLayer: rl,
|
|
}
|
|
rl.references[ref] = struct{}{}
|
|
|
|
return ref
|
|
}
|
|
|
|
func (rl *roLayer) hasReference(ref Layer) bool {
|
|
_, ok := rl.references[ref]
|
|
return ok
|
|
}
|
|
|
|
func (rl *roLayer) hasReferences() bool {
|
|
return len(rl.references) > 0
|
|
}
|
|
|
|
func (rl *roLayer) deleteReference(ref Layer) {
|
|
delete(rl.references, ref)
|
|
}
|
|
|
|
func (rl *roLayer) depth() int {
|
|
if rl.parent == nil {
|
|
return 1
|
|
}
|
|
return rl.parent.depth() + 1
|
|
}
|
|
|
|
func storeLayer(tx MetadataTransaction, layer *roLayer) error {
|
|
if err := tx.SetDiffID(layer.diffID); err != nil {
|
|
return err
|
|
}
|
|
if err := tx.SetSize(layer.size); err != nil {
|
|
return err
|
|
}
|
|
if err := tx.SetCacheID(layer.cacheID); err != nil {
|
|
return err
|
|
}
|
|
if layer.parent != nil {
|
|
if err := tx.SetParent(layer.parent.chainID); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|