satellite/metabase: handle copies with GetStreamPieceCountByNodeID

We missed proper handling of object copies for method
GetStreamPieceCountByNodeID which is used by metabase.GetObjectIPs.
That caused some lack of IPs returned when queriyng IPs of copy and
broke things like pices map on linksharing.

Fixes https://github.com/storj/storj/issues/5406

Change-Id: I9574776f34880788c2dc9ff78a6ae20d44fe628f
This commit is contained in:
Michal Niewrzal 2022-12-13 09:57:49 +01:00
parent 1cb2eb4c3b
commit 0759cbdc7f
3 changed files with 93 additions and 0 deletions

View File

@ -32,6 +32,10 @@ func (db *DB) GetStreamPieceCountByNodeID(ctx context.Context, opts GetStreamPie
SELECT remote_alias_pieces
FROM segments
WHERE stream_id = $1 AND remote_alias_pieces IS NOT null
UNION
SELECT remote_alias_pieces
FROM segments
WHERE stream_id = (SELECT ancestor_stream_id FROM segment_copies WHERE stream_id = $1) AND remote_alias_pieces IS NOT null
`, opts.StreamID))(func(rows tagsql.Rows) error {
for rows.Next() {
var aliasPieces AliasPieces

View File

@ -150,5 +150,72 @@ func TestGetStreamPieceCountByNodeID(t *testing.T) {
},
}.Check(ctx, t, db)
})
t.Run("segments copy", func(t *testing.T) {
defer metabasetest.DeleteAll{}.Check(ctx, t, db)
encryptedKey := testrand.Bytes(32)
encryptedKeyNonce := testrand.Bytes(32)
testNodeIDs := make([]storj.NodeID, 3)
for i := range testNodeIDs {
testNodeIDs[i] = testrand.NodeID()
}
// each segment will have one test node ID
originalObj, _ := metabasetest.CreateTestObject{
CreateSegment: func(object metabase.Object, index int) metabase.Segment {
metabasetest.CommitSegment{
Opts: metabase.CommitSegment{
ObjectStream: obj,
Position: metabase.SegmentPosition{Part: 0, Index: uint32(index)},
RootPieceID: testrand.PieceID(),
Pieces: metabase.Pieces{
{Number: 1, StorageNode: testNodeIDs[index]},
},
EncryptedKey: encryptedKey,
EncryptedKeyNonce: encryptedKeyNonce,
EncryptedSize: 1024,
PlainSize: 512,
PlainOffset: 0,
Redundancy: metabasetest.DefaultRedundancy,
},
}.Check(ctx, t, db)
return metabase.Segment{}
},
}.Run(ctx, t, db, obj, byte(len(testNodeIDs)))
copyStream := metabasetest.RandObjectStream()
_, _, _ = metabasetest.CreateObjectCopy{
OriginalObject: originalObj,
CopyObjectStream: &copyStream,
}.Run(ctx, t, db)
metabasetest.GetStreamPieceCountByNodeID{
Opts: metabase.GetStreamPieceCountByNodeID{
StreamID: obj.StreamID,
},
Result: map[storj.NodeID]int64{
testNodeIDs[0]: 1,
testNodeIDs[1]: 1,
testNodeIDs[2]: 1,
},
}.Check(ctx, t, db)
metabasetest.GetStreamPieceCountByNodeID{
Opts: metabase.GetStreamPieceCountByNodeID{
StreamID: copyStream.StreamID,
},
Result: map[storj.NodeID]int64{
testNodeIDs[0]: 1,
testNodeIDs[1]: 1,
testNodeIDs[2]: 1,
},
}.Check(ctx, t, db)
})
})
}

View File

@ -900,10 +900,32 @@ func TestEndpoint_Object_With_StorageNodes(t *testing.T) {
require.NoError(t, uplnk.CreateBucket(uplinkCtx, sat, bucketName))
require.NoError(t, uplnk.Upload(uplinkCtx, sat, bucketName, "jones", testrand.Bytes(20*memory.KB)))
project, err := uplnk.OpenProject(ctx, planet.Satellites[0])
require.NoError(t, err)
defer ctx.Check(project.Close)
// make a copy
_, err = project.CopyObject(ctx, bucketName, "jones", bucketName, "jones_copy", nil)
require.NoError(t, err)
ips, err := object.GetObjectIPs(ctx, uplink.Config{}, access, bucketName, "jones")
require.NoError(t, err)
require.True(t, len(ips) > 0)
copyIPs, err := object.GetObjectIPs(ctx, uplink.Config{}, access, bucketName, "jones_copy")
require.NoError(t, err)
sort.Slice(ips, func(i, j int) bool {
return bytes.Compare(ips[i], ips[j]) < 0
})
sort.Slice(copyIPs, func(i, j int) bool {
return bytes.Compare(copyIPs[i], copyIPs[j]) < 0
})
// verify that orignal and copy has the same results
require.Equal(t, ips, copyIPs)
// verify it's a real IP with valid host and port
for _, ip := range ips {
host, port, err := net.SplitHostPort(string(ip))