[#288] pilorama: Remove childMap from memory forest

Memory forest is here to check the correctness of boltdb optimized
implementation. Let's keep it simple.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
This commit is contained in:
Evgenii Stratonikov 2023-04-26 15:23:07 +03:00 committed by Evgenii Stratonikov
parent ada081dfd5
commit f856ad7480
3 changed files with 22 additions and 49 deletions

View file

@ -153,11 +153,7 @@ func (f *memoryForest) TreeGetChildren(_ context.Context, cid cid.ID, treeID str
return nil, ErrTreeNotFound return nil, ErrTreeNotFound
} }
children, ok := s.childMap[nodeID] children := s.tree.getChildren(nodeID)
if !ok {
return nil, nil
}
res := make([]Node, len(children)) res := make([]Node, len(children))
copy(res, children) copy(res, children)
return res, nil return res, nil

View file

@ -714,13 +714,6 @@ func compareForests(t *testing.T, expected, actual Forest, cid cidSDK.ID, treeID
require.True(t, ok) require.True(t, ok)
require.Equal(t, se.operations, sa.operations) require.Equal(t, se.operations, sa.operations)
require.Equal(t, se.infoMap, sa.infoMap) require.Equal(t, se.infoMap, sa.infoMap)
require.Equal(t, len(se.childMap), len(sa.childMap))
for ck, la := range sa.childMap {
le, ok := se.childMap[ck]
require.True(t, ok)
require.ElementsMatch(t, le, la)
}
} }
require.Equal(t, expected, actual, i) require.Equal(t, expected, actual, i)
} }

View file

@ -1,5 +1,7 @@
package pilorama package pilorama
import "sort"
// nodeInfo couples parent and metadata. // nodeInfo couples parent and metadata.
type nodeInfo struct { type nodeInfo struct {
Parent Node Parent Node
@ -27,27 +29,8 @@ func newState() *state {
// undo un-does op and changes s in-place. // undo un-does op and changes s in-place.
func (s *state) undo(op *move) { func (s *state) undo(op *move) {
children := s.tree.childMap[op.Parent]
for i := range children {
if children[i] == op.Child {
if len(children) > 1 {
s.tree.childMap[op.Parent] = append(children[:i], children[i+1:]...)
} else {
delete(s.tree.childMap, op.Parent)
}
break
}
}
if op.HasOld { if op.HasOld {
s.tree.infoMap[op.Child] = op.Old s.tree.infoMap[op.Child] = op.Old
oldChildren := s.tree.childMap[op.Old.Parent]
for i := range oldChildren {
if oldChildren[i] == op.Child {
return
}
}
s.tree.childMap[op.Old.Parent] = append(oldChildren, op.Child)
} else { } else {
delete(s.tree.infoMap, op.Child) delete(s.tree.infoMap, op.Child)
} }
@ -104,28 +87,15 @@ func (s *state) do(op *Move) move {
if !ok { if !ok {
p.Meta.Time = op.Time p.Meta.Time = op.Time
} else {
s.removeChild(op.Child, p.Parent)
} }
p.Meta = op.Meta p.Meta = op.Meta
p.Parent = op.Parent p.Parent = op.Parent
s.tree.infoMap[op.Child] = p s.tree.infoMap[op.Child] = p
s.tree.childMap[op.Parent] = append(s.tree.childMap[op.Parent], op.Child)
return lm return lm
} }
func (s *state) removeChild(child, parent Node) {
oldChildren := s.tree.childMap[parent]
for i := range oldChildren {
if oldChildren[i] == child {
s.tree.childMap[parent] = append(oldChildren[:i], oldChildren[i+1:]...)
break
}
}
}
func (s *state) timestamp(pos, size int) Timestamp { func (s *state) timestamp(pos, size int) Timestamp {
if len(s.operations) == 0 { if len(s.operations) == 0 {
return nextTimestamp(0, uint64(pos), uint64(size)) return nextTimestamp(0, uint64(pos), uint64(size))
@ -145,16 +115,30 @@ func (s *state) findSpareID() Node {
type tree struct { type tree struct {
syncHeight uint64 syncHeight uint64
infoMap map[Node]nodeInfo infoMap map[Node]nodeInfo
childMap map[Node][]Node
} }
func newTree() *tree { func newTree() *tree {
return &tree{ return &tree{
childMap: make(map[Node][]Node),
infoMap: make(map[Node]nodeInfo), infoMap: make(map[Node]nodeInfo),
} }
} }
func (t tree) getChildren(parent Node) []Node {
var children []Node
for c, info := range t.infoMap {
if info.Parent == parent {
children = append(children, c)
}
}
sort.Slice(children, func(i, j int) bool {
a := t.infoMap[children[i]]
b := t.infoMap[children[j]]
return a.Meta.Time < b.Meta.Time
})
return children
}
// isAncestor returns true if parent is an ancestor of a child. // isAncestor returns true if parent is an ancestor of a child.
// For convenience, also return true if parent == child. // For convenience, also return true if parent == child.
func (t tree) isAncestor(parent, child Node) bool { func (t tree) isAncestor(parent, child Node) bool {
@ -176,7 +160,7 @@ func (t tree) getPathPrefix(attr string, path []string) (int, Node) {
loop: loop:
for i := range path { for i := range path {
children := t.childMap[curNode] children := t.getChildren(curNode)
for j := range children { for j := range children {
meta := t.infoMap[children[j]].Meta meta := t.infoMap[children[j]].Meta
f := meta.GetAttr(attr) f := meta.GetAttr(attr)
@ -206,7 +190,7 @@ func (t tree) get(attr string, path []string, latest bool) []Node {
var nodes []Node var nodes []Node
var lastTs Timestamp var lastTs Timestamp
children := t.childMap[curNode] children := t.getChildren(curNode)
for i := range children { for i := range children {
info := t.infoMap[children[i]] info := t.infoMap[children[i]]
fileName := string(info.Meta.GetAttr(attr)) fileName := string(info.Meta.GetAttr(attr))