@@ -416,15 +416,22 @@ func (ndb *nodeDB) saveNodeFromPruning(node *Node) error {
416
416
return ndb .batch .Set (ndb .nodeKey (node .GetKey ()), buf .Bytes ())
417
417
}
418
418
419
+ // rootkey cache of two elements, attempting to mimic a direct-mapped cache.
419
420
type rootkeyCache struct {
420
- version int64
421
- rootKey []byte
421
+ // initial value is set to {-1, -1}, which is an invalid version for a getrootkey call.
422
+ versions [2 ]int64
423
+ rootKeys [2 ][]byte
424
+ next int
422
425
}
423
426
424
427
func (rkc * rootkeyCache ) getRootKey (ndb * nodeDB , version int64 ) ([]byte , error ) {
425
- if rkc .version == version {
426
- return rkc .rootKey , nil
428
+ // Check both cache entries
429
+ for i := 0 ; i < 2 ; i ++ {
430
+ if rkc .versions [i ] == version {
431
+ return rkc .rootKeys [i ], nil
432
+ }
427
433
}
434
+
428
435
rootKey , err := ndb .GetRoot (version )
429
436
if err != nil {
430
437
return nil , err
@@ -434,8 +441,18 @@ func (rkc *rootkeyCache) getRootKey(ndb *nodeDB, version int64) ([]byte, error)
434
441
}
435
442
436
443
func (rkc * rootkeyCache ) setRootKey (version int64 , rootKey []byte ) {
437
- rkc .version = version
438
- rkc .rootKey = rootKey
444
+ // Store in next available slot, cycling between 0 and 1
445
+ rkc .versions [rkc .next ] = version
446
+ rkc .rootKeys [rkc .next ] = rootKey
447
+ rkc .next = (rkc .next + 1 ) % 2
448
+ }
449
+
450
+ func newRootkeyCache () * rootkeyCache {
451
+ return & rootkeyCache {
452
+ versions : [2 ]int64 {- 1 , - 1 },
453
+ rootKeys : [2 ][]byte {},
454
+ next : 0 ,
455
+ }
439
456
}
440
457
441
458
// deleteVersion deletes a tree version from disk.
@@ -446,7 +463,7 @@ func (ndb *nodeDB) deleteVersion(version int64, cache *rootkeyCache) error {
446
463
return err
447
464
}
448
465
449
- if err := ndb .traverseOrphans ( version , version + 1 , func (orphan * Node ) error {
466
+ if err := ndb .traverseOrphansWithRootkeyCache ( cache , version , version + 1 , func (orphan * Node ) error {
450
467
if orphan .nodeKey .nonce == 0 && ! orphan .isLegacy {
451
468
// if the orphan is a reformatted root, it can be a legacy root
452
469
// so it should be removed from the pruning process.
@@ -708,7 +725,7 @@ func (ndb *nodeDB) deleteVersionsTo(toVersion int64) error {
708
725
ndb .resetLegacyLatestVersion (- 1 )
709
726
}
710
727
711
- rootkeyCache := & rootkeyCache {}
728
+ rootkeyCache := newRootkeyCache ()
712
729
for version := first ; version <= toVersion ; version ++ {
713
730
if err := ndb .deleteVersion (version , rootkeyCache ); err != nil {
714
731
return err
@@ -1095,7 +1112,12 @@ func isReferenceRoot(bz []byte) (bool, int) {
1095
1112
// traverseOrphans traverses orphans which removed by the updates of the curVersion in the prevVersion.
1096
1113
// NOTE: it is used for both legacy and new nodes.
1097
1114
func (ndb * nodeDB ) traverseOrphans (prevVersion , curVersion int64 , fn func (* Node ) error ) error {
1098
- curKey , err := ndb .GetRoot (curVersion )
1115
+ cache := newRootkeyCache ()
1116
+ return ndb .traverseOrphansWithRootkeyCache (cache , prevVersion , curVersion , fn )
1117
+ }
1118
+
1119
+ func (ndb * nodeDB ) traverseOrphansWithRootkeyCache (cache * rootkeyCache , prevVersion , curVersion int64 , fn func (* Node ) error ) error {
1120
+ curKey , err := cache .getRootKey (ndb , curVersion )
1099
1121
if err != nil {
1100
1122
return err
1101
1123
}
@@ -1105,7 +1127,7 @@ func (ndb *nodeDB) traverseOrphans(prevVersion, curVersion int64, fn func(*Node)
1105
1127
return err
1106
1128
}
1107
1129
1108
- prevKey , err := ndb . GetRoot ( prevVersion )
1130
+ prevKey , err := cache . getRootKey ( ndb , prevVersion )
1109
1131
if err != nil {
1110
1132
return err
1111
1133
}
0 commit comments