satellite/metainfo/metabase: allow committing empty inline segments

We need to keep empty inline segments as we did it with pointerDB because otherwise old uplinks after uploading data won't be able to download such file. To reduce number of empty inline segments on uplink side we need to implement skipping empty last inline segments for multipart upload.

Change-Id: Ice86c805babba1ad17149754cbd6b3f4fd652722
This commit is contained in:
Michał Niewrzał 2021-02-19 10:28:41 +01:00 committed by Egon Elbre
parent 4c0ea717eb
commit 8b9da01817
4 changed files with 55 additions and 9 deletions

View File

@ -327,10 +327,9 @@ func (db *DB) CommitInlineSegment(ctx context.Context, opts CommitInlineSegment)
}
// TODO: do we have a lower limit for inline data?
// TODO should we move check for max inline segment from metainfo here
switch {
case len(opts.InlineData) == 0:
return ErrInvalidRequest.New("InlineData missing")
case len(opts.EncryptedKey) == 0:
return ErrInvalidRequest.New("EncryptedKey missing")
case len(opts.EncryptedKeyNonce) == 0:

View File

@ -1433,7 +1433,7 @@ func TestCommitInlineSegment(t *testing.T) {
ObjectStream: obj,
},
ErrClass: &metabase.ErrInvalidRequest,
ErrText: "InlineData missing",
ErrText: "EncryptedKey missing",
}.Check(ctx, t, db)
CommitInlineSegment{
@ -1624,6 +1624,58 @@ func TestCommitInlineSegment(t *testing.T) {
}.Check(ctx, t, db)
})
t.Run("commit empty segment of pending object", func(t *testing.T) {
defer DeleteAll{}.Check(ctx, t, db)
encryptedKey := testrand.Bytes(32)
encryptedKeyNonce := testrand.Bytes(32)
now := time.Now()
BeginObjectExactVersion{
Opts: metabase.BeginObjectExactVersion{
ObjectStream: obj,
Encryption: defaultTestEncryption,
},
Version: obj.Version,
}.Check(ctx, t, db)
CommitInlineSegment{
Opts: metabase.CommitInlineSegment{
ObjectStream: obj,
EncryptedKey: encryptedKey,
EncryptedKeyNonce: encryptedKeyNonce,
PlainSize: 0,
PlainOffset: 0,
},
}.Check(ctx, t, db)
Verify{
Objects: []metabase.RawObject{
{
ObjectStream: obj,
CreatedAt: now,
Status: metabase.Pending,
Encryption: defaultTestEncryption,
},
},
Segments: []metabase.RawSegment{
{
StreamID: obj.StreamID,
EncryptedKey: encryptedKey,
EncryptedKeyNonce: encryptedKeyNonce,
PlainOffset: 0,
PlainSize: 0,
EncryptedSize: 0,
},
},
}.Check(ctx, t, db)
})
t.Run("commit segment of pending object", func(t *testing.T) {
defer DeleteAll{}.Check(ctx, t, db)

View File

@ -27,7 +27,7 @@ type Segment RawSegment
// Inline returns true if segment is inline.
func (s Segment) Inline() bool {
return len(s.InlineData) != 0 && s.Redundancy.IsZero()
return s.Redundancy.IsZero() && s.RootPieceID.IsZero()
}
// GetObjectExactVersion contains arguments necessary for fetching an information

View File

@ -1589,11 +1589,6 @@ func (endpoint *Endpoint) makeInlineSegment(ctx context.Context, req *pb.Segment
}
inlineUsed := int64(len(req.EncryptedInlineData))
// TODO silently ignore empty inline segmens to be backward compatible with old uplinks.
// Metabase is rejecting empty inline segments.
if inlineUsed == 0 {
return nil, &pb.SegmentMakeInlineResponse{}, nil
}
if inlineUsed > endpoint.encInlineSegmentSize {
return nil, nil, rpcstatus.Error(rpcstatus.InvalidArgument, fmt.Sprintf("inline segment size cannot be larger than %s", endpoint.config.MaxInlineSegmentSize))
}