Skip to content

Commit

Permalink
NBS-4905 GetCheckpointStatus (#509)
Browse files Browse the repository at this point in the history
* NBS-4905 GetCheckpointStatus

* Fix compilation errors

* Remove go changes

* Fix go build

* Fix review issues
  • Loading branch information
drbasic authored Feb 29, 2024
1 parent 5e7a912 commit 1c2ce7a
Show file tree
Hide file tree
Showing 22 changed files with 418 additions and 42 deletions.
2 changes: 2 additions & 0 deletions cloud/blockstore/apps/client/lib/factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "discover_instances.h"
#include "execute_action.h"
#include "get_changed_blocks.h"
#include "get_checkpoint_status.h"
#include "kick_endpoint.h"
#include "list_endpoints.h"
#include "list_keyrings.h"
Expand Down Expand Up @@ -60,6 +61,7 @@ struct THandlerFactory
{ "createvolume", NewCreateVolumeCommand },
{ "createvolumefromdevice", NewCreateVolumeFromDeviceCommand },
{ "deletecheckpoint", NewDeleteCheckpointCommand },
{ "getcheckpointstatus", NewGetCheckpointStatusCommand },
{ "describediskregistryconfig", NewDescribeDiskRegistryConfigCommand },
{ "describeendpoint", NewDescribeEndpointCommand },
{ "describeplacementgroup", NewDescribePlacementGroupCommand },
Expand Down
104 changes: 104 additions & 0 deletions cloud/blockstore/apps/client/lib/get_checkpoint_status.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#include "get_checkpoint_status.h"

#include <cloud/blockstore/libs/service/context.h>
#include <cloud/blockstore/libs/service/request_helpers.h>
#include <cloud/blockstore/libs/service/service.h>
#include <cloud/storage/core/libs/common/error.h>
#include <cloud/storage/core/libs/diagnostics/logging.h>

#include <library/cpp/protobuf/util/pb_io.h>

namespace NCloud::NBlockStore::NClient {

namespace {

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

class TGetCheckpointStatusCommand final: public TCommand
{
private:
TString DiskId;
TString CheckpointId;

public:
TGetCheckpointStatusCommand(IBlockStorePtr client)
: TCommand(std::move(client))
{
Opts.AddLongOption("disk-id", "volume identifier")
.RequiredArgument("STR")
.StoreResult(&DiskId);

Opts.AddLongOption("checkpoint-id", "Checkpoint identifier")
.RequiredArgument("STR")
.StoreResult(&CheckpointId);
}

protected:
bool DoExecute() override
{
if (!Proto && !CheckOpts()) {
return false;
}

auto& input = GetInputStream();
auto& output = GetOutputStream();

STORAGE_DEBUG("Reading GetCheckpointStatus request");
auto request = std::make_shared<NProto::TGetCheckpointStatusRequest>();
if (Proto) {
ParseFromTextFormat(input, *request);
} else {
request->SetDiskId(DiskId);
request->SetCheckpointId(CheckpointId);
}

STORAGE_DEBUG("Sending GetCheckpointStatus request");
const auto requestId = GetRequestId(*request);
auto result = WaitFor(ClientEndpoint->GetCheckpointStatus(
MakeIntrusive<TCallContext>(requestId),
std::move(request)));

STORAGE_DEBUG("Received GetCheckpointStatus response");
if (Proto) {
SerializeToTextFormat(result, output);
return true;
}

if (HasError(result)) {
output << FormatError(result.GetError()) << Endl;
return false;
}

return true;
}

private:
bool CheckOpts() const
{
const auto* diskId = ParseResultPtr->FindLongOptParseResult("disk-id");
if (!diskId) {
STORAGE_ERROR("Disk id is required");
return false;
}

const auto* checkpointId =
ParseResultPtr->FindLongOptParseResult("checkpoint-id");
if (!checkpointId) {
STORAGE_ERROR("Checkpoint id is required");
return false;
}

return true;
}
};

} // namespace

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

TCommandPtr NewGetCheckpointStatusCommand(IBlockStorePtr client)
{
return MakeIntrusive<TGetCheckpointStatusCommand>(std::move(client));
}

} // namespace NCloud::NBlockStore::NClient
11 changes: 11 additions & 0 deletions cloud/blockstore/apps/client/lib/get_checkpoint_status.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once

#include "command.h"

namespace NCloud::NBlockStore::NClient {

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

TCommandPtr NewGetCheckpointStatusCommand(IBlockStorePtr client);

} // namespace NCloud::NBlockStore::NClient
3 changes: 2 additions & 1 deletion cloud/blockstore/apps/client/lib/ya.make
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ SRCS(
execute_action.cpp
factory.cpp
get_changed_blocks.cpp
get_checkpoint_status.cpp
kick_endpoint.cpp
list_endpoints.cpp
list_keyrings.cpp
Expand Down Expand Up @@ -63,7 +64,7 @@ PEERDIR(
library/cpp/lwtrace/mon
library/cpp/protobuf/util
library/cpp/threading/blocking_queue

contrib/ydb/library/actors/util
)

Expand Down
1 change: 1 addition & 0 deletions cloud/blockstore/libs/service/auth_scheme.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ TPermissionList GetRequestPermissions(EBlockStoreRequest requestType)
EPermission::Read,
EPermission::Write});
case EBlockStoreRequest::GetChangedBlocks:
case EBlockStoreRequest::GetCheckpointStatus:
return CreatePermissionList({EPermission::Read});
case EBlockStoreRequest::DescribeVolume:
case EBlockStoreRequest::DescribeVolumeModel:
Expand Down
1 change: 1 addition & 0 deletions cloud/blockstore/libs/service/request.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ using TWriteBlocksLocalResponse = TWriteBlocksResponse;
xxx(DeleteCheckpoint, __VA_ARGS__) \
xxx(AlterVolume, __VA_ARGS__) \
xxx(GetChangedBlocks, __VA_ARGS__) \
xxx(GetCheckpointStatus, __VA_ARGS__) \
xxx(DescribeVolume, __VA_ARGS__) \
xxx(ListVolumes, __VA_ARGS__) \
xxx(UploadClientMetrics, __VA_ARGS__) \
Expand Down
1 change: 1 addition & 0 deletions cloud/blockstore/libs/service_local/service_local.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,7 @@ class TLocalService final

