forked from TrueCloudLab/frostfs-node
[#948] engine: Define cursor for object listing as a type
Signed-off-by: Alex Vanin <alexey@nspcc.ru>
This commit is contained in:
parent
164cd10af8
commit
aa9ce8a853
4 changed files with 71 additions and 122 deletions
|
@ -1,19 +1,23 @@
|
|||
package engine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/object"
|
||||
core "github.com/nspcc-dev/neofs-node/pkg/core/object"
|
||||
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/shard"
|
||||
)
|
||||
|
||||
// Cursor is a type for continuous object listing.
|
||||
type Cursor struct {
|
||||
shardID string
|
||||
shardCursor *shard.Cursor
|
||||
}
|
||||
|
||||
// ListWithCursorPrm contains parameters for ListWithCursor operation.
|
||||
type ListWithCursorPrm struct {
|
||||
count uint32
|
||||
cursor string
|
||||
cursor *Cursor
|
||||
}
|
||||
|
||||
// WithCount sets maximum amount of addresses that ListWithCursor can return.
|
||||
|
@ -23,9 +27,9 @@ func (p *ListWithCursorPrm) WithCount(count uint32) *ListWithCursorPrm {
|
|||
}
|
||||
|
||||
// WithCursor sets cursor for ListWithCursor operation. For initial request
|
||||
// ignore this param or use empty string. For continues requests, use value
|
||||
// ignore this param or use nil value. For continues requests, use value
|
||||
// from ListWithCursorRes.
|
||||
func (p *ListWithCursorPrm) WithCursor(cursor string) *ListWithCursorPrm {
|
||||
func (p *ListWithCursorPrm) WithCursor(cursor *Cursor) *ListWithCursorPrm {
|
||||
p.cursor = cursor
|
||||
return p
|
||||
}
|
||||
|
@ -33,7 +37,7 @@ func (p *ListWithCursorPrm) WithCursor(cursor string) *ListWithCursorPrm {
|
|||
// ListWithCursorRes contains values returned from ListWithCursor operation.
|
||||
type ListWithCursorRes struct {
|
||||
addrList []*object.Address
|
||||
cursor string
|
||||
cursor *Cursor
|
||||
}
|
||||
|
||||
// AddressList returns addresses selected by ListWithCursor operation.
|
||||
|
@ -42,7 +46,7 @@ func (l ListWithCursorRes) AddressList() []*object.Address {
|
|||
}
|
||||
|
||||
// Cursor returns cursor for consecutive listing requests.
|
||||
func (l ListWithCursorRes) Cursor() string {
|
||||
func (l ListWithCursorRes) Cursor() *Cursor {
|
||||
return l.cursor
|
||||
}
|
||||
|
||||
|
@ -51,10 +55,7 @@ func (l ListWithCursorRes) Cursor() string {
|
|||
// Does not include inhumed objects. Use cursor value from response
|
||||
// for consecutive requests.
|
||||
func (e *StorageEngine) ListWithCursor(prm *ListWithCursorPrm) (*ListWithCursorRes, error) {
|
||||
var (
|
||||
err error
|
||||
result = make([]*object.Address, 0, prm.count)
|
||||
)
|
||||
result := make([]*object.Address, 0, prm.count)
|
||||
|
||||
// 1. Get available shards and sort them.
|
||||
e.mtx.RLock()
|
||||
|
@ -72,14 +73,10 @@ func (e *StorageEngine) ListWithCursor(prm *ListWithCursorPrm) (*ListWithCursorR
|
|||
return shardIDs[i] < shardIDs[j]
|
||||
})
|
||||
|
||||
// 2. Decode shard ID from cursor.
|
||||
// 2. Prepare cursor object.
|
||||
cursor := prm.cursor
|
||||
cursorShardID := shardIDs[0]
|
||||
if len(cursor) > 0 {
|
||||
cursorShardID, cursor, err = decodeID(cursor)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if cursor == nil {
|
||||
cursor = &Cursor{shardID: shardIDs[0]}
|
||||
}
|
||||
|
||||
// 3. Iterate over available shards. Skip unavailable shards.
|
||||
|
@ -88,7 +85,7 @@ func (e *StorageEngine) ListWithCursor(prm *ListWithCursorPrm) (*ListWithCursorR
|
|||
break
|
||||
}
|
||||
|
||||
if shardIDs[i] < cursorShardID {
|
||||
if shardIDs[i] < cursor.shardID {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -101,8 +98,8 @@ func (e *StorageEngine) ListWithCursor(prm *ListWithCursorPrm) (*ListWithCursorR
|
|||
|
||||
count := uint32(int(prm.count) - len(result))
|
||||
shardPrm := new(shard.ListWithCursorPrm).WithCount(count)
|
||||
if shardIDs[i] == cursorShardID {
|
||||
shardPrm.WithCursor(cursor)
|
||||
if shardIDs[i] == cursor.shardID {
|
||||
shardPrm.WithCursor(cursor.shardCursor)
|
||||
}
|
||||
|
||||
res, err := shardInstance.ListWithCursor(shardPrm)
|
||||
|
@ -111,8 +108,8 @@ func (e *StorageEngine) ListWithCursor(prm *ListWithCursorPrm) (*ListWithCursorR
|
|||
}
|
||||
|
||||
result = append(result, res.AddressList()...)
|
||||
cursor = res.Cursor()
|
||||
cursorShardID = shardIDs[i]
|
||||
cursor.shardCursor = res.Cursor()
|
||||
cursor.shardID = shardIDs[i]
|
||||
}
|
||||
|
||||
if len(result) == 0 {
|
||||
|
@ -121,29 +118,6 @@ func (e *StorageEngine) ListWithCursor(prm *ListWithCursorPrm) (*ListWithCursorR
|
|||
|
||||
return &ListWithCursorRes{
|
||||
addrList: result,
|
||||
cursor: encodeID(cursorShardID, cursor),
|
||||
cursor: cursor,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func decodeID(cursor string) (shardID string, shardCursor string, err error) {
|
||||
ln := len(cursor)
|
||||
if ln < 2 {
|
||||
return "", "", fmt.Errorf("invalid cursor %s", cursor)
|
||||
}
|
||||
|
||||
idLen, err := strconv.Atoi(cursor[:2])
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("invalid cursor %s", cursor)
|
||||
}
|
||||
|
||||
if len(cursor) < 2+idLen {
|
||||
return "", "", fmt.Errorf("invalid cursor %s", cursor)
|
||||
}
|
||||
|
||||
return cursor[2 : 2+idLen], cursor[2+idLen:], nil
|
||||
}
|
||||
|
||||
func encodeID(id, cursor string) string {
|
||||
prefix := fmt.Sprintf("%02d", len(id))
|
||||
return prefix + id + cursor
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue