@@ -28,6 +28,10 @@ func init() {
2828
2929// Initialize Need this as public for unit tests
3030func Initialize () {
31+ rootCache = cache {
32+ data : make (map [string ]SmartCopier ),
33+ resourceLocks : locks .NewGCNamedMutex (),
34+ }
3135 nodes = cache {
3236 data : make (map [string ]SmartCopier ),
3337 resourceLocks : locks .NewGCNamedMutex (),
@@ -49,7 +53,6 @@ func Initialize() {
4953 volumes = cache {
5054 data : make (map [string ]SmartCopier ),
5155 resourceLocks : locks .NewGCNamedMutex (),
52-
5356 // volume internal name
5457 key : & uniqueKey {
5558 data : make (map [string ]string ),
@@ -84,6 +87,8 @@ func Initialize() {
8487 for r := range schema {
8588 resourceRanks [r ] = rankForResource (r )
8689 }
90+
91+ rootCache .data ["." ] = SmartCopier (nil )
8792}
8893
8994// SmartCopier is an interface for objects that can be copied for the cache. If the object implements interior
@@ -143,6 +148,7 @@ func (c *cache) runlock() {
143148}
144149
145150var (
151+ rootCache cache
146152 nodes cache
147153 storageClasses cache
148154 backends cache
@@ -153,6 +159,7 @@ var (
153159 autogrowPolicies cache
154160
155161 caches = map [resource ]* cache {
162+ root : & rootCache ,
156163 node : & nodes ,
157164 storageClass : & storageClasses ,
158165 backend : & backends ,
@@ -244,6 +251,7 @@ func assembleQueries(queries [][]Subquery, roots [][]int, cachesPresent map[reso
244251 }
245252 queries [i ], roots [i ] = buildTrees (ri , q )
246253 }
254+
247255 return nil
248256}
249257
@@ -363,7 +371,7 @@ func dedupe(query []Subquery) (map[resource]int, error) {
363371 return resourceIndices , nil
364372}
365373
366- // buildTrees takes subqueries and finds the roots, and fills in any missing parents
374+ // buildTrees takes subqueries and finds the roots, and fills in any missing dependencies
367375func buildTrees (resourceIndices map [resource ]int , query []Subquery ) ([]Subquery , []int ) {
368376 roots := make ([]int , 0 )
369377 l := len (query )
@@ -377,11 +385,11 @@ func buildTrees(resourceIndices map[resource]int, query []Subquery) ([]Subquery,
377385 continue
378386 }
379387
380- // if the current subquery has ownable resources in the query it is not a root
388+ // if the current subquery has dependent resources in the query it is not a root
381389 root := true
382- ownables := inverseSchema [query [i ].res ]
383- for j := 0 ; j < len (ownables ) && root ; j ++ {
384- if _ , ok := resourceIndices [ownables [j ]]; ok {
390+ dependents := inverseSchema [query [i ].res ]
391+ for j := 0 ; j < len (dependents ) && root ; j ++ {
392+ if _ , ok := resourceIndices [dependents [j ]]; ok {
385393 root = false
386394 }
387395 }
@@ -479,11 +487,13 @@ func fillInIDs(root int, query []Subquery) error {
479487}
480488
481489func mergeQueries (queries [][]Subquery ) []Subquery {
482- length := 0
490+ length := 1
483491 for _ , q := range queries {
484492 length += len (q )
485493 }
486494 merged := make ([]Subquery , 0 , length )
495+ // always add implied read root, if write root is present it will take precedence
496+ merged = append (merged , Subquery {res : root , op : read , id : "." })
487497 for i , q := range queries {
488498 for j := range q {
489499 q [j ].result = i
@@ -505,9 +515,9 @@ func mergeQueries(queries [][]Subquery) []Subquery {
505515 }
506516
507517 switch {
508- case resourceRanks [i .res ] > resourceRanks [j .res ]:
509- return - 1
510518 case resourceRanks [i .res ] < resourceRanks [j .res ]:
519+ return - 1
520+ case resourceRanks [i .res ] > resourceRanks [j .res ]:
511521 return 1
512522 }
513523
@@ -688,7 +698,7 @@ func checkDependency(s []Subquery, i int, r resource) error {
688698
689699func rankForResource (r resource ) int {
690700 rank := 0
691- for _ , c := range inverseSchema [r ] {
701+ for _ , c := range schema [r ] {
692702 cRank := 1 + rankForResource (c )
693703 if cRank > rank {
694704 rank = cRank
@@ -786,7 +796,8 @@ var resourceNames = map[resource]string{
786796}
787797
788798const (
789- node = resource (iota )
799+ root = resource (iota )
800+ node
790801 storageClass
791802 backend
792803 volume
@@ -825,6 +836,7 @@ const (
825836// schema is the authoritative source for relationships between resources. For example,
826837// a snapshot depends on a volume, and a volume depends on a backend.
827838var schema = map [resource ][]resource {
839+ root : nil , // root is an implied dependency for all resources
828840 node : nil ,
829841 storageClass : nil ,
830842 backend : nil ,
0 commit comments