github.com/moby/docker@v26.1.3+incompatible/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/docker/docker/layer" 9 "github.com/docker/docker/pkg/longpath" 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 s.layerCreateLocker.Lock(key) 26 defer s.layerCreateLocker.Unlock(key) 27 28 diffIDs, err := s.GetDiffIDs(ctx, key) 29 if err != nil { 30 return nil, err 31 } else if diffIDs != nil { 32 return diffIDs, nil 33 } 34 35 id, committed := s.getGraphDriverID(key) 36 if !committed { 37 return nil, errors.Errorf("can not convert active %s to layer", key) 38 } 39 40 info, err := s.Stat(ctx, key) 41 if err != nil { 42 return nil, err 43 } 44 45 eg, gctx := errgroup.WithContext(ctx) 46 47 // TODO: add flightcontrol 48 49 var parentChainID layer.ChainID 50 if info.Parent != "" { 51 eg.Go(func() error { 52 diffIDs, err := s.EnsureLayer(gctx, info.Parent) 53 if err != nil { 54 return err 55 } 56 parentChainID = layer.CreateChainID(diffIDs) 57 return nil 58 }) 59 } 60 61 tmpDir, err := longpath.MkdirTemp("", "docker-tarsplit") 62 if err != nil { 63 return nil, err 64 } 65 defer os.RemoveAll(tmpDir) 66 tarSplitPath := filepath.Join(tmpDir, "tar-split") 67 68 var diffID layer.DiffID 69 var size int64 70 eg.Go(func() error { 71 parent := "" 72 if p := info.Parent; p != "" { 73 if l, err := s.getLayer(p, true); err != nil { 74 return err 75 } else if l != nil { 76 parent, err = getGraphID(l) 77 if err != nil { 78 return err 79 } 80 } else { 81 parent, _ = s.getGraphDriverID(info.Parent) 82 } 83 } 84 diffID, size, err = s.reg.ChecksumForGraphID(id, parent, tarSplitPath) 85 return err 86 }) 87 88 if err := eg.Wait(); err != nil { 89 return nil, err 90 } 91 92 l, err := s.reg.RegisterByGraphID(id, parentChainID, diffID, tarSplitPath, size) 93 if err != nil { 94 return nil, err 95 } 96 97 if err := s.db.Update(func(tx *bolt.Tx) error { 98 b := tx.Bucket([]byte(key)) 99 b.Put(keyChainID, []byte(l.ChainID())) 100 return nil 101 }); err != nil { 102 return nil, err 103 } 104 105 s.mu.Lock() 106 s.refs[key] = l 107 s.mu.Unlock() 108 109 return getDiffChain(l), nil 110 } 111 112 func getDiffChain(l layer.Layer) []layer.DiffID { 113 if p := l.Parent(); p != nil { 114 return append(getDiffChain(p), l.DiffID()) 115 } 116 return []layer.DiffID{l.DiffID()} 117 } 118 119 func getGraphID(l layer.Layer) (string, error) { 120 if l, ok := l.(interface { 121 CacheID() string 122 }); ok { 123 return l.CacheID(), nil 124 } 125 return "", errors.Errorf("couldn't access cacheID for %s", l.ChainID()) 126 }