fix(shardnode): record Slice.ValidSize when alloc or seal

with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
This commit is contained in:
xiejian 2025-01-23 11:00:09 +08:00 committed by slasher
parent 70f6955e1e
commit 76b2a6e6e3
5 changed files with 76 additions and 27 deletions

View File

@ -174,6 +174,7 @@ var errCodeMap = map[int]string{
CodeNoEnoughRaftMember: "shardnode:no enough raft member",
CodeIllegalUpdateUnit: "shardnode:illegal update suid",
CodeItemIDEmpty: "shardnode:item ID is empty",
CodeIllegalLocationSize: "shardnode:illegal location size",
}
// HTTPError make rpc.HTTPError

View File

@ -34,6 +34,7 @@ const (
CodeNoEnoughRaftMember = 1017
CodeIllegalUpdateUnit = 1018
CodeItemIDEmpty = 1019
CodeIllegalLocationSize = 1020
)
// 10xx
@ -57,4 +58,5 @@ var (
ErrNoEnoughRaftMember = Error(CodeNoEnoughRaftMember)
ErrIllegalUpdateUnit = Error(CodeIllegalUpdateUnit)
ErrItemIDEmpty = Error(CodeItemIDEmpty)
ErrIllegalLocationSize = Error(CodeIllegalLocationSize)
)

View File

