Skip to content

Commit

Permalink
issue-324: DescribeData: 1. BlobOffsets should be in bytes, not block…
Browse files Browse the repository at this point in the history
…s 2. returning FileSize 3. added a ut that checks that we don't return data outside of the aligned superrange that contains the requested range (#399)
  • Loading branch information
qkrorlqr committed Feb 10, 2024
1 parent 70977a2 commit 16515aa
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,12 @@ void FillDescribeDataResponse(
TTxIndexTablet::TReadData& args,
NProtoPrivate::TDescribeDataResponse& record)
{
// metadata

record.SetFileSize(args.Node->Attrs.GetSize());

// data

using TBlocks = TVector<TBlockDataRef>;
// using TMap to make responses more stable and, thus, easier to test
TMap<TPartialBlobId, TBlocks> blobBlocks;
Expand Down Expand Up @@ -179,7 +185,7 @@ void FillDescribeDataResponse(

if (!rangeInBlob.GetLength()) {
rangeInBlob.SetOffset(curOffset);
rangeInBlob.SetBlobOffset(b.BlobOffset);
rangeInBlob.SetBlobOffset(b.BlobOffset * blockSize);
}

rangeInBlob.SetLength(rangeInBlob.GetLength() + blockSize);
Expand Down
95 changes: 93 additions & 2 deletions cloud/filestore/libs/storage/tablet/tablet_ut_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3286,6 +3286,10 @@ Y_UNIT_TEST_SUITE(TIndexTabletTest_Data)
tablet.WriteData(handle, 3 * block, 128_KB, '6');

auto response = tablet.DescribeData(handle, 0, 256_KB);
UNIT_ASSERT_VALUES_EQUAL(
512_KB + 2 * block,
response->Record.GetFileSize());

const auto& freshRanges = response->Record.GetFreshDataRanges();
UNIT_ASSERT_VALUES_EQUAL(4, freshRanges.size());

Expand Down Expand Up @@ -3345,7 +3349,7 @@ Y_UNIT_TEST_SUITE(TIndexTabletTest_Data)
3 * block + 128_KB,
blobPieces[0].GetRanges(0).GetOffset());
UNIT_ASSERT_VALUES_EQUAL(
1 + 128_KB / block,
block + 128_KB,
blobPieces[0].GetRanges(0).GetBlobOffset());
UNIT_ASSERT_VALUES_EQUAL(
192_KB - 128_KB - 3 * block,
Expand All @@ -3354,7 +3358,7 @@ Y_UNIT_TEST_SUITE(TIndexTabletTest_Data)
3 * block + 192_KB,
blobPieces[0].GetRanges(1).GetOffset());
UNIT_ASSERT_VALUES_EQUAL(
1 + 192_KB / block,
block + 192_KB,
blobPieces[0].GetRanges(1).GetBlobOffset());
// blob ranges and fresh byte ranges may intersect - the client should
// prioritize fresh byte ranges
Expand Down Expand Up @@ -3392,6 +3396,93 @@ Y_UNIT_TEST_SUITE(TIndexTabletTest_Data)
// TODO: properly test BSGroupId
}

