Skip to content

Commit

Permalink
issue-2137: GetStorageStats private API action (#2350)
Browse files Browse the repository at this point in the history
  • Loading branch information
qkrorlqr authored Oct 25, 2024
1 parent 4467a85 commit f433131
Show file tree
Hide file tree
Showing 8 changed files with 225 additions and 116 deletions.
4 changes: 4 additions & 0 deletions cloud/filestore/libs/storage/service/service_actor.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,10 @@ class TStorageServiceActor final
TRequestInfoPtr requestInfo,
TString input);

NActors::IActorPtr CreateGetStorageStatsActionActor(
TRequestInfoPtr requestInfo,
TString input);

private:
void RenderSessions(IOutputStream& out);
void RenderLocalFileStores(IOutputStream& out);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ void TStorageServiceActor::HandleExecuteAction(
"unsafegetnode",
&TStorageServiceActor::CreateUnsafeGetNodeActionActor
},
{
"getstoragestats",
&TStorageServiceActor::CreateGetStorageStatsActionActor
},
};

auto it = actions.find(action);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include "service_actor.h"

#include "tablet_action_actor.h"

#include <cloud/filestore/libs/storage/api/tablet.h>
#include <cloud/filestore/libs/storage/core/public.h>

namespace NCloud::NFileStore::NStorage {

using namespace NActors;

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

IActorPtr TStorageServiceActor::CreateGetStorageStatsActionActor(
TRequestInfoPtr requestInfo,
TString input)
{
using TGetStorageStatsActor = TTabletActionActor<
TEvIndexTablet::TEvGetStorageStatsRequest,
TEvIndexTablet::TEvGetStorageStatsResponse>;
return std::make_unique<TGetStorageStatsActor>(
std::move(requestInfo),
std::move(input));
}

} // namespace NCloud::NFileStore::NStorage
Original file line number Diff line number Diff line change
@@ -1,130 +1,16 @@
#include "service_actor.h"

#include <cloud/filestore/libs/storage/api/service.h>
#include "tablet_action_actor.h"

#include <cloud/filestore/libs/storage/api/tablet.h>
#include <cloud/filestore/libs/storage/api/tablet_proxy.h>
#include <cloud/filestore/libs/storage/core/public.h>
#include <cloud/filestore/private/api/protos/tablet.pb.h>

#include <contrib/ydb/library/actors/core/actor_bootstrapped.h>

#include <google/protobuf/util/json_util.h>

