diff options
author | andrew-rykov <arykov@ydb.tech> | 2022-08-10 13:26:34 +0300 |
---|---|---|
committer | andrew-rykov <arykov@ydb.tech> | 2022-08-10 13:26:34 +0300 |
commit | 811b039dffc7d5e35d3b8a34fad80b16c38f570c (patch) | |
tree | 1fed92fff9a6cbd73f8d953b265643d21acf60aa | |
parent | 41c0210dc6f25ccb7584f1efd8dde6f3824a197e (diff) | |
download | ydb-811b039dffc7d5e35d3b8a34fad80b16c38f570c.tar.gz |
audit logs in schemeshard
fixed merge error
remove consistent operation details
audit logs in schemeshard
14 files changed, 1119 insertions, 368 deletions
diff --git a/ydb/core/kqp/ut/kqp_scheme_ut.cpp b/ydb/core/kqp/ut/kqp_scheme_ut.cpp index 06dc4ba969..ee97c8b17f 100644 --- a/ydb/core/kqp/ut/kqp_scheme_ut.cpp +++ b/ydb/core/kqp/ut/kqp_scheme_ut.cpp @@ -100,6 +100,77 @@ Y_UNIT_TEST_SUITE(KqpScheme) { UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); } + Y_UNIT_TEST(CreateAndDropTableCheckAuditLog) { + TStringStream logStream; + TKikimrRunner kikimr(TKikimrSettings().SetLogStream(&logStream)); + kikimr.GetTestServer().GetRuntime()->SetLogPriority(NKikimrServices::FLAT_TX_SCHEMESHARD, NActors::NLog::PRI_INFO); + { + auto schemeClient = kikimr.GetSchemeClient(); + + NYdb::NScheme::TPermissions permissions("user0@builtin", {"ydb.deprecated.create_table"}); + AssertSuccessResult(schemeClient.ModifyPermissions("/Root", + NYdb::NScheme::TModifyPermissionsSettings().AddGrantPermissions(permissions) + ).ExtractValueSync() + ); + } + + auto driverConfig = TDriverConfig() + .SetEndpoint(kikimr.GetEndpoint()) + .SetAuthToken("user0@builtin"); + auto driver = TDriver(driverConfig); + auto db = NYdb::NTable::TTableClient(driver); + + auto session = db.CreateSession().GetValueSync().GetSession(); + + { + const static TString createTableQuery = R"( + CREATE TABLE `/Root/Test1234/KeyValue` ( + Key Uint32, + Value String, + PRIMARY KEY(Key) + ); + )"; + auto result = session.ExecuteSchemeQuery(createTableQuery).ExtractValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + } + + { + const static TString dropTableQuery = R"( + DROP TABLE `/Root/Test1234/KeyValue`; + )"; + auto result = session.ExecuteSchemeQuery(dropTableQuery).ExtractValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + } + + TString line; + int mtc = 0; + int ctc = 0; + int dtc = 0; + while (logStream.ReadLine(line)) { + if (line.find("AUDIT:") == line.npos) + continue; + + const TString modifyAclTablePattern("operation: MODIFY ACL"); + if (line.find(modifyAclTablePattern) != line.npos) { + mtc += 1; + } + + const TString createTablePattern("operation: CREATE TABLE"); + if (line.find(createTablePattern) != line.npos) { + ctc += 1; + } + + const TString dropTablePattern("operation: DROP TABLE"); + if (line.find(dropTablePattern) != line.npos) { + dtc += 1; + } + } + + UNIT_ASSERT_VALUES_EQUAL_C(mtc, 1, mtc); + UNIT_ASSERT_VALUES_EQUAL_C(ctc, 1, ctc); + UNIT_ASSERT_VALUES_EQUAL_C(dtc, 1, dtc); + } + Y_UNIT_TEST(CreateDropTableMultipleTime) { TKikimrRunner kikimr; auto db = kikimr.GetTableClient(); diff --git a/ydb/core/tx/schemeshard/CMakeLists.txt b/ydb/core/tx/schemeshard/CMakeLists.txt index 480e801ccb..ac577e1ce8 100644 --- a/ydb/core/tx/schemeshard/CMakeLists.txt +++ b/ydb/core/tx/schemeshard/CMakeLists.txt @@ -150,6 +150,7 @@ target_sources(core-tx-schemeshard PRIVATE ${CMAKE_SOURCE_DIR}/ydb/core/tx/schemeshard/schemeshard__upgrade_schema.cpp ${CMAKE_SOURCE_DIR}/ydb/core/tx/schemeshard/schemeshard__upgrade_access_database.cpp ${CMAKE_SOURCE_DIR}/ydb/core/tx/schemeshard/schemeshard__make_access_database_no_inheritable.cpp + ${CMAKE_SOURCE_DIR}/ydb/core/tx/schemeshard/schemeshard_audit_log_fragment.cpp ${CMAKE_SOURCE_DIR}/ydb/core/tx/schemeshard/schemeshard_impl.cpp ${CMAKE_SOURCE_DIR}/ydb/core/tx/schemeshard/schemeshard_billing_helpers.cpp ${CMAKE_SOURCE_DIR}/ydb/core/tx/schemeshard/schemeshard_domain_links.cpp @@ -157,6 +158,7 @@ target_sources(core-tx-schemeshard PRIVATE ${CMAKE_SOURCE_DIR}/ydb/core/tx/schemeshard/schemeshard_identificators.cpp ${CMAKE_SOURCE_DIR}/ydb/core/tx/schemeshard/schemeshard_info_types.cpp ${CMAKE_SOURCE_DIR}/ydb/core/tx/schemeshard/schemeshard_path_describer.cpp + ${CMAKE_SOURCE_DIR}/ydb/core/tx/schemeshard/schemeshard_path_element.cpp ${CMAKE_SOURCE_DIR}/ydb/core/tx/schemeshard/schemeshard_path.cpp ${CMAKE_SOURCE_DIR}/ydb/core/tx/schemeshard/schemeshard_types.cpp ${CMAKE_SOURCE_DIR}/ydb/core/tx/schemeshard/schemeshard_ui64id.cpp diff --git a/ydb/core/tx/schemeshard/schemeshard__operation.cpp b/ydb/core/tx/schemeshard/schemeshard__operation.cpp index 517e7f3eb0..4180c031fa 100644 --- a/ydb/core/tx/schemeshard/schemeshard__operation.cpp +++ b/ydb/core/tx/schemeshard/schemeshard__operation.cpp @@ -1,9 +1,12 @@ #include "schemeshard__operation.h" +#include "schemeshard__operation_part.h" #include "schemeshard__operation_side_effects.h" #include "schemeshard__operation_memory_changes.h" #include "schemeshard__operation_db_changes.h" +#include "schemeshard_audit_log_fragment.h" + #include "schemeshard_impl.h" #include <ydb/core/tablet/tablet_exception.h> @@ -68,6 +71,33 @@ NKikimrScheme::TEvModifySchemeTransaction GetRecordForPrint(const NKikimrScheme: return recordForPrint; } +TString GetAuditLogEntry(const TTxId& txId, const THolder<TProposeResponse>& response, TOperationContext& context) { + auto auditLog = TStringBuilder(); + + auditLog << "txId: " << txId; + for (const auto& frag: context.AuditLogFragments) { + auditLog << ", "; + auditLog << frag.ToString(); + } + + auto fragPath = TPath::Resolve(context.AuditLogFragments.front().GetAnyPath(), context.SS); + if (!fragPath.IsResolved()) { + fragPath.RiseUntilFirstResolvedParent(); + } + if (!fragPath.IsEmpty()) { + auditLog << ", database: " << fragPath.GetDomainPathString(); + } + + auditLog << ", subject: " << context.GetSubject(); + + auditLog << ", status: " << NKikimrScheme::EStatus_Name(response->Record.GetStatus()); + if (response->Record.HasReason()) { + auditLog << ", reason: " << response->Record.GetReason(); + } + + return auditLog; +} + THolder<TProposeResponse> TSchemeShard::IgniteOperation(TProposeRequest& request, TOperationContext& context) { THolder<TProposeResponse> response = nullptr; @@ -85,7 +115,7 @@ THolder<TProposeResponse> TSchemeShard::IgniteOperation(TProposeRequest& request } TOperation::TPtr operation = new TOperation(txId); - Operations[operation->GetTxId()] = operation; //record is erased at ApplyOnExecute if all parts are done at propose + Operations[txId] = operation; //record is erased at ApplyOnExecute if all parts are done at propose if (record.GetUserToken()) { NACLibProto::TUserToken tokenPb; @@ -100,12 +130,18 @@ THolder<TProposeResponse> TSchemeShard::IgniteOperation(TProposeRequest& request } for (const auto& transaction: record.GetTransaction()) { + context.AddAuditLogFragment(transaction); + } + + for (const auto& transaction: record.GetTransaction()) { auto quotaResult = operation->ConsumeQuota(transaction, context); if (quotaResult.Status != NKikimrScheme::StatusSuccess) { response.Reset(new TEvSchemeShard::TEvModifySchemeTransactionResult( quotaResult.Status, ui64(txId), ui64(selfId))); response->SetError(quotaResult.Status, quotaResult.Reason); - Operations.erase(operation->GetTxId()); + Operations.erase(txId); + + LOG_NOTICE_S(context.Ctx, NKikimrServices::FLAT_TX_SCHEMESHARD, "AUDIT: " << GetAuditLogEntry(txId, response, context)); return std::move(response); } } @@ -126,16 +162,20 @@ THolder<TProposeResponse> TSchemeShard::IgniteOperation(TProposeRequest& request response.Reset(new TEvSchemeShard::TEvModifySchemeTransactionResult( splitResult.Status, ui64(txId), ui64(selfId))); response->SetError(splitResult.Status, splitResult.Reason); - Operations.erase(operation->GetTxId()); + Operations.erase(txId); + + LOG_NOTICE_S(context.Ctx, NKikimrServices::FLAT_TX_SCHEMESHARD, "AUDIT: " << GetAuditLogEntry(txId, response, context)); return std::move(response); } transactions.insert(transactions.end(), splitResult.Transactions.begin(), splitResult.Transactions.end()); } + const TString owner = record.HasOwner() ? record.GetOwner() : BUILTIN_ACL_ROOT; + context.ClearAuditLogFragments(); + //for all tx in transactions for (const auto& transaction: transactions) { - const TOperationId pathOpId = TOperationId(txId, operation->Parts.size()); TVector<ISubOperationBase::TPtr> parts = operation->ConstructParts(transaction, context); if (parts.size() > 1) { @@ -143,15 +183,17 @@ THolder<TProposeResponse> TSchemeShard::IgniteOperation(TProposeRequest& request context.IsAllowedPrivateTables = true; } - const TString owner = record.HasOwner() ? record.GetOwner() : BUILTIN_ACL_ROOT; + context.AddAuditLogFragment(transaction); for (auto& part: parts) { + const TOperationId pathOpId = operation->NextPartId(); + response = part->Propose(owner, context); Y_VERIFY(response); LOG_NOTICE_S(context.Ctx, NKikimrServices::FLAT_TX_SCHEMESHARD, "IgniteOperation" - << ", opId: " << pathOpId + << ", opId: " << operation->NextPartId() << ", propose status:" << NKikimrScheme::EStatus_Name(response->Record.GetStatus()) << ", reason: " << response->Record.GetReason() << ", at schemeshard: " << selfId); @@ -199,12 +241,15 @@ THolder<TProposeResponse> TSchemeShard::IgniteOperation(TProposeRequest& request context.MemChanges.UnDo(context.SS); context.OnComplete.ApplyOnExecute(context.SS, context.GetTxc(), context.Ctx); - Operations.erase(operation->GetTxId()); + Operations.erase(txId); + + LOG_NOTICE_S(context.Ctx, NKikimrServices::FLAT_TX_SCHEMESHARD, "AUDIT: " << GetAuditLogEntry(txId, response, context)); return std::move(response); } } } + LOG_NOTICE_S(context.Ctx, NKikimrServices::FLAT_TX_SCHEMESHARD, "AUDIT: " << GetAuditLogEntry(txId, response, context)); return std::move(response); } @@ -1121,7 +1166,7 @@ TVector<ISubOperationBase::TPtr> TOperation::ConstructParts(const TTxTransaction switch (opType) { case NKikimrSchemeOp::EOperationType::ESchemeOpCreateTable: if (tx.GetCreateTable().HasCopyFromTable()) { - return {CreateCopyTable(NextPartId(), tx, context)}; // Copy indexes table as well as common table + return CreateCopyTable(NextPartId(), tx, context); // Copy indexes table as well as common table } return {ConstructPart(opType, tx)}; case NKikimrSchemeOp::EOperationType::ESchemeOpCreateIndexedTable: diff --git a/ydb/core/tx/schemeshard/schemeshard__operation.h b/ydb/core/tx/schemeshard/schemeshard__operation.h index 5d19d8edbd..ea66e3c5c8 100644 --- a/ydb/core/tx/schemeshard/schemeshard__operation.h +++ b/ydb/core/tx/schemeshard/schemeshard__operation.h @@ -132,7 +132,6 @@ struct TOperation: TSimpleRefCount<TOperation> { Y_VERIFY(Barriers.begin()->first == name); Barriers.erase(name); } -private: TOperationId NextPartId() { return TOperationId(TxId, TSubTxId(Parts.size())); } }; diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_create_build_index.cpp b/ydb/core/tx/schemeshard/schemeshard__operation_create_build_index.cpp index 2d957165c6..417fc98806 100644 --- a/ydb/core/tx/schemeshard/schemeshard__operation_create_build_index.cpp +++ b/ydb/core/tx/schemeshard/schemeshard__operation_create_build_index.cpp @@ -62,7 +62,7 @@ TVector<ISubOperationBase::TPtr> CreateBuildIndex(TOperationId nextId, const TTx TString explain; if (!NTableIndex::IsCompatibleIndex(baseTableColumns, indexKeys, explain)) { - return {CreateReject(nextId, NKikimrScheme::EStatus::StatusInvalidParameter, explain)}; + return {CreateReject(nextId, NKikimrScheme::EStatus::StatusInvalidParameter, explain)}; } NTableIndex::TTableColumns impTableColumns = NTableIndex::CalcTableImplDescription(baseTableColumns, indexKeys); diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_move_index.cpp b/ydb/core/tx/schemeshard/schemeshard__operation_move_index.cpp index 539c7d74c3..8ebf3bd757 100644 --- a/ydb/core/tx/schemeshard/schemeshard__operation_move_index.cpp +++ b/ydb/core/tx/schemeshard/schemeshard__operation_move_index.cpp @@ -503,6 +503,11 @@ TVector<ISubOperationBase::TPtr> CreateConsistentMoveIndex(TOperationId nextId, return {CreateReject(nextId, NKikimrScheme::EStatus::StatusPreconditionFailed, errStr)}; } + const auto& moving = tx.GetMoveIndex(); + const auto& mainTable = moving.GetTablePath(); + const auto& srcIndex = moving.GetSrcPath(); + const auto& dstIndex = moving.GetDstPath(); + { TString errStr; if (!context.SS->CheckApplyIf(tx, errStr)) { @@ -510,11 +515,6 @@ TVector<ISubOperationBase::TPtr> CreateConsistentMoveIndex(TOperationId nextId, } } - auto moving = tx.GetMoveIndex(); - - const auto& mainTable = moving.GetTablePath(); - const auto& srcIndex = moving.GetSrcPath(); - const auto& dstIndex = moving.GetDstPath(); bool allowOverwrite = moving.HasAllowOverwrite() && moving.GetAllowOverwrite(); TPath mainTablePath = TPath::Resolve(mainTable, context.SS); diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_move_tables.cpp b/ydb/core/tx/schemeshard/schemeshard__operation_move_tables.cpp index 57b66f0ca8..e221523f8a 100644 --- a/ydb/core/tx/schemeshard/schemeshard__operation_move_tables.cpp +++ b/ydb/core/tx/schemeshard/schemeshard__operation_move_tables.cpp @@ -16,6 +16,10 @@ TVector<ISubOperationBase::TPtr> CreateConsistentMoveTable(TOperationId nextId, TVector<ISubOperationBase::TPtr> result; + const auto& moving = tx.GetMoveTable(); + const auto& srcStr = moving.GetSrcPath(); + const auto& dstStr = moving.GetDstPath(); + { TString errStr; if (!context.SS->CheckApplyIf(tx, errStr)) { @@ -23,11 +27,6 @@ TVector<ISubOperationBase::TPtr> CreateConsistentMoveTable(TOperationId nextId, } } - auto moving = tx.GetMoveTable(); - - auto& srcStr = moving.GetSrcPath(); - auto& dstStr = moving.GetDstPath(); - TPath srcPath = TPath::Resolve(srcStr, context.SS); { TPath::TChecker checks = srcPath.Check(); diff --git a/ydb/core/tx/schemeshard/schemeshard__operation_part.h b/ydb/core/tx/schemeshard/schemeshard__operation_part.h index f961f6cfaf..8d42df6893 100644 --- a/ydb/core/tx/schemeshard/schemeshard__operation_part.h +++ b/ydb/core/tx/schemeshard/schemeshard__operation_part.h @@ -4,6 +4,7 @@ #include "schemeshard_private.h" #include "schemeshard_tx_infly.h" #include "schemeshard_types.h" +#include "schemeshard_audit_log_fragment.h" #include "schemeshard__operation_side_effects.h" #include "schemeshard__operation_memory_changes.h" #include "schemeshard__operation_db_changes.h" @@ -89,6 +90,8 @@ public: TAutoPtr<NACLib::TUserToken> UserToken = nullptr; bool IsAllowedPrivateTables = false; + TVector<TAuditLogFragment> AuditLogFragments; + private: NTabletFlatExecutor::TTransactionContext& Txc; bool ProtectDB = false; @@ -107,6 +110,21 @@ public: , Txc(txc) {} + void AddAuditLogFragment(TAuditLogFragment&& op) { + AuditLogFragments.push_back(std::move(op)); + } + + void ClearAuditLogFragments() { + AuditLogFragments.clear(); + } + + TString GetSubject() const { + if (UserToken) { + return UserToken->GetUserSID(); + } + return "no subject"; + } + NTable::TDatabase& GetDB() { Y_VERIFY_S(ProtectDB == false, "there is attempt to write to the DB when it is protected," diff --git a/ydb/core/tx/schemeshard/schemeshard_audit_log_fragment.cpp b/ydb/core/tx/schemeshard/schemeshard_audit_log_fragment.cpp new file mode 100644 index 0000000000..289e80451d --- /dev/null +++ b/ydb/core/tx/schemeshard/schemeshard_audit_log_fragment.cpp @@ -0,0 +1,513 @@ +#include "schemeshard_audit_log_fragment.h" + +#include <ydb/library/aclib/aclib.h> +#include <ydb/core/base/path.h> + +namespace NKikimr { +namespace NSchemeShard { + +TString DefineUserOperationName(NKikimrSchemeOp::EOperationType type) { + switch (type) { + case NKikimrSchemeOp::EOperationType::ESchemeOpMkDir: + return "CREATE DIRECTORY"; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateTable: + return "CREATE TABLE"; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreatePersQueueGroup: + return "CREATE PERSISTENT QUEUE"; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropTable: + return "DROP TABLE"; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropPersQueueGroup: + return "DROP PERSISTENT QUEUE"; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterTable: + return "ALTER TABLE"; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterPersQueueGroup: + return "ALTER PERSISTENT QUEUE"; + case NKikimrSchemeOp::EOperationType::ESchemeOpModifyACL: + return "MODIFY ACL"; + case NKikimrSchemeOp::EOperationType::ESchemeOpRmDir: + return "DROP DIRECTORY"; + case NKikimrSchemeOp::EOperationType::ESchemeOpSplitMergeTablePartitions: + return "ALTER TABLE PARTITIONS"; + case NKikimrSchemeOp::EOperationType::ESchemeOpBackup: + return "BACKUP TABLE"; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateSubDomain: + return "CREATE DATABASE"; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropSubDomain: + return "DROP DATABASE"; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateRtmrVolume: + return "CREATE RTMR VOLUME"; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateBlockStoreVolume: + return "CREATE BLOCK STORE VOLUME"; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterBlockStoreVolume: + return "ALTER BLOCK STORE VOLUME"; + case NKikimrSchemeOp::EOperationType::ESchemeOpAssignBlockStoreVolume: + return "ALTER BLOCK STORE VOLUME ASSIGN"; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropBlockStoreVolume: + return "DROP BLOCK STORE VOLUME"; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateKesus: + return "CREATE KESUS"; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropKesus: + return "DROP KESUS"; + case NKikimrSchemeOp::EOperationType::ESchemeOpForceDropSubDomain: + return "DROP DATABASE"; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateSolomonVolume: + return "CREATE SOLOMON VOLUME"; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropSolomonVolume: + return "DROP SOLOMON VOLUME"; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterKesus: + return "ALTER KESUS"; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterSubDomain: + return "ALTER DATABASE"; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterUserAttributes: + return "ALTER USER ATTRIBUTES"; + case NKikimrSchemeOp::EOperationType::ESchemeOpForceDropUnsafe: + return "DROP PATH UNSAFE"; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateIndexedTable: + return "CREATE TABLE WITH INDEXES"; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateTableIndex: + return "CREATE INDEX"; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateConsistentCopyTables: + return "CREATE TABLE COPY FROM"; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropTableIndex: + return "DROP INDEX"; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateExtSubDomain: + return "CREATE DATABASE"; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterExtSubDomain: + return "ALTER DATABASE"; + case NKikimrSchemeOp::EOperationType::ESchemeOpForceDropExtSubDomain: + return "DROP DATABASE"; + case NKikimrSchemeOp::EOperationType::ESchemeOp_DEPRECATED_35: + return "ESchemeOp_DEPRECATED_35"; + case NKikimrSchemeOp::EOperationType::ESchemeOpUpgradeSubDomain: + return "ALTER DATABASE MIGRATE"; + case NKikimrSchemeOp::EOperationType::ESchemeOpUpgradeSubDomainDecision: + return "ALTER DATABASE MIGRATE DECISION"; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateIndexBuild: + return "BUILD INDEX"; + case NKikimrSchemeOp::EOperationType::ESchemeOpInitiateBuildIndexMainTable: + return "ALTER TABLE BUILD INDEX INIT"; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateLockForIndexBuild: + return "ALTER TABLE LOCK"; + case NKikimrSchemeOp::EOperationType::ESchemeOpApplyIndexBuild: + return "ALTER TABLE BUILD INDEX APPLY"; + case NKikimrSchemeOp::EOperationType::ESchemeOpFinalizeBuildIndexMainTable: + return "ALTER TABLE BUILD INDEX FINISH"; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterTableIndex: + return "ALTER INDEX"; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterSolomonVolume: + return "ALTER SOLOMON VOLUME"; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropLock: + return "ALTER TABLE UNLOCK"; + case NKikimrSchemeOp::EOperationType::ESchemeOpFinalizeBuildIndexImplTable: + return "ALTER TABLE BUILD INDEX FINISH"; + case NKikimrSchemeOp::EOperationType::ESchemeOpInitiateBuildIndexImplTable: + return "ALTER TABLE BUILD INDEX INIT"; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropIndex: + return "ALTER TABLE DROP INDEX"; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropTableIndexAtMainTable: + return "ALTER TABLE DROP INDEX"; + case NKikimrSchemeOp::EOperationType::ESchemeOpCancelIndexBuild: + return "ALTER TABLE BUILD INDEX CANCEL"; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateFileStore: + return "CREATE FILE STORE"; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterFileStore: + return "ALTER FILE STORE"; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropFileStore: + return "DROP FILE STORE"; + case NKikimrSchemeOp::EOperationType::ESchemeOpRestore: + return "RESTORE TABLE"; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateColumnStore: + return "CREATE COLUMN STORE"; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterColumnStore: + return "ALTER COLUMN STORE"; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropColumnStore: + return "DROP COLUMN STORE"; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateColumnTable: + return "CREATE COLUMN TABLE"; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterColumnTable: + return "ALTER COLUMN TABLE"; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropColumnTable: + return "DROP COLUMN TABLE"; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterLogin: + return "ALTER LOGIN"; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateCdcStream: + return "ATER TABLE CREATE CDC STREAM"; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateCdcStreamImpl: + return "CREATE CDC STREAM"; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateCdcStreamAtTable: + return "ATER TABLE CREATE CDC STREAM"; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterCdcStream: + return "ATER CDC STREAM"; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterCdcStreamImpl: + return "ATER CDC STREAM"; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterCdcStreamAtTable: + return "ATER TABLE ATER CDC STREAM"; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropCdcStream: + return "DROP CDC STREAM"; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropCdcStreamImpl: + return "DROP CDC STREAM"; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropCdcStreamAtTable: + return "ATER TABLE DROP CDC STREAM"; + case NKikimrSchemeOp::EOperationType::ESchemeOpMoveTable: + return "ALTER TABLE RENAME"; + case NKikimrSchemeOp::EOperationType::ESchemeOpMoveTableIndex: + return "ALTER TABLE INDEX RENAME"; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateSequence: + return "CREATE SEQUENCE"; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterSequence: + return "ALTER SEQUENCE"; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropSequence: + return "DROP SEQUENCE"; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateReplication: + return "CREATE REPLICATION"; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterReplication: + return "ALTER REPLICATION"; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropReplication: + return "DROP REPLICATION"; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateBlobDepot: + return "CREATE BLOB DEPOT"; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterBlobDepot: + return "ALTER BLOB DEPOT"; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropBlobDepot: + return "DROP BLOB DEPOT"; + case NKikimrSchemeOp::EOperationType::ESchemeOpMoveIndex: + return "ALTER TABLE INDEX RENAME"; + }; +} + +TAuditLogFragment::TAuditLogFragment(const NKikimrSchemeOp::TModifyScheme& tx) + : Operation(DefineUserOperationName(tx.GetOperationType())) + , ProtoRequest(tx.ShortDebugString()) +{ + FillPathes(tx); + FillACL(tx); +} + +void TAuditLogFragment::FillACL(const NKikimrSchemeOp::TModifyScheme& tx) { + using namespace NACLib; + + bool hasACL = tx.HasModifyACL() && tx.GetModifyACL().HasDiffACL(); + if (hasACL) { + NACLib::TDiffACL diffACL(tx.GetModifyACL().GetDiffACL()); + for (const NACLibProto::TDiffACE& diffACE : diffACL.GetDiffACE()) { + const NACLibProto::TACE& ace = diffACE.GetACE(); + switch (static_cast<EDiffType>(diffACE.GetDiffType())) { + case EDiffType::Add: + AddACL.push_back(TACL::ToString(ace)); + break; + case EDiffType::Remove: + RmACL.push_back(TACL::ToString(ace)); + break; + } + } + } + + bool hasOwner = tx.HasModifyACL() && tx.GetModifyACL().HasNewOwner(); + if (hasOwner) { + NewOwner = tx.GetModifyACL().GetNewOwner(); + } +} + +void TAuditLogFragment::FillPathes(const NKikimrSchemeOp::TModifyScheme& tx) { + switch (tx.GetOperationType()) { + case NKikimrSchemeOp::EOperationType::ESchemeOpMkDir: + Path = JoinPath({tx.GetWorkingDir(), tx.GetMkDir().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateTable: + Path = JoinPath({tx.GetWorkingDir(), tx.GetCreateTable().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreatePersQueueGroup: + Path = JoinPath({tx.GetWorkingDir(), tx.GetCreatePersQueueGroup().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropTable: + Path = JoinPath({tx.GetWorkingDir(), tx.GetDrop().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropPersQueueGroup: + Path = JoinPath({tx.GetWorkingDir(), tx.GetDrop().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterTable: + Path = JoinPath({tx.GetWorkingDir(), tx.GetAlterTable().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterPersQueueGroup: + Path = JoinPath({tx.GetWorkingDir(), tx.GetAlterPersQueueGroup().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpModifyACL: + Path = JoinPath({tx.GetWorkingDir(), tx.GetModifyACL().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpRmDir: + Path = JoinPath({tx.GetWorkingDir(), tx.GetDrop().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpSplitMergeTablePartitions: + Path = JoinPath({tx.GetWorkingDir(), tx.GetSplitMergeTablePartitions().GetTablePath()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpBackup: + Path = JoinPath({tx.GetWorkingDir(), tx.GetBackup().GetTableName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateSubDomain: + Path = JoinPath({tx.GetWorkingDir(), tx.GetSubDomain().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropSubDomain: + Path = JoinPath({tx.GetWorkingDir(), tx.GetDrop().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateRtmrVolume: + Path = JoinPath({tx.GetWorkingDir(), tx.GetCreateRtmrVolume().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateBlockStoreVolume: + Path = JoinPath({tx.GetWorkingDir(), tx.GetCreateBlockStoreVolume().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterBlockStoreVolume: + Path = JoinPath({tx.GetWorkingDir(), tx.GetAlterBlockStoreVolume().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpAssignBlockStoreVolume: + Path = JoinPath({tx.GetWorkingDir(), tx.GetAssignBlockStoreVolume().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropBlockStoreVolume: + Path = JoinPath({tx.GetWorkingDir(), tx.GetDrop().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateKesus: + Path = JoinPath({tx.GetWorkingDir(), tx.GetKesus().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropKesus: + Path = JoinPath({tx.GetWorkingDir(), tx.GetDrop().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpForceDropSubDomain: + Path = JoinPath({tx.GetWorkingDir(), tx.GetDrop().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateSolomonVolume: + Path = JoinPath({tx.GetWorkingDir(), tx.GetCreateSolomonVolume().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropSolomonVolume: + Path = JoinPath({tx.GetWorkingDir(), tx.GetDrop().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterKesus: + Path = JoinPath({tx.GetWorkingDir(), tx.GetKesus().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterSubDomain: + Path = JoinPath({tx.GetWorkingDir(), tx.GetSubDomain().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterUserAttributes: + Path = JoinPath({tx.GetWorkingDir(), tx.GetAlterUserAttributes().GetPathName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpForceDropUnsafe: + Path = JoinPath({tx.GetWorkingDir(), tx.GetDrop().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateIndexedTable: + Path = JoinPath({tx.GetWorkingDir(), tx.GetCreateIndexedTable().GetTableDescription().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateTableIndex: + Path = JoinPath({tx.GetWorkingDir(), tx.GetCreateTableIndex().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateConsistentCopyTables: + for (const auto& item: tx.GetCreateConsistentCopyTables().GetCopyTableDescriptions()) { + SrcPaths.push_back(item.GetSrcPath()); + DstPaths.push_back(item.GetDstPath()); + } + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropTableIndex: + Path = JoinPath({tx.GetWorkingDir(), tx.GetDrop().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateExtSubDomain: + Path = JoinPath({tx.GetWorkingDir(), tx.GetSubDomain().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterExtSubDomain: + Path = JoinPath({tx.GetWorkingDir(), tx.GetSubDomain().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpForceDropExtSubDomain: + Path = JoinPath({tx.GetWorkingDir(), tx.GetSubDomain().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOp_DEPRECATED_35: + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpUpgradeSubDomain: + Path = JoinPath({tx.GetWorkingDir(), tx.GetUpgradeSubDomain().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpUpgradeSubDomainDecision: + Path = JoinPath({tx.GetWorkingDir(), tx.GetUpgradeSubDomain().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateIndexBuild: + Path = JoinPath({tx.GetInitiateIndexBuild().GetTable(), tx.GetInitiateIndexBuild().GetIndex().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpInitiateBuildIndexMainTable: + Path = JoinPath({tx.GetWorkingDir(), tx.GetInitiateBuildIndexMainTable().GetTableName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateLockForIndexBuild: + Path = JoinPath({tx.GetWorkingDir(), tx.GetLockConfig().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpApplyIndexBuild: + Path = JoinPath({tx.GetApplyIndexBuild().GetTablePath(), tx.GetApplyIndexBuild().GetIndexName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpFinalizeBuildIndexMainTable: + Path = JoinPath({tx.GetWorkingDir(), tx.GetFinalizeBuildIndexMainTable().GetTableName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterTableIndex: + Path = JoinPath({tx.GetWorkingDir(), tx.GetAlterTableIndex().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterSolomonVolume: + Path = JoinPath({tx.GetWorkingDir(), tx.GetAlterSolomonVolume().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropLock: + Path = JoinPath({tx.GetWorkingDir(), tx.GetLockConfig().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpFinalizeBuildIndexImplTable: + Path = JoinPath({tx.GetWorkingDir(), tx.GetAlterTable().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpInitiateBuildIndexImplTable: + Path = JoinPath({tx.GetWorkingDir(), tx.GetCreateTable().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropIndex: + Path = JoinPath({tx.GetWorkingDir(), tx.GetDropIndex().GetTableName(), tx.GetDropIndex().GetIndexName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropTableIndexAtMainTable: + Path = JoinPath({tx.GetWorkingDir(), tx.GetDropIndex().GetTableName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpCancelIndexBuild: + Path = JoinPath({tx.GetCancelIndexBuild().GetTablePath(), tx.GetCancelIndexBuild().GetIndexName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateFileStore: + Path = JoinPath({tx.GetWorkingDir(), tx.GetCreateFileStore().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterFileStore: + Path = JoinPath({tx.GetWorkingDir(), tx.GetAlterFileStore().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropFileStore: + Path = JoinPath({tx.GetWorkingDir(), tx.GetDrop().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpRestore: + Path = JoinPath({tx.GetWorkingDir(), tx.GetRestore().GetTableName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateColumnStore: + Path = JoinPath({tx.GetWorkingDir(), tx.GetCreateColumnStore().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterColumnStore: + Path = JoinPath({tx.GetWorkingDir(), tx.GetAlterColumnStore().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropColumnStore: + Path = JoinPath({tx.GetWorkingDir(), tx.GetDrop().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateColumnTable: + Path = JoinPath({tx.GetWorkingDir(), tx.GetAlterColumnTable().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterColumnTable: + Path = JoinPath({tx.GetWorkingDir(), tx.GetAlterColumnTable().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropColumnTable: + Path = JoinPath({tx.GetWorkingDir(), tx.GetDrop().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterLogin: + Path = tx.GetWorkingDir(); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateCdcStream: + Path = JoinPath({tx.GetWorkingDir(), tx.GetCreateCdcStream().GetTableName(), tx.GetCreateCdcStream().GetStreamDescription().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateCdcStreamImpl: + Path = JoinPath({tx.GetWorkingDir(), tx.GetCreateCdcStream().GetStreamDescription().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateCdcStreamAtTable: + Path = JoinPath({tx.GetWorkingDir(), tx.GetCreateCdcStream().GetTableName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterCdcStream: + Path = JoinPath({tx.GetWorkingDir(), tx.GetAlterCdcStream().GetTableName(), tx.GetAlterCdcStream().GetStreamName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterCdcStreamImpl: + Path = JoinPath({tx.GetWorkingDir(), tx.GetAlterCdcStream().GetStreamName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterCdcStreamAtTable: + Path = JoinPath({tx.GetWorkingDir(), tx.GetAlterCdcStream().GetTableName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropCdcStream: + Path = JoinPath({tx.GetWorkingDir(), tx.GetDropCdcStream().GetTableName(), tx.GetDropCdcStream().GetStreamName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropCdcStreamImpl: + Path = JoinPath({tx.GetWorkingDir(), tx.GetDrop().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropCdcStreamAtTable: + Path = JoinPath({tx.GetWorkingDir(), tx.GetDropCdcStream().GetTableName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpMoveTable: + SrcPaths.push_back(tx.GetMoveTable().GetSrcPath()); + DstPaths.push_back(tx.GetMoveTable().GetDstPath()); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpMoveTableIndex: + SrcPaths.push_back(tx.GetMoveTableIndex().GetSrcPath()); + DstPaths.push_back(tx.GetMoveTableIndex().GetDstPath()); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateSequence: + Path = JoinPath({tx.GetWorkingDir(), tx.GetSequence().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterSequence: + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropSequence: + Path = JoinPath({tx.GetWorkingDir(), tx.GetDrop().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateReplication: + Path = JoinPath({tx.GetWorkingDir(), tx.GetReplication().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterReplication: + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropReplication: + Path = JoinPath({tx.GetWorkingDir(), tx.GetDrop().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpCreateBlobDepot: + Path = JoinPath({tx.GetWorkingDir(), tx.GetBlobDepot().GetName()}); + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpAlterBlobDepot: + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpDropBlobDepot: + break; + case NKikimrSchemeOp::EOperationType::ESchemeOpMoveIndex: + SrcPaths.push_back(JoinPath({tx.GetMoveIndex().GetTablePath(), tx.GetMoveIndex().GetSrcPath()})); + DstPaths.push_back(JoinPath({tx.GetMoveIndex().GetTablePath(), tx.GetMoveIndex().GetDstPath()})); + break; + }; +} + +TString TAuditLogFragment::GetAnyPath() const { + if (Path) { + return *Path; + } else if (SrcPaths) { + return SrcPaths.front(); + } else if (DstPaths) { + return DstPaths.front(); + } else { + return ""; + } +} + +TString TAuditLogFragment::ToString() const { + auto result = TStringBuilder(); + + result << "operation: " << Operation; + + if (Path) { + result << ", path: " << Path; + } else if (SrcPaths && DstPaths) { + Y_VERIFY_DEBUG(SrcPaths.size() == DstPaths.size()); + auto minSize = Min(SrcPaths.size(), DstPaths.size()); + for (size_t i = 0; i < minSize; ++i) { + result << ", src path: " << SrcPaths[i]; + result << ", dst path: " << DstPaths[i]; + } + } else { + result << ", no path"; + } + + if (NewOwner) { + result << ", set owner: " << NewOwner; + } + + for (const auto& acl: AddACL) { + result << ", add access: " << acl; + } + + for (const auto& acl: RmACL) { + result << ", remove access: " << acl; + } + + if (ProtoRequest) { + result << ", protobuf request: " << ProtoRequest; + } + + return result; +} + +} +} diff --git a/ydb/core/tx/schemeshard/schemeshard_audit_log_fragment.h b/ydb/core/tx/schemeshard/schemeshard_audit_log_fragment.h new file mode 100644 index 0000000000..4829f0a795 --- /dev/null +++ b/ydb/core/tx/schemeshard/schemeshard_audit_log_fragment.h @@ -0,0 +1,34 @@ +#pragma once + +#include "schemeshard_identificators.h" + +#include <ydb/core/protos/flat_scheme_op.pb.h> + +#include <util/generic/string.h> +#include <util/generic/maybe.h> + +namespace NKikimr { +namespace NSchemeShard { + +struct TAuditLogFragment { + TString Operation; + TMaybe<TString> Path; + TVector<TString> SrcPaths; + TVector<TString> DstPaths; + TVector<TString> AddACL; + TVector<TString> RmACL; + TMaybe<TString> NewOwner; + TMaybe<TString> ProtoRequest; + + TAuditLogFragment(const NKikimrSchemeOp::TModifyScheme& tx); + + void FillACL(const NKikimrSchemeOp::TModifyScheme& tx); + void FillPathes(const NKikimrSchemeOp::TModifyScheme& tx); + + TString GetAnyPath() const; + TString ToString() const; +}; + + +} // NSchemeShard +} // NKikimr diff --git a/ydb/core/tx/schemeshard/schemeshard_path.cpp b/ydb/core/tx/schemeshard/schemeshard_path.cpp index 1a4c6aa511..a568424a6c 100644 --- a/ydb/core/tx/schemeshard/schemeshard_path.cpp +++ b/ydb/core/tx/schemeshard/schemeshard_path.cpp @@ -1080,7 +1080,7 @@ TPath TPath::Root(TSchemeShard* ss) { return result; } -TString TPath::PathString() const { // O(result length) complexity +TString TPath::PathString() const { //O(1) if resolved, in other case O(result length) complexity if (!NameParts) { return TString(); } @@ -1147,6 +1147,11 @@ TPath TPath::FirstExistedParent() const { return result; } +TString TPath::GetDomainPathString() const { + // TODO: not effective because of creating vectors in Init() method. should keep subdomain path somethere in struct TSubDomainInfo + return Init(GetPathIdForDomain(), SS).PathString(); +} + TSubDomainInfo::TPtr TPath::DomainInfo() const { Y_VERIFY(!IsEmpty()); Y_VERIFY(Elements.size()); diff --git a/ydb/core/tx/schemeshard/schemeshard_path.h b/ydb/core/tx/schemeshard/schemeshard_path.h index 2a43e66d50..0593a0f258 100644 --- a/ydb/core/tx/schemeshard/schemeshard_path.h +++ b/ydb/core/tx/schemeshard/schemeshard_path.h @@ -12,6 +12,7 @@ namespace NKikimr { namespace NSchemeShard { class TSchemeShard; +struct TPathElement; class TPath { private: @@ -120,6 +121,7 @@ public: TPath FirstResoledParent() const; TPath& RiseUntilExisted(); TPath FirstExistedParent() const; + TString GetDomainPathString() const; TSubDomainInfo::TPtr DomainInfo() const; TPathId GetPathIdForDomain() const; TPathId GetDomainKey() const; diff --git a/ydb/core/tx/schemeshard/schemeshard_path_element.cpp b/ydb/core/tx/schemeshard/schemeshard_path_element.cpp new file mode 100644 index 0000000000..09c225372c --- /dev/null +++ b/ydb/core/tx/schemeshard/schemeshard_path_element.cpp @@ -0,0 +1,352 @@ +#include "schemeshard_path_element.h" + +namespace NKikimr { +namespace NSchemeShard { + +TPathElement::TPathElement(TPathId pathId, TPathId parentPathId, TPathId domainPathId, const TString& name, const TString& owner) + : PathId(pathId) + , ParentPathId(parentPathId) + , DomainPathId(domainPathId) + , Name(name) + , Owner(owner) + , UserAttrs(new TUserAttributes(1)) +{} + +ui64 TPathElement::GetAliveChildren() const { + return AliveChildrenCount; +} + +void TPathElement::SetAliveChildren(ui64 val) { + AliveChildrenCount = val; +} + +void TPathElement::IncAliveChildren(ui64 delta) { + Y_VERIFY(Max<ui64>() - AliveChildrenCount >= delta); + AliveChildrenCount += delta; +} + +void TPathElement::DecAliveChildren(ui64 delta) { + Y_VERIFY(AliveChildrenCount >= delta); + AliveChildrenCount -= delta; +} + +ui64 TPathElement::GetShardsInside() const { + return ShardsInsideCount; +} + +void TPathElement::SetShardsInside(ui64 val) { + ShardsInsideCount = val; +} + +void TPathElement::IncShardsInside(ui64 delta) { + Y_VERIFY(Max<ui64>() - ShardsInsideCount >= delta); + ShardsInsideCount += delta; +} + +void TPathElement::DecShardsInside(ui64 delta) { + Y_VERIFY(ShardsInsideCount >= delta); + ShardsInsideCount -= delta; +} + +bool TPathElement::IsRoot() const { + return PathId.LocalPathId == RootPathId; +} + +bool TPathElement::IsDirectory() const { + return PathType == EPathType::EPathTypeDir; +} + +bool TPathElement::IsTableIndex() const { + return PathType == EPathType::EPathTypeTableIndex; +} + +bool TPathElement::IsCdcStream() const { + return PathType == EPathType::EPathTypeCdcStream; +} + +bool TPathElement::IsTable() const { + return PathType == EPathType::EPathTypeTable; +} + +bool TPathElement::IsSolomon() const { + return PathType == EPathType::EPathTypeSolomonVolume; +} + +bool TPathElement::IsPQGroup() const { + return PathType == EPathType::EPathTypePersQueueGroup; +} + +bool TPathElement::IsDomainRoot() const { + return IsSubDomainRoot() || IsExternalSubDomainRoot(); +} + +bool TPathElement::IsSubDomainRoot() const { + return PathType == EPathType::EPathTypeSubDomain || IsRoot(); +} + +bool TPathElement::IsExternalSubDomainRoot() const { + return PathType == EPathType::EPathTypeExtSubDomain; +} + +bool TPathElement::IsRtmrVolume() const { + return PathType == EPathType::EPathTypeRtmrVolume; +} + +bool TPathElement::IsBlockStoreVolume() const { + return PathType == EPathType::EPathTypeBlockStoreVolume; +} + +bool TPathElement::IsFileStore() const { + return PathType == EPathType::EPathTypeFileStore; +} + +bool TPathElement::IsKesus() const { + return PathType == EPathType::EPathTypeKesus; +} + +bool TPathElement::IsOlapStore() const { + return PathType == EPathType::EPathTypeColumnStore; +} + +bool TPathElement::IsColumnTable() const { + return PathType == EPathType::EPathTypeColumnTable; +} + +bool TPathElement::IsSequence() const { + return PathType == EPathType::EPathTypeSequence; +} + +bool TPathElement::IsReplication() const { + return PathType == EPathType::EPathTypeReplication; +} + +bool TPathElement::IsBlobDepot() const { + return PathType == EPathType::EPathTypeBlobDepot; +} + +bool TPathElement::IsContainer() const { + return PathType == EPathType::EPathTypeDir || PathType == EPathType::EPathTypeSubDomain + || PathType == EPathType::EPathTypeColumnStore; +} + +bool TPathElement::IsLikeDirectory() const { + return IsDirectory() || IsDomainRoot() || IsOlapStore(); +} + +bool TPathElement::HasActiveChanges() const { + // there are old clusters where Root node has CreateTxId == 0 + return (!IsRoot() && !CreateTxId) || (PathState != EPathState::EPathStateNoChanges); +} + +bool TPathElement::IsCreateFinished() const { + return (IsRoot() && CreateTxId) || StepCreated; +} + +TGlobalTimestamp TPathElement::GetCreateTS() const { + return TGlobalTimestamp(StepCreated, CreateTxId); +} + +TGlobalTimestamp TPathElement::GetDropTS() const { + return TGlobalTimestamp(StepDropped, DropTxId); +} + +void TPathElement::SetDropped(TStepId step, TTxId txId) { + PathState = EPathState::EPathStateNotExist; + StepDropped = step; + DropTxId = txId; +} + +bool TPathElement::NormalState() const { + return PathState == EPathState::EPathStateNoChanges; +} + +bool TPathElement::Dropped() const { + if (StepDropped) { + Y_VERIFY_DEBUG_S(PathState == EPathState::EPathStateNotExist, + "Non consistent PathState and StepDropped." + << " PathState: " << NKikimrSchemeOp::EPathState_Name(PathState) + << ", StepDropped: " << StepDropped + << ", PathId: " << PathId); + } + return bool(StepDropped); +} + +bool TPathElement::IsMigrated() const { + return PathState == EPathState::EPathStateMigrated; +} + +bool TPathElement::IsUnderMoving() const { + return PathState == EPathState::EPathStateMoving; +} + +bool TPathElement::IsUnderCreating() const { + return PathState == EPathState::EPathStateCreate; +} + +bool TPathElement::PlannedToCreate() const { + return PathState == EPathState::EPathStateCreate; +} + +bool TPathElement::PlannedToDrop() const { + return PathState == EPathState::EPathStateDrop; +} + +bool TPathElement::AddChild(const TString& name, TPathId pathId, bool replace) { + TPathId* ptr = FindChild(name); + if (ptr && !replace) + return false; + Children[name] = pathId; + return true; +} + +bool TPathElement::RemoveChild(const TString& name, TPathId pathId) { + auto it = Children.find(name); + if (it != Children.end() && it->second == pathId) { + Children.erase(it); + return true; + } + return false; +} + +TPathId* TPathElement::FindChild(const TString& name) { + return Children.FindPtr(name); +} + +const TPathElement::TChildrenCont& TPathElement::GetChildren() const { + return Children; +} + +void TPathElement::SwapChildren(TChildrenCont& container) { + container.swap(Children); +} + +void TPathElement::ApplyACL(const TString& acl) { + NACLib::TACL secObj(ACL); + NACLib::TDiffACL diffACL(acl); + secObj.ApplyDiff(diffACL); + ACL = secObj.SerializeAsString(); +} + +void TPathElement::ApplySpecialAttributes() { + VolumeSpaceRaw.Limit = Max<ui64>(); + VolumeSpaceSSD.Limit = Max<ui64>(); + VolumeSpaceHDD.Limit = Max<ui64>(); + VolumeSpaceSSDNonrepl.Limit = Max<ui64>(); + VolumeSpaceSSDSystem.Limit = Max<ui64>(); + ExtraPathSymbolsAllowed = TString(); + for (const auto& item : UserAttrs->Attrs) { + switch (TUserAttributes::ParseName(item.first)) { + case EAttribute::VOLUME_SPACE_LIMIT: + HandleAttributeValue(item.second, VolumeSpaceRaw.Limit); + break; + case EAttribute::VOLUME_SPACE_LIMIT_SSD: + HandleAttributeValue(item.second, VolumeSpaceSSD.Limit); + break; + case EAttribute::VOLUME_SPACE_LIMIT_HDD: + HandleAttributeValue(item.second, VolumeSpaceHDD.Limit); + break; + case EAttribute::VOLUME_SPACE_LIMIT_SSD_NONREPL: + HandleAttributeValue(item.second, VolumeSpaceSSDNonrepl.Limit); + break; + case EAttribute::VOLUME_SPACE_LIMIT_SSD_SYSTEM: + HandleAttributeValue(item.second, VolumeSpaceSSDSystem.Limit); + break; + case EAttribute::EXTRA_PATH_SYMBOLS_ALLOWED: + HandleAttributeValue(item.second, ExtraPathSymbolsAllowed); + break; + case EAttribute::DOCUMENT_API_VERSION: + HandleAttributeValue(item.second, DocumentApiVersion); + break; + default: + break; + } + } +} + +void TPathElement::HandleAttributeValue(const TString& value, TString& target) { + target = value; +} + +void TPathElement::HandleAttributeValue(const TString& value, ui64& target) { + ui64 parsed; + if (TryFromString(value, parsed)) { + target = parsed; + } +} + +void TPathElement::ChangeVolumeSpaceBegin(TVolumeSpace newSpace, TVolumeSpace oldSpace) { + auto update = [](TVolumeSpaceLimits& limits, ui64 newValue, ui64 oldValue) { + if (newValue > oldValue) { + // Volume space increase is handled at tx begin + limits.Allocated += newValue - oldValue; + } + }; + update(VolumeSpaceRaw, newSpace.Raw, oldSpace.Raw); + update(VolumeSpaceSSD, newSpace.SSD, oldSpace.SSD); + update(VolumeSpaceHDD, newSpace.HDD, oldSpace.HDD); + update(VolumeSpaceSSDNonrepl, newSpace.SSDNonrepl, oldSpace.SSDNonrepl); + update(VolumeSpaceSSDSystem, newSpace.SSDSystem, oldSpace.SSDSystem); +} + +void TPathElement::ChangeVolumeSpaceCommit(TVolumeSpace newSpace, TVolumeSpace oldSpace) { + auto update = [](TVolumeSpaceLimits& limits, ui64 newValue, ui64 oldValue) { + if (newValue < oldValue) { + // Volume space decrease is handled at tx commit + ui64 diff = oldValue - newValue; + Y_VERIFY(limits.Allocated >= diff); + limits.Allocated -= diff; + } + }; + update(VolumeSpaceRaw, newSpace.Raw, oldSpace.Raw); + update(VolumeSpaceSSD, newSpace.SSD, oldSpace.SSD); + update(VolumeSpaceHDD, newSpace.HDD, oldSpace.HDD); + update(VolumeSpaceSSDNonrepl, newSpace.SSDNonrepl, oldSpace.SSDNonrepl); + update(VolumeSpaceSSDSystem, newSpace.SSDSystem, oldSpace.SSDSystem); +} + +bool TPathElement::CheckVolumeSpaceChange(TVolumeSpace newSpace, TVolumeSpace oldSpace, TString& errStr) { + auto check = [&errStr](const TVolumeSpaceLimits& limits, ui64 newValue, ui64 oldValue, const char* suffix) -> bool { + if (newValue > oldValue) { + ui64 newAllocated = limits.Allocated + newValue - oldValue; + if (newAllocated > limits.Limit) { + errStr = TStringBuilder() + << "New volume space is over a limit" << suffix + << ": " << newAllocated << " > " << limits.Limit; + return false; + } + } + return true; + }; + return (check(VolumeSpaceRaw, newSpace.Raw, oldSpace.Raw, "") && + check(VolumeSpaceSSD, newSpace.SSD, oldSpace.SSD, " (ssd)") && + check(VolumeSpaceHDD, newSpace.HDD, oldSpace.HDD, " (hdd)") && + check(VolumeSpaceSSDNonrepl, newSpace.SSDNonrepl, oldSpace.SSDNonrepl, " (ssd_nonrepl)") && + check(VolumeSpaceSSDSystem, newSpace.SSDSystem, oldSpace.SSDSystem, " (ssd_system)")); +} + +bool TPathElement::HasRuntimeAttrs() const { + return (VolumeSpaceRaw.Allocated > 0 || + VolumeSpaceSSD.Allocated > 0 || + VolumeSpaceHDD.Allocated > 0 || + VolumeSpaceSSDNonrepl.Allocated > 0 || + VolumeSpaceSSDSystem.Allocated > 0); +} + +void TPathElement::SerializeRuntimeAttrs( + google::protobuf::RepeatedPtrField<NKikimrSchemeOp::TUserAttribute>* userAttrs) const +{ + auto process = [userAttrs](const TVolumeSpaceLimits& limits, const char* name) { + if (limits.Allocated > 0) { + auto* attr = userAttrs->Add(); + attr->SetKey(name); + attr->SetValue(TStringBuilder() << limits.Allocated); + } + }; + process(VolumeSpaceRaw, "__volume_space_allocated"); + process(VolumeSpaceSSD, "__volume_space_allocated_ssd"); + process(VolumeSpaceHDD, "__volume_space_allocated_hdd"); + process(VolumeSpaceSSDNonrepl, "__volume_space_allocated_ssd_nonrepl"); + process(VolumeSpaceSSDSystem, "__volume_space_allocated_ssd_system"); +} +} +} diff --git a/ydb/core/tx/schemeshard/schemeshard_path_element.h b/ydb/core/tx/schemeshard/schemeshard_path_element.h index 6fd2fbc313..499f661130 100644 --- a/ydb/core/tx/schemeshard/schemeshard_path_element.h +++ b/ydb/core/tx/schemeshard/schemeshard_path_element.h @@ -16,6 +16,8 @@ namespace NKikimr { namespace NSchemeShard { +class TPath; + constexpr TStringBuf ATTR_PREFIX = "__"; constexpr TStringBuf ATTR_VOLUME_SPACE_LIMIT = "__volume_space_limit"; constexpr TStringBuf ATTR_VOLUME_SPACE_LIMIT_HDD = "__volume_space_limit_hdd"; @@ -341,354 +343,63 @@ private: ui64 AliveChildrenCount = 0; ui64 ShardsInsideCount = 0; TChildrenCont Children; - public: - TPathElement(TPathId pathId, TPathId parentPathId, TPathId domainPathId, const TString& name, const TString& owner) - : PathId(pathId) - , ParentPathId(parentPathId) - , DomainPathId(domainPathId) - , Name(name) - , Owner(owner) - , UserAttrs(new TUserAttributes(1)) - {} - - ui64 GetAliveChildren() const { - return AliveChildrenCount; - } - - void SetAliveChildren(ui64 val) { - AliveChildrenCount = val; - } - - void IncAliveChildren(ui64 delta = 1) { - Y_VERIFY(Max<ui64>() - AliveChildrenCount >= delta); - AliveChildrenCount += delta; - } - - void DecAliveChildren(ui64 delta = 1) { - Y_VERIFY(AliveChildrenCount >= delta); - AliveChildrenCount -= delta; - } - - ui64 GetShardsInside() const { - return ShardsInsideCount; - } - - void SetShardsInside(ui64 val) { - ShardsInsideCount = val; - } - - void IncShardsInside(ui64 delta = 1) { - Y_VERIFY(Max<ui64>() - ShardsInsideCount >= delta); - ShardsInsideCount += delta; - } - - void DecShardsInside(ui64 delta = 1) { - Y_VERIFY(ShardsInsideCount >= delta); - ShardsInsideCount -= delta; - } - - bool IsRoot() const { - return PathId.LocalPathId == RootPathId; - } - - bool IsDirectory() const { - return PathType == EPathType::EPathTypeDir; - } - - bool IsTableIndex() const { - return PathType == EPathType::EPathTypeTableIndex; - } - - bool IsCdcStream() const { - return PathType == EPathType::EPathTypeCdcStream; - } - - bool IsTable() const { - return PathType == EPathType::EPathTypeTable; - } - - bool IsSolomon() const { - return PathType == EPathType::EPathTypeSolomonVolume; - } - - bool IsPQGroup() const { - return PathType == EPathType::EPathTypePersQueueGroup; - } - - bool IsDomainRoot() const { - return IsSubDomainRoot() || IsExternalSubDomainRoot(); - } - - bool IsSubDomainRoot() const { - return PathType == EPathType::EPathTypeSubDomain || IsRoot(); - } - - bool IsExternalSubDomainRoot() const { - return PathType == EPathType::EPathTypeExtSubDomain; - } - - bool IsRtmrVolume() const { - return PathType == EPathType::EPathTypeRtmrVolume; - } - - bool IsBlockStoreVolume() const { - return PathType == EPathType::EPathTypeBlockStoreVolume; - } - - bool IsFileStore() const { - return PathType == EPathType::EPathTypeFileStore; - } - - bool IsKesus() const { - return PathType == EPathType::EPathTypeKesus; - } - - bool IsOlapStore() const { - return PathType == EPathType::EPathTypeColumnStore; - } - - bool IsColumnTable() const { - return PathType == EPathType::EPathTypeColumnTable; - } - - bool IsSequence() const { - return PathType == EPathType::EPathTypeSequence; - } - - bool IsReplication() const { - return PathType == EPathType::EPathTypeReplication; - } - - bool IsBlobDepot() const { - return PathType == EPathType::EPathTypeBlobDepot; - } - - bool IsContainer() const { - return PathType == EPathType::EPathTypeDir || PathType == EPathType::EPathTypeSubDomain - || PathType == EPathType::EPathTypeColumnStore; - } - - bool IsLikeDirectory() const { - return IsDirectory() || IsDomainRoot() || IsOlapStore(); - } - - bool HasActiveChanges() const { - // there are old clusters where Root node has CreateTxId == 0 - return (!IsRoot() && !CreateTxId) || (PathState != EPathState::EPathStateNoChanges); - } - - bool IsCreateFinished() const { - return (IsRoot() && CreateTxId) || StepCreated; - } - - TGlobalTimestamp GetCreateTS() const { - return TGlobalTimestamp(StepCreated, CreateTxId); - } - - TGlobalTimestamp GetDropTS() const { - return TGlobalTimestamp(StepDropped, DropTxId); - } - - void SetDropped(TStepId step, TTxId txId) { - PathState = EPathState::EPathStateNotExist; - StepDropped = step; - DropTxId = txId; - } - - bool NormalState() const { - return PathState == EPathState::EPathStateNoChanges; - } - - bool Dropped() const { - if (StepDropped) { - Y_VERIFY_DEBUG_S(PathState == EPathState::EPathStateNotExist, - "Non consistent PathState and StepDropped." - << " PathState: " << NKikimrSchemeOp::EPathState_Name(PathState) - << ", StepDropped: " << StepDropped - << ", PathId: " << PathId); - } - return bool(StepDropped); - } - - bool IsMigrated() const { - return PathState == EPathState::EPathStateMigrated; - } - - bool IsUnderMoving() const { - return PathState == EPathState::EPathStateMoving; - } - - bool IsUnderCreating() const { - return PathState == EPathState::EPathStateCreate; - } - - bool PlannedToCreate() const { - return PathState == EPathState::EPathStateCreate; - } - - bool PlannedToDrop() const { - return PathState == EPathState::EPathStateDrop; - } - - bool AddChild(const TString& name, TPathId pathId, bool replace = false) { - TPathId* ptr = FindChild(name); - if (ptr && !replace) - return false; - Children[name] = pathId; - return true; - } - - bool RemoveChild(const TString& name, TPathId pathId) { - auto it = Children.find(name); - if (it != Children.end() && it->second == pathId) { - Children.erase(it); - return true; - } - return false; - } - - TPathId* FindChild(const TString& name) { - return Children.FindPtr(name); - } - - const TChildrenCont& GetChildren() const { - return Children; - } - - void SwapChildren(TChildrenCont& container) { - container.swap(Children); - } - - void ApplyACL(const TString& acl) { - NACLib::TACL secObj(ACL); - NACLib::TDiffACL diffACL(acl); - secObj.ApplyDiff(diffACL); - ACL = secObj.SerializeAsString(); - } - - void ApplySpecialAttributes() { - VolumeSpaceRaw.Limit = Max<ui64>(); - VolumeSpaceSSD.Limit = Max<ui64>(); - VolumeSpaceHDD.Limit = Max<ui64>(); - VolumeSpaceSSDNonrepl.Limit = Max<ui64>(); - VolumeSpaceSSDSystem.Limit = Max<ui64>(); - ExtraPathSymbolsAllowed = TString(); - for (const auto& item : UserAttrs->Attrs) { - switch (TUserAttributes::ParseName(item.first)) { - case EAttribute::VOLUME_SPACE_LIMIT: - HandleAttributeValue(item.second, VolumeSpaceRaw.Limit); - break; - case EAttribute::VOLUME_SPACE_LIMIT_SSD: - HandleAttributeValue(item.second, VolumeSpaceSSD.Limit); - break; - case EAttribute::VOLUME_SPACE_LIMIT_HDD: - HandleAttributeValue(item.second, VolumeSpaceHDD.Limit); - break; - case EAttribute::VOLUME_SPACE_LIMIT_SSD_NONREPL: - HandleAttributeValue(item.second, VolumeSpaceSSDNonrepl.Limit); - break; - case EAttribute::VOLUME_SPACE_LIMIT_SSD_SYSTEM: - HandleAttributeValue(item.second, VolumeSpaceSSDSystem.Limit); - break; - case EAttribute::EXTRA_PATH_SYMBOLS_ALLOWED: - HandleAttributeValue(item.second, ExtraPathSymbolsAllowed); - break; - case EAttribute::DOCUMENT_API_VERSION: - HandleAttributeValue(item.second, DocumentApiVersion); - break; - default: - break; - } - } - } - - void HandleAttributeValue(const TString& value, TString& target) { - target = value; - } - - void HandleAttributeValue(const TString& value, ui64& target) { - ui64 parsed; - if (TryFromString(value, parsed)) { - target = parsed; - } - } - - void ChangeVolumeSpaceBegin(TVolumeSpace newSpace, TVolumeSpace oldSpace) { - auto update = [](TVolumeSpaceLimits& limits, ui64 newValue, ui64 oldValue) { - if (newValue > oldValue) { - // Volume space increase is handled at tx begin - limits.Allocated += newValue - oldValue; - } - }; - update(VolumeSpaceRaw, newSpace.Raw, oldSpace.Raw); - update(VolumeSpaceSSD, newSpace.SSD, oldSpace.SSD); - update(VolumeSpaceHDD, newSpace.HDD, oldSpace.HDD); - update(VolumeSpaceSSDNonrepl, newSpace.SSDNonrepl, oldSpace.SSDNonrepl); - update(VolumeSpaceSSDSystem, newSpace.SSDSystem, oldSpace.SSDSystem); - } - - void ChangeVolumeSpaceCommit(TVolumeSpace newSpace, TVolumeSpace oldSpace) { - auto update = [](TVolumeSpaceLimits& limits, ui64 newValue, ui64 oldValue) { - if (newValue < oldValue) { - // Volume space decrease is handled at tx commit - ui64 diff = oldValue - newValue; - Y_VERIFY(limits.Allocated >= diff); - limits.Allocated -= diff; - } - }; - update(VolumeSpaceRaw, newSpace.Raw, oldSpace.Raw); - update(VolumeSpaceSSD, newSpace.SSD, oldSpace.SSD); - update(VolumeSpaceHDD, newSpace.HDD, oldSpace.HDD); - update(VolumeSpaceSSDNonrepl, newSpace.SSDNonrepl, oldSpace.SSDNonrepl); - update(VolumeSpaceSSDSystem, newSpace.SSDSystem, oldSpace.SSDSystem); - } - - bool CheckVolumeSpaceChange(TVolumeSpace newSpace, TVolumeSpace oldSpace, TString& errStr) { - auto check = [&errStr](const TVolumeSpaceLimits& limits, ui64 newValue, ui64 oldValue, const char* suffix) -> bool { - if (newValue > oldValue) { - ui64 newAllocated = limits.Allocated + newValue - oldValue; - if (newAllocated > limits.Limit) { - errStr = TStringBuilder() - << "New volume space is over a limit" << suffix - << ": " << newAllocated << " > " << limits.Limit; - return false; - } - } - return true; - }; - return (check(VolumeSpaceRaw, newSpace.Raw, oldSpace.Raw, "") && - check(VolumeSpaceSSD, newSpace.SSD, oldSpace.SSD, " (ssd)") && - check(VolumeSpaceHDD, newSpace.HDD, oldSpace.HDD, " (hdd)") && - check(VolumeSpaceSSDNonrepl, newSpace.SSDNonrepl, oldSpace.SSDNonrepl, " (ssd_nonrepl)") && - check(VolumeSpaceSSDSystem, newSpace.SSDSystem, oldSpace.SSDSystem, " (ssd_system)")); - } - - bool HasRuntimeAttrs() const { - return (VolumeSpaceRaw.Allocated > 0 || - VolumeSpaceSSD.Allocated > 0 || - VolumeSpaceHDD.Allocated > 0 || - VolumeSpaceSSDNonrepl.Allocated > 0 || - VolumeSpaceSSDSystem.Allocated > 0); - } - - void SerializeRuntimeAttrs( - google::protobuf::RepeatedPtrField<NKikimrSchemeOp::TUserAttribute>* userAttrs) const - { - auto process = [userAttrs](const TVolumeSpaceLimits& limits, const char* name) { - if (limits.Allocated > 0) { - auto* attr = userAttrs->Add(); - attr->SetKey(name); - attr->SetValue(TStringBuilder() << limits.Allocated); - } - }; - process(VolumeSpaceRaw, "__volume_space_allocated"); - process(VolumeSpaceSSD, "__volume_space_allocated_ssd"); - process(VolumeSpaceHDD, "__volume_space_allocated_hdd"); - process(VolumeSpaceSSDNonrepl, "__volume_space_allocated_ssd_nonrepl"); - process(VolumeSpaceSSDSystem, "__volume_space_allocated_ssd_system"); - } - + TPathElement(TPathId pathId, TPathId parentPathId, TPathId domainPathId, const TString& name, const TString& owner); + ui64 GetAliveChildren() const; + void SetAliveChildren(ui64 val); + void IncAliveChildren(ui64 delta = 1); + void DecAliveChildren(ui64 delta = 1); + ui64 GetShardsInside() const; + void SetShardsInside(ui64 val); + void IncShardsInside(ui64 delta = 1); + void DecShardsInside(ui64 delta = 1); + bool IsRoot() const; + bool IsDirectory() const; + bool IsTableIndex() const; + bool IsCdcStream() const; + bool IsTable() const; + bool IsSolomon() const; + bool IsPQGroup() const; + bool IsDomainRoot() const; + bool IsSubDomainRoot() const; + bool IsExternalSubDomainRoot() const; + bool IsRtmrVolume() const; + bool IsBlockStoreVolume() const; + bool IsFileStore() const; + bool IsKesus() const; + bool IsOlapStore() const; + bool IsColumnTable() const; + bool IsSequence() const; + bool IsReplication() const; + bool IsBlobDepot() const; + bool IsContainer() const; + bool IsLikeDirectory() const; + bool HasActiveChanges() const; + bool IsCreateFinished() const; + TGlobalTimestamp GetCreateTS() const; + TGlobalTimestamp GetDropTS() const; + void SetDropped(TStepId step, TTxId txId); + bool NormalState() const; + bool Dropped() const; + bool IsMigrated() const; + bool IsUnderMoving() const; + bool IsUnderCreating() const; + bool PlannedToCreate() const; + bool PlannedToDrop() const; + bool AddChild(const TString& name, TPathId pathId, bool replace = false); + bool RemoveChild(const TString& name, TPathId pathId); + TPathId* FindChild(const TString& name); + const TChildrenCont& GetChildren() const; + void SwapChildren(TChildrenCont& container); + void ApplyACL(const TString& acl); + void ApplySpecialAttributes(); + void HandleAttributeValue(const TString& value, TString& target); + void HandleAttributeValue(const TString& value, ui64& target); + void ChangeVolumeSpaceBegin(TVolumeSpace newSpace, TVolumeSpace oldSpace); + void ChangeVolumeSpaceCommit(TVolumeSpace newSpace, TVolumeSpace oldSpace); + bool CheckVolumeSpaceChange(TVolumeSpace newSpace, TVolumeSpace oldSpace, TString& errStr); + bool HasRuntimeAttrs() const; + void SerializeRuntimeAttrs(google::protobuf::RepeatedPtrField<NKikimrSchemeOp::TUserAttribute>* userAttrs) const; }; } } |