TABLET_TEST_16K(ShouldDescribeDataOnlyInTheRequestedRange)
{
const auto block = tabletConfig.BlockSize;

TTestEnv env;
env.CreateSubDomain("nfs");

ui32 nodeIdx = env.CreateNode("nfs");
ui64 tabletId = env.BootIndexTablet(nodeIdx);

TIndexTabletClient tablet(
env.GetRuntime(),
nodeIdx,
tabletId,
tabletConfig);
tablet.InitSession("client", "session");

auto id = CreateNode(tablet, TCreateNodeArgs::File(RootNodeId, "test"));

ui64 handle = CreateHandle(tablet, id);
// blobs
tablet.WriteData(handle, 0, 128_KB, '0'); // outside
tablet.WriteData(handle, 128_KB, 128_KB, '1'); // inside
tablet.WriteData(handle, 256_KB, 128_KB, '2'); // outside
tablet.WriteData(handle, 384_KB, 128_KB, '3'); // outside
// fresh bytes
tablet.WriteData(handle, 0, 1_KB, '4'); // outside
tablet.WriteData(handle, 128_KB, 1_KB, '5'); // inside
tablet.WriteData(handle, 256_KB, 1_KB, '6'); // outside
// fresh blocks
tablet.WriteData(handle, block, block, '7'); // outside
tablet.WriteData(handle, 128_KB + block, block, '8'); // inside
tablet.WriteData(handle, 256_KB + block, block, '9'); // outside

auto response = tablet.DescribeData(handle, 128_KB, 128_KB);
UNIT_ASSERT_VALUES_EQUAL(512_KB, response->Record.GetFileSize());

const auto& freshRanges = response->Record.GetFreshDataRanges();
UNIT_ASSERT_VALUES_EQUAL(2, freshRanges.size());

TString expected;
expected.ReserveAndResize(1_KB);
memset(expected.begin(), '5', 1_KB);

UNIT_ASSERT_VALUES_EQUAL(128_KB, freshRanges[0].GetOffset());
UNIT_ASSERT_VALUES_EQUAL(expected, freshRanges[0].GetContent());

expected.ReserveAndResize(block);
memset(expected.begin(), '8', block);

UNIT_ASSERT_VALUES_EQUAL(128_KB + block, freshRanges[1].GetOffset());
UNIT_ASSERT_VALUES_EQUAL(expected, freshRanges[1].GetContent());

const auto& blobPieces = response->Record.GetBlobPieces();
UNIT_ASSERT_VALUES_EQUAL(1, blobPieces.size());

const auto blobId0 =
NKikimr::LogoBlobIDFromLogoBlobID(blobPieces[0].GetBlobId());
UNIT_ASSERT_VALUES_EQUAL(tabletId, blobId0.TabletID());
UNIT_ASSERT_VALUES_EQUAL(2, blobId0.Generation());
UNIT_ASSERT_VALUES_EQUAL(5, blobId0.Step());
UNIT_ASSERT_VALUES_EQUAL(4, blobId0.Channel());
UNIT_ASSERT_VALUES_EQUAL(0, blobId0.Cookie());
UNIT_ASSERT_VALUES_EQUAL(0, blobId0.PartId());
UNIT_ASSERT_VALUES_EQUAL(0, blobPieces[0].GetBSGroupId());

UNIT_ASSERT_VALUES_EQUAL(2, blobPieces[0].RangesSize());
UNIT_ASSERT_VALUES_EQUAL(
128_KB,
blobPieces[0].GetRanges(0).GetOffset());
UNIT_ASSERT_VALUES_EQUAL(
0,
blobPieces[0].GetRanges(0).GetBlobOffset());
UNIT_ASSERT_VALUES_EQUAL(
block,
blobPieces[0].GetRanges(0).GetLength());
UNIT_ASSERT_VALUES_EQUAL(
128_KB + 2 * block,
blobPieces[0].GetRanges(1).GetOffset());
UNIT_ASSERT_VALUES_EQUAL(
2 * block,
blobPieces[0].GetRanges(1).GetBlobOffset());
UNIT_ASSERT_VALUES_EQUAL(
128_KB - 2 * block,
blobPieces[0].GetRanges(1).GetLength());
}

TABLET_TEST(ShouldHandleErrorDuringDescribeData)
{
TTestEnv env;
Expand Down
7 changes: 7 additions & 0 deletions cloud/filestore/libs/storage/testlib/tablet_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,13 @@ class TIndexTabletClient
return std::make_unique<TEvIndexTabletPrivate::TEvCollectGarbageRequest>();
}

auto CreateTruncateRequest(ui64 node, ui64 length)
{
return std::make_unique<TEvIndexTabletPrivate::TEvTruncateRequest>(
node,
TByteRange(0, length, DefaultBlockSize));
}

auto CreateTruncateRangeRequest(ui64 node, ui64 offset, ui32 length)
{
return std::make_unique<TEvIndexTabletPrivate::TEvTruncateRangeRequest>(
Expand Down
7 changes: 5 additions & 2 deletions cloud/filestore/private/api/protos/tablet.proto
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ message TDescribeDataRequest
// blobs yet.
message TFreshDataRange
{
// This offset is relative to the beginning of the inode.
// This offset is relative to the beginning of the inode. Measured in bytes.
uint64 Offset = 1;
// Data bytes.
bytes Content = 2;
Expand All @@ -303,7 +303,7 @@ message TFreshDataRange
// Represents a range of consecutive bytes inside some blob.
message TRangeInBlob
{
// This offset is relative to the beginning of the inode.
// This offset is relative to the beginning of the inode. Measured in bytes.
uint64 Offset = 1;
// This offset is relative to the beginning of the blob. Measured in bytes.
uint32 BlobOffset = 2;
Expand Down Expand Up @@ -331,6 +331,9 @@ message TDescribeDataResponse
repeated TFreshDataRange FreshDataRanges = 2;
repeated TBlobPiece BlobPieces = 3;

// File size.
uint64 FileSize = 4;

// Optional response headers.
NProto.TResponseHeaders Headers = 1000;
}

0 comments on commit 16515aa

Please sign in to comment.