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