1package solver 2 3import ( 4 "context" 5 6 digest "github.com/opencontainers/go-digest" 7 "github.com/sirupsen/logrus" 8) 9 10type CacheOpts map[interface{}]interface{} 11 12type cacheOptGetterKey struct{} 13 14func CacheOptGetterOf(ctx context.Context) func(keys ...interface{}) map[interface{}]interface{} { 15 if v := ctx.Value(cacheOptGetterKey{}); v != nil { 16 if getter, ok := v.(func(keys ...interface{}) map[interface{}]interface{}); ok { 17 return getter 18 } 19 } 20 return nil 21} 22 23func withAncestorCacheOpts(ctx context.Context, start *state) context.Context { 24 return context.WithValue(ctx, cacheOptGetterKey{}, func(keys ...interface{}) map[interface{}]interface{} { 25 keySet := make(map[interface{}]struct{}) 26 for _, k := range keys { 27 keySet[k] = struct{}{} 28 } 29 values := make(map[interface{}]interface{}) 30 walkAncestors(start, func(st *state) bool { 31 if st.clientVertex.Error != "" { 32 // don't use values from cancelled or otherwise error'd vertexes 33 return false 34 } 35 for _, res := range st.op.cacheRes { 36 if res.Opts == nil { 37 continue 38 } 39 for k := range keySet { 40 if v, ok := res.Opts[k]; ok { 41 values[k] = v 42 delete(keySet, k) 43 if len(keySet) == 0 { 44 return true 45 } 46 } 47 } 48 } 49 return false 50 }) 51 return values 52 }) 53} 54 55func walkAncestors(start *state, f func(*state) bool) { 56 stack := [][]*state{{start}} 57 cache := make(map[digest.Digest]struct{}) 58 for len(stack) > 0 { 59 sts := stack[len(stack)-1] 60 if len(sts) == 0 { 61 stack = stack[:len(stack)-1] 62 continue 63 } 64 st := sts[len(sts)-1] 65 stack[len(stack)-1] = sts[:len(sts)-1] 66 if st == nil { 67 continue 68 } 69 if _, ok := cache[st.origDigest]; ok { 70 continue 71 } 72 cache[st.origDigest] = struct{}{} 73 if shouldStop := f(st); shouldStop { 74 return 75 } 76 stack = append(stack, []*state{}) 77 for _, parentDgst := range st.clientVertex.Inputs { 78 st.solver.mu.RLock() 79 parent := st.solver.actives[parentDgst] 80 st.solver.mu.RUnlock() 81 if parent == nil { 82 logrus.Warnf("parent %q not found in active job list during cache opt search", parentDgst) 83 continue 84 } 85 stack[len(stack)-1] = append(stack[len(stack)-1], parent) 86 } 87 } 88} 89