Skip to content

Commit dae8c90

Browse files
authored
refactor 'ydb scheme rmdir' implementation (#16232)
1 parent 4d4d83d commit dae8c90

File tree

12 files changed

+381
-190
lines changed

12 files changed

+381
-190
lines changed

ydb/apps/ydb/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
* Fixed bugs in `ydb scheme rmdir`: 1) do not try to delete subdomains, 2) order the deletion of external tables before the deletion of external data sources.
12
* YDB CLI help message improvements. Different display for detailed help and brief help.
23
* Support coordination nodes in `ydb scheme rmdir --recursive`.
34
* Fixed return code of command `ydb workload * run --check-canonical` for the case when benchmark query results differ from canonical ones.

ydb/library/backup/backup.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -935,9 +935,7 @@ void RemoveClusterDirectory(const TDriver& driver, const TString& path) {
935935

936936
void RemoveClusterDirectoryRecursive(const TDriver& driver, const TString& path) {
937937
LOG_I("Remove temporary directory " << path.Quote() << " in database");
938-
NScheme::TSchemeClient schemeClient(driver);
939-
NTable::TTableClient tableClient(driver);
940-
TStatus status = NConsoleClient::RemoveDirectoryRecursive(schemeClient, tableClient, path, {}, true, false);
938+
TStatus status = NConsoleClient::RemoveDirectoryRecursive(driver, path);
941939
VerifyStatus(status, TStringBuilder() << "Remove temporary directory " << path.Quote() << " failed");
942940
}
943941

ydb/public/lib/ydb_cli/commands/ydb_service_scheme.cpp

+4-6
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,10 @@ int TCommandRemoveDirectory::Run(TConfig& config) {
8787
const auto settings = FillSettings(NScheme::TRemoveDirectorySettings());
8888

8989
if (Recursive) {
90-
NTable::TTableClient tableClient(driver);
91-
NTopic::TTopicClient topicClient(driver);
92-
NQuery::TQueryClient queryClient(driver);
93-
NCoordination::TClient coordinationClient(driver);
94-
const auto prompt = Prompt.GetOrElse(ERecursiveRemovePrompt::Once);
95-
NStatusHelpers::ThrowOnErrorOrPrintIssues(RemoveDirectoryRecursive(schemeClient, tableClient, &topicClient, &queryClient, &coordinationClient, Path, prompt, settings));
90+
const auto settings = TRemoveDirectoryRecursiveSettings()
91+
.Prompt(Prompt.GetOrElse(ERecursiveRemovePrompt::Once))
92+
.CreateProgressBar(true);
93+
NStatusHelpers::ThrowOnErrorOrPrintIssues(RemoveDirectoryRecursive(driver, Path, settings));
9694
} else {
9795
if (Prompt) {
9896
if (!NConsoleClient::Prompt(*Prompt, Path, NScheme::ESchemeEntryType::Directory)) {

ydb/public/lib/ydb_cli/commands/ydb_workload.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -389,15 +389,15 @@ int TWorkloadCommandBase::Run(TConfig& config) {
389389

390390
void TWorkloadCommandBase::CleanTables(NYdbWorkload::IWorkloadQueryGenerator& workloadGen, TConfig& config) {
391391
auto pathsToDelete = workloadGen.GetCleanPaths();
392-
TRemovePathRecursiveSettings settings;
392+
TRemoveDirectoryRecursiveSettings settings;
393393
settings.NotExistsIsOk(true);
394394
for (const auto& path : pathsToDelete) {
395395
Cout << "Remove path " << path << "..." << Endl;
396396
auto fullPath = config.Database + "/" + path.c_str();
397397
if (DryRun) {
398398
Cout << "Remove " << fullPath << Endl;
399399
} else {
400-
NStatusHelpers::ThrowOnErrorOrPrintIssues(RemovePathRecursive(*SchemeClient, *TableClient, TopicClient.Get(), QueryClient.Get(), nullptr, fullPath, ERecursiveRemovePrompt::Never, settings));
400+
NStatusHelpers::ThrowOnErrorOrPrintIssues(RemovePathRecursive(*Driver.Get(), fullPath, settings));
401401
}
402402
Cout << "Remove path " << path << "...Ok" << Endl;
403403
}

ydb/public/lib/ydb_cli/common/recursive_remove.cpp

+116-73
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#include "interactive.h"
2-
#include "progress_bar.h"
32
#include "recursive_remove.h"
43

54
#include <ydb/public/lib/ydb_cli/common/recursive_list.h>
@@ -106,16 +105,17 @@ template <typename TClient, typename TSettings>
106105
using TRemoveFunc = TStatus(*)(TClient&, const TString&, const TSettings&);
107106

108107
template <typename TClient, typename TSettings>
109-
TStatus Remove(TRemoveFunc<TClient, TSettings> func, TSchemeClient& schemeClient, TClient* client, const ESchemeEntryType type,
110-
const TString& path, ERecursiveRemovePrompt prompt, const TRemoveDirectorySettings& settings)
111-
{
112-
if (!client) {
113-
return TStatus(EStatus::GENERIC_ERROR, MakeIssues(TStringBuilder()
114-
<< TypeName<TClient>() << " not specified"));
115-
}
116-
108+
TStatus Remove(
109+
TRemoveFunc<TClient, TSettings> func,
110+
TSchemeClient& schemeClient,
111+
TClient& specializedClient,
112+
const ESchemeEntryType type,
113+
const TString& path,
114+
ERecursiveRemovePrompt prompt,
115+
const TRemoveDirectorySettings& settings
116+
) {
117117
if (Prompt(prompt, path, type, false)) {
118-
auto status = func(*client, path, TSettings(settings));
118+
auto status = func(specializedClient, path, TSettings(settings));
119119
if (status.GetStatus() == EStatus::SCHEME_ERROR && schemeClient.DescribePath(path).ExtractValueSync().GetStatus() == EStatus::SCHEME_ERROR) {
120120
Cerr << "WARNING: Couldn't delete path: \'" << path << "\'. It was probably already deleted in another process" << Endl;
121121
return TStatus(EStatus::SUCCESS, {});
@@ -127,12 +127,19 @@ TStatus Remove(TRemoveFunc<TClient, TSettings> func, TSchemeClient& schemeClient
127127
}
128128

129129
TStatus Remove(
130-
TSchemeClient& schemeClient, TTableClient* tableClient, TTopicClient* topicClient, NQuery::TQueryClient* queryClient, NCoordination::TClient* coordinationClient,
131-
const ESchemeEntryType type, const TString& path, ERecursiveRemovePrompt prompt, const TRemoveDirectorySettings& settings)
132-
{
130+
TSchemeClient& schemeClient,
131+
TTableClient& tableClient,
132+
TTopicClient& topicClient,
133+
NQuery::TQueryClient& queryClient,
134+
NCoordination::TClient& coordinationClient,
135+
const ESchemeEntryType type,
136+
const TString& path,
137+
ERecursiveRemovePrompt prompt,
138+
const TRemoveDirectorySettings& settings
139+
) {
133140
switch (type) {
134141
case ESchemeEntryType::Directory:
135-
return Remove(&RemoveDirectory, schemeClient, &schemeClient, type, path, prompt, settings);
142+
return Remove(&RemoveDirectory, schemeClient, schemeClient, type, path, prompt, settings);
136143

137144
case ESchemeEntryType::ColumnStore:
138145
return Remove(&RemoveColumnStore, schemeClient, tableClient, type, path, prompt, settings);
@@ -151,6 +158,9 @@ TStatus Remove(
151158
return Remove(&RemoveView, schemeClient, queryClient, type, path, prompt, settings);
152159
case ESchemeEntryType::CoordinationNode:
153160
return Remove(&RemoveCoordinationNode, schemeClient, coordinationClient, type, path, prompt, settings);
161+
case ESchemeEntryType::SubDomain:
162+
// continue silently
163+
return TStatus(EStatus::SUCCESS, {});
154164

155165
default:
156166
return TStatus(EStatus::UNSUPPORTED, MakeIssues(TStringBuilder()
@@ -159,86 +169,119 @@ TStatus Remove(
159169
}
160170

161171
TStatus RemoveDirectoryRecursive(
162-
TSchemeClient& schemeClient,
163-
TTableClient* tableClient,
164-
TTopicClient* topicClient,
165-
NQuery::TQueryClient* queryClient,
166-
NCoordination::TClient* coordinationClient,
167-
const TString& path,
168-
ERecursiveRemovePrompt prompt,
169-
const TRemoveDirectorySettings& settings,
170-
bool removeSelf,
171-
bool createProgressBar)
172-
{
173-
auto recursiveListResult = RecursiveList(schemeClient, path, {}, removeSelf);
172+
TSchemeClient& schemeClient,
173+
TTableClient& tableClient,
174+
TTopicClient& topicClient,
175+
NQuery::TQueryClient& queryClient,
176+
NCoordination::TClient& coordinationClient,
177+
const TString& path,
178+
const TRemoveDirectoryRecursiveSettings& settings
179+
) {
180+
const auto listingSettings = TRecursiveListSettings()
181+
.Filter([](const TSchemeEntry& entry) {
182+
// explicitly skip subdomains
183+
return entry.Type != ESchemeEntryType::SubDomain;
184+
});
185+
auto recursiveListResult = RecursiveList(schemeClient, path, listingSettings, settings.RemoveSelf_);
174186
if (!recursiveListResult.Status.IsSuccess()) {
175187
return recursiveListResult.Status;
176188
}
177189

178-
if (prompt == ERecursiveRemovePrompt::Once) {
190+
if (settings.Prompt_ == ERecursiveRemovePrompt::Once) {
179191
if (!Prompt(path, ESchemeEntryType::Directory)) {
180192
return TStatus(EStatus::SUCCESS, {});
181193
}
182194
}
183195

184-
std::unique_ptr<TProgressBar> bar;
185-
if (createProgressBar) {
186-
bar = std::make_unique<TProgressBar>(recursiveListResult.Entries.size());
187-
}
188-
// output order is: Root, Recursive(children)...
189-
// we need to reverse it to delete recursively
190-
for (auto it = recursiveListResult.Entries.rbegin(); it != recursiveListResult.Entries.rend(); ++it) {
191-
if (auto result = Remove(schemeClient, tableClient, topicClient, queryClient, coordinationClient, it->Type, TString{it->Name}, prompt, settings); !result.IsSuccess()) {
192-
return result;
193-
}
194-
if (createProgressBar) {
195-
bar->AddProgress(1);
196-
}
197-
}
198-
199-
return TStatus(EStatus::SUCCESS, {});
196+
// RecursiveList outputs elements in pre-order: root, recurse(children)...
197+
// We need to reverse it to delete scheme objects before directories.
198+
return RemovePathsRecursive(
199+
schemeClient,
200+
tableClient,
201+
topicClient,
202+
queryClient,
203+
coordinationClient,
204+
recursiveListResult.Entries.rbegin(),
205+
recursiveListResult.Entries.rend(),
206+
settings
207+
);
200208
}
201209

202210
TStatus RemoveDirectoryRecursive(
203-
TSchemeClient& schemeClient,
204-
TTableClient& tableClient,
205-
const TString& path,
206-
const TRemoveDirectorySettings& settings,
207-
bool removeSelf,
208-
bool createProgressBar)
209-
{
210-
return RemoveDirectoryRecursive(schemeClient, &tableClient, nullptr, nullptr, nullptr, path, ERecursiveRemovePrompt::Never, settings, removeSelf, createProgressBar);
211+
const TDriver& driver,
212+
const TString& path,
213+
const TRemoveDirectoryRecursiveSettings& settings
214+
) {
215+
TSchemeClient schemeClient(driver);
216+
TTableClient tableClient(driver);
217+
TTopicClient topicClient(driver);
218+
NQuery::TQueryClient queryClient(driver);
219+
NCoordination::TClient coordinationClient(driver);
220+
return RemoveDirectoryRecursive(schemeClient, tableClient, topicClient, queryClient, coordinationClient, path, settings);
211221
}
212222

213-
TStatus RemoveDirectoryRecursive(
214-
TSchemeClient& schemeClient,
215-
TTableClient& tableClient,
216-
TTopicClient* topicClient,
217-
NQuery::TQueryClient* queryClient,
218-
NCoordination::TClient* coordinationClient,
219-
const TString& path,
220-
ERecursiveRemovePrompt prompt,
221-
const TRemoveDirectorySettings& settings,
222-
bool removeSelf,
223-
bool createProgressBar)
224-
{
225-
return RemoveDirectoryRecursive(schemeClient, &tableClient, topicClient, queryClient, coordinationClient, path, prompt, settings, removeSelf, createProgressBar);
226-
}
227-
228-
NYdb::TStatus RemovePathRecursive(NScheme::TSchemeClient& schemeClient, NTable::TTableClient& tableClient, NTopic::TTopicClient* topicClient, NQuery::TQueryClient* queryClient, NCoordination::TClient* coordinationClient, const TString& path, ERecursiveRemovePrompt prompt, const TRemovePathRecursiveSettings& settings /*= {}*/, bool createProgressBar /*= true*/) {
223+
TStatus RemovePathRecursive(
224+
const TDriver& driver,
225+
const TString& path,
226+
const TRemoveDirectoryRecursiveSettings& settings
227+
) {
228+
TSchemeClient schemeClient(driver);
229229
auto entity = schemeClient.DescribePath(path).ExtractValueSync();
230230
if (!entity.IsSuccess()) {
231231
if (settings.NotExistsIsOk_ && entity.GetStatus() == EStatus::SCHEME_ERROR && entity.GetIssues().ToString().find("Path not found") != TString::npos) {
232232
return TStatus(EStatus::SUCCESS, {});
233233
}
234234
return entity;
235235
}
236-
switch (entity.GetEntry().Type) {
237-
case ESchemeEntryType::Directory:
238-
case ESchemeEntryType::ColumnStore:
239-
return RemoveDirectoryRecursive(schemeClient, tableClient, topicClient, queryClient, coordinationClient, path, prompt, settings, true, createProgressBar);
240-
default:
241-
return Remove(schemeClient, &tableClient, topicClient, queryClient, coordinationClient, entity.GetEntry().Type, path, prompt, settings);
236+
237+
TTableClient tableClient(driver);
238+
TTopicClient topicClient(driver);
239+
NQuery::TQueryClient queryClient(driver);
240+
NCoordination::TClient coordinationClient(driver);
241+
auto remover = NInternal::CreateDefaultRemover(schemeClient, tableClient, topicClient, queryClient, coordinationClient, settings);
242+
return remover(entity.GetEntry());
243+
}
244+
245+
TStatus RemovePathRecursive(
246+
const TDriver& driver,
247+
const TSchemeEntry& entry,
248+
const TRemoveDirectoryRecursiveSettings& settings
249+
) {
250+
TSchemeClient schemeClient(driver);
251+
TTableClient tableClient(driver);
252+
TTopicClient topicClient(driver);
253+
NQuery::TQueryClient queryClient(driver);
254+
NCoordination::TClient coordinationClient(driver);
255+
auto remover = NInternal::CreateDefaultRemover(schemeClient, tableClient, topicClient, queryClient, coordinationClient, settings);
256+
return remover(entry);
257+
}
258+
259+
namespace NInternal {
260+
261+
TRemover CreateDefaultRemover(
262+
NScheme::TSchemeClient& schemeClient,
263+
NTable::TTableClient& tableClient,
264+
NTopic::TTopicClient& topicClient,
265+
NQuery::TQueryClient& queryClient,
266+
NCoordination::TClient& coordinationClient,
267+
const TRemoveDirectoryRecursiveSettings& settings
268+
) {
269+
return [&](const TSchemeEntry& entry) {
270+
return Remove(schemeClient, tableClient, topicClient, queryClient, coordinationClient, entry.Type, TString(entry.Name), settings.Prompt_, settings);
271+
};
242272
}
273+
274+
bool MightHaveDependents(ESchemeEntryType type) {
275+
switch (type) {
276+
// directories might contain external data sources, which might have dependent objects (i.e. external tables)
277+
case ESchemeEntryType::Directory:
278+
case ESchemeEntryType::ExternalDataSource:
279+
return true;
280+
default:
281+
return false;
282+
}
283+
}
284+
243285
}
286+
244287
}

0 commit comments

Comments
 (0)