[#1902] pilorama: Add TreeList method

To both `bolt` and `memory` forests; extend `Forest` interface.

Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
This commit is contained in:
Pavel Karpy 2022-10-18 14:59:32 +03:00 committed by Pavel Karpy
parent 3aa9938b8f
commit 19850ef157
6 changed files with 104 additions and 0 deletions

View file

@ -180,3 +180,9 @@ func (e *StorageEngine) TreeDrop(cid cidSDK.ID, treeID string) error {
}
return err
}
// TreeList implements the pilorama.Forest interface.
func (e *StorageEngine) TreeList(cid cidSDK.ID) ([]string, error) {
//TODO implement me
panic("implement me")
}

View file

@ -557,6 +557,31 @@ func (t *boltForest) TreeGetChildren(cid cidSDK.ID, treeID string, nodeID Node)
return children, err
}
// TreeList implements the Forest interface.
func (t *boltForest) TreeList(cid cidSDK.ID) ([]string, error) {
var ids []string
cidRaw := []byte(cid.EncodeToString())
cidLen := len(cidRaw)
err := t.db.View(func(tx *bbolt.Tx) error {
c := tx.Cursor()
for k, _ := c.Seek(cidRaw); k != nil; k, _ = c.Next() {
if !bytes.HasPrefix(k, cidRaw) {
return nil
}
ids = append(ids, string(k[cidLen:]))
}
return nil
})
if err != nil {
return nil, fmt.Errorf("could not list trees: %w", err)
}
return ids, nil
}
// TreeGetOpLog implements the pilorama.Forest interface.
func (t *boltForest) TreeGetOpLog(cid cidSDK.ID, treeID string, height uint64) (Move, error) {
key := make([]byte, 8)

View file

@ -2,6 +2,7 @@ package pilorama
import (
"sort"
"strings"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/shard/mode"
cidSDK "github.com/nspcc-dev/neofs-sdk-go/container/id"
@ -191,3 +192,20 @@ func (f *memoryForest) TreeDrop(cid cidSDK.ID, treeID string) error {
delete(f.treeMap, fullID)
return nil
}
// TreeGetTrees implements the pilorama.Forest interface.
func (f *memoryForest) TreeList(cid cidSDK.ID) ([]string, error) {
var res []string
cidStr := cid.EncodeToString()
for k := range f.treeMap {
cidAndTree := strings.Split(k, "/")
if cidAndTree[0] != cidStr {
continue
}
res = append(res, cidAndTree[1])
}
return res, nil
}

View file

@ -1,6 +1,7 @@
package pilorama
import (
"fmt"
"math/rand"
"os"
"path/filepath"
@ -9,6 +10,7 @@ import (
cidSDK "github.com/nspcc-dev/neofs-sdk-go/container/id"
cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test"
objectSDK "github.com/nspcc-dev/neofs-sdk-go/object"
"github.com/stretchr/testify/require"
)
@ -720,3 +722,47 @@ func testMove(t *testing.T, s Forest, ts int, node, parent Node, d CIDDescriptor
},
}))
}
func TestGetTrees(t *testing.T) {
for i := range providers {
t.Run(providers[i].name, func(t *testing.T) {
testTreeGetTrees(t, providers[i].construct(t))
})
}
}
func testTreeGetTrees(t *testing.T, s Forest) {
cids := []cidSDK.ID{cidtest.ID(), cidtest.ID()}
d := CIDDescriptor{Position: 0, Size: 1}
treeIDs := make(map[cidSDK.ID][]string, len(cids))
for i, cid := range cids {
treeIDs[cid] = []string{
fmt.Sprintf("test1_%d", i),
fmt.Sprintf("test2_%d", i),
fmt.Sprintf("test3_%d", i),
fmt.Sprintf("1test_%d", i),
fmt.Sprintf("2test_%d", i),
fmt.Sprintf("3test_%d", i),
"",
}
}
for _, cid := range cids {
d.CID = cid
for _, treeID := range treeIDs[cid] {
_, err := s.TreeAddByPath(d, treeID, objectSDK.AttributeFileName, []string{"path"}, nil)
require.NoError(t, err)
}
}
for _, cid := range cids {
d.CID = cid
trees, err := s.TreeList(cid)
require.NoError(t, err)
require.ElementsMatch(t, treeIDs[cid], trees)
}
}

View file

@ -37,6 +37,9 @@ type Forest interface {
// TreeDrop drops a tree from the database.
// If the tree is not found, ErrTreeNotFound should be returned.
TreeDrop(cid cidSDK.ID, treeID string) error
// TreeList returns all the tree IDs that have been added to the
// passed container ID. Nil slice should be returned if no tree found.
TreeList(cid cidSDK.ID) ([]string, error)
}
type ForestStorage interface {

View file

@ -84,3 +84,9 @@ func (s *Shard) TreeDrop(cid cidSDK.ID, treeID string) error {
}
return s.pilorama.TreeDrop(cid, treeID)
}
// TreeList implements the pilorama.Forest interface.
func (s *Shard) TreeList(cid cidSDK.ID) ([]string, error) {
//TODO implement me
panic("implement me")
}