Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Filestore] NBSNEBIUS-91: Add ForcedCleanup handle for fs #268

Merged
merged 6 commits into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
171 changes: 122 additions & 49 deletions cloud/filestore/libs/storage/tablet/tablet_actor_compactionforced.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,22 @@ namespace {

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

class TForcedCompactionActor final
: public TActorBootstrapped<TForcedCompactionActor>
/**
* @brief An actor that performs forced compaction or forced cleanup. It is
* implemented as a template class to avoid code duplication.
*
* @tparam TRequestConstructor A functor that constructs a unique_ptr to a
* request that is necessary to be performed to passed range.
*/
template <typename TResponseType, typename TRequestConstructor>
class TForcedCompactionActorBase final
: public TActorBootstrapped<
TForcedCompactionActorBase<TResponseType, TRequestConstructor>>
{
private:
using TBase = NActors::TActorBootstrapped<
TForcedCompactionActorBase<TResponseType, TRequestConstructor>>;

const TActorId Tablet;
const TString LogTag;
const TDuration RetryTimeout;
Expand All @@ -34,7 +46,7 @@ class TForcedCompactionActor final
const TRequestInfoPtr RequestInfo;

public:
TForcedCompactionActor(
TForcedCompactionActorBase(
TActorId tablet,
TString logTag,
TDuration retry,
Expand All @@ -49,7 +61,7 @@ class TForcedCompactionActor final
void SendCompactionRequest(const TActorContext& ctx);

void HandleCompactionResponse(
const TEvIndexTabletPrivate::TEvCompactionResponse::TPtr& ev,
const TResponseType::TPtr& ev,
const TActorContext& ctx);

void HandleWakeUp(
Expand All @@ -67,7 +79,9 @@ class TForcedCompactionActor final

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

TForcedCompactionActor::TForcedCompactionActor(
template <typename TResponseType, typename TRequestConstructor>
TForcedCompactionActorBase<TResponseType, TRequestConstructor>::
TForcedCompactionActorBase(
TActorId tablet,
TString logTag,
TDuration retry,
Expand All @@ -79,12 +93,14 @@ TForcedCompactionActor::TForcedCompactionActor(
, State(std::move(state))
, RequestInfo(std::move(requestInfo))
{
ActivityType = TFileStoreActivities::TABLET_WORKER;
TBase::ActivityType = TFileStoreActivities::TABLET_WORKER;
}

void TForcedCompactionActor::Bootstrap(const TActorContext& ctx)
template <typename TResponseType, typename TRequestConstructor>
void TForcedCompactionActorBase<TResponseType, TRequestConstructor>::Bootstrap(
const TActorContext& ctx)
{
Become(&TThis::StateWork);
TBase::Become(&TBase::TThis::StateWork);

FILESTORE_TRACK(
RequestReceived_TabletWorker,
Expand All @@ -94,31 +110,36 @@ void TForcedCompactionActor::Bootstrap(const TActorContext& ctx)
SendCompactionRequest(ctx);
}

void TForcedCompactionActor::SendCompactionRequest(const TActorContext& ctx)
template <typename TResponseType, typename TRequestConstructor>
void TForcedCompactionActorBase<TResponseType, TRequestConstructor>::
SendCompactionRequest(const TActorContext& ctx)
{
auto request = std::make_unique<TEvIndexTabletPrivate::TEvCompactionRequest>(
State->GetCurrentRange(), true);
auto request = TRequestConstructor()(State->GetCurrentRange());

ctx.Send(Tablet, request.release());
}

STFUNC(TForcedCompactionActor::StateWork)
template <typename TResponseType, typename TRequestConstructor>
STFUNC(
(TForcedCompactionActorBase<TResponseType, TRequestConstructor>::StateWork))
{
switch (ev->GetTypeRewrite()) {
HFunc(TEvents::TEvWakeup, HandleWakeUp);
HFunc(TEvents::TEvPoisonPill, HandlePoisonPill);

HFunc(TEvIndexTabletPrivate::TEvCompactionResponse, HandleCompactionResponse);
HFunc(TResponseType, HandleCompactionResponse);

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

void TForcedCompactionActor::HandleCompactionResponse(
const TEvIndexTabletPrivate::TEvCompactionResponse::TPtr& ev,
const TActorContext& ctx)
template <typename TResponseType, typename TRequestConstructor>
void TForcedCompactionActorBase<TResponseType, TRequestConstructor>::
HandleCompactionResponse(
debnatkh marked this conversation as resolved.
Show resolved Hide resolved
const TResponseType::TPtr& ev,
const TActorContext& ctx)
{
auto* msg = ev->Get();

Expand All @@ -138,30 +159,32 @@ void TForcedCompactionActor::HandleCompactionResponse(
SendCompactionRequest(ctx);
}

void TForcedCompactionActor::HandleWakeUp(
const TEvents::TEvWakeup::TPtr& ev,
const TActorContext& ctx)
template <typename TResponseType, typename TRequestConstructor>
void TForcedCompactionActorBase<TResponseType, TRequestConstructor>::
HandleWakeUp(const TEvents::TEvWakeup::TPtr& ev, const TActorContext& ctx)
{
Y_UNUSED(ev);
SendCompactionRequest(ctx);
}

void TForcedCompactionActor::HandlePoisonPill(
const TEvents::TEvPoison::TPtr& ev,
const TActorContext& ctx)
template <typename TResponseType, typename TRequestConstructor>
void TForcedCompactionActorBase<TResponseType, TRequestConstructor>::
HandlePoisonPill(
const TEvents::TEvPoison::TPtr& ev,
const TActorContext& ctx)
{
Y_UNUSED(ev);
ReplyAndDie(ctx, MakeError(E_FAIL, "actor killed"));
}

void TForcedCompactionActor::ReplyAndDie(
const TActorContext& ctx,
const NProto::TError& error)
template <typename TResponseType, typename TRequestConstructor>
void TForcedCompactionActorBase<TResponseType, TRequestConstructor>::
ReplyAndDie(const TActorContext& ctx, const NProto::TError& error)
{
{
// notify tablet
auto response = std::make_unique<TEvIndexTabletPrivate::TEvForcedCompactionCompleted>(
error);
auto response = std::make_unique<
TEvIndexTabletPrivate::TEvForcedCompactionCompleted>(error);
debnatkh marked this conversation as resolved.
Show resolved Hide resolved
NCloud::Send(ctx, Tablet, std::move(response));
}

Expand All @@ -172,14 +195,45 @@ void TForcedCompactionActor::ReplyAndDie(

if (RequestInfo->Sender != Tablet) {
// reply to caller
auto response = std::make_unique<TEvIndexTabletPrivate::TEvForcedCompactionResponse>(
error);
auto response = std::make_unique<
TEvIndexTabletPrivate::TEvForcedCompactionResponse>(error);
debnatkh marked this conversation as resolved.
Show resolved Hide resolved
NCloud::Reply(ctx, *RequestInfo, std::move(response));
}

Die(ctx);
TBase::Die(ctx);
}

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

struct TCompactionRequestConstructor
{
std::unique_ptr<TEvIndexTabletPrivate::TEvCompactionRequest> operator()(
const ui32 range) const
debnatkh marked this conversation as resolved.
Show resolved Hide resolved
{
return std::make_unique<TEvIndexTabletPrivate::TEvCompactionRequest>(
range,
true);
}
};

struct TCleanupRequestConstructor
{
std::unique_ptr<TEvIndexTabletPrivate::TEvCleanupRequest> operator()(
const ui32 range) const
{
return std::make_unique<TEvIndexTabletPrivate::TEvCleanupRequest>(
range);
}
};

using TForcedCompactionActor = TForcedCompactionActorBase<
TEvIndexTabletPrivate::TEvCompactionResponse,
TCompactionRequestConstructor>;

using TForcedCleanupActor = TForcedCompactionActorBase<
TEvIndexTabletPrivate::TEvCleanupResponse,
TCleanupRequestConstructor>;

} // namespace

////////////////////////////////////////////////////////////////////////////////
Expand All @@ -190,13 +244,15 @@ void TIndexTabletActor::EnqueueForcedCompactionIfNeeded(const TActorContext& ctx
return;
}

auto ranges = DequeueForcedCompaction();
if (ranges.empty()) {
auto pendingRequest = DequeueForcedCompaction();
if (pendingRequest.Ranges.empty()) {
return;
}

auto request =
std::make_unique<TEvIndexTabletPrivate::TEvForcedCompactionRequest>(std::move(ranges));
std::make_unique<TEvIndexTabletPrivate::TEvForcedCompactionRequest>(
std::move(pendingRequest.Ranges),
pendingRequest.Mode);
ctx.Send(ctx.SelfID, request.release());
}

Expand All @@ -206,20 +262,21 @@ void TIndexTabletActor::HandleForcedCompaction(
{
auto* msg = ev->Get();

LOG_DEBUG(ctx, TFileStoreComponents::TABLET,
LOG_DEBUG(
ctx,
TFileStoreComponents::TABLET,
"%s ForcedCompaction request for %lu ranges",
LogTag.c_str(),
msg->Ranges.size());

auto replyError = [&] (
const NProto::TError& error)
auto replyError = [&](const NProto::TError& error)
{
if (ev->Sender == ctx.SelfID) {
return;
}

auto response =
std::make_unique<TEvIndexTabletPrivate::TEvForcedCompactionResponse>(error);
auto response = std::make_unique<
TEvIndexTabletPrivate::TEvForcedCompactionResponse>(error);
NCloud::Reply(ctx, *ev, std::move(response));
};

Expand All @@ -228,25 +285,41 @@ void TIndexTabletActor::HandleForcedCompaction(
return;
}

auto requestInfo = CreateRequestInfo(
ev->Sender,
ev->Cookie,
msg->CallContext);
auto requestInfo =
CreateRequestInfo(ev->Sender, ev->Cookie, msg->CallContext);

// will loose original request info in case of enqueueing external request
if (IsForcedCompactionRunning()) {
EnqueueForcedCompaction(std::move(msg->Ranges));
EnqueueForcedCompaction(std::move(msg->Ranges), msg->Mode);
debnatkh marked this conversation as resolved.
Show resolved Hide resolved
return;
}

StartForcedCompaction(std::move(msg->Ranges));

auto actor = std::make_unique<TForcedCompactionActor>(
ctx.SelfID,
LogTag,
Config->GetCompactionRetryTimeout(),
GetForcedCompactionState(),
std::move(requestInfo));
std::unique_ptr<IActor> actor;

switch (msg->Mode) {
case TEvIndexTabletPrivate::EForcedCompactionMode::Compaction:
actor = std::make_unique<TForcedCompactionActor>(
ctx.SelfID,
LogTag,
Config->GetCompactionRetryTimeout(),
GetForcedCompactionState(),
std::move(requestInfo));
break;

case TEvIndexTabletPrivate::EForcedCompactionMode::Cleanup:
actor = std::make_unique<TForcedCleanupActor>(
ctx.SelfID,
LogTag,
Config->GetCompactionRetryTimeout(),
GetForcedCompactionState(),
std::move(requestInfo));
break;

default:
TABLET_VERIFY_C(false, "unexpected forced compaction mode");
}

auto actorId = ctx.Register(actor.release());
WorkerActors.insert(actorId);
Expand Down
33 changes: 32 additions & 1 deletion cloud/filestore/libs/storage/tablet/tablet_actor_monitoring.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,24 @@ void BuildForceCompactionButton(IOutputStream& out, ui64 tabletId)
"Force compaction",
"Are you sure you want to force compaction for ALL ranges?",
"forceCompactionAll();");

out << "<p><a href='' data-toggle='modal' "
"data-target='#force-cleanup'>Force Full Cleanup</a></p>"
<< "<form method='POST' name='ForceCleanup' style='display:none'>"
<< "<input type='hidden' name='TabletID' value='" << tabletId << "'/>"
<< "<input type='hidden' name='action' value='compactAll'/>"
debnatkh marked this conversation as resolved.
Show resolved Hide resolved
<< "<input type='hidden' name='Cleanup' value='true'/>"
<< "<input class='btn btn-primary' type='button' value='Cleanup ALL "
"ranges'"
<< " data-toggle='modal' data-target='#force-cleanup'/>"
<< "</form>";

BuildConfirmActionDialog(
out,
"force-cleanup",
"Force cleanup",
"Are you sure you want to force cleanup for ALL ranges?",
"forceCleanupAll();");
}

////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -672,6 +690,14 @@ void GenerateActionsJS(IOutputStream& out)
}
</script>
)___";

out << R"___(
<script type='text/javascript'>
function forceCleanupAll() {
document.forms['ForceCleanup'].submit();
}
</script>
)___";
}

////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -1008,7 +1034,12 @@ void TIndexTabletActor::HandleHttpInfo_Compaction(
ranges = GetNonEmptyCompactionRanges();
}

EnqueueForcedCompaction(std::move(ranges));
TEvIndexTabletPrivate::EForcedCompactionMode mode =
params.Has("Cleanup")
? TEvIndexTabletPrivate::EForcedCompactionMode::Cleanup
: TEvIndexTabletPrivate::EForcedCompactionMode::Compaction;

EnqueueForcedCompaction(std::move(ranges), mode);
EnqueueForcedCompactionIfNeeded(ctx);

SendHttpResponse(
Expand Down
12 changes: 11 additions & 1 deletion cloud/filestore/libs/storage/tablet/tablet_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -375,12 +375,22 @@ struct TEvIndexTabletPrivate
// ForcedCompaction
//

enum EForcedCompactionMode
{
Compaction = 0,
Cleanup = 1,
};

struct TForcedCompactionRequest
{
TVector<ui32> Ranges;
EForcedCompactionMode Mode;

TForcedCompactionRequest(TVector<ui32> ranges)
TForcedCompactionRequest(
TVector<ui32> ranges,
EForcedCompactionMode mode)
: Ranges(std::move(ranges))
, Mode(mode)
{}
};

Expand Down
Loading
Loading