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