mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
ddaba80467
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
123 lines
2.5 KiB
Go
123 lines
2.5 KiB
Go
package snapshot
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/docker/docker/layer"
|
|
"github.com/docker/docker/pkg/ioutils"
|
|
"github.com/pkg/errors"
|
|
bolt "go.etcd.io/bbolt"
|
|
"golang.org/x/sync/errgroup"
|
|
)
|
|
|
|
func (s *snapshotter) GetDiffIDs(ctx context.Context, key string) ([]layer.DiffID, error) {
|
|
if l, err := s.getLayer(key, true); err != nil {
|
|
return nil, err
|
|
} else if l != nil {
|
|
return getDiffChain(l), nil
|
|
}
|
|
return nil, nil
|
|
}
|
|
|
|
func (s *snapshotter) EnsureLayer(ctx context.Context, key string) ([]layer.DiffID, error) {
|
|
diffIDs, err := s.GetDiffIDs(ctx, key)
|
|
if err != nil {
|
|
return nil, err
|
|
} else if diffIDs != nil {
|
|
return diffIDs, nil
|
|
}
|
|
|
|
id, committed := s.getGraphDriverID(key)
|
|
if !committed {
|
|
return nil, errors.Errorf("can not convert active %s to layer", key)
|
|
}
|
|
|
|
info, err := s.Stat(ctx, key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
eg, gctx := errgroup.WithContext(ctx)
|
|
|
|
// TODO: add flightcontrol
|
|
|
|
var parentChainID layer.ChainID
|
|
if info.Parent != "" {
|
|
eg.Go(func() error {
|
|
diffIDs, err := s.EnsureLayer(gctx, info.Parent)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
parentChainID = layer.CreateChainID(diffIDs)
|
|
return nil
|
|
})
|
|
}
|
|
|
|
tmpDir, err := ioutils.TempDir("", "docker-tarsplit")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer os.RemoveAll(tmpDir)
|
|
tarSplitPath := filepath.Join(tmpDir, "tar-split")
|
|
|
|
var diffID layer.DiffID
|
|
var size int64
|
|
eg.Go(func() error {
|
|
parent := ""
|
|
if p := info.Parent; p != "" {
|
|
if l, err := s.getLayer(p, true); err != nil {
|
|
return err
|
|
} else if l != nil {
|
|
parent, err = getGraphID(l)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
parent, _ = s.getGraphDriverID(info.Parent)
|
|
}
|
|
}
|
|
diffID, size, err = s.reg.ChecksumForGraphID(id, parent, "", tarSplitPath)
|
|
return err
|
|
})
|
|
|
|
if err := eg.Wait(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
l, err := s.reg.RegisterByGraphID(id, parentChainID, diffID, tarSplitPath, size)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := s.db.Update(func(tx *bolt.Tx) error {
|
|
b := tx.Bucket([]byte(key))
|
|
b.Put(keyChainID, []byte(l.ChainID()))
|
|
return nil
|
|
}); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
s.mu.Lock()
|
|
s.refs[key] = l
|
|
s.mu.Unlock()
|
|
|
|
return getDiffChain(l), nil
|
|
}
|
|
|
|
func getDiffChain(l layer.Layer) []layer.DiffID {
|
|
if p := l.Parent(); p != nil {
|
|
return append(getDiffChain(p), l.DiffID())
|
|
}
|
|
return []layer.DiffID{l.DiffID()}
|
|
}
|
|
|
|
func getGraphID(l layer.Layer) (string, error) {
|
|
if l, ok := l.(interface {
|
|
CacheID() string
|
|
}); ok {
|
|
return l.CacheID(), nil
|
|
}
|
|
return "", errors.Errorf("couldn't access cacheID for %s", l.ChainID())
|
|
}
|