@@ -87,7 +87,8 @@ void BackupableDBOptions::Dump(Logger* logger) const {
87
87
// -------- BackupEngineImpl class ---------
88
88
class BackupEngineImpl : public BackupEngine {
89
89
public:
90
- BackupEngineImpl (Env* db_env, const BackupableDBOptions& options);
90
+ BackupEngineImpl (Env* db_env, const BackupableDBOptions& options,
91
+ bool read_only = false );
91
92
~BackupEngineImpl ();
92
93
Status CreateNewBackup (DB* db, bool flush_before_backup = false );
93
94
Status PurgeOldBackups (uint32_t num_backups_to_keep);
@@ -149,7 +150,7 @@ class BackupEngineImpl : public BackupEngine {
149
150
150
151
Status AddFile (const FileInfo& file_info);
151
152
152
- void Delete ();
153
+ void Delete (bool delete_meta = true );
153
154
154
155
bool Empty () {
155
156
return files_.empty ();
@@ -258,6 +259,7 @@ class BackupEngineImpl : public BackupEngine {
258
259
259
260
static const size_t kDefaultCopyFileBufferSize = 5 * 1024 * 1024LL ; // 5MB
260
261
size_t copy_file_buffer_size_;
262
+ bool read_only_;
261
263
};
262
264
263
265
BackupEngine* BackupEngine::NewBackupEngine (
@@ -266,27 +268,34 @@ BackupEngine* BackupEngine::NewBackupEngine(
266
268
}
267
269
268
270
BackupEngineImpl::BackupEngineImpl (Env* db_env,
269
- const BackupableDBOptions& options)
271
+ const BackupableDBOptions& options,
272
+ bool read_only)
270
273
: stop_backup_(false ),
271
274
options_(options),
272
275
db_env_(db_env),
273
276
backup_env_(options.backup_env != nullptr ? options.backup_env : db_env_),
274
- copy_file_buffer_size_(kDefaultCopyFileBufferSize ) {
277
+ copy_file_buffer_size_(kDefaultCopyFileBufferSize ),
278
+ read_only_(read_only) {
279
+ if (read_only_) {
280
+ Log (options_.info_log , " Starting read_only backup engine" );
281
+ }
275
282
options_.Dump (options_.info_log );
276
283
277
- // create all the dirs we need
278
- backup_env_->CreateDirIfMissing (GetAbsolutePath ());
279
- backup_env_->NewDirectory (GetAbsolutePath (), &backup_directory_);
280
- if (options_.share_table_files ) {
281
- backup_env_->CreateDirIfMissing (GetAbsolutePath (GetSharedFileRel ()));
282
- backup_env_->NewDirectory (GetAbsolutePath (GetSharedFileRel ()),
283
- &shared_directory_);
284
+ if (!read_only_) {
285
+ // create all the dirs we need
286
+ backup_env_->CreateDirIfMissing (GetAbsolutePath ());
287
+ backup_env_->NewDirectory (GetAbsolutePath (), &backup_directory_);
288
+ if (options_.share_table_files ) {
289
+ backup_env_->CreateDirIfMissing (GetAbsolutePath (GetSharedFileRel ()));
290
+ backup_env_->NewDirectory (GetAbsolutePath (GetSharedFileRel ()),
291
+ &shared_directory_);
292
+ }
293
+ backup_env_->CreateDirIfMissing (GetAbsolutePath (GetPrivateDirRel ()));
294
+ backup_env_->NewDirectory (GetAbsolutePath (GetPrivateDirRel ()),
295
+ &private_directory_);
296
+ backup_env_->CreateDirIfMissing (GetBackupMetaDir ());
297
+ backup_env_->NewDirectory (GetBackupMetaDir (), &meta_directory_);
284
298
}
285
- backup_env_->CreateDirIfMissing (GetAbsolutePath (GetPrivateDirRel ()));
286
- backup_env_->NewDirectory (GetAbsolutePath (GetPrivateDirRel ()),
287
- &private_directory_);
288
- backup_env_->CreateDirIfMissing (GetBackupMetaDir ());
289
- backup_env_->NewDirectory (GetBackupMetaDir (), &meta_directory_);
290
299
291
300
std::vector<std::string> backup_meta_files;
292
301
backup_env_->GetChildren (GetBackupMetaDir (), &backup_meta_files);
@@ -295,8 +304,10 @@ BackupEngineImpl::BackupEngineImpl(Env* db_env,
295
304
BackupID backup_id = 0 ;
296
305
sscanf (file.c_str (), " %u" , &backup_id);
297
306
if (backup_id == 0 || file != std::to_string (backup_id)) {
298
- // invalid file name, delete that
299
- backup_env_->DeleteFile (GetBackupMetaDir () + " /" + file);
307
+ if (!read_only_) {
308
+ // invalid file name, delete that
309
+ backup_env_->DeleteFile (GetBackupMetaDir () + " /" + file);
310
+ }
300
311
continue ;
301
312
}
302
313
assert (backups_.find (backup_id) == backups_.end ());
@@ -306,6 +317,7 @@ BackupEngineImpl::BackupEngineImpl(Env* db_env,
306
317
}
307
318
308
319
if (options_.destroy_old_data ) { // Destory old data
320
+ assert (!read_only_);
309
321
for (auto & backup : backups_) {
310
322
backup.second .Delete ();
311
323
obsolete_backups_.push_back (backup.first );
@@ -319,9 +331,12 @@ BackupEngineImpl::BackupEngineImpl(Env* db_env,
319
331
for (auto & backup : backups_) {
320
332
Status s = backup.second .LoadFromFile (options_.backup_dir );
321
333
if (!s.ok ()) {
322
- Log (options_.info_log , " Backup %u corrupted - deleting -- %s" ,
323
- backup.first , s.ToString ().c_str ());
324
- backup.second .Delete ();
334
+ Log (options_.info_log , " Backup %u corrupted -- %s" , backup.first ,
335
+ s.ToString ().c_str ());
336
+ if (!read_only_) {
337
+ Log (options_.info_log , " -> Deleting backup %u" , backup.first );
338
+ }
339
+ backup.second .Delete (!read_only_);
325
340
obsolete_backups_.push_back (backup.first );
326
341
}
327
342
}
@@ -331,6 +346,7 @@ BackupEngineImpl::BackupEngineImpl(Env* db_env,
331
346
}
332
347
333
348
Status s = GetLatestBackupFileContents (&latest_backup_id_);
349
+
334
350
// If latest backup file is corrupted or non-existent
335
351
// set latest backup as the biggest backup we have
336
352
// or 0 if we have no backups
@@ -349,16 +365,18 @@ BackupEngineImpl::BackupEngineImpl(Env* db_env,
349
365
itr = backups_.erase (itr);
350
366
}
351
367
352
- PutLatestBackupFileContents (latest_backup_id_); // Ignore errors
353
- GarbageCollection (true );
354
- Log (options_.info_log ,
355
- " Initialized BackupEngine, the latest backup is %u." ,
368
+ if (!read_only_) {
369
+ PutLatestBackupFileContents (latest_backup_id_); // Ignore errors
370
+ GarbageCollection (true );
371
+ }
372
+ Log (options_.info_log , " Initialized BackupEngine, the latest backup is %u." ,
356
373
latest_backup_id_);
357
374
}
358
375
359
376
BackupEngineImpl::~BackupEngineImpl () { LogFlush (options_.info_log ); }
360
377
361
378
Status BackupEngineImpl::CreateNewBackup (DB* db, bool flush_before_backup) {
379
+ assert (!read_only_);
362
380
Status s;
363
381
std::vector<std::string> live_files;
364
382
VectorLogPtr live_wal_files;
@@ -499,6 +517,7 @@ Status BackupEngineImpl::CreateNewBackup(DB* db, bool flush_before_backup) {
499
517
}
500
518
501
519
Status BackupEngineImpl::PurgeOldBackups (uint32_t num_backups_to_keep) {
520
+ assert (!read_only_);
502
521
Log (options_.info_log , " Purging old backups, keeping %u" ,
503
522
num_backups_to_keep);
504
523
while (num_backups_to_keep < backups_.size ()) {
@@ -512,6 +531,7 @@ Status BackupEngineImpl::PurgeOldBackups(uint32_t num_backups_to_keep) {
512
531
}
513
532
514
533
Status BackupEngineImpl::DeleteBackup (BackupID backup_id) {
534
+ assert (!read_only_);
515
535
Log (options_.info_log , " Deleting backup %u" , backup_id);
516
536
auto backup = backups_.find (backup_id);
517
537
if (backup == backups_.end ()) {
@@ -662,6 +682,7 @@ Status BackupEngineImpl::GetLatestBackupFileContents(uint32_t* latest_backup) {
662
682
// do something like 1. delete file, 2. write new file
663
683
// We write to a tmp file and then atomically rename
664
684
Status BackupEngineImpl::PutLatestBackupFileContents (uint32_t latest_backup) {
685
+ assert (!read_only_);
665
686
Status s;
666
687
unique_ptr<WritableFile> file;
667
688
EnvOptions env_options;
@@ -871,6 +892,7 @@ void BackupEngineImpl::DeleteChildren(const std::string& dir,
871
892
}
872
893
873
894
void BackupEngineImpl::GarbageCollection (bool full_scan) {
895
+ assert (!read_only_);
874
896
Log (options_.info_log , " Starting garbage collection" );
875
897
std::vector<std::string> to_delete;
876
898
for (auto & itr : backuped_file_infos_) {
@@ -973,15 +995,17 @@ Status BackupEngineImpl::BackupMeta::AddFile(const FileInfo& file_info) {
973
995
return Status::OK ();
974
996
}
975
997
976
- void BackupEngineImpl::BackupMeta::Delete () {
998
+ void BackupEngineImpl::BackupMeta::Delete (bool delete_meta ) {
977
999
for (const auto & file : files_) {
978
1000
auto itr = file_infos_->find (file);
979
1001
assert (itr != file_infos_->end ());
980
1002
--(itr->second .refs ); // decrease refcount
981
1003
}
982
1004
files_.clear ();
983
1005
// delete meta file
984
- env_->DeleteFile (meta_filename_);
1006
+ if (delete_meta) {
1007
+ env_->DeleteFile (meta_filename_);
1008
+ }
985
1009
timestamp_ = 0 ;
986
1010
}
987
1011
@@ -1107,6 +1131,45 @@ Status BackupEngineImpl::BackupMeta::StoreToFile(bool sync) {
1107
1131
return s;
1108
1132
}
1109
1133
1134
+ // -------- BackupEngineReadOnlyImpl ---------
1135
+ class BackupEngineReadOnlyImpl : public BackupEngineReadOnly {
1136
+ public:
1137
+ BackupEngineReadOnlyImpl (Env* db_env, const BackupableDBOptions& options) {
1138
+ backup_engine_ = new BackupEngineImpl (db_env, options, true );
1139
+ }
1140
+ virtual ~BackupEngineReadOnlyImpl () {}
1141
+
1142
+ virtual void GetBackupInfo (std::vector<BackupInfo>* backup_info) {
1143
+ backup_engine_->GetBackupInfo (backup_info);
1144
+ }
1145
+
1146
+ virtual Status RestoreDBFromBackup (
1147
+ BackupID backup_id, const std::string& db_dir, const std::string& wal_dir,
1148
+ const RestoreOptions& restore_options = RestoreOptions()) {
1149
+ return backup_engine_->RestoreDBFromBackup (backup_id, db_dir, wal_dir,
1150
+ restore_options);
1151
+ }
1152
+
1153
+ virtual Status RestoreDBFromLatestBackup (
1154
+ const std::string& db_dir, const std::string& wal_dir,
1155
+ const RestoreOptions& restore_options = RestoreOptions()) {
1156
+ return backup_engine_->RestoreDBFromLatestBackup (db_dir, wal_dir,
1157
+ restore_options);
1158
+ }
1159
+
1160
+ private:
1161
+ BackupEngineImpl* backup_engine_;
1162
+ };
1163
+
1164
+ BackupEngineReadOnly* BackupEngineReadOnly::NewReadOnlyBackupEngine (
1165
+ Env* db_env, const BackupableDBOptions& options) {
1166
+ if (options.destroy_old_data ) {
1167
+ assert (false );
1168
+ return nullptr ;
1169
+ }
1170
+ return new BackupEngineReadOnlyImpl (db_env, options);
1171
+ }
1172
+
1110
1173
// --- BackupableDB methods --------
1111
1174
1112
1175
BackupableDB::BackupableDB (DB* db, const BackupableDBOptions& options)
0 commit comments