4
4
5
5
#include < ydb/public/api/protos/ydb_table.pb.h>
6
6
#include < ydb/public/sdk/cpp/client/ydb_proto/accessor.h>
7
+ #include < ydb/public/lib/ydb_cli/common/recursive_list.h>
7
8
#include < ydb/public/lib/ydb_cli/common/recursive_remove.h>
8
9
#include < ydb/public/lib/ydb_cli/common/retry_func.h>
9
10
#include < ydb/public/lib/ydb_cli/dump/util/util.h>
19
20
namespace NYdb {
20
21
namespace NDump {
21
22
23
+ using namespace NConsoleClient ;
22
24
using namespace NImport ;
23
25
using namespace NOperation ;
24
26
using namespace NScheme ;
@@ -43,6 +45,12 @@ TTableDescription TableDescriptionFromProto(const Ydb::Table::CreateTableRequest
43
45
return TProtoAccessor::FromProto (proto);
44
46
}
45
47
48
+ Ydb::Scheme::ModifyPermissionsRequest ReadPermissions (const TString& fsPath) {
49
+ Ydb::Scheme::ModifyPermissionsRequest proto;
50
+ Y_ENSURE (google::protobuf::TextFormat::ParseFromString (TFileInput (fsPath).ReadAll (), &proto));
51
+ return proto;
52
+ }
53
+
46
54
bool HasRunningIndexBuilds (TOperationClient& client, const TString& dbPath) {
47
55
const ui64 pageSize = 100 ;
48
56
TString pageToken;
@@ -131,34 +139,34 @@ TRestoreResult TRestoreClient::Restore(const TString& fsPath, const TString& dbP
131
139
dbBasePath = dbBasePath.Parent ();
132
140
}
133
141
134
- auto oldDirectoryList = SchemeClient. ListDirectory ( dbBasePath). GetValueSync ( );
135
- if (!oldDirectoryList.IsSuccess ()) {
142
+ auto oldDirectoryList = RecursiveList (SchemeClient, dbBasePath);
143
+ if (!oldDirectoryList.Status . IsSuccess ()) {
136
144
return Result<TRestoreResult>(EStatus::SCHEME_ERROR, " Can not list existing directory" );
137
145
}
138
146
139
147
THashSet<TString> oldEntries;
140
- for (const auto & entry : oldDirectoryList.GetChildren () ) {
148
+ for (const auto & entry : oldDirectoryList.Entries ) {
141
149
oldEntries.insert (entry.Name );
142
150
}
143
151
144
152
// restore
145
- auto restoreResult = RestoreFolder (fsPath, dbPath, settings);
153
+ auto restoreResult = RestoreFolder (fsPath, dbPath, settings, oldEntries );
146
154
if (restoreResult.IsSuccess () || settings.SavePartialResult_ ) {
147
155
return restoreResult;
148
156
}
149
157
150
158
// cleanup
151
- auto newDirectoryList = SchemeClient. ListDirectory ( dbBasePath). GetValueSync ( );
152
- if (!newDirectoryList.IsSuccess ()) {
159
+ auto newDirectoryList = RecursiveList (SchemeClient, dbBasePath);
160
+ if (!newDirectoryList.Status . IsSuccess ()) {
153
161
return restoreResult;
154
162
}
155
163
156
- for (const auto & entry : newDirectoryList.GetChildren () ) {
164
+ for (const auto & entry : newDirectoryList.Entries ) {
157
165
if (oldEntries.contains (entry.Name )) {
158
166
continue ;
159
167
}
160
168
161
- auto fullPath = dbBasePath. Child ( entry.Name );
169
+ const auto & fullPath = entry.Name ; // RecursiveList returns full path instead of entry's name
162
170
163
171
switch (entry.Type ) {
164
172
case ESchemeEntryType::Directory: {
@@ -185,7 +193,9 @@ TRestoreResult TRestoreClient::Restore(const TString& fsPath, const TString& dbP
185
193
return restoreResult;
186
194
}
187
195
188
- TRestoreResult TRestoreClient::RestoreFolder (const TFsPath& fsPath, const TString& dbPath, const TRestoreSettings& settings) {
196
+ TRestoreResult TRestoreClient::RestoreFolder (const TFsPath& fsPath, const TString& dbPath,
197
+ const TRestoreSettings& settings, const THashSet<TString>& oldEntries)
198
+ {
189
199
if (!fsPath) {
190
200
return Result<TRestoreResult>(EStatus::BAD_REQUEST, " Folder is not specified" );
191
201
}
@@ -206,11 +216,11 @@ TRestoreResult TRestoreClient::RestoreFolder(const TFsPath& fsPath, const TStrin
206
216
}
207
217
208
218
if (IsFileExists (fsPath.Child (SCHEME_FILE_NAME))) {
209
- return RestoreTable (fsPath, Join (' /' , dbPath, fsPath.GetName ()), settings);
219
+ return RestoreTable (fsPath, Join (' /' , dbPath, fsPath.GetName ()), settings, oldEntries );
210
220
}
211
221
212
222
if (IsFileExists (fsPath.Child (EMPTY_FILE_NAME))) {
213
- return MakeDirectory (SchemeClient , Join (' /' , dbPath, fsPath.GetName ()));
223
+ return RestoreEmptyDir (fsPath , Join (' /' , dbPath, fsPath.GetName ()), settings, oldEntries );
214
224
}
215
225
216
226
TMaybe<TRestoreResult> result;
@@ -219,26 +229,24 @@ TRestoreResult TRestoreClient::RestoreFolder(const TFsPath& fsPath, const TStrin
219
229
fsPath.List (children);
220
230
for (const auto & child : children) {
221
231
if (IsFileExists (child.Child (SCHEME_FILE_NAME))) {
222
- result = RestoreTable (child, Join (' /' , dbPath, child.GetName ()), settings);
232
+ result = RestoreTable (child, Join (' /' , dbPath, child.GetName ()), settings, oldEntries );
223
233
} else if (IsFileExists (child.Child (EMPTY_FILE_NAME))) {
224
- result = MakeDirectory (SchemeClient , Join (' /' , dbPath, child.GetName ()));
225
- } else {
226
- result = RestoreFolder (child, Join (' /' , dbPath, child.GetName ()), settings);
234
+ result = RestoreEmptyDir (child , Join (' /' , dbPath, child.GetName ()), settings, oldEntries );
235
+ } else if (child. IsDirectory ()) {
236
+ result = RestoreFolder (child, Join (' /' , dbPath, child.GetName ()), settings, oldEntries );
227
237
}
228
238
229
- if (!result->IsSuccess ()) {
239
+ if (result. Defined () && !result->IsSuccess ()) {
230
240
return *result;
231
241
}
232
242
}
233
-
234
- if (!result) {
235
- return Result<TRestoreResult>();
236
- }
237
-
238
- return *result;
243
+
244
+ return RestorePermissions (fsPath, dbPath, settings, oldEntries);
239
245
}
240
246
241
- TRestoreResult TRestoreClient::RestoreTable (const TFsPath& fsPath, const TString& dbPath, const TRestoreSettings& settings) {
247
+ TRestoreResult TRestoreClient::RestoreTable (const TFsPath& fsPath, const TString& dbPath,
248
+ const TRestoreSettings& settings, const THashSet<TString>& oldEntries)
249
+ {
242
250
if (fsPath.Child (INCOMPLETE_FILE_NAME).Exists ()) {
243
251
return Result<TRestoreResult>(EStatus::BAD_REQUEST,
244
252
TStringBuilder () << " There is incomplete file in folder: " << fsPath.GetPath ());
@@ -268,7 +276,7 @@ TRestoreResult TRestoreClient::RestoreTable(const TFsPath& fsPath, const TString
268
276
}
269
277
}
270
278
271
- return Result<TRestoreResult>( );
279
+ return RestorePermissions (fsPath, dbPath, settings, oldEntries );
272
280
}
273
281
274
282
TRestoreResult TRestoreClient::CheckSchema (const TString& dbPath, const TTableDescription& desc) {
@@ -444,5 +452,45 @@ TRestoreResult TRestoreClient::RestoreIndexes(const TString& dbPath, const TTabl
444
452
return Result<TRestoreResult>();
445
453
}
446
454
455
+ TRestoreResult TRestoreClient::RestorePermissions (const TFsPath& fsPath, const TString& dbPath,
456
+ const TRestoreSettings& settings, const THashSet<TString>& oldEntries)
457
+ {
458
+ if (fsPath.Child (INCOMPLETE_FILE_NAME).Exists ()) {
459
+ return Result<TRestoreResult>(EStatus::BAD_REQUEST,
460
+ TStringBuilder () << " There is incomplete file in folder: " << fsPath.GetPath ());
461
+ }
462
+
463
+ if (!settings.RestoreACL_ ) {
464
+ return Result<TRestoreResult>();
465
+ }
466
+
467
+ if (oldEntries.contains (dbPath)) {
468
+ return Result<TRestoreResult>();
469
+ }
470
+
471
+ if (!fsPath.Child (PERMISSIONS_FILE_NAME).Exists ()) {
472
+ return Result<TRestoreResult>();
473
+ }
474
+
475
+ auto permissions = ReadPermissions (fsPath.Child (PERMISSIONS_FILE_NAME));
476
+ return ModifyPermissions (SchemeClient, dbPath, TModifyPermissionsSettings (permissions));
477
+ }
478
+
479
+ TRestoreResult TRestoreClient::RestoreEmptyDir (const TFsPath& fsPath, const TString &dbPath,
480
+ const TRestoreSettings& settings, const THashSet<TString>& oldEntries)
481
+ {
482
+ if (fsPath.Child (INCOMPLETE_FILE_NAME).Exists ()) {
483
+ return Result<TRestoreResult>(EStatus::BAD_REQUEST,
484
+ TStringBuilder () << " There is incomplete file in folder: " << fsPath.GetPath ());
485
+ }
486
+
487
+ auto result = MakeDirectory (SchemeClient, dbPath);
488
+ if (!result.IsSuccess ()) {
489
+ return result;
490
+ }
491
+
492
+ return RestorePermissions (fsPath, dbPath, settings, oldEntries);
493
+ }
494
+
447
495
} // NDump
448
496
} // NYdb
0 commit comments