157 lines
6.1 KiB
Go
157 lines
6.1 KiB
Go
package pilorama
|
|
|
|
import (
|
|
"context"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode"
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr"
|
|
cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
|
)
|
|
|
|
// Forest represents CRDT tree.
|
|
type Forest interface {
|
|
// TreeMove moves node in the tree.
|
|
// If the parent of the move operation is TrashID, the node is removed.
|
|
// If the child of the move operation is RootID, new ID is generated and added to a tree.
|
|
TreeMove(ctx context.Context, d CIDDescriptor, treeID string, m *Move) (*Move, error)
|
|
// TreeAddByPath adds new node in the tree using provided path.
|
|
// The path is constructed by descending from the root using the values of the attr in meta.
|
|
// Internal nodes in path should have exactly one attribute, otherwise a new node is created.
|
|
TreeAddByPath(ctx context.Context, d CIDDescriptor, treeID string, attr string, path []string, meta []KeyValue) ([]Move, error)
|
|
// TreeApply applies replicated operation from another node.
|
|
// If background is true, TreeApply will first check whether an operation exists.
|
|
TreeApply(ctx context.Context, cnr cidSDK.ID, treeID string, m *Move, backgroundSync bool) error
|
|
// TreeGetByPath returns all nodes corresponding to the path.
|
|
// The path is constructed by descending from the root using the values of the
|
|
// AttributeFilename in meta.
|
|
// The last argument determines whether only the node with the latest timestamp is returned.
|
|
// Should return ErrTreeNotFound if the tree is not found, and empty result if the path is not in the tree.
|
|
TreeGetByPath(ctx context.Context, cid cidSDK.ID, treeID string, attr string, path []string, latest bool) ([]Node, error)
|
|
// TreeGetMeta returns meta information of the node with the specified ID.
|
|
// Should return ErrTreeNotFound if the tree is not found, and empty result if the node is not in the tree.
|
|
TreeGetMeta(ctx context.Context, cid cidSDK.ID, treeID string, nodeID Node) (Meta, Node, error)
|
|
// TreeGetChildren returns children of the node with the specified ID. The order is arbitrary.
|
|
// Should return ErrTreeNotFound if the tree is not found, and empty result if the node is not in the tree.
|
|
TreeGetChildren(ctx context.Context, cid cidSDK.ID, treeID string, nodeID Node) ([]NodeInfo, error)
|
|
// TreeGetOpLog returns first log operation stored at or above the height.
|
|
// In case no such operation is found, empty Move and nil error should be returned.
|
|
TreeGetOpLog(ctx context.Context, cid cidSDK.ID, treeID string, height uint64) (Move, error)
|
|
// TreeDrop drops a tree from the database.
|
|
// If the tree is not found, ErrTreeNotFound should be returned.
|
|
// In case of empty treeID drops all trees related to container.
|
|
TreeDrop(ctx context.Context, 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(ctx context.Context, cid cidSDK.ID) ([]string, error)
|
|
// TreeExists checks if a tree exists locally.
|
|
// If the tree is not found, false and a nil error should be returned.
|
|
TreeExists(ctx context.Context, cid cidSDK.ID, treeID string) (bool, error)
|
|
// TreeUpdateLastSyncHeight updates last log height synchronized with _all_ container nodes.
|
|
TreeUpdateLastSyncHeight(ctx context.Context, cid cidSDK.ID, treeID string, height uint64) error
|
|
// TreeLastSyncHeight returns last log height synchronized with _all_ container nodes.
|
|
TreeLastSyncHeight(ctx context.Context, cid cidSDK.ID, treeID string) (uint64, error)
|
|
// TreeHeight returns current tree height.
|
|
TreeHeight(ctx context.Context, cid cidSDK.ID, treeID string) (uint64, error)
|
|
}
|
|
|
|
type ForestStorage interface {
|
|
// DumpInfo returns information about the pilorama.
|
|
DumpInfo() Info
|
|
Init() error
|
|
Open(context.Context, mode.Mode) error
|
|
Close() error
|
|
SetMode(m mode.Mode) error
|
|
SetParentID(id string)
|
|
Forest
|
|
|
|
// TreeListTrees returns all pairs "containerID:treeID".
|
|
TreeListTrees(ctx context.Context, prm TreeListTreesPrm) (*TreeListTreesResult, error)
|
|
TreeApplyStream(ctx context.Context, cnr cidSDK.ID, treeID string, source <-chan *Move) error
|
|
}
|
|
|
|
const (
|
|
AttributeFilename = "FileName"
|
|
AttributeVersion = "Version"
|
|
)
|
|
|
|
// CIDDescriptor contains container ID and information about the node position
|
|
// in the list of container nodes.
|
|
type CIDDescriptor struct {
|
|
CID cidSDK.ID
|
|
Position int
|
|
Size int
|
|
}
|
|
|
|
// ErrInvalidCIDDescriptor is returned when info about tne node position
|
|
// in the container is invalid.
|
|
var ErrInvalidCIDDescriptor = logicerr.New("cid descriptor is invalid")
|
|
|
|
func (d CIDDescriptor) checkValid() bool {
|
|
return 0 <= d.Position && d.Position < d.Size
|
|
}
|
|
|
|
var treeListTreesBatchSizeDefault = 1000
|
|
|
|
type ContainerIDTreeID struct {
|
|
CID cidSDK.ID
|
|
TreeID string
|
|
}
|
|
|
|
type TreeListTreesPrm struct {
|
|
NextPageToken []byte
|
|
// BatchSize is batch size to list trees. If not lower or equals zero, than treeListTreesBatchSizeDefault is used.
|
|
BatchSize int
|
|
}
|
|
|
|
type TreeListTreesResult struct {
|
|
NextPageToken []byte
|
|
Items []ContainerIDTreeID
|
|
}
|
|
|
|
type treeList interface {
|
|
TreeListTrees(ctx context.Context, prm TreeListTreesPrm) (*TreeListTreesResult, error)
|
|
}
|
|
|
|
func TreeListAll(ctx context.Context, f treeList) ([]ContainerIDTreeID, error) {
|
|
return treeListAll(ctx, f, treeListTreesBatchSizeDefault)
|
|
}
|
|
|
|
func treeListAll(ctx context.Context, f treeList, batchSize int) ([]ContainerIDTreeID, error) {
|
|
var prm TreeListTreesPrm
|
|
prm.BatchSize = batchSize
|
|
var result []ContainerIDTreeID
|
|
first := true
|
|
|
|
for len(prm.NextPageToken) > 0 || first {
|
|
first = false
|
|
|
|
res, err := f.TreeListTrees(ctx, prm)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
prm.NextPageToken = res.NextPageToken
|
|
result = append(result, res.Items...)
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func TreeCountAll(ctx context.Context, f treeList) (uint64, error) {
|
|
var prm TreeListTreesPrm
|
|
var result uint64
|
|
first := true
|
|
|
|
for len(prm.NextPageToken) > 0 || first {
|
|
first = false
|
|
|
|
res, err := f.TreeListTrees(ctx, prm)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
prm.NextPageToken = res.NextPageToken
|
|
result += uint64(len(res.Items))
|
|
}
|
|
|
|
return result, nil
|
|
}
|