namespace NCloud::NFileStore::NStorage {

using namespace NActors;

using namespace NKikimr;

namespace {

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

template <typename TRequest, typename TResponse>
class TTabletActionActor final
: public TActorBootstrapped<TTabletActionActor<TRequest, TResponse>>
{
private:
const TRequestInfoPtr RequestInfo;
const TString Input;

using TBase = TActorBootstrapped<TTabletActionActor<TRequest, TResponse>>;

public:
TTabletActionActor(
TRequestInfoPtr requestInfo,
TString input);

void Bootstrap(const TActorContext& ctx);

private:
void ReplyAndDie(
const TActorContext& ctx,
const TResponse::ProtoRecordType& responseRecord);

private:
STFUNC(StateWork)
{
switch (ev->GetTypeRewrite()) {
HFunc(TResponse, HandleResponse);

default:
HandleUnexpectedEvent(ev, TFileStoreComponents::SERVICE);
break;
}
}

void HandleResponse(const TResponse::TPtr& ev, const TActorContext& ctx);
};

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

template <typename TRequest, typename TResponse>
TTabletActionActor<TRequest, TResponse>::TTabletActionActor(
TRequestInfoPtr requestInfo,
TString input)
: RequestInfo(std::move(requestInfo))
, Input(std::move(input))
{}

template <typename TRequest, typename TResponse>
void TTabletActionActor<TRequest, TResponse>::Bootstrap(
const TActorContext& ctx)
{
typename TRequest::ProtoRecordType request;
if (!google::protobuf::util::JsonStringToMessage(Input, &request).ok()) {
ReplyAndDie(
ctx,
TErrorResponse(E_ARGUMENT, "Failed to parse input"));
return;
}

if (!request.GetFileSystemId()) {
ReplyAndDie(
ctx,
TErrorResponse(E_ARGUMENT, "FileSystem id should be supplied"));
return;
}

auto requestToTablet = std::make_unique<TRequest>();
requestToTablet->Record = std::move(request);

NCloud::Send(
ctx,
MakeIndexTabletProxyServiceId(),
std::move(requestToTablet));

TBase::Become(&TTabletActionActor<TRequest, TResponse>::StateWork);
}

template <typename TRequest, typename TResponse>
void TTabletActionActor<TRequest, TResponse>::ReplyAndDie(
const TActorContext& ctx,
const TResponse::ProtoRecordType& response)
{
auto msg = std::make_unique<TEvService::TEvExecuteActionResponse>(
response.GetError());

google::protobuf::util::MessageToJsonString(
response,
msg->Record.MutableOutput());

NCloud::Reply(ctx, *RequestInfo, std::move(msg));
TBase::Die(ctx);
}

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

template <typename TRequest, typename TResponse>
void TTabletActionActor<TRequest, TResponse>::HandleResponse(
const TResponse::TPtr& ev,
const TActorContext& ctx)
{
ReplyAndDie(ctx, ev->Get()->Record);
}

} // namespace

IActorPtr TStorageServiceActor::CreateUnsafeDeleteNodeActionActor(
TRequestInfoPtr requestInfo,
TString input)
Expand Down
64 changes: 64 additions & 0 deletions cloud/filestore/libs/storage/service/service_actor_actions_ut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,70 @@ Y_UNIT_TEST_SUITE(TStorageServiceActionsTest)

service.DestroySession(headers);
}

Y_UNIT_TEST(ShouldGetStorageStats)
{
NProto::TStorageConfig config;
TTestEnv env{{}, config};
env.CreateSubDomain("nfs");

ui32 nodeIdx = env.CreateNode("nfs");

TServiceClient service(env.GetRuntime(), nodeIdx);

const TString fsId = "test";
service.CreateFileStore(fsId, 1'000);

auto headers = service.InitSession("test", "client");

const auto handle = service.CreateHandle(
headers,
fsId,
RootNodeId,
"file",
TCreateHandleArgs::CREATE
)->Record;
const auto nodeId = handle.GetNodeAttr().GetId();
const auto handleId = handle.GetHandle();

service.WriteData(
headers,
fsId,
nodeId,
handleId,
0,
TString(256_KB, 'a'));

service.WriteData(
headers,
fsId,
nodeId,
handleId,
256_KB,
TString(256_KB, 'a'));

{
NProtoPrivate::TGetStorageStatsRequest request;
request.SetFileSystemId(fsId);
request.SetCompactionRangeCountByCompactionScore(2);
TString buf;
google::protobuf::util::MessageToJsonString(request, &buf);
const auto response = service.ExecuteAction("GetStorageStats", buf);
NProtoPrivate::TGetStorageStatsResponse record;
auto status = google::protobuf::util::JsonStringToMessage(
response->Record.GetOutput(),
&record);
const auto& stats = record.GetStats();
const auto& compactionRanges = stats.GetCompactionRangeStats();
UNIT_ASSERT_VALUES_EQUAL(1, stats.GetUsedNodesCount());
UNIT_ASSERT_VALUES_EQUAL(2, stats.GetUsedCompactionRanges());
UNIT_ASSERT_VALUES_EQUAL(2, compactionRanges.size());
UNIT_ASSERT_VALUES_EQUAL(1, compactionRanges[0].GetBlobCount());
UNIT_ASSERT_VALUES_EQUAL(1, compactionRanges[1].GetBlobCount());
}

service.DestroySession(headers);
}
}

} // namespace NCloud::NFileStore::NStorage
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include "tablet_action_actor.h"
122 changes: 122 additions & 0 deletions cloud/filestore/libs/storage/service/tablet_action_actor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#pragma once

