github.com/demonoid81/moby@v0.0.0-20200517203328-62dd8e17c460/builder/builder-next/imagerefchecker/checker.go (about) 1 package imagerefchecker 2 3 import ( 4 "sync" 5 6 "github.com/demonoid81/moby/image" 7 "github.com/demonoid81/moby/layer" 8 "github.com/moby/buildkit/cache" 9 digest "github.com/opencontainers/go-digest" 10 ) 11 12 // LayerGetter abstracts away the snapshotter 13 type LayerGetter interface { 14 GetLayer(string) (layer.Layer, error) 15 } 16 17 // Opt represents the options needed to create a refchecker 18 type Opt struct { 19 LayerGetter LayerGetter 20 ImageStore image.Store 21 } 22 23 // New creates new image reference checker that can be used to see if a reference 24 // is being used by any of the images in the image store 25 func New(opt Opt) cache.ExternalRefCheckerFunc { 26 return func() (cache.ExternalRefChecker, error) { 27 return &checker{opt: opt, layers: lchain{}, cache: map[string]bool{}}, nil 28 } 29 } 30 31 type lchain map[layer.DiffID]lchain 32 33 func (c lchain) add(ids []layer.DiffID) { 34 if len(ids) == 0 { 35 return 36 } 37 id := ids[0] 38 ch, ok := c[id] 39 if !ok { 40 ch = lchain{} 41 c[id] = ch 42 } 43 ch.add(ids[1:]) 44 } 45 46 func (c lchain) has(ids []layer.DiffID) bool { 47 if len(ids) == 0 { 48 return true 49 } 50 ch, ok := c[ids[0]] 51 return ok && ch.has(ids[1:]) 52 } 53 54 type checker struct { 55 opt Opt 56 once sync.Once 57 layers lchain 58 cache map[string]bool 59 } 60 61 func (c *checker) Exists(key string, chain []digest.Digest) bool { 62 if c.opt.ImageStore == nil { 63 return false 64 } 65 66 c.once.Do(c.init) 67 68 if b, ok := c.cache[key]; ok { 69 return b 70 } 71 72 l, err := c.opt.LayerGetter.GetLayer(key) 73 if err != nil || l == nil { 74 c.cache[key] = false 75 return false 76 } 77 78 ok := c.layers.has(diffIDs(l)) 79 c.cache[key] = ok 80 return ok 81 } 82 83 func (c *checker) init() { 84 imgs := c.opt.ImageStore.Map() 85 86 for _, img := range imgs { 87 c.layers.add(img.RootFS.DiffIDs) 88 } 89 } 90 91 func diffIDs(l layer.Layer) []layer.DiffID { 92 p := l.Parent() 93 if p == nil { 94 return []layer.DiffID{l.DiffID()} 95 } 96 return append(diffIDs(p), l.DiffID()) 97 }