BLOCKSTORE_IMPLEMENT_METHOD(CreateCheckpoint)
BLOCKSTORE_IMPLEMENT_METHOD(DeleteCheckpoint)
BLOCKSTORE_IMPLEMENT_METHOD(GetCheckpointStatus)
BLOCKSTORE_IMPLEMENT_METHOD(UploadClientMetrics)
BLOCKSTORE_IMPLEMENT_METHOD(QueryAvailableStorage)

Expand Down
3 changes: 3 additions & 0 deletions cloud/blockstore/libs/storage/api/service.h
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,9 @@ struct TEvService
EvRunVolumesLivenessCheckRequest = EvBegin + 84,
EvRunVolumesLivenessCheckResponse = EvBegin + 85,

EvGetCheckpointStatusRequest = EvBegin + 86,
EvGetCheckpointStatusResponse = EvBegin + 87,

EvEnd
};

Expand Down
36 changes: 19 additions & 17 deletions cloud/blockstore/libs/storage/api/volume.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,16 @@ namespace NCloud::NBlockStore::NStorage {

// requests forwarded from service to volume
#define BLOCKSTORE_VOLUME_REQUESTS_FWD_SERVICE(xxx, ...) \
xxx(ReadBlocks, __VA_ARGS__) \
xxx(WriteBlocks, __VA_ARGS__) \
xxx(ZeroBlocks, __VA_ARGS__) \
xxx(StatVolume, __VA_ARGS__) \
xxx(CreateCheckpoint, __VA_ARGS__) \
xxx(DeleteCheckpoint, __VA_ARGS__) \
xxx(GetChangedBlocks, __VA_ARGS__) \
xxx(ReadBlocksLocal, __VA_ARGS__) \
xxx(WriteBlocksLocal, __VA_ARGS__) \
xxx(ReadBlocks, __VA_ARGS__) \
xxx(WriteBlocks, __VA_ARGS__) \
xxx(ZeroBlocks, __VA_ARGS__) \
xxx(StatVolume, __VA_ARGS__) \
xxx(CreateCheckpoint, __VA_ARGS__) \
xxx(DeleteCheckpoint, __VA_ARGS__) \
xxx(GetChangedBlocks, __VA_ARGS__) \
xxx(GetCheckpointStatus, __VA_ARGS__) \
xxx(ReadBlocksLocal, __VA_ARGS__) \
xxx(WriteBlocksLocal, __VA_ARGS__) \
// BLOCKSTORE_VOLUME_REQUESTS_FWD_SERVICE

// responses which are forwarded back via volume (volume has handlers for these)
Expand All @@ -66,14 +67,15 @@ namespace NCloud::NBlockStore::NStorage {
// responses for the requests forwarded from service which are forwarded back
// via volume (volume has handlers for these)
#define BLOCKSTORE_VOLUME_HANDLED_RESPONSES_FWD_SERVICE(xxx, ...) \
xxx(ReadBlocks, __VA_ARGS__) \
xxx(WriteBlocks, __VA_ARGS__) \
xxx(ZeroBlocks, __VA_ARGS__) \
xxx(CreateCheckpoint, __VA_ARGS__) \
xxx(DeleteCheckpoint, __VA_ARGS__) \
xxx(GetChangedBlocks, __VA_ARGS__) \
xxx(ReadBlocksLocal, __VA_ARGS__) \
xxx(WriteBlocksLocal, __VA_ARGS__) \
xxx(ReadBlocks, __VA_ARGS__) \
xxx(WriteBlocks, __VA_ARGS__) \
xxx(ZeroBlocks, __VA_ARGS__) \
xxx(CreateCheckpoint, __VA_ARGS__) \
xxx(DeleteCheckpoint, __VA_ARGS__) \
xxx(GetChangedBlocks, __VA_ARGS__) \
xxx(GetCheckpointStatus, __VA_ARGS__) \
xxx(ReadBlocksLocal, __VA_ARGS__) \
xxx(WriteBlocksLocal, __VA_ARGS__) \
// BLOCKSTORE_VOLUME_HANDLED_RESPONSES_FWD_SERVICE

////////////////////////////////////////////////////////////////////////////////
Expand Down
19 changes: 10 additions & 9 deletions cloud/blockstore/libs/storage/service/service_actor_forward.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,15 +209,16 @@ void TServiceActor::ForwardRequest(
} \
// BLOCKSTORE_FORWARD_REQUEST

BLOCKSTORE_FORWARD_REQUEST(ReadBlocks, TEvService)
BLOCKSTORE_FORWARD_REQUEST(WriteBlocks, TEvService)
BLOCKSTORE_FORWARD_REQUEST(ZeroBlocks, TEvService)
BLOCKSTORE_FORWARD_REQUEST(StatVolume, TEvService)
BLOCKSTORE_FORWARD_REQUEST(CreateCheckpoint, TEvService)
BLOCKSTORE_FORWARD_REQUEST(DeleteCheckpoint, TEvService)
BLOCKSTORE_FORWARD_REQUEST(GetChangedBlocks, TEvService)
BLOCKSTORE_FORWARD_REQUEST(ReadBlocksLocal, TEvService)
BLOCKSTORE_FORWARD_REQUEST(WriteBlocksLocal, TEvService)
BLOCKSTORE_FORWARD_REQUEST(ReadBlocks, TEvService)
BLOCKSTORE_FORWARD_REQUEST(WriteBlocks, TEvService)
BLOCKSTORE_FORWARD_REQUEST(ZeroBlocks, TEvService)
BLOCKSTORE_FORWARD_REQUEST(StatVolume, TEvService)
BLOCKSTORE_FORWARD_REQUEST(CreateCheckpoint, TEvService)
BLOCKSTORE_FORWARD_REQUEST(DeleteCheckpoint, TEvService)
BLOCKSTORE_FORWARD_REQUEST(GetChangedBlocks, TEvService)
BLOCKSTORE_FORWARD_REQUEST(GetCheckpointStatus, TEvService)
BLOCKSTORE_FORWARD_REQUEST(ReadBlocksLocal, TEvService)
BLOCKSTORE_FORWARD_REQUEST(WriteBlocksLocal, TEvService)

#undef BLOCKSTORE_FORWARD_REQUEST

Expand Down
9 changes: 9 additions & 0 deletions cloud/blockstore/libs/storage/volume/testlib/test_env.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,15 @@ TVolumeClient::CreateDeleteCheckpointDataRequest(
return request;
}

std::unique_ptr<TEvService::TEvGetCheckpointStatusRequest>
TVolumeClient::CreateGetCheckpointStatusRequest(const TString& checkpointId)
{
auto request =
std::make_unique<TEvService::TEvGetCheckpointStatusRequest>();
request->Record.SetCheckpointId(checkpointId);
return request;
}

std::unique_ptr<TEvPartition::TEvBackpressureReport>
TVolumeClient::CreateBackpressureReport(
const TBackpressureReport& report)
Expand Down
3 changes: 3 additions & 0 deletions cloud/blockstore/libs/storage/volume/testlib/test_env.h
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,9 @@ class TVolumeClient
std::unique_ptr<TEvVolume::TEvDeleteCheckpointDataRequest> CreateDeleteCheckpointDataRequest(
const TString& checkpointId);

std::unique_ptr<TEvService::TEvGetCheckpointStatusRequest>
CreateGetCheckpointStatusRequest(const TString& checkpointId);

std::unique_ptr<TEvPartition::TEvBackpressureReport> CreateBackpressureReport(
const TBackpressureReport& report);

Expand Down
4 changes: 4 additions & 0 deletions cloud/blockstore/libs/storage/volume/volume_actor.h
Original file line number Diff line number Diff line change
Expand Up @@ -878,6 +878,10 @@ class TVolumeActor final
const TEvVolume::TEvDeleteCheckpointDataResponse::TPtr& ev,
const NActors::TActorContext& ctx);

void HandleGetCheckpointStatusResponse(
const TEvService::TEvGetCheckpointStatusResponse::TPtr& ev,
const NActors::TActorContext& ctx);

void HandleWriteBlocksLocalResponse(
const TEvService::TEvWriteBlocksLocalResponse::TPtr& ev,
const NActors::TActorContext& ctx);
Expand Down
76 changes: 76 additions & 0 deletions cloud/blockstore/libs/storage/volume/volume_actor_checkpoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ using TCreateCheckpointMethod = TEvService::TCreateCheckpointMethod;
using TDeleteCheckpointMethod = TEvService::TDeleteCheckpointMethod;
using TDeleteCheckpointDataMethod = TEvVolume::TDeleteCheckpointDataMethod;
using TGetChangedBlocksMethod = TEvService::TGetChangedBlocksMethod;
using TGetCheckpointStatusMethod = TEvService::TGetCheckpointStatusMethod;

const char* GetCheckpointRequestName(ECheckpointRequestType reqType) {
switch (reqType) {
Expand Down Expand Up @@ -86,6 +87,38 @@ ECheckpointRequestType ProtoCheckpointType2Create(
return proto2enum.Value(checkpointType, ECheckpointRequestType::Create);
}

NProto::ECheckpointStatus GetCheckpointStatus(const TActiveCheckpointInfo& checkpointInfo)
{
switch (checkpointInfo.Type) {
case ECheckpointType::Normal:
break;
case ECheckpointType::Light:
return NProto::ECheckpointStatus::READY;
}

switch (checkpointInfo.Data) {
case ECheckpointData::DataPresent:
break;
case ECheckpointData::DataDeleted:
return NProto::ECheckpointStatus::ERROR;
}

if (checkpointInfo.ShadowDiskId.Empty()) {
return NProto::ECheckpointStatus::READY;
}

switch (checkpointInfo.ShadowDiskState) {
case EShadowDiskState::None:
case EShadowDiskState::New:
case EShadowDiskState::Preparing:
return NProto::ECheckpointStatus::NOT_READY;
case EShadowDiskState::Ready:
return NProto::ECheckpointStatus::READY;
case EShadowDiskState::Error:
return NProto::ECheckpointStatus::ERROR;
}
}

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

template <typename TMethod>
Expand Down Expand Up @@ -966,6 +999,49 @@ bool TVolumeActor::HandleRequest<TDeleteCheckpointDataMethod>(
return true;
}

template <>
bool TVolumeActor::HandleRequest<TGetCheckpointStatusMethod>(
const TActorContext& ctx,
const TGetCheckpointStatusMethod::TRequest::TPtr& ev,
ui64 volumeRequestId,
bool isTraced,
ui64 traceTs)
{
Y_UNUSED(volumeRequestId);
Y_UNUSED(isTraced);
Y_UNUSED(traceTs);

const auto& msg = *ev->Get();
const auto& checkpointId = msg.Record.GetCheckpointId();

auto reply =
[&](const NProto::TError& error, NProto::ECheckpointStatus status)
{
auto response =
std::make_unique<TGetCheckpointStatusMethod::TResponse>(error);
response->Record.SetCheckpointStatus(status);
NCloud::Reply(ctx, *ev, std::move(response));
};

LOG_INFO(
ctx,
TBlockStoreComponents::VOLUME,
"[%lu] Get checkpoint status for checkpoint %s",
TabletID(),
checkpointId.Quote().c_str());

auto checkpoint = State->GetCheckpointStore().GetCheckpoint(checkpointId);
if (!checkpoint) {
reply(
MakeError(E_NOT_FOUND, "Checkpoint not found"),
NProto::ECheckpointStatus::ERROR);
return true;
}

reply(MakeError(S_OK), GetCheckpointStatus(*checkpoint));
return true;
}

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

void TVolumeActor::HandleUpdateCheckpointRequest(
Expand Down
Loading

0 comments on commit 1c2ce7a

Please sign in to comment.