9
9
#include < ydb/public/lib/ydb_cli/common/retry_func.h>
10
10
#include < ydb/public/lib/ydb_cli/dump/util/util.h>
11
11
12
+ #include < library/cpp/logger/log.h>
13
+
12
14
#include < util/generic/hash.h>
13
15
#include < util/generic/hash_set.h>
14
16
#include < util/generic/maybe.h>
17
19
#include < util/string/builder.h>
18
20
#include < util/string/join.h>
19
21
22
+ #define LOG_IMPL (log, level, message ) \
23
+ if (log.FiltrationLevel() >= level) { \
24
+ log .Write (level, TStringBuilder () << message); \
25
+ } \
26
+ Y_SEMICOLON_GUARD
27
+
28
+ #define LOG_D (message ) LOG_IMPL(Log, ELogPriority::TLOG_DEBUG, message)
29
+ #define LOG_I (message ) LOG_IMPL(Log, ELogPriority::TLOG_INFO, message)
30
+ #define LOG_W (message ) LOG_IMPL(Log, ELogPriority::TLOG_WARN, message)
31
+ #define LOG_E (message ) LOG_IMPL(Log, ELogPriority::TLOG_ERR, message)
32
+
20
33
namespace NYdb {
21
34
namespace NDump {
22
35
@@ -81,37 +94,45 @@ bool IsOperationStarted(TStatus operationStatus) {
81
94
} // anonymous
82
95
83
96
TRestoreClient::TRestoreClient (
97
+ TLog& log,
84
98
TImportClient& importClient,
85
99
TOperationClient& operationClient,
86
100
TSchemeClient& schemeClient,
87
101
TTableClient& tableClient)
88
- : ImportClient(importClient)
102
+ : Log(log)
103
+ , ImportClient(importClient)
89
104
, OperationClient(operationClient)
90
105
, SchemeClient(schemeClient)
91
106
, TableClient(tableClient)
92
107
{
93
108
}
94
109
95
110
TRestoreResult TRestoreClient::Restore (const TString& fsPath, const TString& dbPath, const TRestoreSettings& settings) {
111
+ LOG_I (" Restore from '" << fsPath << " ' to '" << dbPath << " '" );
112
+
96
113
// find existing items
97
114
TFsPath dbBasePath = dbPath;
98
115
99
116
while (true ) {
100
- auto result = DescribePath (SchemeClient, dbBasePath). GetStatus () ;
117
+ auto result = DescribePath (SchemeClient, dbBasePath);
101
118
102
- if (result == EStatus::SUCCESS) {
119
+ if (result. GetStatus () == EStatus::SUCCESS) {
103
120
break ;
104
121
}
105
122
106
- if (result != EStatus::SCHEME_ERROR) {
123
+ if (result.GetStatus () != EStatus::SCHEME_ERROR) {
124
+ LOG_E (" Error finding db base path: " << result.GetIssues ().ToOneLineString ());
107
125
return Result<TRestoreResult>(EStatus::SCHEME_ERROR, " Can not find existing path" );
108
126
}
109
127
110
128
dbBasePath = dbBasePath.Parent ();
111
129
}
112
130
131
+ LOG_D (" Resolved db base path: '" << dbBasePath << " '" );
132
+
113
133
auto oldDirectoryList = RecursiveList (SchemeClient, dbBasePath);
114
134
if (!oldDirectoryList.Status .IsSuccess ()) {
135
+ LOG_E (" Error listing db base path: '" << dbBasePath << " ': " << oldDirectoryList.Status .GetIssues ().ToOneLineString ());
115
136
return Result<TRestoreResult>(EStatus::SCHEME_ERROR, " Can not list existing directory" );
116
137
}
117
138
@@ -122,10 +143,19 @@ TRestoreResult TRestoreClient::Restore(const TString& fsPath, const TString& dbP
122
143
123
144
// restore
124
145
auto restoreResult = RestoreFolder (fsPath, dbPath, settings, oldEntries);
125
- if (restoreResult.IsSuccess () || settings.SavePartialResult_ ) {
146
+ if (restoreResult.IsSuccess ()) {
147
+ LOG_I (" Restore completed successfully" );
126
148
return restoreResult;
127
149
}
128
150
151
+ LOG_E (" Restore failed: " << restoreResult.GetIssues ().ToOneLineString ());
152
+ if (settings.SavePartialResult_ ) {
153
+ LOG_I (" Partial result saved" );
154
+ return restoreResult;
155
+ }
156
+
157
+ LOG_I (" Cleanup" );
158
+
129
159
// cleanup
130
160
auto newDirectoryList = RecursiveList (SchemeClient, dbBasePath);
131
161
if (!newDirectoryList.Status .IsSuccess ()) {
@@ -143,6 +173,7 @@ TRestoreResult TRestoreClient::Restore(const TString& fsPath, const TString& dbP
143
173
case ESchemeEntryType::Directory: {
144
174
auto result = NConsoleClient::RemoveDirectoryRecursive (SchemeClient, TableClient, fullPath, {}, true , false );
145
175
if (!result.IsSuccess ()) {
176
+ LOG_E (" Error removing directory: '" << fullPath << " ': " << result.GetIssues ().ToOneLineString ());
146
177
return restoreResult;
147
178
}
148
179
break ;
@@ -152,11 +183,13 @@ TRestoreResult TRestoreClient::Restore(const TString& fsPath, const TString& dbP
152
183
return session.DropTable (path).GetValueSync ();
153
184
});
154
185
if (!result.IsSuccess ()) {
186
+ LOG_E (" Error removing table: '" << fullPath << " ': " << result.GetIssues ().ToOneLineString ());
155
187
return restoreResult;
156
188
}
157
189
break ;
158
190
}
159
191
default :
192
+ LOG_E (" Error removing unexpected object: '" << fullPath << " '" );
160
193
return restoreResult;
161
194
}
162
195
}
@@ -166,7 +199,9 @@ TRestoreResult TRestoreClient::Restore(const TString& fsPath, const TString& dbP
166
199
167
200
TRestoreResult TRestoreClient::RestoreFolder (const TFsPath& fsPath, const TString& dbPath,
168
201
const TRestoreSettings& settings, const THashSet<TString>& oldEntries)
169
- {
202
+ {
203
+ LOG_D (" Restore folder '" << fsPath << " ' to '" << dbPath << " '" );
204
+
170
205
if (!fsPath) {
171
206
return Result<TRestoreResult>(EStatus::BAD_REQUEST, " Folder is not specified" );
172
207
}
@@ -218,28 +253,37 @@ TRestoreResult TRestoreClient::RestoreFolder(const TFsPath& fsPath, const TStrin
218
253
TRestoreResult TRestoreClient::RestoreTable (const TFsPath& fsPath, const TString& dbPath,
219
254
const TRestoreSettings& settings, const THashSet<TString>& oldEntries)
220
255
{
256
+ LOG_D (" Process '" << fsPath << " '" );
257
+
221
258
if (fsPath.Child (INCOMPLETE_FILE_NAME).Exists ()) {
222
259
return Result<TRestoreResult>(EStatus::BAD_REQUEST,
223
260
TStringBuilder () << " There is incomplete file in folder: " << fsPath.GetPath ());
224
261
}
225
262
263
+ LOG_D (" Read scheme from '" << fsPath.Child (SCHEME_FILE_NAME) << " '" );
226
264
auto scheme = ReadTableScheme (fsPath.Child (SCHEME_FILE_NAME));
227
265
auto dumpedDesc = TableDescriptionFromProto (scheme);
228
266
229
267
if (dumpedDesc.GetAttributes ().contains (DOC_API_TABLE_VERSION_ATTR) && settings.SkipDocumentTables_ ) {
268
+ LOG_I (" Skip document table: '" << fsPath << " '" );
230
269
return Result<TRestoreResult>();
231
270
}
232
271
233
272
if (settings.DryRun_ ) {
234
273
return CheckSchema (dbPath, dumpedDesc);
235
274
}
236
275
276
+ LOG_I (" Restore table '" << fsPath << " ' to '" << dbPath << " '" );
277
+
237
278
auto withoutIndexesDesc = TableDescriptionWithoutIndexesFromProto (scheme);
238
279
auto createResult = TableClient.RetryOperationSync ([&dbPath, &withoutIndexesDesc](TSession session) {
239
280
return session.CreateTable (dbPath, TTableDescription (withoutIndexesDesc),
240
281
TCreateTableSettings ().RequestType (DOC_API_REQUEST_TYPE)).GetValueSync ();
241
282
});
242
- if (!createResult.IsSuccess ()) {
283
+ if (createResult.IsSuccess ()) {
284
+ LOG_D (" Created '" << dbPath << " '" );
285
+ } else {
286
+ LOG_E (" Failed to create '" << dbPath << " '" );
243
287
return Result<TRestoreResult>(dbPath, std::move (createResult));
244
288
}
245
289
@@ -261,6 +305,8 @@ TRestoreResult TRestoreClient::RestoreTable(const TFsPath& fsPath, const TString
261
305
}
262
306
263
307
TRestoreResult TRestoreClient::CheckSchema (const TString& dbPath, const TTableDescription& desc) {
308
+ LOG_I (" Check schema of '" << dbPath << " '" );
309
+
264
310
TMaybe<TTableDescription> actualDesc;
265
311
auto descResult = DescribeTable (TableClient, dbPath, actualDesc);
266
312
if (!descResult.IsSuccess ()) {
@@ -349,23 +395,28 @@ TRestoreResult TRestoreClient::RestoreData(const TFsPath& fsPath, const TString&
349
395
TFsPath dataFile = fsPath.Child (DataFileName (dataFileId));
350
396
351
397
while (dataFile.Exists ()) {
398
+ LOG_D (" Read data from '" << dataFile << " '" );
399
+
352
400
TFileInput input (dataFile, settings.FileBufferSize_ );
353
401
TString line;
354
402
355
403
while (input.ReadLine (line)) {
356
404
while (!accumulator->Fits (line)) {
357
405
if (!accumulator->Ready (true )) {
406
+ LOG_E (" Error reading data from '" << dataFile << " '" );
358
407
return Result<TRestoreResult>(dbPath, EStatus::INTERNAL_ERROR, " Data is not ready" );
359
408
}
360
409
361
410
if (!writer->Push (accumulator->GetData (true ))) {
411
+ LOG_E (" Error writing data to '" << dbPath << " ', file: '" << dataFile << " '" );
362
412
return Result<TRestoreResult>(dbPath, EStatus::GENERIC_ERROR, " Cannot write data #1" );
363
413
}
364
414
}
365
415
366
416
accumulator->Feed (std::move (line));
367
417
if (accumulator->Ready ()) {
368
418
if (!writer->Push (accumulator->GetData ())) {
419
+ LOG_E (" Error writing data to '" << dbPath << " ', file: '" << dataFile << " '" );
369
420
return Result<TRestoreResult>(dbPath, EStatus::GENERIC_ERROR, " Cannot write data #2" );
370
421
}
371
422
}
@@ -376,6 +427,7 @@ TRestoreResult TRestoreClient::RestoreData(const TFsPath& fsPath, const TString&
376
427
377
428
while (accumulator->Ready (true )) {
378
429
if (!writer->Push (accumulator->GetData (true ))) {
430
+ LOG_E (" Error writing data to '" << dbPath << " ', file: '" << dataFile << " '" );
379
431
return Result<TRestoreResult>(dbPath, EStatus::GENERIC_ERROR, " Cannot write data #3" );
380
432
}
381
433
}
@@ -395,6 +447,8 @@ TRestoreResult TRestoreClient::RestoreIndexes(const TString& dbPath, const TTabl
395
447
continue ;
396
448
}
397
449
450
+ LOG_D (" Build index '" << index .GetIndexName () << " ' on '" << dbPath << " '" );
451
+
398
452
TOperation::TOperationId buildIndexId;
399
453
auto buildIndexStatus = TableClient.RetryOperationSync ([&, &outId = buildIndexId](TSession session) {
400
454
auto settings = TAlterTableSettings ().AppendAddIndexes (index );
@@ -406,18 +460,21 @@ TRestoreResult TRestoreClient::RestoreIndexes(const TString& dbPath, const TTabl
406
460
});
407
461
408
462
if (!IsOperationStarted (buildIndexStatus)) {
463
+ LOG_E (" Error building index '" << index .GetIndexName () << " ' on '" << dbPath << " '" );
409
464
return Result<TRestoreResult>(dbPath, std::move (buildIndexStatus));
410
465
}
411
466
412
467
auto waitForIndexBuildStatus = WaitForIndexBuild (OperationClient, buildIndexId);
413
468
if (!waitForIndexBuildStatus.IsSuccess ()) {
469
+ LOG_E (" Error building index '" << index .GetIndexName () << " ' on '" << dbPath << " '" );
414
470
return Result<TRestoreResult>(dbPath, std::move (waitForIndexBuildStatus));
415
471
}
416
472
417
473
auto forgetStatus = NConsoleClient::RetryFunction ([&]() {
418
474
return OperationClient.Forget (buildIndexId).GetValueSync ();
419
475
});
420
476
if (!forgetStatus.IsSuccess ()) {
477
+ LOG_E (" Error building index '" << index .GetIndexName () << " ' on '" << dbPath << " '" );
421
478
return Result<TRestoreResult>(dbPath, std::move (forgetStatus));
422
479
}
423
480
}
@@ -445,18 +502,24 @@ TRestoreResult TRestoreClient::RestorePermissions(const TFsPath& fsPath, const T
445
502
return Result<TRestoreResult>();
446
503
}
447
504
505
+ LOG_D (" Restore permissions to '" << dbPath << " '" );
506
+
448
507
auto permissions = ReadPermissions (fsPath.Child (PERMISSIONS_FILE_NAME));
449
508
return ModifyPermissions (SchemeClient, dbPath, TModifyPermissionsSettings (permissions));
450
509
}
451
510
452
- TRestoreResult TRestoreClient::RestoreEmptyDir (const TFsPath& fsPath, const TString & dbPath,
511
+ TRestoreResult TRestoreClient::RestoreEmptyDir (const TFsPath& fsPath, const TString& dbPath,
453
512
const TRestoreSettings& settings, const THashSet<TString>& oldEntries)
454
513
{
514
+ LOG_D (" Process '" << fsPath << " '" );
515
+
455
516
if (fsPath.Child (INCOMPLETE_FILE_NAME).Exists ()) {
456
517
return Result<TRestoreResult>(EStatus::BAD_REQUEST,
457
518
TStringBuilder () << " There is incomplete file in folder: " << fsPath.GetPath ());
458
519
}
459
520
521
+ LOG_I (" Restore empty directory '" << fsPath << " ' to '" << dbPath << " '" );
522
+
460
523
auto result = MakeDirectory (SchemeClient, dbPath);
461
524
if (!result.IsSuccess ()) {
462
525
return result;
0 commit comments