forked from TrueCloudLab/frostfs-s3-gw
[#416] Use tree service to list objects
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
This commit is contained in:
parent
7e8b57605a
commit
25477cdaf8
6 changed files with 342 additions and 35 deletions
14
api/cache/objectslist.go
vendored
14
api/cache/objectslist.go
vendored
|
@ -33,8 +33,9 @@ type (
|
||||||
|
|
||||||
// ObjectsListKey is a key to find a ObjectsListCache's entry.
|
// ObjectsListKey is a key to find a ObjectsListCache's entry.
|
||||||
ObjectsListKey struct {
|
ObjectsListKey struct {
|
||||||
cid string
|
cid string
|
||||||
prefix string
|
prefix string
|
||||||
|
latestOnly bool
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -103,11 +104,12 @@ func (l *ObjectsListCache) CleanCacheEntriesContainingObject(objectName string,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateObjectsListCacheKey returns ObjectsListKey with the given CID and prefix.
|
// CreateObjectsListCacheKey returns ObjectsListKey with the given CID, prefix and latestOnly flag.
|
||||||
func CreateObjectsListCacheKey(cnr cid.ID, prefix string) ObjectsListKey {
|
func CreateObjectsListCacheKey(cnr *cid.ID, prefix string, latestOnly bool) ObjectsListKey {
|
||||||
p := ObjectsListKey{
|
p := ObjectsListKey{
|
||||||
cid: cnr.EncodeToString(),
|
cid: cnr.EncodeToString(),
|
||||||
prefix: prefix,
|
prefix: prefix,
|
||||||
|
latestOnly: latestOnly,
|
||||||
}
|
}
|
||||||
|
|
||||||
return p
|
return p
|
||||||
|
|
|
@ -17,6 +17,7 @@ import (
|
||||||
"github.com/nspcc-dev/neofs-s3-gw/api/data"
|
"github.com/nspcc-dev/neofs-s3-gw/api/data"
|
||||||
"github.com/nspcc-dev/neofs-s3-gw/api/layer"
|
"github.com/nspcc-dev/neofs-s3-gw/api/layer"
|
||||||
"github.com/nspcc-dev/neofs-s3-gw/api/resolver"
|
"github.com/nspcc-dev/neofs-s3-gw/api/resolver"
|
||||||
|
treetest "github.com/nspcc-dev/neofs-s3-gw/internal/neofstest/tree"
|
||||||
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/object"
|
"github.com/nspcc-dev/neofs-sdk-go/object"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/user"
|
"github.com/nspcc-dev/neofs-sdk-go/user"
|
||||||
|
@ -55,9 +56,10 @@ func prepareHandlerContext(t *testing.T) *handlerContext {
|
||||||
})
|
})
|
||||||
|
|
||||||
layerCfg := &layer.Config{
|
layerCfg := &layer.Config{
|
||||||
Caches: layer.DefaultCachesConfigs(zap.NewExample()),
|
Caches: layer.DefaultCachesConfigs(zap.NewExample()),
|
||||||
AnonKey: layer.AnonymousKey{Key: key},
|
AnonKey: layer.AnonymousKey{Key: key},
|
||||||
Resolver: testResolver,
|
Resolver: testResolver,
|
||||||
|
TreeService: treetest.NewTreeService(),
|
||||||
}
|
}
|
||||||
|
|
||||||
h := &handler{
|
h := &handler{
|
||||||
|
|
|
@ -503,19 +503,11 @@ func (n *layer) ListObjectsV2(ctx context.Context, p *ListObjectsParamsV2) (*Lis
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *layer) listSortedObjects(ctx context.Context, p allObjectParams) ([]*data.ObjectInfo, error) {
|
func (n *layer) listSortedObjects(ctx context.Context, p allObjectParams) ([]*data.ObjectInfo, error) {
|
||||||
versions, err := n.getAllObjectsVersions(ctx, p.Bucket, p.Prefix, p.Delimiter)
|
objects, err := n.getLatestObjectsVersions(ctx, p.Bucket, p.Prefix, p.Delimiter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
objects := make([]*data.ObjectInfo, 0, len(versions))
|
|
||||||
for _, v := range versions {
|
|
||||||
lastVersion := v.getLast()
|
|
||||||
if lastVersion != nil {
|
|
||||||
objects = append(objects, lastVersion)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.Slice(objects, func(i, j int) bool {
|
sort.Slice(objects, func(i, j int) bool {
|
||||||
return objects[i].Name < objects[j].Name
|
return objects[i].Name < objects[j].Name
|
||||||
})
|
})
|
||||||
|
@ -523,10 +515,49 @@ func (n *layer) listSortedObjects(ctx context.Context, p allObjectParams) ([]*da
|
||||||
return objects, nil
|
return objects, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *layer) getLatestObjectsVersions(ctx context.Context, bkt *data.BucketInfo, prefix, delimiter string) ([]*data.ObjectInfo, error) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
cacheKey := cache.CreateObjectsListCacheKey(&bkt.CID, prefix, true)
|
||||||
|
ids := n.listsCache.Get(cacheKey)
|
||||||
|
|
||||||
|
if ids == nil {
|
||||||
|
ids, err = n.treeService.GetLatestVersionsByPrefix(ctx, &bkt.CID, prefix)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := n.listsCache.Put(cacheKey, ids); err != nil {
|
||||||
|
n.log.Error("couldn't cache list of objects", zap.Error(err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
objectsMap := make(map[string]*data.ObjectInfo, len(ids)) // to squash the same directories
|
||||||
|
for i := 0; i < len(ids); i++ {
|
||||||
|
obj := n.objectFromObjectsCacheOrNeoFS(ctx, bkt, ids[i])
|
||||||
|
if obj == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if oi := objectInfoFromMeta(bkt, obj, prefix, delimiter); oi != nil {
|
||||||
|
if isSystem(oi) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
objectsMap[oi.Name] = oi
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
objects := make([]*data.ObjectInfo, 0, len(objectsMap))
|
||||||
|
for _, obj := range objectsMap {
|
||||||
|
objects = append(objects, obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
return objects, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (n *layer) getAllObjectsVersions(ctx context.Context, bkt *data.BucketInfo, prefix, delimiter string) (map[string]*objectVersions, error) {
|
func (n *layer) getAllObjectsVersions(ctx context.Context, bkt *data.BucketInfo, prefix, delimiter string) (map[string]*objectVersions, error) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
cacheKey := cache.CreateObjectsListCacheKey(bkt.CID, prefix)
|
cacheKey := cache.CreateObjectsListCacheKey(&bkt.CID, prefix, false)
|
||||||
ids := n.listsCache.Get(cacheKey)
|
ids := n.listsCache.Get(cacheKey)
|
||||||
|
|
||||||
if ids == nil {
|
if ids == nil {
|
||||||
|
|
|
@ -32,6 +32,7 @@ type TreeService interface {
|
||||||
|
|
||||||
GetVersions(ctx context.Context, cnrID *cid.ID, objectName string) ([]*NodeVersion, error)
|
GetVersions(ctx context.Context, cnrID *cid.ID, objectName string) ([]*NodeVersion, error)
|
||||||
GetLatestVersion(ctx context.Context, cnrID *cid.ID, objectName string) (*NodeVersion, error)
|
GetLatestVersion(ctx context.Context, cnrID *cid.ID, objectName string) (*NodeVersion, error)
|
||||||
|
GetLatestVersionsByPrefix(ctx context.Context, cnrID *cid.ID, prefix string) ([]oid.ID, error)
|
||||||
GetUnversioned(ctx context.Context, cnrID *cid.ID, objectName string) (*NodeVersion, error)
|
GetUnversioned(ctx context.Context, cnrID *cid.ID, objectName string) (*NodeVersion, error)
|
||||||
AddVersion(ctx context.Context, cnrID *cid.ID, objectName string, newVersion *NodeVersion) error
|
AddVersion(ctx context.Context, cnrID *cid.ID, objectName string, newVersion *NodeVersion) error
|
||||||
RemoveVersion(ctx context.Context, cnrID *cid.ID, nodeID uint64) error
|
RemoveVersion(ctx context.Context, cnrID *cid.ID, nodeID uint64) error
|
||||||
|
|
|
@ -56,8 +56,12 @@ const (
|
||||||
systemTree = "system"
|
systemTree = "system"
|
||||||
|
|
||||||
separator = "/"
|
separator = "/"
|
||||||
|
|
||||||
|
maxGetSubTreeDepth = 10 // current limit on storage node side
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var emptyOID oid.ID
|
||||||
|
|
||||||
// NewTreeClient creates instance of TreeClient using provided address and create grpc connection.
|
// NewTreeClient creates instance of TreeClient using provided address and create grpc connection.
|
||||||
func NewTreeClient(addr string, key *keys.PrivateKey) (*TreeClient, error) {
|
func NewTreeClient(addr string, key *keys.PrivateKey) (*TreeClient, error) {
|
||||||
conn, err := grpc.Dial(addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
conn, err := grpc.Dial(addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||||
|
@ -74,7 +78,13 @@ func NewTreeClient(addr string, key *keys.PrivateKey) (*TreeClient, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTreeNode(nodeInfo *tree.GetNodeByPathResponse_Info) (*TreeNode, error) {
|
type NodeResponse interface {
|
||||||
|
GetMeta() []*tree.KeyValue
|
||||||
|
GetNodeId() uint64
|
||||||
|
GetTimestamp() uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
func newTreeNode(nodeInfo NodeResponse) (*TreeNode, error) {
|
||||||
var objID oid.ID
|
var objID oid.ID
|
||||||
meta := make(map[string]string, len(nodeInfo.GetMeta()))
|
meta := make(map[string]string, len(nodeInfo.GetMeta()))
|
||||||
|
|
||||||
|
@ -92,7 +102,7 @@ func newTreeNode(nodeInfo *tree.GetNodeByPathResponse_Info) (*TreeNode, error) {
|
||||||
return &TreeNode{
|
return &TreeNode{
|
||||||
ID: nodeInfo.GetNodeId(),
|
ID: nodeInfo.GetNodeId(),
|
||||||
ObjID: objID,
|
ObjID: objID,
|
||||||
TimeStamp: nodeInfo.Timestamp,
|
TimeStamp: nodeInfo.GetTimestamp(),
|
||||||
Meta: meta,
|
Meta: meta,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -102,7 +112,7 @@ func (n *TreeNode) Get(key string) (string, bool) {
|
||||||
return value, ok
|
return value, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func newNodeVersion(node *tree.GetNodeByPathResponse_Info) (*layer.NodeVersion, error) {
|
func newNodeVersion(node NodeResponse) (*layer.NodeVersion, error) {
|
||||||
treeNode, err := newTreeNode(node)
|
treeNode, err := newTreeNode(node)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("invalid tree node: %w", err)
|
return nil, fmt.Errorf("invalid tree node: %w", err)
|
||||||
|
@ -113,7 +123,7 @@ func newNodeVersion(node *tree.GetNodeByPathResponse_Info) (*layer.NodeVersion,
|
||||||
|
|
||||||
return &layer.NodeVersion{
|
return &layer.NodeVersion{
|
||||||
BaseNodeVersion: layer.BaseNodeVersion{
|
BaseNodeVersion: layer.BaseNodeVersion{
|
||||||
ID: node.NodeId,
|
ID: treeNode.ID,
|
||||||
OID: treeNode.ObjID,
|
OID: treeNode.ObjID,
|
||||||
},
|
},
|
||||||
IsUnversioned: isUnversioned,
|
IsUnversioned: isUnversioned,
|
||||||
|
@ -242,6 +252,96 @@ func (c *TreeClient) GetLatestVersion(ctx context.Context, cnrID *cid.ID, object
|
||||||
return c.getLatestVersion(ctx, cnrID, versionTree, fileNameKV, path, meta)
|
return c.getLatestVersion(ctx, cnrID, versionTree, fileNameKV, path, meta)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *TreeClient) GetLatestVersionsByPrefix(ctx context.Context, cnrID *cid.ID, prefix string) ([]oid.ID, error) {
|
||||||
|
var rootID uint64
|
||||||
|
path := strings.Split(prefix, separator)
|
||||||
|
tailPrefix := path[len(path)-1]
|
||||||
|
|
||||||
|
if len(path) > 1 {
|
||||||
|
meta := []string{fileNameKV}
|
||||||
|
|
||||||
|
nodes, err := c.getNodes(ctx, cnrID, versionTree, fileNameKV, path[:len(path)-1], meta, true)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(nodes) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
if len(nodes) != 1 {
|
||||||
|
return nil, layer.ErrNodeNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
rootID = nodes[0].NodeId
|
||||||
|
}
|
||||||
|
|
||||||
|
subTree, err := c.getSubTree(ctx, cnrID, versionTree, rootID, 1)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var result []oid.ID
|
||||||
|
for _, node := range subTree {
|
||||||
|
if node.GetNodeId() != 0 && hasPrefix(node, tailPrefix) {
|
||||||
|
latestNodes, err := c.getSubTreeLatestVersions(ctx, cnrID, node.GetNodeId())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = append(result, latestNodes...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func hasPrefix(node *tree.GetSubTreeResponse_Body, prefix string) bool {
|
||||||
|
for _, kv := range node.GetMeta() {
|
||||||
|
if kv.GetKey() == fileNameKV {
|
||||||
|
return strings.HasPrefix(string(kv.GetValue()), prefix)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *TreeClient) getSubTreeLatestVersions(ctx context.Context, cnrID *cid.ID, nodeID uint64) ([]oid.ID, error) {
|
||||||
|
subTree, err := c.getSubTree(ctx, cnrID, versionTree, nodeID, maxGetSubTreeDepth)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
latestVersions := make(map[string]*TreeNode, len(subTree))
|
||||||
|
for _, node := range subTree {
|
||||||
|
treeNode, err := newTreeNode(node)
|
||||||
|
if err != nil || treeNode.ObjID.Equals(emptyOID) { // invalid OID attribute
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fileName, ok := treeNode.Get(fileNameKV)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
key := formLatestNodeKey(node.GetParentId(), fileName)
|
||||||
|
latest, ok := latestVersions[key]
|
||||||
|
if !ok || latest.TimeStamp <= treeNode.TimeStamp { // todo also compare oid
|
||||||
|
latestVersions[key] = treeNode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result := make([]oid.ID, 0, len(latestVersions))
|
||||||
|
for _, treeNode := range latestVersions {
|
||||||
|
if _, ok := treeNode.Get(isDeleteMarkerKV); ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
result = append(result, treeNode.ObjID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func formLatestNodeKey(parentID uint64, fileName string) string {
|
||||||
|
return strconv.FormatUint(parentID, 10) + fileName
|
||||||
|
}
|
||||||
|
|
||||||
func (c *TreeClient) GetSystemVersion(ctx context.Context, cnrID *cid.ID, objectName string) (*layer.BaseNodeVersion, error) {
|
func (c *TreeClient) GetSystemVersion(ctx context.Context, cnrID *cid.ID, objectName string) (*layer.BaseNodeVersion, error) {
|
||||||
meta := []string{oidKV}
|
meta := []string{oidKV}
|
||||||
path := strings.Split(objectName, separator)
|
path := strings.Split(objectName, separator)
|
||||||
|
@ -379,11 +479,21 @@ func (c *TreeClient) getVersions(ctx context.Context, cnrID *cid.ID, treeID, fil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TreeClient) getParent(ctx context.Context, cnrID *cid.ID, treeID string, id uint64) (uint64, error) {
|
func (c *TreeClient) getParent(ctx context.Context, cnrID *cid.ID, treeID string, id uint64) (uint64, error) {
|
||||||
|
subTree, err := c.getSubTree(ctx, cnrID, treeID, id, 0)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return subTree[0].GetParentId(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *TreeClient) getSubTree(ctx context.Context, cnrID *cid.ID, treeID string, rootID uint64, depth uint32) ([]*tree.GetSubTreeResponse_Body, error) {
|
||||||
request := &tree.GetSubTreeRequest{
|
request := &tree.GetSubTreeRequest{
|
||||||
Body: &tree.GetSubTreeRequest_Body{
|
Body: &tree.GetSubTreeRequest_Body{
|
||||||
ContainerId: cnrID[:],
|
ContainerId: cnrID[:],
|
||||||
TreeId: treeID,
|
TreeId: treeID,
|
||||||
RootId: id,
|
RootId: rootID,
|
||||||
|
Depth: depth,
|
||||||
BearerToken: getBearer(ctx),
|
BearerToken: getBearer(ctx),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -394,28 +504,32 @@ func (c *TreeClient) getParent(ctx context.Context, cnrID *cid.ID, treeID string
|
||||||
Sign: sign,
|
Sign: sign,
|
||||||
}
|
}
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return 0, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cli, err := c.service.GetSubTree(ctx, request)
|
cli, err := c.service.GetSubTree(ctx, request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, fmt.Errorf("failed to get sub tree client: %w", err)
|
if strings.Contains(err.Error(), "not found") {
|
||||||
}
|
return nil, nil
|
||||||
|
}
|
||||||
resp, err := cli.Recv()
|
return nil, fmt.Errorf("failed to get sub tree client: %w", err)
|
||||||
if err != nil {
|
|
||||||
return 0, fmt.Errorf("failed to get sub tree: %w", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var subtree []*tree.GetSubTreeResponse_Body
|
||||||
for {
|
for {
|
||||||
if _, err = cli.Recv(); err == io.EOF {
|
resp, err := cli.Recv()
|
||||||
|
if err == io.EOF {
|
||||||
break
|
break
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return 0, fmt.Errorf("failed to read out sub tree stream: %w", err)
|
if strings.Contains(err.Error(), "not found") {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("failed to get sub tree: %w", err)
|
||||||
}
|
}
|
||||||
|
subtree = append(subtree, resp.Body)
|
||||||
}
|
}
|
||||||
|
|
||||||
return resp.GetBody().GetParentId(), nil
|
return subtree, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func metaFromSettings(settings *data.BucketSettings) map[string]string {
|
func metaFromSettings(settings *data.BucketSettings) map[string]string {
|
||||||
|
@ -474,7 +588,7 @@ func (c *TreeClient) getNodes(ctx context.Context, cnrID *cid.ID, treeID, pathAt
|
||||||
|
|
||||||
resp, err := c.service.GetNodeByPath(ctx, request)
|
resp, err := c.service.GetNodeByPath(ctx, request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to get node path deb: %w", err)
|
return nil, fmt.Errorf("failed to get node path: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return resp.GetBody().GetNodes(), nil
|
return resp.GetBody().GetNodes(), nil
|
||||||
|
|
157
internal/neofstest/tree/tree_mock.go
Normal file
157
internal/neofstest/tree/tree_mock.go
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
package tree
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neofs-s3-gw/api/data"
|
||||||
|
"github.com/nspcc-dev/neofs-s3-gw/api/layer"
|
||||||
|
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||||
|
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TreeServiceMock struct {
|
||||||
|
settings map[string]*data.BucketSettings
|
||||||
|
versions map[string]map[string][]*layer.NodeVersion
|
||||||
|
system map[string]map[string]*layer.BaseNodeVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTreeService() *TreeServiceMock {
|
||||||
|
return &TreeServiceMock{
|
||||||
|
settings: make(map[string]*data.BucketSettings),
|
||||||
|
versions: make(map[string]map[string][]*layer.NodeVersion),
|
||||||
|
system: make(map[string]map[string]*layer.BaseNodeVersion),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TreeServiceMock) PutSettingsNode(_ context.Context, id *cid.ID, settings *data.BucketSettings) error {
|
||||||
|
t.settings[id.EncodeToString()] = settings
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TreeServiceMock) GetSettingsNode(_ context.Context, id *cid.ID) (*data.BucketSettings, error) {
|
||||||
|
settings, ok := t.settings[id.EncodeToString()]
|
||||||
|
if !ok {
|
||||||
|
return nil, layer.ErrNodeNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
return settings, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TreeServiceMock) GetNotificationConfigurationNode(ctx context.Context, cnrID *cid.ID) (*oid.ID, error) {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TreeServiceMock) PutNotificationConfigurationNode(ctx context.Context, cnrID *cid.ID, objID *oid.ID) (*oid.ID, error) {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TreeServiceMock) GetBucketCORS(ctx context.Context, cnrID *cid.ID) (*oid.ID, error) {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TreeServiceMock) PutBucketCORS(ctx context.Context, cnrID *cid.ID, objID *oid.ID) (*oid.ID, error) {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TreeServiceMock) DeleteBucketCORS(ctx context.Context, cnrID *cid.ID) (*oid.ID, error) {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TreeServiceMock) GetVersions(ctx context.Context, cnrID *cid.ID, objectName string) ([]*layer.NodeVersion, error) {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TreeServiceMock) GetLatestVersion(ctx context.Context, cnrID *cid.ID, objectName string) (*layer.NodeVersion, error) {
|
||||||
|
cnrVersionsMap, ok := t.versions[cnrID.EncodeToString()]
|
||||||
|
if !ok {
|
||||||
|
return nil, layer.ErrNodeNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
versions, ok := cnrVersionsMap[objectName]
|
||||||
|
if !ok {
|
||||||
|
return nil, layer.ErrNodeNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Slice(versions, func(i, j int) bool {
|
||||||
|
return versions[i].ID < versions[j].ID
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(versions) != 0 {
|
||||||
|
return versions[len(versions)-1], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, layer.ErrNodeNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TreeServiceMock) GetLatestVersionsByPrefix(ctx context.Context, cnrID *cid.ID, prefix string) ([]oid.ID, error) {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TreeServiceMock) GetUnversioned(ctx context.Context, cnrID *cid.ID, objectName string) (*layer.NodeVersion, error) {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TreeServiceMock) AddVersion(_ context.Context, cnrID *cid.ID, objectName string, newVersion *layer.NodeVersion) error {
|
||||||
|
cnrVersionsMap, ok := t.versions[cnrID.EncodeToString()]
|
||||||
|
if !ok {
|
||||||
|
t.versions[cnrID.EncodeToString()] = map[string][]*layer.NodeVersion{
|
||||||
|
objectName: {newVersion},
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
versions, ok := cnrVersionsMap[objectName]
|
||||||
|
if !ok {
|
||||||
|
cnrVersionsMap[objectName] = []*layer.NodeVersion{newVersion}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Slice(versions, func(i, j int) bool {
|
||||||
|
return versions[i].ID < versions[j].ID
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(versions) != 0 {
|
||||||
|
newVersion.ID = versions[len(versions)-1].ID + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
cnrVersionsMap[objectName] = append(versions, newVersion)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TreeServiceMock) RemoveVersion(ctx context.Context, cnrID *cid.ID, nodeID uint64) error {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TreeServiceMock) AddSystemVersion(_ context.Context, cnrID *cid.ID, objectName string, newVersion *layer.BaseNodeVersion) error {
|
||||||
|
cnrSystemMap, ok := t.system[cnrID.EncodeToString()]
|
||||||
|
if !ok {
|
||||||
|
t.system[cnrID.EncodeToString()] = map[string]*layer.BaseNodeVersion{
|
||||||
|
objectName: newVersion,
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
cnrSystemMap[objectName] = newVersion
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TreeServiceMock) GetSystemVersion(_ context.Context, cnrID *cid.ID, objectName string) (*layer.BaseNodeVersion, error) {
|
||||||
|
cnrSystemMap, ok := t.system[cnrID.EncodeToString()]
|
||||||
|
if !ok {
|
||||||
|
return nil, layer.ErrNodeNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
sysVersion, ok := cnrSystemMap[objectName]
|
||||||
|
if !ok {
|
||||||
|
return nil, layer.ErrNodeNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
return sysVersion, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TreeServiceMock) RemoveSystemVersion(ctx context.Context, cnrID *cid.ID, nodeID uint64) error {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
Loading…
Reference in a new issue