Skip to content

Commit 65d23c6

Browse files
committed
bboltcachestorage: delete links outside of cursor
The `emptyBranchWithParents` method could accidentally leave link entries that shouldn't exist. When finding these links, deleting during the iteration can sometimes cause the cursor to jump entries that should be deleted. This changes the code path to delete the links outside of the iteration to avoid this. This is caused by a long-standing bug in bolt that can't be fixed easily. See etcd-io/bbolt#611 for details. Signed-off-by: Jonathan A. Sternberg <[email protected]>
1 parent 449856f commit 65d23c6

File tree

1 file changed

+8
-1
lines changed

1 file changed

+8
-1
lines changed

solver/bboltcachestorage/storage.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,19 +267,26 @@ func (s *Store) emptyBranchWithParents(tx *bolt.Tx, id []byte) error {
267267
if backlinks := tx.Bucket([]byte(backlinksBucket)).Bucket(id); backlinks != nil {
268268
if err := backlinks.ForEach(func(k, v []byte) error {
269269
if subLinks := tx.Bucket([]byte(linksBucket)).Bucket(k); subLinks != nil {
270+
var toDelete []string
270271
if err := subLinks.ForEach(func(k, v []byte) error {
271272
parts := bytes.Split(k, []byte("@"))
272273
if len(parts) != 2 {
273274
return errors.Errorf("invalid key %s", k)
274275
}
275276
if bytes.Equal(id, parts[1]) {
276-
return subLinks.Delete(k)
277+
toDelete = append(toDelete, string(k))
277278
}
278279
return nil
279280
}); err != nil {
280281
return err
281282
}
282283

284+
for _, k := range toDelete {
285+
if err := subLinks.Delete([]byte(k)); err != nil {
286+
return err
287+
}
288+
}
289+
283290
if isEmptyBucket(subLinks) {
284291
if subResult := tx.Bucket([]byte(resultBucket)).Bucket(k); isEmptyBucket(subResult) {
285292
if err := tx.Bucket([]byte(linksBucket)).DeleteBucket(k); err != nil {

0 commit comments

Comments
 (0)