@@ -30,6 +30,7 @@ namespace NYdb::NBackup {
30
30
31
31
32
32
static constexpr const char *SCHEME_FILE_NAME = " scheme.pb" ;
33
+ static constexpr const char *PERMISSIONS_FILE_NAME = " permissions.pb" ;
33
34
static constexpr const char *INCOMPLETE_DATA_FILE_NAME = " incomplete.csv" ;
34
35
static constexpr const char *INCOMPLETE_FILE_NAME = " incomplete" ;
35
36
static constexpr const char *EMPTY_FILE_NAME = " empty_dir" ;
@@ -429,6 +430,16 @@ Ydb::Table::CreateTableRequest ProtoFromTableDescription(const NTable::TTableDes
429
430
return proto;
430
431
}
431
432
433
+ NScheme::TSchemeEntry DescribePath (TDriver driver, const TString& fullPath) {
434
+ NScheme::TSchemeClient client (driver);
435
+
436
+ auto status = client.DescribePath (fullPath).GetValueSync ();
437
+ VerifyStatus (status);
438
+ LOG_DEBUG (" Path is described, fullPath: " << fullPath);
439
+
440
+ return status.GetEntry ();
441
+ }
442
+
432
443
TAsyncStatus CopyTableAsyncStart (TDriver driver, const TString& src, const TString& dst) {
433
444
NTable::TTableClient client (driver);
434
445
@@ -480,6 +491,19 @@ void DropTable(TDriver driver, const TString& path) {
480
491
LOG_DEBUG (" Table is dropped, path: " << path.Quote ());
481
492
}
482
493
494
+ void BackupPermissions (TDriver driver, const TString& dbPrefix, const TString& path, const TFsPath& folderPath) {
495
+ auto entry = DescribePath (driver, JoinDatabasePath (dbPrefix, path));
496
+ Ydb::Scheme::ModifyPermissionsRequest proto;
497
+ entry.SerializeTo (proto);
498
+
499
+ TString permissionsStr;
500
+ google::protobuf::TextFormat::PrintToString (proto, &permissionsStr);
501
+ LOG_DEBUG (" ModifyPermissionsRequest.proto: " << permissionsStr);
502
+
503
+ TFile outFile (folderPath.Child (PERMISSIONS_FILE_NAME), CreateAlways | WrOnly);
504
+ outFile.Write (permissionsStr.data (), permissionsStr.size ());
505
+ }
506
+
483
507
void BackupTable (TDriver driver, const TString& dbPrefix, const TString& backupPrefix, const TString& path,
484
508
const TFsPath& folderPath, bool schemaOnly, bool preservePoolKinds, bool ordered) {
485
509
Y_ENSURE (!path.empty ());
@@ -497,6 +521,8 @@ void BackupTable(TDriver driver, const TString& dbPrefix, const TString& backupP
497
521
TFile outFile (folderPath.Child (SCHEME_FILE_NAME), CreateAlways | WrOnly);
498
522
outFile.Write (schemaStr.data (), schemaStr.size ());
499
523
524
+ BackupPermissions (driver, dbPrefix, path, folderPath);
525
+
500
526
if (!schemaOnly) {
501
527
const TString pathToTemporal = JoinDatabasePath (backupPrefix, path);
502
528
ReadTable (driver, desc, pathToTemporal, folderPath, ordered);
@@ -535,6 +561,14 @@ static bool IsExcluded(const TString& path, const TVector<TRegExMatch>& exclusio
535
561
return false ;
536
562
}
537
563
564
+ static void MaybeCreateEmptyFile (const TFsPath& folderPath) {
565
+ TVector<TString> children;
566
+ folderPath.ListNames (children);
567
+ if (children.empty () || (children.size () == 1 && children[0 ] == INCOMPLETE_FILE_NAME)) {
568
+ TFile (folderPath.Child (EMPTY_FILE_NAME), CreateAlways);
569
+ }
570
+ }
571
+
538
572
void BackupFolderImpl (TDriver driver, const TString& dbPrefix, const TString& backupPrefix, TString path,
539
573
const TFsPath folderPath, const TVector<TRegExMatch>& exclusionPatterns,
540
574
bool schemaOnly, bool useConsistentCopyTable, bool avoidCopy, bool preservePoolKinds, bool ordered) {
@@ -562,6 +596,9 @@ void BackupFolderImpl(TDriver driver, const TString& dbPrefix, const TString& ba
562
596
BackupTable (driver, dbIt.GetTraverseRoot (), backupPrefix, dbIt.GetRelPath (),
563
597
childFolderPath, schemaOnly, preservePoolKinds, ordered);
564
598
childFolderPath.Child (INCOMPLETE_FILE_NAME).DeleteIfExists ();
599
+ } else if (dbIt.IsDir ()) {
600
+ BackupPermissions (driver, dbIt.GetTraverseRoot (), dbIt.GetRelPath (), childFolderPath);
601
+ childFolderPath.Child (INCOMPLETE_FILE_NAME).DeleteIfExists ();
565
602
}
566
603
} else if (!avoidCopy) {
567
604
if (dbIt.IsTable ()) {
@@ -594,13 +631,7 @@ void BackupFolderImpl(TDriver driver, const TString& dbPrefix, const TString& ba
594
631
// so control flow can't reach this line. Check it just to be sure
595
632
Y_ENSURE (!childFolderPath.Child (INCOMPLETE_FILE_NAME).Exists ());
596
633
} else if (dbIt.IsDir ()) {
597
- childFolderPath.Child (INCOMPLETE_FILE_NAME).DeleteIfExists ();
598
-
599
- TVector<TString> children;
600
- childFolderPath.ListNames (children);
601
- if (children.empty ()) {
602
- TFile (childFolderPath.Child (EMPTY_FILE_NAME), CreateAlways);
603
- }
634
+ MaybeCreateEmptyFile (childFolderPath);
604
635
}
605
636
606
637
childFolderPath.Child (INCOMPLETE_FILE_NAME).DeleteIfExists ();
@@ -639,14 +670,8 @@ void BackupFolderImpl(TDriver driver, const TString& dbPrefix, const TString& ba
639
670
DropTable (driver, tmpTablePath);
640
671
}
641
672
} else if (dbIt.IsDir ()) {
642
- childFolderPath.Child (INCOMPLETE_FILE_NAME).DeleteIfExists ();
643
-
644
- TVector<TString> children;
645
- childFolderPath.ListNames (children);
646
- if (children.empty ()) {
647
- TFile (childFolderPath.Child (EMPTY_FILE_NAME), CreateAlways);
648
- }
649
-
673
+ BackupPermissions (driver, dbIt.GetTraverseRoot (), dbIt.GetRelPath (), childFolderPath);
674
+ MaybeCreateEmptyFile (childFolderPath);
650
675
if (!avoidCopy) {
651
676
RemoveClusterDirectory (driver, tmpTablePath);
652
677
}
0 commit comments