@@ -64,6 +64,18 @@ func scanRoots(ctx context.Context, tx *bolt.Tx, nc chan<- gc.Node) error {
6464 // iterate through each namespace
6565 v1c := v1bkt .Cursor ()
6666
67+ // cerr indicates the scan did not successfully send all
68+ // the roots. The scan does not need to be cancelled but
69+ // must return error at the end.
70+ var cerr error
71+ fn := func (n gc.Node ) {
72+ select {
73+ case nc <- n :
74+ case <- ctx .Done ():
75+ cerr = ctx .Err ()
76+ }
77+ }
78+
6779 for k , v := v1c .First (); k != nil ; k , v = v1c .Next () {
6880 if v != nil {
6981 continue
@@ -92,11 +104,7 @@ func scanRoots(ctx context.Context, tx *bolt.Tx, nc chan<- gc.Node) error {
92104 }
93105 }
94106
95- select {
96- case nc <- gcnode (ResourceLease , ns , string (k )):
97- case <- ctx .Done ():
98- return ctx .Err ()
99- }
107+ fn (gcnode (ResourceLease , ns , string (k )))
100108
101109 // Emit content and snapshots as roots instead of implementing
102110 // in references. Since leases cannot be referenced there is
@@ -106,11 +114,7 @@ func scanRoots(ctx context.Context, tx *bolt.Tx, nc chan<- gc.Node) error {
106114 cbkt := libkt .Bucket (bucketKeyObjectContent )
107115 if cbkt != nil {
108116 if err := cbkt .ForEach (func (k , v []byte ) error {
109- select {
110- case nc <- gcnode (ResourceContent , ns , string (k )):
111- case <- ctx .Done ():
112- return ctx .Err ()
113- }
117+ fn (gcnode (ResourceContent , ns , string (k )))
114118 return nil
115119 }); err != nil {
116120 return err
@@ -126,11 +130,7 @@ func scanRoots(ctx context.Context, tx *bolt.Tx, nc chan<- gc.Node) error {
126130 snbkt := sbkt .Bucket (sk )
127131
128132 return snbkt .ForEach (func (k , v []byte ) error {
129- select {
130- case nc <- gcnode (ResourceSnapshot , ns , fmt .Sprintf ("%s/%s" , sk , k )):
131- case <- ctx .Done ():
132- return ctx .Err ()
133- }
133+ fn (gcnode (ResourceSnapshot , ns , fmt .Sprintf ("%s/%s" , sk , k )))
134134 return nil
135135 })
136136 }); err != nil {
@@ -141,11 +141,7 @@ func scanRoots(ctx context.Context, tx *bolt.Tx, nc chan<- gc.Node) error {
141141 ibkt := libkt .Bucket (bucketKeyObjectIngests )
142142 if ibkt != nil {
143143 if err := ibkt .ForEach (func (k , v []byte ) error {
144- select {
145- case nc <- gcnode (ResourceIngest , ns , string (k )):
146- case <- ctx .Done ():
147- return ctx .Err ()
148- }
144+ fn (gcnode (ResourceIngest , ns , string (k )))
149145 return nil
150146 }); err != nil {
151147 return err
@@ -168,18 +164,9 @@ func scanRoots(ctx context.Context, tx *bolt.Tx, nc chan<- gc.Node) error {
168164 target := ibkt .Bucket (k ).Bucket (bucketKeyTarget )
169165 if target != nil {
170166 contentKey := string (target .Get (bucketKeyDigest ))
171- select {
172- case nc <- gcnode (ResourceContent , ns , contentKey ):
173- case <- ctx .Done ():
174- return ctx .Err ()
175- }
167+ fn (gcnode (ResourceContent , ns , contentKey ))
176168 }
177- return sendSnapshotRefs (ns , ibkt .Bucket (k ), func (n gc.Node ) {
178- select {
179- case nc <- n :
180- case <- ctx .Done ():
181- }
182- })
169+ return sendLabelRefs (ns , ibkt .Bucket (k ), fn )
183170 }); err != nil {
184171 return err
185172 }
@@ -200,11 +187,7 @@ func scanRoots(ctx context.Context, tx *bolt.Tx, nc chan<- gc.Node) error {
200187 if ea == nil || expThreshold .After (* ea ) {
201188 return nil
202189 }
203- select {
204- case nc <- gcnode (ResourceIngest , ns , string (k )):
205- case <- ctx .Done ():
206- return ctx .Err ()
207- }
190+ fn (gcnode (ResourceIngest , ns , string (k )))
208191 return nil
209192 }); err != nil {
210193 return err
@@ -216,7 +199,12 @@ func scanRoots(ctx context.Context, tx *bolt.Tx, nc chan<- gc.Node) error {
216199 if v != nil {
217200 return nil
218201 }
219- return sendRootRef (ctx , nc , gcnode (ResourceContent , ns , string (k )), cbkt .Bucket (k ))
202+
203+ if isRootRef (cbkt .Bucket (k )) {
204+ fn (gcnode (ResourceContent , ns , string (k )))
205+ }
206+
207+ return nil
220208 }); err != nil {
221209 return err
222210 }
@@ -229,23 +217,15 @@ func scanRoots(ctx context.Context, tx *bolt.Tx, nc chan<- gc.Node) error {
229217 if v != nil {
230218 return nil
231219 }
232- snapshotter := string (cbkt .Bucket (k ).Get (bucketKeySnapshotter ))
220+
221+ cibkt := cbkt .Bucket (k )
222+ snapshotter := string (cibkt .Get (bucketKeySnapshotter ))
233223 if snapshotter != "" {
234- ss := string (cbkt .Bucket (k ).Get (bucketKeySnapshotKey ))
235- select {
236- case nc <- gcnode (ResourceSnapshot , ns , fmt .Sprintf ("%s/%s" , snapshotter , ss )):
237- case <- ctx .Done ():
238- return ctx .Err ()
239- }
224+ ss := string (cibkt .Get (bucketKeySnapshotKey ))
225+ fn (gcnode (ResourceSnapshot , ns , fmt .Sprintf ("%s/%s" , snapshotter , ss )))
240226 }
241227
242- // TODO: Send additional snapshot refs through labels
243- return sendSnapshotRefs (ns , cbkt .Bucket (k ), func (n gc.Node ) {
244- select {
245- case nc <- n :
246- case <- ctx .Done ():
247- }
248- })
228+ return sendLabelRefs (ns , cibkt , fn )
249229 }); err != nil {
250230 return err
251231 }
@@ -263,15 +243,17 @@ func scanRoots(ctx context.Context, tx *bolt.Tx, nc chan<- gc.Node) error {
263243 if v != nil {
264244 return nil
265245 }
266-
267- return sendRootRef (ctx , nc , gcnode (ResourceSnapshot , ns , fmt .Sprintf ("%s/%s" , sk , k )), snbkt .Bucket (k ))
246+ if isRootRef (snbkt .Bucket (k )) {
247+ fn (gcnode (ResourceSnapshot , ns , fmt .Sprintf ("%s/%s" , sk , k )))
248+ }
249+ return nil
268250 })
269251 }); err != nil {
270252 return err
271253 }
272254 }
273255 }
274- return nil
256+ return cerr
275257}
276258
277259func references (ctx context.Context , tx * bolt.Tx , node gc.Node , fn func (gc.Node )) error {
@@ -282,10 +264,7 @@ func references(ctx context.Context, tx *bolt.Tx, node gc.Node, fn func(gc.Node)
282264 return nil
283265 }
284266
285- if err := sendSnapshotRefs (node .Namespace , bkt , fn ); err != nil {
286- return err
287- }
288- return sendContentRefs (node .Namespace , bkt , fn )
267+ return sendLabelRefs (node .Namespace , bkt , fn )
289268 } else if node .Type == ResourceSnapshot {
290269 parts := strings .SplitN (node .Key , "/" , 2 )
291270 if len (parts ) != 2 {
@@ -304,7 +283,7 @@ func references(ctx context.Context, tx *bolt.Tx, node gc.Node, fn func(gc.Node)
304283 fn (gcnode (ResourceSnapshot , node .Namespace , fmt .Sprintf ("%s/%s" , ss , pv )))
305284 }
306285
307- return sendSnapshotRefs (node .Namespace , bkt , fn )
286+ return sendLabelRefs (node .Namespace , bkt , fn )
308287 } else if node .Type == ResourceIngest {
309288 // Send expected value
310289 bkt := getBucket (tx , bucketKeyVersion , []byte (node .Namespace ), bucketKeyObjectContent , bucketKeyObjectIngests , []byte (node .Key ))
@@ -456,25 +435,8 @@ func remove(ctx context.Context, tx *bolt.Tx, node gc.Node) error {
456435 return nil
457436}
458437
459- // sendSnapshotRefs sends all snapshot references referred to by the labels in the bkt
460- func sendSnapshotRefs (ns string , bkt * bolt.Bucket , fn func (gc.Node )) error {
461- lbkt := bkt .Bucket (bucketKeyObjectLabels )
462- if lbkt != nil {
463- lc := lbkt .Cursor ()
464-
465- for k , v := lc .Seek (labelGCSnapRef ); k != nil && strings .HasPrefix (string (k ), string (labelGCSnapRef )); k , v = lc .Next () {
466- snapshotter := k [len (labelGCSnapRef ):]
467- if i := bytes .IndexByte (snapshotter , '/' ); i >= 0 {
468- snapshotter = snapshotter [:i ]
469- }
470- fn (gcnode (ResourceSnapshot , ns , fmt .Sprintf ("%s/%s" , snapshotter , v )))
471- }
472- }
473- return nil
474- }
475-
476- // sendContentRefs sends all content references referred to by the labels in the bkt
477- func sendContentRefs (ns string , bkt * bolt.Bucket , fn func (gc.Node )) error {
438+ // sendLabelRefs sends all snapshot and content references referred to by the labels in the bkt
439+ func sendLabelRefs (ns string , bkt * bolt.Bucket , fn func (gc.Node )) error {
478440 lbkt := bkt .Bucket (bucketKeyObjectLabels )
479441 if lbkt != nil {
480442 lc := lbkt .Cursor ()
@@ -490,6 +452,15 @@ func sendContentRefs(ns string, bkt *bolt.Bucket, fn func(gc.Node)) error {
490452
491453 fn (gcnode (ResourceContent , ns , string (v )))
492454 }
455+
456+ for k , v := lc .Seek (labelGCSnapRef ); k != nil && strings .HasPrefix (string (k ), string (labelGCSnapRef )); k , v = lc .Next () {
457+ snapshotter := k [len (labelGCSnapRef ):]
458+ if i := bytes .IndexByte (snapshotter , '/' ); i >= 0 {
459+ snapshotter = snapshotter [:i ]
460+ }
461+ fn (gcnode (ResourceSnapshot , ns , fmt .Sprintf ("%s/%s" , snapshotter , v )))
462+ }
463+
493464 }
494465 return nil
495466}
@@ -506,17 +477,6 @@ func isRootRef(bkt *bolt.Bucket) bool {
506477 return false
507478}
508479
509- func sendRootRef (ctx context.Context , nc chan <- gc.Node , n gc.Node , bkt * bolt.Bucket ) error {
510- if isRootRef (bkt ) {
511- select {
512- case nc <- n :
513- case <- ctx .Done ():
514- return ctx .Err ()
515- }
516- }
517- return nil
518- }
519-
520480func gcnode (t gc.ResourceType , ns , key string ) gc.Node {
521481 return gc.Node {
522482 Type : t ,
0 commit comments