krotik/eliasdb

Node deletion while iterating

bmfs opened this issue · 1 comments

bmfs commented

Noticed that while using a NodeKeyIteration, If nodes were deleted the iterator misses some results.

Is this expected?

An example:

package main

import (
	"fmt"

	"devt.de/krotik/eliasdb/graph"
	"devt.de/krotik/eliasdb/graph/data"
	"devt.de/krotik/eliasdb/graph/graphstorage"
)

func main() {
	TestNodeDeletion()
}

func TestNodeDeletion() {
	gs := graphstorage.NewMemoryGraphStorage("memdb")
	gm := graph.NewGraphManager(gs)

	nodeA1 := data.NewGraphNode()
	nodeA1.SetAttr(data.NodeKey, "nodeA1")
	nodeA1.SetAttr(data.NodeKind, "typeA")

	nodeA2 := data.NewGraphNode()
	nodeA2.SetAttr(data.NodeKey, "nodeA2")
	nodeA2.SetAttr(data.NodeKind, "typeA")

	nodeA3 := data.NewGraphNode()
	nodeA3.SetAttr(data.NodeKey, "nodeA3")
	nodeA3.SetAttr(data.NodeKind, "typeA")

	nodeA4 := data.NewGraphNode()
	nodeA4.SetAttr(data.NodeKey, "nodeA4")
	nodeA4.SetAttr(data.NodeKind, "typeA")

	gm.StoreNode("main", nodeA1)
	gm.StoreNode("main", nodeA2)
	gm.StoreNode("main", nodeA3)
	gm.StoreNode("main", nodeA4)

	fmt.Printf("Node Count: %d\n", gm.NodeCount("typeA"))

	it, _ := gm.NodeKeyIterator("main", "typeA")
	if it != nil {
		for it.HasNext() {
			key := it.Next()
			fmt.Printf("-- Node key = %s lastError = %v\n", key, it.LastError)
			if it.LastError != nil {
				break
			}

			gm.RemoveNode("main", key, "typeA")
		}
	}

	fmt.Printf("Node Count: %d\n", gm.NodeCount("typeA"))

}

The iterator uses the underlying H-Tree structure - this structure is changed when nodes get deleted. So, unfortunately, the behavior which you observed is expected. A better way to do this would be with a transaction (graph.NewGraphTrans) - this would also be significantly faster.