@ -60,7 +60,6 @@ func (alc *allocator) AllocSlices(ctx context.Context, codeMode codemode.CodeMod
blobN := blobCount(fileSize, sliceSize)
blobs := make([]proto.Slice, 0, blobN)
var size uint64
for _, bidRet := range allocRets {
if blobN <= 0 {
break
@ -68,18 +67,12 @@ func (alc *allocator) AllocSlices(ctx context.Context, codeMode codemode.CodeMod
count := minU64(blobN, uint64(bidRet.BidEnd)-uint64(bidRet.BidStart)+1)
blobN -= count
validSize := uint64(sliceSize) * count
if blobN <= 0 {
validSize = fileSize - size
}
blobs = append(blobs, proto.Slice{
MinSliceID: bidRet.BidStart,
Vid: bidRet.Vid,
Count: uint32(count),
ValidSize: validSize,
})
size += validSize
}
if blobN > 0 {
return nil, errors.New("no enough blob ids from allocator")

View File

@ -337,7 +337,35 @@ func (s *Space) SealBlob(ctx context.Context, req *shardnode.SealBlobArgs) error
b.Sealed = true
b.Location.Size_ = req.GetSize_()
b.Location.Slices = req.GetSlices()
sliceSize := b.Location.SliceSize
remainSize := req.GetSize_()
for i := range req.Slices {
if i == len(req.Slices)-1 {
if remainSize > uint64(req.Slices[i].Count*sliceSize) {
return apierr.ErrIllegalLocationSize
}
req.Slices[i].ValidSize = remainSize
break
}
// local validSize recorded
if b.Location.Slices[i].ValidSize != 0 {
validSize := b.Location.Slices[i].ValidSize
if validSize >= remainSize {
return apierr.ErrIllegalLocationSize
}
req.Slices[i].ValidSize = validSize
remainSize -= validSize
continue
}
validSize := uint64(req.Slices[i].Count * sliceSize)
if validSize >= remainSize {
return apierr.ErrIllegalLocationSize
}
req.Slices[i].ValidSize = validSize
remainSize -= validSize
}
if err = security.LocationCrcFill(&b.Location); err != nil {
return err
}
@ -425,6 +453,7 @@ func (s *Space) AllocSlice(ctx context.Context, req *shardnode.AllocSliceArgs) (
var (
idxes []uint32
idx uint32
validIdx uint32
ok bool
failedVid []proto.Vid
)
@ -456,10 +485,17 @@ func (s *Space) AllocSlice(ctx context.Context, req *shardnode.AllocSliceArgs) (
localSlices[idx] = failedSlice
localSlices = append(localSlices[:idx+1], append(slices, localSlices[idx+1:]...)...)
}
validIdx = idx
} else {
validIdx = uint32(len(localSlices))
localSlices = append(localSlices, slices...)
}
var i uint32
for i = 0; i < validIdx; i++ {
localSlices[i].ValidSize = uint64(sliceSize * localSlices[i].Count)
}
b.Location.Slices = localSlices
if err = security.LocationCrcFill(&b.Location); err != nil {
return
@ -574,7 +610,7 @@ func checkSlices(loc, req []proto.Slice, sliceSize uint32) ([]uint32, bool) {
if _, ok := locMap[id]; !ok {
return idxes, false
}
if req[i].Vid != locMap[id].Vid || req[i].Count > locMap[id].Count || req[i].ValidSize > locMap[id].ValidSize {
if req[i].Vid != locMap[id].Vid || req[i].Count > locMap[id].Count {
return idxes, false
}
idxes = append(idxes, locIndexMap[id])

View File

@ -206,9 +206,9 @@ func TestSpace_AllocSlice(t *testing.T) {
space.allocator = alc
locSlices := []proto.Slice{
{Vid: 1, MinSliceID: 1, Count: 10, ValidSize: 100},
{Vid: 1, MinSliceID: 2, Count: 20, ValidSize: 200},
{Vid: 1, MinSliceID: 3, Count: 30, ValidSize: 300},
{Vid: 1, MinSliceID: 1, Count: 10, ValidSize: 0},
{Vid: 1, MinSliceID: 2, Count: 20, ValidSize: 0},
{Vid: 1, MinSliceID: 3, Count: 30, ValidSize: 0},
}
name := []byte("blob")
mode := codemode.EC6P6
@ -240,7 +240,7 @@ func TestSpace_AllocSlice(t *testing.T) {
require.Equal(t, newSlices, ret.Slices)
// illegal failedSlice
args.FailedSlice = proto.Slice{Vid: 1, MinSliceID: 2, Count: 10, ValidSize: 300}
args.FailedSlice = proto.Slice{Vid: 1, MinSliceID: 2, Count: 30, ValidSize: 300}
_, err = space.AllocSlice(ctx, args)
require.Equal(t, apierr.ErrIllegalSlices, err)
@ -282,8 +282,8 @@ func TestSpace_SealBlob(t *testing.T) {
locSlices := []proto.Slice{
{Vid: 1, MinSliceID: 1, Count: 10, ValidSize: 100},
{Vid: 1, MinSliceID: 2, Count: 20, ValidSize: 200},
{Vid: 1, MinSliceID: 3, Count: 30, ValidSize: 300},
{Vid: 1, MinSliceID: 2, Count: 20, ValidSize: 100},
{Vid: 1, MinSliceID: 3, Count: 30, ValidSize: 0},
}
name := []byte("blob")
mode := codemode.EC6P6
@ -297,19 +297,36 @@ func TestSpace_SealBlob(t *testing.T) {
}
raw, err := b.Marshal()
require.Nil(t, err)
mockSpace.mockHandler.EXPECT().Get(A, A, A).Return(newMockValGetter(raw), nil).Times(2)
mockSpace.mockHandler.EXPECT().Update(A, A, A).Return(nil).Times(1)
mockSpace.mockHandler.EXPECT().Get(A, A, A).Return(newMockValGetter(raw), nil).Times(6)
mockSpace.mockHandler.EXPECT().Update(A, A, A).Return(nil).Times(3)
args := &shardnode.SealBlobArgs{
Header: shardnode.ShardOpHeader{},
Name: name,
Size_: 600,
Size_: 300,
Slices: locSlices,
}
err = space.SealBlob(ctx, args)
require.Nil(t, err)
args.Slices[1].ValidSize = 300
args.Size_ = 500
err = space.SealBlob(ctx, args)
require.Nil(t, err)
args.Size_ = 200
err = space.SealBlob(ctx, args)
require.Equal(t, apierr.ErrIllegalLocationSize, err)
args.Size_ = 700
err = space.SealBlob(ctx, args)
require.Equal(t, apierr.ErrIllegalLocationSize, err)
args.Size_ = 200
args.Slices = args.Slices[:2]
err = space.SealBlob(ctx, args)
require.Equal(t, nil, err)
args.Slices[1].Count = 30
err = space.SealBlob(ctx, args)
require.Equal(t, apierr.ErrIllegalSlices, err)
}
@ -445,8 +462,8 @@ func TestCheckSlices(t *testing.T) {
name: "valid slices",
args: args{
loc: []proto.Slice{
{Vid: 1, MinSliceID: 1, Count: 10, ValidSize: 100},
{Vid: 1, MinSliceID: 2, Count: 20, ValidSize: 200},
{Vid: 1, MinSliceID: 1, Count: 10, ValidSize: 0},
{Vid: 1, MinSliceID: 2, Count: 20, ValidSize: 0},
},
req: []proto.Slice{
{Vid: 1, MinSliceID: 1, Count: 5, ValidSize: 50},
@ -460,8 +477,8 @@ func TestCheckSlices(t *testing.T) {
name: "invalid slices - missing MinSliceID",
args: args{
loc: []proto.Slice{
{Vid: 1, MinSliceID: 1, Count: 10, ValidSize: 100},
{Vid: 1, MinSliceID: 2, Count: 20, ValidSize: 200},
{Vid: 1, MinSliceID: 1, Count: 10, ValidSize: 0},
{Vid: 1, MinSliceID: 2, Count: 20, ValidSize: 0},
},
req: []proto.Slice{
{Vid: 1, MinSliceID: 3, Count: 5, ValidSize: 50},
@ -474,8 +491,8 @@ func TestCheckSlices(t *testing.T) {
name: "invalid slices - count exceeds",
args: args{
loc: []proto.Slice{
{Vid: 1, MinSliceID: 1, Count: 10, ValidSize: 100},
{Vid: 1, MinSliceID: 2, Count: 20, ValidSize: 200},
{Vid: 1, MinSliceID: 1, Count: 10, ValidSize: 0},
{Vid: 1, MinSliceID: 2, Count: 20, ValidSize: 0},
},
req: []proto.Slice{
{Vid: 1, MinSliceID: 1, Count: 15, ValidSize: 150},
@ -488,8 +505,8 @@ func TestCheckSlices(t *testing.T) {
name: "invalid slices - valid size exceeds",
args: args{
loc: []proto.Slice{
{Vid: 1, MinSliceID: 1, Count: 10, ValidSize: 100},
{Vid: 1, MinSliceID: 2, Count: 20, ValidSize: 200},
{Vid: 1, MinSliceID: 1, Count: 10, ValidSize: 0},
{Vid: 1, MinSliceID: 2, Count: 20, ValidSize: 0},
},
req: []proto.Slice{
{Vid: 1, MinSliceID: 1, Count: 20, ValidSize: 200},