diff --git a/pkg/local_object_storage/pilorama/boltdb.go b/pkg/local_object_storage/pilorama/boltdb.go index 0a5cd1130..489f5785d 100644 --- a/pkg/local_object_storage/pilorama/boltdb.go +++ b/pkg/local_object_storage/pilorama/boltdb.go @@ -322,6 +322,8 @@ func (t *boltForest) applyOperation(logBucket, treeBucket *bbolt.Bucket, lm *Log key, value = c.Prev() } + key, _ = c.Next() + // 2. Insert the operation. if len(key) != 8 || binary.BigEndian.Uint64(key) != lm.Time { if err := t.do(logBucket, treeBucket, cKey[:], lm); err != nil { @@ -334,7 +336,7 @@ func (t *boltForest) applyOperation(logBucket, treeBucket *bbolt.Bucket, lm *Log // Otherwise, `Next` call will return currently inserted operation. c.First() } - key, value = c.Next() + key, value = c.Seek(key) // 3. Re-apply all other operations. for len(key) == 8 { @@ -352,8 +354,6 @@ func (t *boltForest) applyOperation(logBucket, treeBucket *bbolt.Bucket, lm *Log } func (t *boltForest) do(lb *bbolt.Bucket, b *bbolt.Bucket, key []byte, op *LogMove) error { - shouldPut := !t.isAncestor(b, key, op.Child, op.Parent) - currParent := b.Get(parentKey(key, op.Child)) op.HasOld = currParent != nil if currParent != nil { // node is already in tree @@ -361,6 +361,9 @@ func (t *boltForest) do(lb *bbolt.Bucket, b *bbolt.Bucket, key []byte, op *LogMo if err := op.Old.Meta.FromBytes(b.Get(metaKey(key, op.Child))); err != nil { return err } + } else { + op.HasOld = false + op.Old = nodeInfo{} } binary.BigEndian.PutUint64(key, op.Time) @@ -368,7 +371,7 @@ func (t *boltForest) do(lb *bbolt.Bucket, b *bbolt.Bucket, key []byte, op *LogMo return err } - if !shouldPut { + if t.isAncestor(b, key, op.Child, op.Parent) || op.Child == op.Parent { return nil } diff --git a/pkg/local_object_storage/pilorama/forest_test.go b/pkg/local_object_storage/pilorama/forest_test.go index 9e161d882..e31e5fe9a 100644 --- a/pkg/local_object_storage/pilorama/forest_test.go +++ b/pkg/local_object_storage/pilorama/forest_test.go @@ -707,7 +707,7 @@ func testForestTreeApplyRandom(t *testing.T, constructor func(t testing.TB) Fore for i := 0; i < iterCount; i++ { // Shuffle random operations, leave initialization in place. - rand.Shuffle(len(ops)-nodeCount, func(i, j int) { ops[i+nodeCount], ops[j+nodeCount] = ops[j+nodeCount], ops[i+nodeCount] }) + rand.Shuffle(len(ops), func(i, j int) { ops[i], ops[j] = ops[j], ops[i] }) actual := constructor(t) for i := range ops {