github.com/demonoid81/moby@v0.0.0-20200517203328-62dd8e17c460/builder/builder-next/adapters/snapshot/layer.go (about) 1 package snapshot 2 3 import ( 4 "context" 5 "os" 6 "path/filepath" 7 8 "github.com/demonoid81/moby/layer" 9 "github.com/demonoid81/moby/pkg/ioutils" 10 "github.com/pkg/errors" 11 bolt "go.etcd.io/bbolt" 12 "golang.org/x/sync/errgroup" 13 ) 14 15 func (s *snapshotter) GetDiffIDs(ctx context.Context, key string) ([]layer.DiffID, error) { 16 if l, err := s.getLayer(key, true); err != nil { 17 return nil, err 18 } else if l != nil { 19 return getDiffChain(l), nil 20 } 21 return nil, nil 22 } 23 24 func (s *snapshotter) EnsureLayer(ctx context.Context, key string) ([]layer.DiffID, error) { 25 diffIDs, err := s.GetDiffIDs(ctx, key) 26 if err != nil { 27 return nil, err 28 } else if diffIDs != nil { 29 return diffIDs, nil 30 } 31 32 id, committed := s.getGraphDriverID(key) 33 if !committed { 34 return nil, errors.Errorf("can not convert active %s to layer", key) 35 } 36 37 info, err := s.Stat(ctx, key) 38 if err != nil { 39 return nil, err 40 } 41 42 eg, gctx := errgroup.WithContext(ctx) 43 44 // TODO: add flightcontrol 45 46 var parentChainID layer.ChainID 47 if info.Parent != "" { 48 eg.Go(func() error { 49 diffIDs, err := s.EnsureLayer(gctx, info.Parent) 50 if err != nil { 51 return err 52 } 53 parentChainID = layer.CreateChainID(diffIDs) 54 return nil 55 }) 56 } 57 58 tmpDir, err := ioutils.TempDir("", "docker-tarsplit") 59 if err != nil { 60 return nil, err 61 } 62 defer os.RemoveAll(tmpDir) 63 tarSplitPath := filepath.Join(tmpDir, "tar-split") 64 65 var diffID layer.DiffID 66 var size int64 67 eg.Go(func() error { 68 parent := "" 69 if p := info.Parent; p != "" { 70 if l, err := s.getLayer(p, true); err != nil { 71 return err 72 } else if l != nil { 73 parent, err = getGraphID(l) 74 if err != nil { 75 return err 76 } 77 } else { 78 parent, _ = s.getGraphDriverID(info.Parent) 79 } 80 } 81 diffID, size, err = s.reg.ChecksumForGraphID(id, parent, "", tarSplitPath) 82 return err 83 }) 84 85 if err := eg.Wait(); err != nil { 86 return nil, err 87 } 88 89 l, err := s.reg.RegisterByGraphID(id, parentChainID, diffID, tarSplitPath, size) 90 if err != nil { 91 return nil, err 92 } 93 94 if err := s.db.Update(func(tx *bolt.Tx) error { 95 b := tx.Bucket([]byte(key)) 96 b.Put(keyChainID, []byte(l.ChainID())) 97 return nil 98 }); err != nil { 99 return nil, err 100 } 101 102 s.mu.Lock() 103 s.refs[key] = l 104 s.mu.Unlock() 105 106 return getDiffChain(l), nil 107 } 108 109 func getDiffChain(l layer.Layer) []layer.DiffID { 110 if p := l.Parent(); p != nil { 111 return append(getDiffChain(p), l.DiffID()) 112 } 113 return []layer.DiffID{l.DiffID()} 114 } 115 116 func getGraphID(l layer.Layer) (string, error) { 117 if l, ok := l.(interface { 118 CacheID() string 119 }); ok { 120 return l.CacheID(), nil 121 } 122 return "", errors.Errorf("couldn't access cacheID for %s", l.ChainID()) 123 }