#include <cloud/filestore/libs/storage/api/service.h>
#include <cloud/filestore/libs/storage/api/tablet_proxy.h>
#include <cloud/filestore/libs/storage/core/public.h>

#include <contrib/ydb/library/actors/core/actor_bootstrapped.h>
#include <contrib/ydb/library/actors/core/hfunc.h>

#include <google/protobuf/util/json_util.h>

namespace NCloud::NFileStore::NStorage {

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

template <typename TRequest, typename TResponse>
class TTabletActionActor final
: public NActors::TActorBootstrapped<TTabletActionActor<TRequest, TResponse>>
{
private:
const TRequestInfoPtr RequestInfo;
const TString Input;

using TBase =
NActors::TActorBootstrapped<TTabletActionActor<TRequest, TResponse>>;

public:
TTabletActionActor(
TRequestInfoPtr requestInfo,
TString input);

void Bootstrap(const NActors::TActorContext& ctx);

private:
void ReplyAndDie(
const NActors::TActorContext& ctx,
const TResponse::ProtoRecordType& responseRecord);

private:
STFUNC(StateWork)
{
switch (ev->GetTypeRewrite()) {
HFunc(TResponse, HandleResponse);

default:
HandleUnexpectedEvent(ev, TFileStoreComponents::SERVICE);
break;
}
}

void HandleResponse(
const TResponse::TPtr& ev,
const NActors::TActorContext& ctx);
};

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

template <typename TRequest, typename TResponse>
TTabletActionActor<TRequest, TResponse>::TTabletActionActor(
TRequestInfoPtr requestInfo,
TString input)
: RequestInfo(std::move(requestInfo))
, Input(std::move(input))
{}

template <typename TRequest, typename TResponse>
void TTabletActionActor<TRequest, TResponse>::Bootstrap(
const NActors::TActorContext& ctx)
{
typename TRequest::ProtoRecordType request;
if (!google::protobuf::util::JsonStringToMessage(Input, &request).ok()) {
ReplyAndDie(
ctx,
TErrorResponse(E_ARGUMENT, "Failed to parse input"));
return;
}

if (!request.GetFileSystemId()) {
ReplyAndDie(
ctx,
TErrorResponse(E_ARGUMENT, "FileSystem id should be supplied"));
return;
}

auto requestToTablet = std::make_unique<TRequest>();
requestToTablet->Record = std::move(request);

NCloud::Send(
ctx,
MakeIndexTabletProxyServiceId(),
std::move(requestToTablet));

TBase::Become(&TTabletActionActor<TRequest, TResponse>::StateWork);
}

template <typename TRequest, typename TResponse>
void TTabletActionActor<TRequest, TResponse>::ReplyAndDie(
const NActors::TActorContext& ctx,
const TResponse::ProtoRecordType& response)
{
auto msg = std::make_unique<TEvService::TEvExecuteActionResponse>(
response.GetError());

google::protobuf::util::MessageToJsonString(
response,
msg->Record.MutableOutput());

NCloud::Reply(ctx, *RequestInfo, std::move(msg));
TBase::Die(ctx);
}

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

template <typename TRequest, typename TResponse>
void TTabletActionActor<TRequest, TResponse>::HandleResponse(
const TResponse::TPtr& ev,
const NActors::TActorContext& ctx)
{
ReplyAndDie(ctx, ev->Get()->Record);
}

} // namespace NCloud::NFileStore::NStorage
2 changes: 2 additions & 0 deletions cloud/filestore/libs/storage/service/ya.make
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ SRCS(
service_actor_actions_get_storage_config_fields.cpp
service_actor_actions_get_storage_config.cpp
service_actor_actions_reassign_tablet.cpp
service_actor_actions_stats.cpp
service_actor_actions_unsafe_node_ops.cpp
service_actor_actions_write_compaction_map.cpp
service_actor_actions.cpp
Expand Down Expand Up @@ -40,6 +41,7 @@ SRCS(
service_actor_update_stats.cpp
service_actor_writedata.cpp
service_state.cpp
tablet_action_actor.cpp
)

PEERDIR(
Expand Down

0 comments on commit f433131

Please sign in to comment.