From f856ad74802d62ef487d18e624856da4fcde5665 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 26 Apr 2023 15:23:07 +0300 Subject: [PATCH] [#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 --- pkg/local_object_storage/pilorama/forest.go | 6 +- .../pilorama/forest_test.go | 7 --- pkg/local_object_storage/pilorama/inmemory.go | 58 +++++++------------ 3 files changed, 22 insertions(+), 49 deletions(-) diff --git a/pkg/local_object_storage/pilorama/forest.go b/pkg/local_object_storage/pilorama/forest.go index 84530977c7..0db9193517 100644 --- a/pkg/local_object_storage/pilorama/forest.go +++ b/pkg/local_object_storage/pilorama/forest.go @@ -153,11 +153,7 @@ func (f *memoryForest) TreeGetChildren(_ context.Context, cid cid.ID, treeID str return nil, ErrTreeNotFound } - children, ok := s.childMap[nodeID] - if !ok { - return nil, nil - } - + children := s.tree.getChildren(nodeID) res := make([]Node, len(children)) copy(res, children) return res, nil diff --git a/pkg/local_object_storage/pilorama/forest_test.go b/pkg/local_object_storage/pilorama/forest_test.go index be53b3fe27..94b14457ae 100644 --- a/pkg/local_object_storage/pilorama/forest_test.go +++ b/pkg/local_object_storage/pilorama/forest_test.go @@ -714,13 +714,6 @@ func compareForests(t *testing.T, expected, actual Forest, cid cidSDK.ID, treeID require.True(t, ok) require.Equal(t, se.operations, sa.operations) 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) } diff --git a/pkg/local_object_storage/pilorama/inmemory.go b/pkg/local_object_storage/pilorama/inmemory.go index 92dc9b6aa0..bfc2a5b26f 100644 --- a/pkg/local_object_storage/pilorama/inmemory.go +++ b/pkg/local_object_storage/pilorama/inmemory.go @@ -1,5 +1,7 @@ package pilorama +import "sort" + // nodeInfo couples parent and metadata. type nodeInfo struct { Parent Node @@ -27,27 +29,8 @@ func newState() *state { // undo un-does op and changes s in-place. 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 { 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 { delete(s.tree.infoMap, op.Child) } @@ -104,28 +87,15 @@ func (s *state) do(op *Move) move { if !ok { p.Meta.Time = op.Time - } else { - s.removeChild(op.Child, p.Parent) } p.Meta = op.Meta p.Parent = op.Parent s.tree.infoMap[op.Child] = p - s.tree.childMap[op.Parent] = append(s.tree.childMap[op.Parent], op.Child) 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 { if len(s.operations) == 0 { return nextTimestamp(0, uint64(pos), uint64(size)) @@ -145,16 +115,30 @@ func (s *state) findSpareID() Node { type tree struct { syncHeight uint64 infoMap map[Node]nodeInfo - childMap map[Node][]Node } func newTree() *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. // For convenience, also return true if parent == child. func (t tree) isAncestor(parent, child Node) bool { @@ -176,7 +160,7 @@ func (t tree) getPathPrefix(attr string, path []string) (int, Node) { loop: for i := range path { - children := t.childMap[curNode] + children := t.getChildren(curNode) for j := range children { meta := t.infoMap[children[j]].Meta f := meta.GetAttr(attr) @@ -206,7 +190,7 @@ func (t tree) get(attr string, path []string, latest bool) []Node { var nodes []Node var lastTs Timestamp - children := t.childMap[curNode] + children := t.getChildren(curNode) for i := range children { info := t.infoMap[children[i]] fileName := string(info.Meta.GetAttr(attr))