Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cloud/filestore/apps/client/lib/diagnose_filesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,5 +179,5 @@ TCommandPtr NewDiagnoseFilesystemCommand()
{
return std::make_shared<TDiagnoseFilesystemCommand>();
}

} // namespace NCloud::NFileStore::NClient
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"test.test_max_file_count": {
"uri": "file://test.test_max_file_count/results.txt"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/ max-file-count-loadtest:<random_guid>
/ max-file-count-loadtest:<random_guid>
/ max-file-count-loadtest:<random_guid>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
Tests {
LoadTest {
Name: "max-file-count"
ClientId: "max-file-count-loadtest"
CreateFileStoreRequest {
FileSystemId: "max-file-count"
FolderId: "folder"
CloudId: "cloud"
BlocksCount: 10241024
BlockSize: 4096
}
KeepFileStore: true
MaxNodes: 3
RequestsCount: 30
IODepth: 16
DataLoadSpec {
Actions {
Action: ACTION_READ
Rate: 1
}
ReadBytes: 4096
WriteBytes: 4096
MinFileCount: 3
}
}
}
43 changes: 43 additions & 0 deletions cloud/filestore/tests/loadtest/max-file-count-test/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import os
import re
import yatest.common as common

from cloud.filestore.tests.python.lib.client import FilestoreCliClient
from cloud.filestore.tests.python.lib.loadtest import run_load_test


def test_max_file_count():
filesystem_id = "max-file-count"
results_path = common.output_path("results.txt")
config_path = common.source_path(
"cloud/filestore/tests/loadtest/max-file-count-test/max-file-count.txt"
)
client = FilestoreCliClient(
common.binary_path("cloud/filestore/apps/client/filestore-client"),
os.getenv("NFS_SERVER_PORT"),
cwd=common.output_path())

try:
run_load_test(
filesystem_id,
config_path,
os.getenv("NFS_SERVER_PORT"),
)

files = client.find(filesystem_id, depth=1).decode().splitlines()
normalized_entries = [
re.sub(
r"(?<=max-file-count-loadtest:)[0-9a-f-]+$",
"<random_guid>",
file.rsplit("\t", 1)[0],
)
for file in files
]

with open(results_path, "w") as results:
results.write("\n".join(normalized_entries) + "\n")

finally:
client.destroy(filesystem_id)

return common.canonical_file(results_path, local=True)
25 changes: 25 additions & 0 deletions cloud/filestore/tests/loadtest/max-file-count-test/ya.make
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
PY3TEST()

INCLUDE(${ARCADIA_ROOT}/cloud/filestore/tests/recipes/medium.inc)

TEST_SRCS(
test.py
)

DEPENDS(
cloud/filestore/apps/client
cloud/filestore/tools/testing/loadtest/bin
)

PEERDIR(
cloud/filestore/tests/python/lib
)

SET(
NFS_STORAGE_CONFIG_PATCH
cloud/filestore/tests/common_configs/nfs-storage-migration-patch.txt
)

INCLUDE(${ARCADIA_ROOT}/cloud/filestore/tests/recipes/service-kikimr.inc)

END()
63 changes: 63 additions & 0 deletions cloud/filestore/tools/testing/loadtest/lib/count_limiter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#pragma once

#include <cloud/filestore/tools/testing/loadtest/protos/loadtest.pb.h>

#include <atomic>
#include <memory>

namespace NCloud::NFileStore::NLoadTest {

////////////////////////////////////////////////////////////////////////////////

class TCountLimiter
{
private:
const ui64 MaxCount;
std::atomic<ui64> ReservedCount = 0;

bool TryReserve()
{
if (!MaxCount) {
// MaxCount == 0 means unlimited.
return true;
}

ui64 count = ReservedCount.load(std::memory_order_relaxed);
while (count < MaxCount){
if (ReservedCount.compare_exchange_weak(
count,
count + 1,
std::memory_order_relaxed))
{
return true;
}
}
return count < MaxCount;
}

public:
explicit TCountLimiter(ui64 maxCount)
: MaxCount(maxCount)
{}

bool TryReserveHandle()
{
return TryReserve();
}

bool TryReserveNode()
{
return TryReserve();
}

void Release()
{
if (MaxCount) {
ReservedCount.fetch_sub(1, std::memory_order_relaxed);
}
}
};

using TCountLimiterPtr = std::shared_ptr<TCountLimiter>;

} // namespace NCloud::NFileStore::NLoadTest
13 changes: 9 additions & 4 deletions cloud/filestore/tools/testing/loadtest/lib/request.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "shm_client.h"

#include <cloud/filestore/tools/testing/loadtest/protos/loadtest.pb.h>
#include <cloud/filestore/tools/testing/loadtest/lib/count_limiter.h>

#include <cloud/filestore/libs/client/public.h>
#include <cloud/filestore/libs/service/public.h>
Expand Down Expand Up @@ -72,14 +73,16 @@ IRequestGeneratorPtr CreateIndexRequestGenerator(
IFileStoreServicePtr client,
NClient::ISessionPtr session,
TString filesystemId,
NProto::THeaders headers);
NProto::THeaders headers,
TCountLimiterPtr countLimiter);

IRequestGeneratorPtr CreateDataRequestGenerator(
NProto::TDataLoadSpec spec,
ILoggingServicePtr logging,
NClient::ISessionPtr session,
TString filesystemId,
NProto::THeaders headers);
NProto::THeaders headers,
TCountLimiterPtr countLimiter);

