Skip to content

Commit

Permalink
simlify Iterate in mutable tree, add debug log for
Browse files Browse the repository at this point in the history
  • Loading branch information
p0mvn committed Feb 11, 2022
1 parent 9b46195 commit 7862717
Showing 1 changed file with 65 additions and 55 deletions.
120 changes: 65 additions & 55 deletions mutable_tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,78 +163,78 @@ func (t *MutableTree) Iterate(fn func(key []byte, value []byte) bool) (stopped b
return false
}

if t.IsFastCacheEnabled() {
// We need to ensure that we iterate over saved and unsaved state in order.
// The strategy is to sort unsaved nodes, the fast node on disk are already sorted.
// Then, we keep a pointer to both the unsaved and saved nodes, and iterate over them in order efficiently.
unsavedFastNodesToSort := make([]string, 0, len(t.unsavedFastNodeAdditions))

for _, fastNode := range t.unsavedFastNodeAdditions {
unsavedFastNodesToSort = append(unsavedFastNodesToSort, string(fastNode.key))
}

sort.Strings(unsavedFastNodesToSort)
if !t.IsFastCacheEnabled() {
return t.ImmutableTree.Iterate(fn)
}

itr := t.ImmutableTree.Iterator(nil, nil, true)
// We need to ensure that we iterate over saved and unsaved state in order.
// The strategy is to sort unsaved nodes, the fast node on disk are already sorted.
// Then, we keep a pointer to both the unsaved and saved nodes, and iterate over them in order efficiently.
unsavedFastNodesToSort := make([]string, 0, len(t.unsavedFastNodeAdditions))

nextUnsavedIdx := 0
for itr.Valid() && nextUnsavedIdx < len(unsavedFastNodesToSort) {
diskKeyStr := string(itr.Key())
for _, fastNode := range t.unsavedFastNodeAdditions {
unsavedFastNodesToSort = append(unsavedFastNodesToSort, string(fastNode.key))
}

if t.unsavedFastNodeRemovals[string(diskKeyStr)] != nil {
// If next fast node from disk is to be removed, skip it.
itr.Next()
continue
}
sort.Strings(unsavedFastNodesToSort)

nextUnsavedKey := unsavedFastNodesToSort[nextUnsavedIdx]
nextUnsavedNode := t.unsavedFastNodeAdditions[nextUnsavedKey]
itr := t.ImmutableTree.Iterator(nil, nil, true)

if diskKeyStr >= nextUnsavedKey {
// Unsaved node is next
nextUnsavedIdx := 0
for itr.Valid() && nextUnsavedIdx < len(unsavedFastNodesToSort) {
diskKeyStr := string(itr.Key())

if diskKeyStr == nextUnsavedKey {
// Unsaved update prevails over saved copy so we skip the copy from disk
itr.Next()
}
if t.unsavedFastNodeRemovals[string(diskKeyStr)] != nil {
// If next fast node from disk is to be removed, skip it.
itr.Next()
continue
}

if fn(nextUnsavedNode.key, nextUnsavedNode.value) {
return true
}
nextUnsavedKey := unsavedFastNodesToSort[nextUnsavedIdx]
nextUnsavedNode := t.unsavedFastNodeAdditions[nextUnsavedKey]

nextUnsavedIdx++
} else {
// Disk node is next
if fn(itr.Key(), itr.Value()) {
return true
}
if diskKeyStr >= nextUnsavedKey {
// Unsaved node is next

if diskKeyStr == nextUnsavedKey {
// Unsaved update prevails over saved copy so we skip the copy from disk
itr.Next()
}
}

// if only nodes on disk are left, we can just iterate
for itr.Valid() {
if fn(nextUnsavedNode.key, nextUnsavedNode.value) {
return true
}

nextUnsavedIdx++
} else {
// Disk node is next
if fn(itr.Key(), itr.Value()) {
return true
}

itr.Next()
}
}

// if only unsaved nodes are left, we can just iterate
for ; nextUnsavedIdx < len(unsavedFastNodesToSort); nextUnsavedIdx++ {
nextUnsavedKey := unsavedFastNodesToSort[nextUnsavedIdx]
nextUnsavedNode := t.unsavedFastNodeAdditions[nextUnsavedKey]

if fn(nextUnsavedNode.key, nextUnsavedNode.value) {
return true
}
// if only nodes on disk are left, we can just iterate
for itr.Valid() {
if fn(itr.Key(), itr.Value()) {
return true
}
itr.Next()
}

return false
// if only unsaved nodes are left, we can just iterate
for ; nextUnsavedIdx < len(unsavedFastNodesToSort); nextUnsavedIdx++ {
nextUnsavedKey := unsavedFastNodesToSort[nextUnsavedIdx]
nextUnsavedNode := t.unsavedFastNodeAdditions[nextUnsavedKey]

if fn(nextUnsavedNode.key, nextUnsavedNode.value) {
return true
}
}

return t.ImmutableTree.Iterate(fn)
return false
}

// Iterator is not supported and is therefore invalid for MutableTree. Get an ImmutableTree instead for a valid iterator.
Expand Down Expand Up @@ -577,26 +577,36 @@ func (tree *MutableTree) enableFastStorageAndCommitLocked() error {
}

func (tree *MutableTree) enableFastStorageAndCommit() error {
debug("enabling fast storage, might take a while.")
var err error
defer func() {
if err != nil {
debug("failed to enable fast storage: %v\n", err)
} else {
debug("fast storage is enabled.")
}
}()

itr := tree.ImmutableTree.Iterator(nil, nil, true)
for ; itr.Valid(); itr.Next() {
if err := tree.ndb.SaveFastNode(NewFastNode(itr.Key(), itr.Value(), tree.version)); err != nil {
if err = tree.ndb.SaveFastNode(NewFastNode(itr.Key(), itr.Value(), tree.version)); err != nil {
return err
}
}

if err := itr.Error(); err != nil {
if err = itr.Error(); err != nil {
return err
}

if err := tree.ndb.batch.Set(metadataKeyFormat.Key([]byte(storageVersionKey)), []byte(fastStorageVersionValue)); err != nil {
if err = tree.ndb.batch.Set(metadataKeyFormat.Key([]byte(storageVersionKey)), []byte(fastStorageVersionValue)); err != nil {
return err
}

if err := tree.ndb.setStorageVersionBatch(fastStorageVersionValue); err != nil {
if err = tree.ndb.setStorageVersionBatch(fastStorageVersionValue); err != nil {
return err
}

if err := tree.ndb.Commit(); err != nil {
if err = tree.ndb.Commit(); err != nil {
return err
}
return nil
Expand Down

0 comments on commit 7862717

Please sign in to comment.