IRequestGeneratorPtr CreateReplayRequestGeneratorFs(
NProto::TReplaySpec spec,
Expand All @@ -98,14 +101,16 @@ IRequestGeneratorPtr CreateReplayRequestGeneratorGRPC(
IRequestGeneratorPtr CreateFastShardRequestGenerator(
NProto::TFastShardLoadSpec spec,
ui32 maxParallelism,
ILoggingServicePtr logging);
ILoggingServicePtr logging,
TCountLimiterPtr countLimiter);

IRequestGeneratorPtr CreateDatashardLikeRequestGenerator(
NProto::TDatashardLikeLoadSpec spec,
ILoggingServicePtr logging,
NClient::ISessionPtr session,
IShmDataClientPtr dataClient,
TString filesystemId,
NProto::THeaders headers);
NProto::THeaders headers,
TCountLimiterPtr countLimiter);

} // namespace NCloud::NFileStore::NLoadTest
18 changes: 15 additions & 3 deletions cloud/filestore/tools/testing/loadtest/lib/request_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ class TDataRequestGenerator final
const NProto::TDataLoadSpec Spec;
const TString FileSystemId;
const NProto::THeaders Headers;
const TCountLimiterPtr CountLimiter;

TLog Log;

Expand Down Expand Up @@ -134,10 +135,12 @@ class TDataRequestGenerator final
ILoggingServicePtr logging,
ISessionPtr session,
TString filesystemId,
NProto::THeaders headers)
NProto::THeaders headers,
TCountLimiterPtr countLimiter)
: Spec(std::move(spec))
, FileSystemId(std::move(filesystemId))
, Headers(std::move(headers))
, CountLimiter(std::move(countLimiter))
, Session(std::move(session))
{
Log = logging->CreateLog(Headers.GetClientId());
Expand Down Expand Up @@ -238,6 +241,12 @@ class TDataRequestGenerator final

auto started = TInstant::Now();
TGuard<TMutex> guard(StateLock);
if (!CountLimiter->TryReserveHandle()) {
return MakeFuture<TCompletedRequest>({
NProto::ACTION_CREATE_HANDLE,
started,
MakeError(S_FALSE)});
}
auto name = GenerateNodeName();

auto request = CreateRequest<NProto::TCreateHandleRequest>();
Expand Down Expand Up @@ -301,6 +310,7 @@ class TDataRequestGenerator final
return HandleResizeAfterCreateHandle(f, name, started);
});
} catch (const TServiceError& e) {
CountLimiter->Release();
auto error = MakeError(e.GetCode(), TString{e.GetMessage()});
STORAGE_ERROR("create handle for %s has failed: %s",
name.Quote().c_str(),
Expand Down Expand Up @@ -646,14 +656,16 @@ IRequestGeneratorPtr CreateDataRequestGenerator(
ILoggingServicePtr logging,
ISessionPtr session,
TString filesystemId,
NProto::THeaders headers)
NProto::THeaders headers,
TCountLimiterPtr countLimiter)
{
return std::make_shared<TDataRequestGenerator>(
std::move(spec),
std::move(logging),
std::move(session),
std::move(filesystemId),
std::move(headers));
std::move(headers),
std::move(countLimiter));
}

} // namespace NCloud::NFileStore::NLoadTest
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class TDatashardLikeRequestGenerator final
const NProto::TDatashardLikeLoadSpec Spec;
const TString FileSystemId;
const NProto::THeaders Headers;
const TCountLimiterPtr CountLimiter;

TLog Log;

Expand Down Expand Up @@ -77,10 +78,12 @@ class TDatashardLikeRequestGenerator final
ISessionPtr session,
IShmDataClientPtr dataClient,
TString filesystemId,
NProto::THeaders headers)
NProto::THeaders headers,
TCountLimiterPtr countLimiter)
: Spec(std::move(spec))
, FileSystemId(std::move(filesystemId))
, Headers(std::move(headers))
, CountLimiter(std::move(countLimiter))
, Session(std::move(session))
, DataClient(std::move(dataClient))
{
Expand Down Expand Up @@ -174,6 +177,12 @@ class TDatashardLikeRequestGenerator final
TFuture<TCompletedRequest> DoCreateNode()
{
auto started = TInstant::Now();
if (!CountLimiter->TryReserveNode()) {
return MakeFuture<TCompletedRequest>({
NProto::ACTION_CREATE_NODE,
started,
MakeError(S_FALSE)});
}

auto request = CreateRequest<NProto::TCreateNodeRequest>();
request->SetNodeId(RootNodeId);
Expand Down Expand Up @@ -231,6 +240,7 @@ class TDatashardLikeRequestGenerator final
[=, this](const TFuture<NProto::TSetNodeAttrResponse>& f)
{ return HandleResizeAfterCreate(f, info, started); });
} catch (const TServiceError& e) {
CountLimiter->Release();
auto error = MakeError(e.GetCode(), TString{e.GetMessage()});
STORAGE_ERROR(
"create node has failed: %s",
Expand Down Expand Up @@ -496,15 +506,17 @@ IRequestGeneratorPtr CreateDatashardLikeRequestGenerator(
NClient::ISessionPtr session,
IShmDataClientPtr dataClient,
TString filesystemId,
NProto::THeaders headers)
NProto::THeaders headers,
TCountLimiterPtr countLimiter)
{
return std::make_shared<TDatashardLikeRequestGenerator>(
std::move(spec),
std::move(logging),
std::move(session),
std::move(dataClient),
std::move(filesystemId),
std::move(headers));
std::move(headers),
std::move(countLimiter));
}

} // namespace NCloud::NFileStore::NLoadTest
Loading
Loading