backupable_db_test.cc 64 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863
  1. // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
  2. // This source code is licensed under both the GPLv2 (found in the
  3. // COPYING file in the root directory) and Apache 2.0 License
  4. // (found in the LICENSE.Apache file in the root directory).
  5. //
  6. // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
  7. // Use of this source code is governed by a BSD-style license that can be
  8. // found in the LICENSE file. See the AUTHORS file for names of contributors.
  9. #if !defined(ROCKSDB_LITE) && !defined(OS_WIN)
  10. #include <algorithm>
  11. #include <limits>
  12. #include <string>
  13. #include <utility>
  14. #include "db/db_impl/db_impl.h"
  15. #include "env/env_chroot.h"
  16. #include "file/filename.h"
  17. #include "port/port.h"
  18. #include "port/stack_trace.h"
  19. #include "rocksdb/rate_limiter.h"
  20. #include "rocksdb/transaction_log.h"
  21. #include "rocksdb/types.h"
  22. #include "rocksdb/utilities/backupable_db.h"
  23. #include "rocksdb/utilities/options_util.h"
  24. #include "test_util/sync_point.h"
  25. #include "test_util/testharness.h"
  26. #include "test_util/testutil.h"
  27. #include "util/mutexlock.h"
  28. #include "util/random.h"
  29. #include "util/stderr_logger.h"
  30. #include "util/string_util.h"
  31. namespace ROCKSDB_NAMESPACE {
  32. namespace {
  33. class DummyDB : public StackableDB {
  34. public:
  35. /* implicit */
  36. DummyDB(const Options& options, const std::string& dbname)
  37. : StackableDB(nullptr), options_(options), dbname_(dbname),
  38. deletions_enabled_(true), sequence_number_(0) {}
  39. SequenceNumber GetLatestSequenceNumber() const override {
  40. return ++sequence_number_;
  41. }
  42. const std::string& GetName() const override { return dbname_; }
  43. Env* GetEnv() const override { return options_.env; }
  44. using DB::GetOptions;
  45. Options GetOptions(ColumnFamilyHandle* /*column_family*/) const override {
  46. return options_;
  47. }
  48. DBOptions GetDBOptions() const override { return DBOptions(options_); }
  49. Status EnableFileDeletions(bool /*force*/) override {
  50. EXPECT_TRUE(!deletions_enabled_);
  51. deletions_enabled_ = true;
  52. return Status::OK();
  53. }
  54. Status DisableFileDeletions() override {
  55. EXPECT_TRUE(deletions_enabled_);
  56. deletions_enabled_ = false;
  57. return Status::OK();
  58. }
  59. Status GetLiveFiles(std::vector<std::string>& vec, uint64_t* mfs,
  60. bool /*flush_memtable*/ = true) override {
  61. EXPECT_TRUE(!deletions_enabled_);
  62. vec = live_files_;
  63. *mfs = 100;
  64. return Status::OK();
  65. }
  66. ColumnFamilyHandle* DefaultColumnFamily() const override { return nullptr; }
  67. class DummyLogFile : public LogFile {
  68. public:
  69. /* implicit */
  70. DummyLogFile(const std::string& path, bool alive = true)
  71. : path_(path), alive_(alive) {}
  72. std::string PathName() const override { return path_; }
  73. uint64_t LogNumber() const override {
  74. // what business do you have calling this method?
  75. ADD_FAILURE();
  76. return 0;
  77. }
  78. WalFileType Type() const override {
  79. return alive_ ? kAliveLogFile : kArchivedLogFile;
  80. }
  81. SequenceNumber StartSequence() const override {
  82. // this seqnum guarantees the dummy file will be included in the backup
  83. // as long as it is alive.
  84. return kMaxSequenceNumber;
  85. }
  86. uint64_t SizeFileBytes() const override { return 0; }
  87. private:
  88. std::string path_;
  89. bool alive_;
  90. }; // DummyLogFile
  91. Status GetSortedWalFiles(VectorLogPtr& files) override {
  92. EXPECT_TRUE(!deletions_enabled_);
  93. files.resize(wal_files_.size());
  94. for (size_t i = 0; i < files.size(); ++i) {
  95. files[i].reset(
  96. new DummyLogFile(wal_files_[i].first, wal_files_[i].second));
  97. }
  98. return Status::OK();
  99. }
  100. // To avoid FlushWAL called on stacked db which is nullptr
  101. Status FlushWAL(bool /*sync*/) override { return Status::OK(); }
  102. std::vector<std::string> live_files_;
  103. // pair<filename, alive?>
  104. std::vector<std::pair<std::string, bool>> wal_files_;
  105. private:
  106. Options options_;
  107. std::string dbname_;
  108. bool deletions_enabled_;
  109. mutable SequenceNumber sequence_number_;
  110. }; // DummyDB
  111. class TestEnv : public EnvWrapper {
  112. public:
  113. explicit TestEnv(Env* t) : EnvWrapper(t) {}
  114. class DummySequentialFile : public SequentialFile {
  115. public:
  116. explicit DummySequentialFile(bool fail_reads)
  117. : SequentialFile(), rnd_(5), fail_reads_(fail_reads) {}
  118. Status Read(size_t n, Slice* result, char* scratch) override {
  119. if (fail_reads_) {
  120. return Status::IOError();
  121. }
  122. size_t read_size = (n > size_left) ? size_left : n;
  123. for (size_t i = 0; i < read_size; ++i) {
  124. scratch[i] = rnd_.Next() & 255;
  125. }
  126. *result = Slice(scratch, read_size);
  127. size_left -= read_size;
  128. return Status::OK();
  129. }
  130. Status Skip(uint64_t n) override {
  131. size_left = (n > size_left) ? size_left - n : 0;
  132. return Status::OK();
  133. }
  134. private:
  135. size_t size_left = 200;
  136. Random rnd_;
  137. bool fail_reads_;
  138. };
  139. Status NewSequentialFile(const std::string& f,
  140. std::unique_ptr<SequentialFile>* r,
  141. const EnvOptions& options) override {
  142. MutexLock l(&mutex_);
  143. if (dummy_sequential_file_) {
  144. r->reset(
  145. new TestEnv::DummySequentialFile(dummy_sequential_file_fail_reads_));
  146. return Status::OK();
  147. } else {
  148. Status s = EnvWrapper::NewSequentialFile(f, r, options);
  149. if (s.ok()) {
  150. if ((*r)->use_direct_io()) {
  151. ++num_direct_seq_readers_;
  152. }
  153. ++num_seq_readers_;
  154. }
  155. return s;
  156. }
  157. }
  158. Status NewWritableFile(const std::string& f, std::unique_ptr<WritableFile>* r,
  159. const EnvOptions& options) override {
  160. MutexLock l(&mutex_);
  161. written_files_.push_back(f);
  162. if (limit_written_files_ <= 0) {
  163. return Status::NotSupported("Sorry, can't do this");
  164. }
  165. limit_written_files_--;
  166. Status s = EnvWrapper::NewWritableFile(f, r, options);
  167. if (s.ok()) {
  168. if ((*r)->use_direct_io()) {
  169. ++num_direct_writers_;
  170. }
  171. ++num_writers_;
  172. }
  173. return s;
  174. }
  175. Status NewRandomAccessFile(const std::string& fname,
  176. std::unique_ptr<RandomAccessFile>* result,
  177. const EnvOptions& options) override {
  178. MutexLock l(&mutex_);
  179. Status s = EnvWrapper::NewRandomAccessFile(fname, result, options);
  180. if (s.ok()) {
  181. if ((*result)->use_direct_io()) {
  182. ++num_direct_rand_readers_;
  183. }
  184. ++num_rand_readers_;
  185. }
  186. return s;
  187. }
  188. Status DeleteFile(const std::string& fname) override {
  189. MutexLock l(&mutex_);
  190. if (fail_delete_files_) {
  191. return Status::IOError();
  192. }
  193. EXPECT_GT(limit_delete_files_, 0U);
  194. limit_delete_files_--;
  195. return EnvWrapper::DeleteFile(fname);
  196. }
  197. Status DeleteDir(const std::string& dirname) override {
  198. MutexLock l(&mutex_);
  199. if (fail_delete_files_) {
  200. return Status::IOError();
  201. }
  202. return EnvWrapper::DeleteDir(dirname);
  203. }
  204. void AssertWrittenFiles(std::vector<std::string>& should_have_written) {
  205. MutexLock l(&mutex_);
  206. std::sort(should_have_written.begin(), should_have_written.end());
  207. std::sort(written_files_.begin(), written_files_.end());
  208. ASSERT_EQ(should_have_written, written_files_);
  209. }
  210. void ClearWrittenFiles() {
  211. MutexLock l(&mutex_);
  212. written_files_.clear();
  213. }
  214. void SetLimitWrittenFiles(uint64_t limit) {
  215. MutexLock l(&mutex_);
  216. limit_written_files_ = limit;
  217. }
  218. void SetLimitDeleteFiles(uint64_t limit) {
  219. MutexLock l(&mutex_);
  220. limit_delete_files_ = limit;
  221. }
  222. void SetDeleteFileFailure(bool fail) {
  223. MutexLock l(&mutex_);
  224. fail_delete_files_ = fail;
  225. }
  226. void SetDummySequentialFile(bool dummy_sequential_file) {
  227. MutexLock l(&mutex_);
  228. dummy_sequential_file_ = dummy_sequential_file;
  229. }
  230. void SetDummySequentialFileFailReads(bool dummy_sequential_file_fail_reads) {
  231. MutexLock l(&mutex_);
  232. dummy_sequential_file_fail_reads_ = dummy_sequential_file_fail_reads;
  233. }
  234. void SetGetChildrenFailure(bool fail) { get_children_failure_ = fail; }
  235. Status GetChildren(const std::string& dir,
  236. std::vector<std::string>* r) override {
  237. if (get_children_failure_) {
  238. return Status::IOError("SimulatedFailure");
  239. }
  240. return EnvWrapper::GetChildren(dir, r);
  241. }
  242. // Some test cases do not actually create the test files (e.g., see
  243. // DummyDB::live_files_) - for those cases, we mock those files' attributes
  244. // so CreateNewBackup() can get their attributes.
  245. void SetFilenamesForMockedAttrs(const std::vector<std::string>& filenames) {
  246. filenames_for_mocked_attrs_ = filenames;
  247. }
  248. Status GetChildrenFileAttributes(
  249. const std::string& dir, std::vector<Env::FileAttributes>* r) override {
  250. if (filenames_for_mocked_attrs_.size() > 0) {
  251. for (const auto& filename : filenames_for_mocked_attrs_) {
  252. r->push_back({dir + filename, 10 /* size_bytes */});
  253. }
  254. return Status::OK();
  255. }
  256. return EnvWrapper::GetChildrenFileAttributes(dir, r);
  257. }
  258. Status GetFileSize(const std::string& path, uint64_t* size_bytes) override {
  259. if (filenames_for_mocked_attrs_.size() > 0) {
  260. auto fname = path.substr(path.find_last_of('/'));
  261. auto filename_iter = std::find(filenames_for_mocked_attrs_.begin(),
  262. filenames_for_mocked_attrs_.end(), fname);
  263. if (filename_iter != filenames_for_mocked_attrs_.end()) {
  264. *size_bytes = 10;
  265. return Status::OK();
  266. }
  267. return Status::NotFound(fname);
  268. }
  269. return EnvWrapper::GetFileSize(path, size_bytes);
  270. }
  271. void SetCreateDirIfMissingFailure(bool fail) {
  272. create_dir_if_missing_failure_ = fail;
  273. }
  274. Status CreateDirIfMissing(const std::string& d) override {
  275. if (create_dir_if_missing_failure_) {
  276. return Status::IOError("SimulatedFailure");
  277. }
  278. return EnvWrapper::CreateDirIfMissing(d);
  279. }
  280. void SetNewDirectoryFailure(bool fail) { new_directory_failure_ = fail; }
  281. Status NewDirectory(const std::string& name,
  282. std::unique_ptr<Directory>* result) override {
  283. if (new_directory_failure_) {
  284. return Status::IOError("SimulatedFailure");
  285. }
  286. return EnvWrapper::NewDirectory(name, result);
  287. }
  288. void ClearFileOpenCounters() {
  289. MutexLock l(&mutex_);
  290. num_rand_readers_ = 0;
  291. num_direct_rand_readers_ = 0;
  292. num_seq_readers_ = 0;
  293. num_direct_seq_readers_ = 0;
  294. num_writers_ = 0;
  295. num_direct_writers_ = 0;
  296. }
  297. int num_rand_readers() { return num_rand_readers_; }
  298. int num_direct_rand_readers() { return num_direct_rand_readers_; }
  299. int num_seq_readers() { return num_seq_readers_; }
  300. int num_direct_seq_readers() { return num_direct_seq_readers_; }
  301. int num_writers() { return num_writers_; }
  302. int num_direct_writers() { return num_direct_writers_; }
  303. private:
  304. port::Mutex mutex_;
  305. bool dummy_sequential_file_ = false;
  306. bool dummy_sequential_file_fail_reads_ = false;
  307. std::vector<std::string> written_files_;
  308. std::vector<std::string> filenames_for_mocked_attrs_;
  309. uint64_t limit_written_files_ = 1000000;
  310. uint64_t limit_delete_files_ = 1000000;
  311. bool fail_delete_files_ = false;
  312. bool get_children_failure_ = false;
  313. bool create_dir_if_missing_failure_ = false;
  314. bool new_directory_failure_ = false;
  315. // Keeps track of how many files of each type were successfully opened, and
  316. // out of those, how many were opened with direct I/O.
  317. std::atomic<int> num_rand_readers_;
  318. std::atomic<int> num_direct_rand_readers_;
  319. std::atomic<int> num_seq_readers_;
  320. std::atomic<int> num_direct_seq_readers_;
  321. std::atomic<int> num_writers_;
  322. std::atomic<int> num_direct_writers_;
  323. }; // TestEnv
  324. class FileManager : public EnvWrapper {
  325. public:
  326. explicit FileManager(Env* t) : EnvWrapper(t), rnd_(5) {}
  327. Status DeleteRandomFileInDir(const std::string& dir) {
  328. std::vector<std::string> children;
  329. GetChildren(dir, &children);
  330. if (children.size() <= 2) { // . and ..
  331. return Status::NotFound("");
  332. }
  333. while (true) {
  334. int i = rnd_.Next() % children.size();
  335. if (children[i] != "." && children[i] != "..") {
  336. return DeleteFile(dir + "/" + children[i]);
  337. }
  338. }
  339. // should never get here
  340. assert(false);
  341. return Status::NotFound("");
  342. }
  343. Status AppendToRandomFileInDir(const std::string& dir,
  344. const std::string& data) {
  345. std::vector<std::string> children;
  346. GetChildren(dir, &children);
  347. if (children.size() <= 2) {
  348. return Status::NotFound("");
  349. }
  350. while (true) {
  351. int i = rnd_.Next() % children.size();
  352. if (children[i] != "." && children[i] != "..") {
  353. return WriteToFile(dir + "/" + children[i], data);
  354. }
  355. }
  356. // should never get here
  357. assert(false);
  358. return Status::NotFound("");
  359. }
  360. Status CorruptFile(const std::string& fname, uint64_t bytes_to_corrupt) {
  361. std::string file_contents;
  362. Status s = ReadFileToString(this, fname, &file_contents);
  363. if (!s.ok()) {
  364. return s;
  365. }
  366. s = DeleteFile(fname);
  367. if (!s.ok()) {
  368. return s;
  369. }
  370. for (uint64_t i = 0; i < bytes_to_corrupt; ++i) {
  371. std::string tmp;
  372. test::RandomString(&rnd_, 1, &tmp);
  373. file_contents[rnd_.Next() % file_contents.size()] = tmp[0];
  374. }
  375. return WriteToFile(fname, file_contents);
  376. }
  377. Status CorruptChecksum(const std::string& fname, bool appear_valid) {
  378. std::string metadata;
  379. Status s = ReadFileToString(this, fname, &metadata);
  380. if (!s.ok()) {
  381. return s;
  382. }
  383. s = DeleteFile(fname);
  384. if (!s.ok()) {
  385. return s;
  386. }
  387. auto pos = metadata.find("private");
  388. if (pos == std::string::npos) {
  389. return Status::Corruption("private file is expected");
  390. }
  391. pos = metadata.find(" crc32 ", pos + 6);
  392. if (pos == std::string::npos) {
  393. return Status::Corruption("checksum not found");
  394. }
  395. if (metadata.size() < pos + 7) {
  396. return Status::Corruption("bad CRC32 checksum value");
  397. }
  398. if (appear_valid) {
  399. if (metadata[pos + 8] == '\n') {
  400. // single digit value, safe to insert one more digit
  401. metadata.insert(pos + 8, 1, '0');
  402. } else {
  403. metadata.erase(pos + 8, 1);
  404. }
  405. } else {
  406. metadata[pos + 7] = 'a';
  407. }
  408. return WriteToFile(fname, metadata);
  409. }
  410. Status WriteToFile(const std::string& fname, const std::string& data) {
  411. std::unique_ptr<WritableFile> file;
  412. EnvOptions env_options;
  413. env_options.use_mmap_writes = false;
  414. Status s = EnvWrapper::NewWritableFile(fname, &file, env_options);
  415. if (!s.ok()) {
  416. return s;
  417. }
  418. return file->Append(Slice(data));
  419. }
  420. private:
  421. Random rnd_;
  422. }; // FileManager
  423. // utility functions
  424. static size_t FillDB(DB* db, int from, int to) {
  425. size_t bytes_written = 0;
  426. for (int i = from; i < to; ++i) {
  427. std::string key = "testkey" + ToString(i);
  428. std::string value = "testvalue" + ToString(i);
  429. bytes_written += key.size() + value.size();
  430. EXPECT_OK(db->Put(WriteOptions(), Slice(key), Slice(value)));
  431. }
  432. return bytes_written;
  433. }
  434. static void AssertExists(DB* db, int from, int to) {
  435. for (int i = from; i < to; ++i) {
  436. std::string key = "testkey" + ToString(i);
  437. std::string value;
  438. Status s = db->Get(ReadOptions(), Slice(key), &value);
  439. ASSERT_EQ(value, "testvalue" + ToString(i));
  440. }
  441. }
  442. static void AssertEmpty(DB* db, int from, int to) {
  443. for (int i = from; i < to; ++i) {
  444. std::string key = "testkey" + ToString(i);
  445. std::string value = "testvalue" + ToString(i);
  446. Status s = db->Get(ReadOptions(), Slice(key), &value);
  447. ASSERT_TRUE(s.IsNotFound());
  448. }
  449. }
  450. class BackupableDBTest : public testing::Test {
  451. public:
  452. enum ShareOption {
  453. kNoShare,
  454. kShareNoChecksum,
  455. kShareWithChecksum,
  456. };
  457. const std::vector<ShareOption> kAllShareOptions = {
  458. kNoShare, kShareNoChecksum, kShareWithChecksum};
  459. BackupableDBTest() {
  460. // set up files
  461. std::string db_chroot = test::PerThreadDBPath("backupable_db");
  462. std::string backup_chroot = test::PerThreadDBPath("backupable_db_backup");
  463. Env::Default()->CreateDir(db_chroot);
  464. Env::Default()->CreateDir(backup_chroot);
  465. dbname_ = "/tempdb";
  466. backupdir_ = "/tempbk";
  467. // set up envs
  468. db_chroot_env_.reset(NewChrootEnv(Env::Default(), db_chroot));
  469. backup_chroot_env_.reset(NewChrootEnv(Env::Default(), backup_chroot));
  470. test_db_env_.reset(new TestEnv(db_chroot_env_.get()));
  471. test_backup_env_.reset(new TestEnv(backup_chroot_env_.get()));
  472. file_manager_.reset(new FileManager(backup_chroot_env_.get()));
  473. // set up db options
  474. options_.create_if_missing = true;
  475. options_.paranoid_checks = true;
  476. options_.write_buffer_size = 1 << 17; // 128KB
  477. options_.env = test_db_env_.get();
  478. options_.wal_dir = dbname_;
  479. // Create logger
  480. DBOptions logger_options;
  481. logger_options.env = db_chroot_env_.get();
  482. CreateLoggerFromOptions(dbname_, logger_options, &logger_);
  483. // set up backup db options
  484. backupable_options_.reset(new BackupableDBOptions(
  485. backupdir_, test_backup_env_.get(), true, logger_.get(), true));
  486. // most tests will use multi-threaded backups
  487. backupable_options_->max_background_operations = 7;
  488. // delete old files in db
  489. DestroyDB(dbname_, options_);
  490. }
  491. DB* OpenDB() {
  492. DB* db;
  493. EXPECT_OK(DB::Open(options_, dbname_, &db));
  494. return db;
  495. }
  496. void OpenDBAndBackupEngine(bool destroy_old_data = false, bool dummy = false,
  497. ShareOption shared_option = kShareNoChecksum) {
  498. // reset all the defaults
  499. test_backup_env_->SetLimitWrittenFiles(1000000);
  500. test_db_env_->SetLimitWrittenFiles(1000000);
  501. test_db_env_->SetDummySequentialFile(dummy);
  502. DB* db;
  503. if (dummy) {
  504. dummy_db_ = new DummyDB(options_, dbname_);
  505. db = dummy_db_;
  506. } else {
  507. ASSERT_OK(DB::Open(options_, dbname_, &db));
  508. }
  509. db_.reset(db);
  510. backupable_options_->destroy_old_data = destroy_old_data;
  511. backupable_options_->share_table_files = shared_option != kNoShare;
  512. backupable_options_->share_files_with_checksum =
  513. shared_option == kShareWithChecksum;
  514. BackupEngine* backup_engine;
  515. ASSERT_OK(BackupEngine::Open(test_db_env_.get(), *backupable_options_,
  516. &backup_engine));
  517. backup_engine_.reset(backup_engine);
  518. }
  519. void CloseDBAndBackupEngine() {
  520. db_.reset();
  521. backup_engine_.reset();
  522. }
  523. void OpenBackupEngine() {
  524. backupable_options_->destroy_old_data = false;
  525. BackupEngine* backup_engine;
  526. ASSERT_OK(BackupEngine::Open(test_db_env_.get(), *backupable_options_,
  527. &backup_engine));
  528. backup_engine_.reset(backup_engine);
  529. }
  530. void CloseBackupEngine() { backup_engine_.reset(nullptr); }
  531. // restores backup backup_id and asserts the existence of
  532. // [start_exist, end_exist> and not-existence of
  533. // [end_exist, end>
  534. //
  535. // if backup_id == 0, it means restore from latest
  536. // if end == 0, don't check AssertEmpty
  537. void AssertBackupConsistency(BackupID backup_id, uint32_t start_exist,
  538. uint32_t end_exist, uint32_t end = 0,
  539. bool keep_log_files = false) {
  540. RestoreOptions restore_options(keep_log_files);
  541. bool opened_backup_engine = false;
  542. if (backup_engine_.get() == nullptr) {
  543. opened_backup_engine = true;
  544. OpenBackupEngine();
  545. }
  546. if (backup_id > 0) {
  547. ASSERT_OK(backup_engine_->RestoreDBFromBackup(backup_id, dbname_, dbname_,
  548. restore_options));
  549. } else {
  550. ASSERT_OK(backup_engine_->RestoreDBFromLatestBackup(dbname_, dbname_,
  551. restore_options));
  552. }
  553. DB* db = OpenDB();
  554. AssertExists(db, start_exist, end_exist);
  555. if (end != 0) {
  556. AssertEmpty(db, end_exist, end);
  557. }
  558. delete db;
  559. if (opened_backup_engine) {
  560. CloseBackupEngine();
  561. }
  562. }
  563. void DeleteLogFiles() {
  564. std::vector<std::string> delete_logs;
  565. db_chroot_env_->GetChildren(dbname_, &delete_logs);
  566. for (auto f : delete_logs) {
  567. uint64_t number;
  568. FileType type;
  569. bool ok = ParseFileName(f, &number, &type);
  570. if (ok && type == kLogFile) {
  571. db_chroot_env_->DeleteFile(dbname_ + "/" + f);
  572. }
  573. }
  574. }
  575. // files
  576. std::string dbname_;
  577. std::string backupdir_;
  578. // logger_ must be above backup_engine_ such that the engine's destructor,
  579. // which uses a raw pointer to the logger, executes first.
  580. std::shared_ptr<Logger> logger_;
  581. // envs
  582. std::unique_ptr<Env> db_chroot_env_;
  583. std::unique_ptr<Env> backup_chroot_env_;
  584. std::unique_ptr<TestEnv> test_db_env_;
  585. std::unique_ptr<TestEnv> test_backup_env_;
  586. std::unique_ptr<FileManager> file_manager_;
  587. // all the dbs!
  588. DummyDB* dummy_db_; // BackupableDB owns dummy_db_
  589. std::unique_ptr<DB> db_;
  590. std::unique_ptr<BackupEngine> backup_engine_;
  591. // options
  592. Options options_;
  593. protected:
  594. std::unique_ptr<BackupableDBOptions> backupable_options_;
  595. }; // BackupableDBTest
  596. void AppendPath(const std::string& path, std::vector<std::string>& v) {
  597. for (auto& f : v) {
  598. f = path + f;
  599. }
  600. }
  601. class BackupableDBTestWithParam : public BackupableDBTest,
  602. public testing::WithParamInterface<bool> {
  603. public:
  604. BackupableDBTestWithParam() {
  605. backupable_options_->share_files_with_checksum = GetParam();
  606. }
  607. };
  608. // This test verifies that the verifyBackup method correctly identifies
  609. // invalid backups
  610. TEST_P(BackupableDBTestWithParam, VerifyBackup) {
  611. const int keys_iteration = 5000;
  612. Random rnd(6);
  613. Status s;
  614. OpenDBAndBackupEngine(true);
  615. // create five backups
  616. for (int i = 0; i < 5; ++i) {
  617. FillDB(db_.get(), keys_iteration * i, keys_iteration * (i + 1));
  618. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  619. }
  620. CloseDBAndBackupEngine();
  621. OpenDBAndBackupEngine();
  622. // ---------- case 1. - valid backup -----------
  623. ASSERT_TRUE(backup_engine_->VerifyBackup(1).ok());
  624. // ---------- case 2. - delete a file -----------i
  625. file_manager_->DeleteRandomFileInDir(backupdir_ + "/private/1");
  626. ASSERT_TRUE(backup_engine_->VerifyBackup(1).IsNotFound());
  627. // ---------- case 3. - corrupt a file -----------
  628. std::string append_data = "Corrupting a random file";
  629. file_manager_->AppendToRandomFileInDir(backupdir_ + "/private/2",
  630. append_data);
  631. ASSERT_TRUE(backup_engine_->VerifyBackup(2).IsCorruption());
  632. // ---------- case 4. - invalid backup -----------
  633. ASSERT_TRUE(backup_engine_->VerifyBackup(6).IsNotFound());
  634. CloseDBAndBackupEngine();
  635. }
  636. // open DB, write, close DB, backup, restore, repeat
  637. TEST_P(BackupableDBTestWithParam, OfflineIntegrationTest) {
  638. // has to be a big number, so that it triggers the memtable flush
  639. const int keys_iteration = 5000;
  640. const int max_key = keys_iteration * 4 + 10;
  641. // first iter -- flush before backup
  642. // second iter -- don't flush before backup
  643. for (int iter = 0; iter < 2; ++iter) {
  644. // delete old data
  645. DestroyDB(dbname_, options_);
  646. bool destroy_data = true;
  647. // every iteration --
  648. // 1. insert new data in the DB
  649. // 2. backup the DB
  650. // 3. destroy the db
  651. // 4. restore the db, check everything is still there
  652. for (int i = 0; i < 5; ++i) {
  653. // in last iteration, put smaller amount of data,
  654. int fill_up_to = std::min(keys_iteration * (i + 1), max_key);
  655. // ---- insert new data and back up ----
  656. OpenDBAndBackupEngine(destroy_data);
  657. destroy_data = false;
  658. FillDB(db_.get(), keys_iteration * i, fill_up_to);
  659. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), iter == 0));
  660. CloseDBAndBackupEngine();
  661. DestroyDB(dbname_, options_);
  662. // ---- make sure it's empty ----
  663. DB* db = OpenDB();
  664. AssertEmpty(db, 0, fill_up_to);
  665. delete db;
  666. // ---- restore the DB ----
  667. OpenBackupEngine();
  668. if (i >= 3) { // test purge old backups
  669. // when i == 4, purge to only 1 backup
  670. // when i == 3, purge to 2 backups
  671. ASSERT_OK(backup_engine_->PurgeOldBackups(5 - i));
  672. }
  673. // ---- make sure the data is there ---
  674. AssertBackupConsistency(0, 0, fill_up_to, max_key);
  675. CloseBackupEngine();
  676. }
  677. }
  678. }
  679. // open DB, write, backup, write, backup, close, restore
  680. TEST_P(BackupableDBTestWithParam, OnlineIntegrationTest) {
  681. // has to be a big number, so that it triggers the memtable flush
  682. const int keys_iteration = 5000;
  683. const int max_key = keys_iteration * 4 + 10;
  684. Random rnd(7);
  685. // delete old data
  686. DestroyDB(dbname_, options_);
  687. OpenDBAndBackupEngine(true);
  688. // write some data, backup, repeat
  689. for (int i = 0; i < 5; ++i) {
  690. if (i == 4) {
  691. // delete backup number 2, online delete!
  692. ASSERT_OK(backup_engine_->DeleteBackup(2));
  693. }
  694. // in last iteration, put smaller amount of data,
  695. // so that backups can share sst files
  696. int fill_up_to = std::min(keys_iteration * (i + 1), max_key);
  697. FillDB(db_.get(), keys_iteration * i, fill_up_to);
  698. // we should get consistent results with flush_before_backup
  699. // set to both true and false
  700. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), !!(rnd.Next() % 2)));
  701. }
  702. // close and destroy
  703. CloseDBAndBackupEngine();
  704. DestroyDB(dbname_, options_);
  705. // ---- make sure it's empty ----
  706. DB* db = OpenDB();
  707. AssertEmpty(db, 0, max_key);
  708. delete db;
  709. // ---- restore every backup and verify all the data is there ----
  710. OpenBackupEngine();
  711. for (int i = 1; i <= 5; ++i) {
  712. if (i == 2) {
  713. // we deleted backup 2
  714. Status s = backup_engine_->RestoreDBFromBackup(2, dbname_, dbname_);
  715. ASSERT_TRUE(!s.ok());
  716. } else {
  717. int fill_up_to = std::min(keys_iteration * i, max_key);
  718. AssertBackupConsistency(i, 0, fill_up_to, max_key);
  719. }
  720. }
  721. // delete some backups -- this should leave only backups 3 and 5 alive
  722. ASSERT_OK(backup_engine_->DeleteBackup(4));
  723. ASSERT_OK(backup_engine_->PurgeOldBackups(2));
  724. std::vector<BackupInfo> backup_info;
  725. backup_engine_->GetBackupInfo(&backup_info);
  726. ASSERT_EQ(2UL, backup_info.size());
  727. // check backup 3
  728. AssertBackupConsistency(3, 0, 3 * keys_iteration, max_key);
  729. // check backup 5
  730. AssertBackupConsistency(5, 0, max_key);
  731. CloseBackupEngine();
  732. }
  733. INSTANTIATE_TEST_CASE_P(BackupableDBTestWithParam, BackupableDBTestWithParam,
  734. ::testing::Bool());
  735. // this will make sure that backup does not copy the same file twice
  736. TEST_F(BackupableDBTest, NoDoubleCopy_And_AutoGC) {
  737. OpenDBAndBackupEngine(true, true);
  738. // should write 5 DB files + one meta file
  739. test_backup_env_->SetLimitWrittenFiles(7);
  740. test_backup_env_->ClearWrittenFiles();
  741. test_db_env_->SetLimitWrittenFiles(0);
  742. dummy_db_->live_files_ = {"/00010.sst", "/00011.sst", "/CURRENT",
  743. "/MANIFEST-01"};
  744. dummy_db_->wal_files_ = {{"/00011.log", true}, {"/00012.log", false}};
  745. test_db_env_->SetFilenamesForMockedAttrs(dummy_db_->live_files_);
  746. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), false));
  747. std::vector<std::string> should_have_written = {
  748. "/shared/.00010.sst.tmp", "/shared/.00011.sst.tmp", "/private/1/CURRENT",
  749. "/private/1/MANIFEST-01", "/private/1/00011.log", "/meta/.1.tmp"};
  750. AppendPath(backupdir_, should_have_written);
  751. test_backup_env_->AssertWrittenFiles(should_have_written);
  752. char db_number = '1';
  753. for (std::string other_sst : {"00015.sst", "00017.sst", "00019.sst"}) {
  754. // should write 4 new DB files + one meta file
  755. // should not write/copy 00010.sst, since it's already there!
  756. test_backup_env_->SetLimitWrittenFiles(6);
  757. test_backup_env_->ClearWrittenFiles();
  758. dummy_db_->live_files_ = {"/00010.sst", "/" + other_sst, "/CURRENT",
  759. "/MANIFEST-01"};
  760. dummy_db_->wal_files_ = {{"/00011.log", true}, {"/00012.log", false}};
  761. test_db_env_->SetFilenamesForMockedAttrs(dummy_db_->live_files_);
  762. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), false));
  763. // should not open 00010.sst - it's already there
  764. ++db_number;
  765. std::string private_dir = std::string("/private/") + db_number;
  766. should_have_written = {
  767. "/shared/." + other_sst + ".tmp", private_dir + "/CURRENT",
  768. private_dir + "/MANIFEST-01", private_dir + "/00011.log",
  769. std::string("/meta/.") + db_number + ".tmp"};
  770. AppendPath(backupdir_, should_have_written);
  771. test_backup_env_->AssertWrittenFiles(should_have_written);
  772. }
  773. ASSERT_OK(backup_engine_->DeleteBackup(1));
  774. ASSERT_OK(test_backup_env_->FileExists(backupdir_ + "/shared/00010.sst"));
  775. // 00011.sst was only in backup 1, should be deleted
  776. ASSERT_EQ(Status::NotFound(),
  777. test_backup_env_->FileExists(backupdir_ + "/shared/00011.sst"));
  778. ASSERT_OK(test_backup_env_->FileExists(backupdir_ + "/shared/00015.sst"));
  779. // MANIFEST file size should be only 100
  780. uint64_t size = 0;
  781. test_backup_env_->GetFileSize(backupdir_ + "/private/2/MANIFEST-01", &size);
  782. ASSERT_EQ(100UL, size);
  783. test_backup_env_->GetFileSize(backupdir_ + "/shared/00015.sst", &size);
  784. ASSERT_EQ(200UL, size);
  785. CloseBackupEngine();
  786. //
  787. // Now simulate incomplete delete by removing just meta
  788. //
  789. ASSERT_OK(test_backup_env_->DeleteFile(backupdir_ + "/meta/2"));
  790. OpenBackupEngine();
  791. // 1 appears to be removed, so
  792. // 2 non-corrupt and 0 corrupt seen
  793. std::vector<BackupInfo> backup_info;
  794. std::vector<BackupID> corrupt_backup_ids;
  795. backup_engine_->GetBackupInfo(&backup_info);
  796. backup_engine_->GetCorruptedBackups(&corrupt_backup_ids);
  797. ASSERT_EQ(2UL, backup_info.size());
  798. ASSERT_EQ(0UL, corrupt_backup_ids.size());
  799. // Keep the two we see, but this should suffice to purge unreferenced
  800. // shared files from incomplete delete.
  801. ASSERT_OK(backup_engine_->PurgeOldBackups(2));
  802. // Make sure dangling sst file has been removed (somewhere along this
  803. // process). GarbageCollect should not be needed.
  804. ASSERT_EQ(Status::NotFound(),
  805. test_backup_env_->FileExists(backupdir_ + "/shared/00015.sst"));
  806. ASSERT_OK(test_backup_env_->FileExists(backupdir_ + "/shared/00017.sst"));
  807. ASSERT_OK(test_backup_env_->FileExists(backupdir_ + "/shared/00019.sst"));
  808. // Now actually purge a good one
  809. ASSERT_OK(backup_engine_->PurgeOldBackups(1));
  810. ASSERT_EQ(Status::NotFound(),
  811. test_backup_env_->FileExists(backupdir_ + "/shared/00017.sst"));
  812. ASSERT_OK(test_backup_env_->FileExists(backupdir_ + "/shared/00019.sst"));
  813. CloseDBAndBackupEngine();
  814. }
  815. // test various kind of corruptions that may happen:
  816. // 1. Not able to write a file for backup - that backup should fail,
  817. // everything else should work
  818. // 2. Corrupted backup meta file or missing backuped file - we should
  819. // not be able to open that backup, but all other backups should be
  820. // fine
  821. // 3. Corrupted checksum value - if the checksum is not a valid uint32_t,
  822. // db open should fail, otherwise, it aborts during the restore process.
  823. TEST_F(BackupableDBTest, CorruptionsTest) {
  824. const int keys_iteration = 5000;
  825. Random rnd(6);
  826. Status s;
  827. OpenDBAndBackupEngine(true);
  828. // create five backups
  829. for (int i = 0; i < 5; ++i) {
  830. FillDB(db_.get(), keys_iteration * i, keys_iteration * (i + 1));
  831. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), !!(rnd.Next() % 2)));
  832. }
  833. // ---------- case 1. - fail a write -----------
  834. // try creating backup 6, but fail a write
  835. FillDB(db_.get(), keys_iteration * 5, keys_iteration * 6);
  836. test_backup_env_->SetLimitWrittenFiles(2);
  837. // should fail
  838. s = backup_engine_->CreateNewBackup(db_.get(), !!(rnd.Next() % 2));
  839. ASSERT_TRUE(!s.ok());
  840. test_backup_env_->SetLimitWrittenFiles(1000000);
  841. // latest backup should have all the keys
  842. CloseDBAndBackupEngine();
  843. AssertBackupConsistency(0, 0, keys_iteration * 5, keys_iteration * 6);
  844. // --------- case 2. corrupted backup meta or missing backuped file ----
  845. ASSERT_OK(file_manager_->CorruptFile(backupdir_ + "/meta/5", 3));
  846. // since 5 meta is now corrupted, latest backup should be 4
  847. AssertBackupConsistency(0, 0, keys_iteration * 4, keys_iteration * 5);
  848. OpenBackupEngine();
  849. s = backup_engine_->RestoreDBFromBackup(5, dbname_, dbname_);
  850. ASSERT_TRUE(!s.ok());
  851. CloseBackupEngine();
  852. ASSERT_OK(file_manager_->DeleteRandomFileInDir(backupdir_ + "/private/4"));
  853. // 4 is corrupted, 3 is the latest backup now
  854. AssertBackupConsistency(0, 0, keys_iteration * 3, keys_iteration * 5);
  855. OpenBackupEngine();
  856. s = backup_engine_->RestoreDBFromBackup(4, dbname_, dbname_);
  857. CloseBackupEngine();
  858. ASSERT_TRUE(!s.ok());
  859. // --------- case 3. corrupted checksum value ----
  860. ASSERT_OK(file_manager_->CorruptChecksum(backupdir_ + "/meta/3", false));
  861. // checksum of backup 3 is an invalid value, this can be detected at
  862. // db open time, and it reverts to the previous backup automatically
  863. AssertBackupConsistency(0, 0, keys_iteration * 2, keys_iteration * 5);
  864. // checksum of the backup 2 appears to be valid, this can cause checksum
  865. // mismatch and abort restore process
  866. ASSERT_OK(file_manager_->CorruptChecksum(backupdir_ + "/meta/2", true));
  867. ASSERT_OK(file_manager_->FileExists(backupdir_ + "/meta/2"));
  868. OpenBackupEngine();
  869. ASSERT_OK(file_manager_->FileExists(backupdir_ + "/meta/2"));
  870. s = backup_engine_->RestoreDBFromBackup(2, dbname_, dbname_);
  871. ASSERT_TRUE(!s.ok());
  872. // make sure that no corrupt backups have actually been deleted!
  873. ASSERT_OK(file_manager_->FileExists(backupdir_ + "/meta/1"));
  874. ASSERT_OK(file_manager_->FileExists(backupdir_ + "/meta/2"));
  875. ASSERT_OK(file_manager_->FileExists(backupdir_ + "/meta/3"));
  876. ASSERT_OK(file_manager_->FileExists(backupdir_ + "/meta/4"));
  877. ASSERT_OK(file_manager_->FileExists(backupdir_ + "/meta/5"));
  878. ASSERT_OK(file_manager_->FileExists(backupdir_ + "/private/1"));
  879. ASSERT_OK(file_manager_->FileExists(backupdir_ + "/private/2"));
  880. ASSERT_OK(file_manager_->FileExists(backupdir_ + "/private/3"));
  881. ASSERT_OK(file_manager_->FileExists(backupdir_ + "/private/4"));
  882. ASSERT_OK(file_manager_->FileExists(backupdir_ + "/private/5"));
  883. // delete the corrupt backups and then make sure they're actually deleted
  884. ASSERT_OK(backup_engine_->DeleteBackup(5));
  885. ASSERT_OK(backup_engine_->DeleteBackup(4));
  886. ASSERT_OK(backup_engine_->DeleteBackup(3));
  887. ASSERT_OK(backup_engine_->DeleteBackup(2));
  888. // Should not be needed anymore with auto-GC on DeleteBackup
  889. //(void)backup_engine_->GarbageCollect();
  890. ASSERT_EQ(Status::NotFound(),
  891. file_manager_->FileExists(backupdir_ + "/meta/5"));
  892. ASSERT_EQ(Status::NotFound(),
  893. file_manager_->FileExists(backupdir_ + "/private/5"));
  894. ASSERT_EQ(Status::NotFound(),
  895. file_manager_->FileExists(backupdir_ + "/meta/4"));
  896. ASSERT_EQ(Status::NotFound(),
  897. file_manager_->FileExists(backupdir_ + "/private/4"));
  898. ASSERT_EQ(Status::NotFound(),
  899. file_manager_->FileExists(backupdir_ + "/meta/3"));
  900. ASSERT_EQ(Status::NotFound(),
  901. file_manager_->FileExists(backupdir_ + "/private/3"));
  902. ASSERT_EQ(Status::NotFound(),
  903. file_manager_->FileExists(backupdir_ + "/meta/2"));
  904. ASSERT_EQ(Status::NotFound(),
  905. file_manager_->FileExists(backupdir_ + "/private/2"));
  906. CloseBackupEngine();
  907. AssertBackupConsistency(0, 0, keys_iteration * 1, keys_iteration * 5);
  908. // new backup should be 2!
  909. OpenDBAndBackupEngine();
  910. FillDB(db_.get(), keys_iteration * 1, keys_iteration * 2);
  911. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), !!(rnd.Next() % 2)));
  912. CloseDBAndBackupEngine();
  913. AssertBackupConsistency(2, 0, keys_iteration * 2, keys_iteration * 5);
  914. }
  915. TEST_F(BackupableDBTest, InterruptCreationTest) {
  916. // Interrupt backup creation by failing new writes and failing cleanup of the
  917. // partial state. Then verify a subsequent backup can still succeed.
  918. const int keys_iteration = 5000;
  919. Random rnd(6);
  920. OpenDBAndBackupEngine(true /* destroy_old_data */);
  921. FillDB(db_.get(), 0, keys_iteration);
  922. test_backup_env_->SetLimitWrittenFiles(2);
  923. test_backup_env_->SetDeleteFileFailure(true);
  924. // should fail creation
  925. ASSERT_FALSE(
  926. backup_engine_->CreateNewBackup(db_.get(), !!(rnd.Next() % 2)).ok());
  927. CloseDBAndBackupEngine();
  928. // should also fail cleanup so the tmp directory stays behind
  929. ASSERT_OK(backup_chroot_env_->FileExists(backupdir_ + "/private/1/"));
  930. OpenDBAndBackupEngine(false /* destroy_old_data */);
  931. test_backup_env_->SetLimitWrittenFiles(1000000);
  932. test_backup_env_->SetDeleteFileFailure(false);
  933. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), !!(rnd.Next() % 2)));
  934. // latest backup should have all the keys
  935. CloseDBAndBackupEngine();
  936. AssertBackupConsistency(0, 0, keys_iteration);
  937. }
  938. inline std::string OptionsPath(std::string ret, int backupID) {
  939. ret += "/private/";
  940. ret += std::to_string(backupID);
  941. ret += "/";
  942. return ret;
  943. }
  944. // Backup the LATEST options file to
  945. // "<backup_dir>/private/<backup_id>/OPTIONS<number>"
  946. TEST_F(BackupableDBTest, BackupOptions) {
  947. OpenDBAndBackupEngine(true);
  948. for (int i = 1; i < 5; i++) {
  949. std::string name;
  950. std::vector<std::string> filenames;
  951. // Must reset() before reset(OpenDB()) again.
  952. // Calling OpenDB() while *db_ is existing will cause LOCK issue
  953. db_.reset();
  954. db_.reset(OpenDB());
  955. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  956. ROCKSDB_NAMESPACE::GetLatestOptionsFileName(db_->GetName(), options_.env,
  957. &name);
  958. ASSERT_OK(file_manager_->FileExists(OptionsPath(backupdir_, i) + name));
  959. backup_chroot_env_->GetChildren(OptionsPath(backupdir_, i), &filenames);
  960. for (auto fn : filenames) {
  961. if (fn.compare(0, 7, "OPTIONS") == 0) {
  962. ASSERT_EQ(name, fn);
  963. }
  964. }
  965. }
  966. CloseDBAndBackupEngine();
  967. }
  968. TEST_F(BackupableDBTest, SetOptionsBackupRaceCondition) {
  969. OpenDBAndBackupEngine(true);
  970. SyncPoint::GetInstance()->LoadDependency(
  971. {{"CheckpointImpl::CreateCheckpoint:SavedLiveFiles1",
  972. "BackupableDBTest::SetOptionsBackupRaceCondition:BeforeSetOptions"},
  973. {"BackupableDBTest::SetOptionsBackupRaceCondition:AfterSetOptions",
  974. "CheckpointImpl::CreateCheckpoint:SavedLiveFiles2"}});
  975. SyncPoint::GetInstance()->EnableProcessing();
  976. ROCKSDB_NAMESPACE::port::Thread setoptions_thread{[this]() {
  977. TEST_SYNC_POINT(
  978. "BackupableDBTest::SetOptionsBackupRaceCondition:BeforeSetOptions");
  979. DBImpl* dbi = static_cast<DBImpl*>(db_.get());
  980. // Change arbitrary option to trigger OPTIONS file deletion
  981. ASSERT_OK(dbi->SetOptions(dbi->DefaultColumnFamily(),
  982. {{"paranoid_file_checks", "false"}}));
  983. ASSERT_OK(dbi->SetOptions(dbi->DefaultColumnFamily(),
  984. {{"paranoid_file_checks", "true"}}));
  985. ASSERT_OK(dbi->SetOptions(dbi->DefaultColumnFamily(),
  986. {{"paranoid_file_checks", "false"}}));
  987. TEST_SYNC_POINT(
  988. "BackupableDBTest::SetOptionsBackupRaceCondition:AfterSetOptions");
  989. }};
  990. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get()));
  991. setoptions_thread.join();
  992. CloseDBAndBackupEngine();
  993. }
  994. // This test verifies we don't delete the latest backup when read-only option is
  995. // set
  996. TEST_F(BackupableDBTest, NoDeleteWithReadOnly) {
  997. const int keys_iteration = 5000;
  998. Random rnd(6);
  999. Status s;
  1000. OpenDBAndBackupEngine(true);
  1001. // create five backups
  1002. for (int i = 0; i < 5; ++i) {
  1003. FillDB(db_.get(), keys_iteration * i, keys_iteration * (i + 1));
  1004. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), !!(rnd.Next() % 2)));
  1005. }
  1006. CloseDBAndBackupEngine();
  1007. ASSERT_OK(file_manager_->WriteToFile(backupdir_ + "/LATEST_BACKUP", "4"));
  1008. backupable_options_->destroy_old_data = false;
  1009. BackupEngineReadOnly* read_only_backup_engine;
  1010. ASSERT_OK(BackupEngineReadOnly::Open(backup_chroot_env_.get(),
  1011. *backupable_options_,
  1012. &read_only_backup_engine));
  1013. // assert that data from backup 5 is still here (even though LATEST_BACKUP
  1014. // says 4 is latest)
  1015. ASSERT_OK(file_manager_->FileExists(backupdir_ + "/meta/5"));
  1016. ASSERT_OK(file_manager_->FileExists(backupdir_ + "/private/5"));
  1017. // Behavior change: We now ignore LATEST_BACKUP contents. This means that
  1018. // we should have 5 backups, even if LATEST_BACKUP says 4.
  1019. std::vector<BackupInfo> backup_info;
  1020. read_only_backup_engine->GetBackupInfo(&backup_info);
  1021. ASSERT_EQ(5UL, backup_info.size());
  1022. delete read_only_backup_engine;
  1023. }
  1024. TEST_F(BackupableDBTest, FailOverwritingBackups) {
  1025. options_.write_buffer_size = 1024 * 1024 * 1024; // 1GB
  1026. options_.disable_auto_compactions = true;
  1027. // create backups 1, 2, 3, 4, 5
  1028. OpenDBAndBackupEngine(true);
  1029. for (int i = 0; i < 5; ++i) {
  1030. CloseDBAndBackupEngine();
  1031. DeleteLogFiles();
  1032. OpenDBAndBackupEngine(false);
  1033. FillDB(db_.get(), 100 * i, 100 * (i + 1));
  1034. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  1035. }
  1036. CloseDBAndBackupEngine();
  1037. // restore 3
  1038. OpenBackupEngine();
  1039. ASSERT_OK(backup_engine_->RestoreDBFromBackup(3, dbname_, dbname_));
  1040. CloseBackupEngine();
  1041. OpenDBAndBackupEngine(false);
  1042. FillDB(db_.get(), 0, 300);
  1043. Status s = backup_engine_->CreateNewBackup(db_.get(), true);
  1044. // the new backup fails because new table files
  1045. // clash with old table files from backups 4 and 5
  1046. // (since write_buffer_size is huge, we can be sure that
  1047. // each backup will generate only one sst file and that
  1048. // a file generated by a new backup is the same as
  1049. // sst file generated by backup 4)
  1050. ASSERT_TRUE(s.IsCorruption());
  1051. ASSERT_OK(backup_engine_->DeleteBackup(4));
  1052. ASSERT_OK(backup_engine_->DeleteBackup(5));
  1053. // now, the backup can succeed
  1054. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  1055. CloseDBAndBackupEngine();
  1056. }
  1057. TEST_F(BackupableDBTest, NoShareTableFiles) {
  1058. const int keys_iteration = 5000;
  1059. OpenDBAndBackupEngine(true, false, kNoShare);
  1060. for (int i = 0; i < 5; ++i) {
  1061. FillDB(db_.get(), keys_iteration * i, keys_iteration * (i + 1));
  1062. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), !!(i % 2)));
  1063. }
  1064. CloseDBAndBackupEngine();
  1065. for (int i = 0; i < 5; ++i) {
  1066. AssertBackupConsistency(i + 1, 0, keys_iteration * (i + 1),
  1067. keys_iteration * 6);
  1068. }
  1069. }
  1070. // Verify that you can backup and restore with share_files_with_checksum on
  1071. TEST_F(BackupableDBTest, ShareTableFilesWithChecksums) {
  1072. const int keys_iteration = 5000;
  1073. OpenDBAndBackupEngine(true, false, kShareWithChecksum);
  1074. for (int i = 0; i < 5; ++i) {
  1075. FillDB(db_.get(), keys_iteration * i, keys_iteration * (i + 1));
  1076. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), !!(i % 2)));
  1077. }
  1078. CloseDBAndBackupEngine();
  1079. for (int i = 0; i < 5; ++i) {
  1080. AssertBackupConsistency(i + 1, 0, keys_iteration * (i + 1),
  1081. keys_iteration * 6);
  1082. }
  1083. }
  1084. // Verify that you can backup and restore using share_files_with_checksum set to
  1085. // false and then transition this option to true
  1086. TEST_F(BackupableDBTest, ShareTableFilesWithChecksumsTransition) {
  1087. const int keys_iteration = 5000;
  1088. // set share_files_with_checksum to false
  1089. OpenDBAndBackupEngine(true, false, kShareNoChecksum);
  1090. for (int i = 0; i < 5; ++i) {
  1091. FillDB(db_.get(), keys_iteration * i, keys_iteration * (i + 1));
  1092. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  1093. }
  1094. CloseDBAndBackupEngine();
  1095. for (int i = 0; i < 5; ++i) {
  1096. AssertBackupConsistency(i + 1, 0, keys_iteration * (i + 1),
  1097. keys_iteration * 6);
  1098. }
  1099. // set share_files_with_checksum to true and do some more backups
  1100. OpenDBAndBackupEngine(false /* destroy_old_data */, false,
  1101. kShareWithChecksum);
  1102. for (int i = 5; i < 10; ++i) {
  1103. FillDB(db_.get(), keys_iteration * i, keys_iteration * (i + 1));
  1104. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  1105. }
  1106. CloseDBAndBackupEngine();
  1107. // Verify first (about to delete)
  1108. AssertBackupConsistency(1, 0, keys_iteration, keys_iteration * 11);
  1109. // For an extra challenge, make sure that GarbageCollect / DeleteBackup
  1110. // is OK even if we open without share_table_files
  1111. OpenDBAndBackupEngine(false /* destroy_old_data */, false, kNoShare);
  1112. backup_engine_->DeleteBackup(1);
  1113. backup_engine_->GarbageCollect();
  1114. CloseDBAndBackupEngine();
  1115. // Verify rest (not deleted)
  1116. for (int i = 1; i < 10; ++i) {
  1117. AssertBackupConsistency(i + 1, 0, keys_iteration * (i + 1),
  1118. keys_iteration * 11);
  1119. }
  1120. }
  1121. // This test simulates cleaning up after aborted or incomplete creation
  1122. // of a new backup.
  1123. TEST_F(BackupableDBTest, DeleteTmpFiles) {
  1124. for (int cleanup_fn : {1, 2, 3, 4}) {
  1125. for (ShareOption shared_option : kAllShareOptions) {
  1126. OpenDBAndBackupEngine(false /* destroy_old_data */, false /* dummy */,
  1127. shared_option);
  1128. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get()));
  1129. BackupID next_id = 1;
  1130. BackupID oldest_id = std::numeric_limits<BackupID>::max();
  1131. {
  1132. std::vector<BackupInfo> backup_info;
  1133. backup_engine_->GetBackupInfo(&backup_info);
  1134. for (const auto& bi : backup_info) {
  1135. next_id = std::max(next_id, bi.backup_id + 1);
  1136. oldest_id = std::min(oldest_id, bi.backup_id);
  1137. }
  1138. }
  1139. CloseDBAndBackupEngine();
  1140. // An aborted or incomplete new backup will always be in the next
  1141. // id (maybe more)
  1142. std::string next_private = "private/" + std::to_string(next_id);
  1143. // NOTE: both shared and shared_checksum should be cleaned up
  1144. // regardless of how the backup engine is opened.
  1145. std::vector<std::string> tmp_files_and_dirs;
  1146. for (const auto& dir_and_file : {
  1147. std::make_pair(std::string("shared"),
  1148. std::string(".00006.sst.tmp")),
  1149. std::make_pair(std::string("shared_checksum"),
  1150. std::string(".00007.sst.tmp")),
  1151. std::make_pair(next_private, std::string("00003.sst")),
  1152. }) {
  1153. std::string dir = backupdir_ + "/" + dir_and_file.first;
  1154. file_manager_->CreateDir(dir);
  1155. ASSERT_OK(file_manager_->FileExists(dir));
  1156. std::string file = dir + "/" + dir_and_file.second;
  1157. file_manager_->WriteToFile(file, "tmp");
  1158. ASSERT_OK(file_manager_->FileExists(file));
  1159. tmp_files_and_dirs.push_back(file);
  1160. }
  1161. if (cleanup_fn != /*CreateNewBackup*/ 4) {
  1162. // This exists after CreateNewBackup because it's deleted then
  1163. // re-created.
  1164. tmp_files_and_dirs.push_back(backupdir_ + "/" + next_private);
  1165. }
  1166. OpenDBAndBackupEngine(false /* destroy_old_data */, false /* dummy */,
  1167. shared_option);
  1168. // Need to call one of these explicitly to delete tmp files
  1169. switch (cleanup_fn) {
  1170. case 1:
  1171. ASSERT_OK(backup_engine_->GarbageCollect());
  1172. break;
  1173. case 2:
  1174. ASSERT_OK(backup_engine_->DeleteBackup(oldest_id));
  1175. break;
  1176. case 3:
  1177. ASSERT_OK(backup_engine_->PurgeOldBackups(1));
  1178. break;
  1179. case 4:
  1180. // Does a garbage collect if it sees that next private dir exists
  1181. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get()));
  1182. break;
  1183. default:
  1184. assert(false);
  1185. }
  1186. CloseDBAndBackupEngine();
  1187. for (std::string file_or_dir : tmp_files_and_dirs) {
  1188. if (file_manager_->FileExists(file_or_dir) != Status::NotFound()) {
  1189. FAIL() << file_or_dir << " was expected to be deleted." << cleanup_fn;
  1190. }
  1191. }
  1192. }
  1193. }
  1194. }
  1195. TEST_F(BackupableDBTest, KeepLogFiles) {
  1196. backupable_options_->backup_log_files = false;
  1197. // basically infinite
  1198. options_.WAL_ttl_seconds = 24 * 60 * 60;
  1199. OpenDBAndBackupEngine(true);
  1200. FillDB(db_.get(), 0, 100);
  1201. ASSERT_OK(db_->Flush(FlushOptions()));
  1202. FillDB(db_.get(), 100, 200);
  1203. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), false));
  1204. FillDB(db_.get(), 200, 300);
  1205. ASSERT_OK(db_->Flush(FlushOptions()));
  1206. FillDB(db_.get(), 300, 400);
  1207. ASSERT_OK(db_->Flush(FlushOptions()));
  1208. FillDB(db_.get(), 400, 500);
  1209. ASSERT_OK(db_->Flush(FlushOptions()));
  1210. CloseDBAndBackupEngine();
  1211. // all data should be there if we call with keep_log_files = true
  1212. AssertBackupConsistency(0, 0, 500, 600, true);
  1213. }
  1214. TEST_F(BackupableDBTest, RateLimiting) {
  1215. size_t const kMicrosPerSec = 1000 * 1000LL;
  1216. uint64_t const MB = 1024 * 1024;
  1217. const std::vector<std::pair<uint64_t, uint64_t>> limits(
  1218. {{1 * MB, 5 * MB}, {2 * MB, 3 * MB}});
  1219. std::shared_ptr<RateLimiter> backupThrottler(NewGenericRateLimiter(1));
  1220. std::shared_ptr<RateLimiter> restoreThrottler(NewGenericRateLimiter(1));
  1221. for (bool makeThrottler : {false, true}) {
  1222. if (makeThrottler) {
  1223. backupable_options_->backup_rate_limiter = backupThrottler;
  1224. backupable_options_->restore_rate_limiter = restoreThrottler;
  1225. }
  1226. // iter 0 -- single threaded
  1227. // iter 1 -- multi threaded
  1228. for (int iter = 0; iter < 2; ++iter) {
  1229. for (const auto& limit : limits) {
  1230. // destroy old data
  1231. DestroyDB(dbname_, Options());
  1232. if (makeThrottler) {
  1233. backupThrottler->SetBytesPerSecond(limit.first);
  1234. restoreThrottler->SetBytesPerSecond(limit.second);
  1235. } else {
  1236. backupable_options_->backup_rate_limit = limit.first;
  1237. backupable_options_->restore_rate_limit = limit.second;
  1238. }
  1239. backupable_options_->max_background_operations = (iter == 0) ? 1 : 10;
  1240. options_.compression = kNoCompression;
  1241. OpenDBAndBackupEngine(true);
  1242. size_t bytes_written = FillDB(db_.get(), 0, 100000);
  1243. auto start_backup = db_chroot_env_->NowMicros();
  1244. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), false));
  1245. auto backup_time = db_chroot_env_->NowMicros() - start_backup;
  1246. auto rate_limited_backup_time =
  1247. (bytes_written * kMicrosPerSec) / limit.first;
  1248. ASSERT_GT(backup_time, 0.8 * rate_limited_backup_time);
  1249. CloseDBAndBackupEngine();
  1250. OpenBackupEngine();
  1251. auto start_restore = db_chroot_env_->NowMicros();
  1252. ASSERT_OK(backup_engine_->RestoreDBFromLatestBackup(dbname_, dbname_));
  1253. auto restore_time = db_chroot_env_->NowMicros() - start_restore;
  1254. CloseBackupEngine();
  1255. auto rate_limited_restore_time =
  1256. (bytes_written * kMicrosPerSec) / limit.second;
  1257. ASSERT_GT(restore_time, 0.8 * rate_limited_restore_time);
  1258. AssertBackupConsistency(0, 0, 100000, 100010);
  1259. }
  1260. }
  1261. }
  1262. }
  1263. TEST_F(BackupableDBTest, ReadOnlyBackupEngine) {
  1264. DestroyDB(dbname_, options_);
  1265. OpenDBAndBackupEngine(true);
  1266. FillDB(db_.get(), 0, 100);
  1267. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  1268. FillDB(db_.get(), 100, 200);
  1269. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  1270. CloseDBAndBackupEngine();
  1271. DestroyDB(dbname_, options_);
  1272. backupable_options_->destroy_old_data = false;
  1273. test_backup_env_->ClearWrittenFiles();
  1274. test_backup_env_->SetLimitDeleteFiles(0);
  1275. BackupEngineReadOnly* read_only_backup_engine;
  1276. ASSERT_OK(BackupEngineReadOnly::Open(
  1277. db_chroot_env_.get(), *backupable_options_, &read_only_backup_engine));
  1278. std::vector<BackupInfo> backup_info;
  1279. read_only_backup_engine->GetBackupInfo(&backup_info);
  1280. ASSERT_EQ(backup_info.size(), 2U);
  1281. RestoreOptions restore_options(false);
  1282. ASSERT_OK(read_only_backup_engine->RestoreDBFromLatestBackup(
  1283. dbname_, dbname_, restore_options));
  1284. delete read_only_backup_engine;
  1285. std::vector<std::string> should_have_written;
  1286. test_backup_env_->AssertWrittenFiles(should_have_written);
  1287. DB* db = OpenDB();
  1288. AssertExists(db, 0, 200);
  1289. delete db;
  1290. }
  1291. TEST_F(BackupableDBTest, ProgressCallbackDuringBackup) {
  1292. DestroyDB(dbname_, options_);
  1293. OpenDBAndBackupEngine(true);
  1294. FillDB(db_.get(), 0, 100);
  1295. bool is_callback_invoked = false;
  1296. ASSERT_OK(backup_engine_->CreateNewBackup(
  1297. db_.get(), true,
  1298. [&is_callback_invoked]() { is_callback_invoked = true; }));
  1299. ASSERT_TRUE(is_callback_invoked);
  1300. CloseDBAndBackupEngine();
  1301. DestroyDB(dbname_, options_);
  1302. }
  1303. TEST_F(BackupableDBTest, GarbageCollectionBeforeBackup) {
  1304. DestroyDB(dbname_, options_);
  1305. OpenDBAndBackupEngine(true);
  1306. backup_chroot_env_->CreateDirIfMissing(backupdir_ + "/shared");
  1307. std::string file_five = backupdir_ + "/shared/000007.sst";
  1308. std::string file_five_contents = "I'm not really a sst file";
  1309. // this depends on the fact that 00007.sst is the first file created by the DB
  1310. ASSERT_OK(file_manager_->WriteToFile(file_five, file_five_contents));
  1311. FillDB(db_.get(), 0, 100);
  1312. // backup overwrites file 000007.sst
  1313. ASSERT_TRUE(backup_engine_->CreateNewBackup(db_.get(), true).ok());
  1314. std::string new_file_five_contents;
  1315. ASSERT_OK(ReadFileToString(backup_chroot_env_.get(), file_five,
  1316. &new_file_five_contents));
  1317. // file 000007.sst was overwritten
  1318. ASSERT_TRUE(new_file_five_contents != file_five_contents);
  1319. CloseDBAndBackupEngine();
  1320. AssertBackupConsistency(0, 0, 100);
  1321. }
  1322. // Test that we properly propagate Env failures
  1323. TEST_F(BackupableDBTest, EnvFailures) {
  1324. BackupEngine* backup_engine;
  1325. // get children failure
  1326. {
  1327. test_backup_env_->SetGetChildrenFailure(true);
  1328. ASSERT_NOK(BackupEngine::Open(test_db_env_.get(), *backupable_options_,
  1329. &backup_engine));
  1330. test_backup_env_->SetGetChildrenFailure(false);
  1331. }
  1332. // created dir failure
  1333. {
  1334. test_backup_env_->SetCreateDirIfMissingFailure(true);
  1335. ASSERT_NOK(BackupEngine::Open(test_db_env_.get(), *backupable_options_,
  1336. &backup_engine));
  1337. test_backup_env_->SetCreateDirIfMissingFailure(false);
  1338. }
  1339. // new directory failure
  1340. {
  1341. test_backup_env_->SetNewDirectoryFailure(true);
  1342. ASSERT_NOK(BackupEngine::Open(test_db_env_.get(), *backupable_options_,
  1343. &backup_engine));
  1344. test_backup_env_->SetNewDirectoryFailure(false);
  1345. }
  1346. // Read from meta-file failure
  1347. {
  1348. DestroyDB(dbname_, options_);
  1349. OpenDBAndBackupEngine(true);
  1350. FillDB(db_.get(), 0, 100);
  1351. ASSERT_TRUE(backup_engine_->CreateNewBackup(db_.get(), true).ok());
  1352. CloseDBAndBackupEngine();
  1353. test_backup_env_->SetDummySequentialFile(true);
  1354. test_backup_env_->SetDummySequentialFileFailReads(true);
  1355. backupable_options_->destroy_old_data = false;
  1356. ASSERT_NOK(BackupEngine::Open(test_db_env_.get(), *backupable_options_,
  1357. &backup_engine));
  1358. test_backup_env_->SetDummySequentialFile(false);
  1359. test_backup_env_->SetDummySequentialFileFailReads(false);
  1360. }
  1361. // no failure
  1362. {
  1363. ASSERT_OK(BackupEngine::Open(test_db_env_.get(), *backupable_options_,
  1364. &backup_engine));
  1365. delete backup_engine;
  1366. }
  1367. }
  1368. // Verify manifest can roll while a backup is being created with the old
  1369. // manifest.
  1370. TEST_F(BackupableDBTest, ChangeManifestDuringBackupCreation) {
  1371. DestroyDB(dbname_, options_);
  1372. options_.max_manifest_file_size = 0; // always rollover manifest for file add
  1373. OpenDBAndBackupEngine(true);
  1374. FillDB(db_.get(), 0, 100);
  1375. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->LoadDependency({
  1376. {"CheckpointImpl::CreateCheckpoint:SavedLiveFiles1",
  1377. "VersionSet::LogAndApply:WriteManifest"},
  1378. {"VersionSet::LogAndApply:WriteManifestDone",
  1379. "CheckpointImpl::CreateCheckpoint:SavedLiveFiles2"},
  1380. });
  1381. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
  1382. ROCKSDB_NAMESPACE::port::Thread flush_thread{
  1383. [this]() { ASSERT_OK(db_->Flush(FlushOptions())); }};
  1384. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), false));
  1385. flush_thread.join();
  1386. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
  1387. // The last manifest roll would've already been cleaned up by the full scan
  1388. // that happens when CreateNewBackup invokes EnableFileDeletions. We need to
  1389. // trigger another roll to verify non-full scan purges stale manifests.
  1390. DBImpl* db_impl = reinterpret_cast<DBImpl*>(db_.get());
  1391. std::string prev_manifest_path =
  1392. DescriptorFileName(dbname_, db_impl->TEST_Current_Manifest_FileNo());
  1393. FillDB(db_.get(), 0, 100);
  1394. ASSERT_OK(db_chroot_env_->FileExists(prev_manifest_path));
  1395. ASSERT_OK(db_->Flush(FlushOptions()));
  1396. ASSERT_TRUE(db_chroot_env_->FileExists(prev_manifest_path).IsNotFound());
  1397. CloseDBAndBackupEngine();
  1398. DestroyDB(dbname_, options_);
  1399. AssertBackupConsistency(0, 0, 100);
  1400. }
  1401. // see https://github.com/facebook/rocksdb/issues/921
  1402. TEST_F(BackupableDBTest, Issue921Test) {
  1403. BackupEngine* backup_engine;
  1404. backupable_options_->share_table_files = false;
  1405. backup_chroot_env_->CreateDirIfMissing(backupable_options_->backup_dir);
  1406. backupable_options_->backup_dir += "/new_dir";
  1407. ASSERT_OK(BackupEngine::Open(backup_chroot_env_.get(), *backupable_options_,
  1408. &backup_engine));
  1409. delete backup_engine;
  1410. }
  1411. TEST_F(BackupableDBTest, BackupWithMetadata) {
  1412. const int keys_iteration = 5000;
  1413. OpenDBAndBackupEngine(true);
  1414. // create five backups
  1415. for (int i = 0; i < 5; ++i) {
  1416. const std::string metadata = std::to_string(i);
  1417. FillDB(db_.get(), keys_iteration * i, keys_iteration * (i + 1));
  1418. ASSERT_OK(
  1419. backup_engine_->CreateNewBackupWithMetadata(db_.get(), metadata, true));
  1420. }
  1421. CloseDBAndBackupEngine();
  1422. OpenDBAndBackupEngine();
  1423. std::vector<BackupInfo> backup_infos;
  1424. backup_engine_->GetBackupInfo(&backup_infos);
  1425. ASSERT_EQ(5, backup_infos.size());
  1426. for (int i = 0; i < 5; i++) {
  1427. ASSERT_EQ(std::to_string(i), backup_infos[i].app_metadata);
  1428. }
  1429. CloseDBAndBackupEngine();
  1430. DestroyDB(dbname_, options_);
  1431. }
  1432. TEST_F(BackupableDBTest, BinaryMetadata) {
  1433. OpenDBAndBackupEngine(true);
  1434. std::string binaryMetadata = "abc\ndef";
  1435. binaryMetadata.push_back('\0');
  1436. binaryMetadata.append("ghi");
  1437. ASSERT_OK(
  1438. backup_engine_->CreateNewBackupWithMetadata(db_.get(), binaryMetadata));
  1439. CloseDBAndBackupEngine();
  1440. OpenDBAndBackupEngine();
  1441. std::vector<BackupInfo> backup_infos;
  1442. backup_engine_->GetBackupInfo(&backup_infos);
  1443. ASSERT_EQ(1, backup_infos.size());
  1444. ASSERT_EQ(binaryMetadata, backup_infos[0].app_metadata);
  1445. CloseDBAndBackupEngine();
  1446. DestroyDB(dbname_, options_);
  1447. }
  1448. TEST_F(BackupableDBTest, MetadataTooLarge) {
  1449. OpenDBAndBackupEngine(true);
  1450. std::string largeMetadata(1024 * 1024 + 1, 0);
  1451. ASSERT_NOK(
  1452. backup_engine_->CreateNewBackupWithMetadata(db_.get(), largeMetadata));
  1453. CloseDBAndBackupEngine();
  1454. DestroyDB(dbname_, options_);
  1455. }
  1456. TEST_F(BackupableDBTest, LimitBackupsOpened) {
  1457. // Verify the specified max backups are opened, including skipping over
  1458. // corrupted backups.
  1459. //
  1460. // Setup:
  1461. // - backups 1, 2, and 4 are valid
  1462. // - backup 3 is corrupt
  1463. // - max_valid_backups_to_open == 2
  1464. //
  1465. // Expectation: the engine opens backups 4 and 2 since those are latest two
  1466. // non-corrupt backups.
  1467. const int kNumKeys = 5000;
  1468. OpenDBAndBackupEngine(true);
  1469. for (int i = 1; i <= 4; ++i) {
  1470. FillDB(db_.get(), kNumKeys * i, kNumKeys * (i + 1));
  1471. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  1472. if (i == 3) {
  1473. ASSERT_OK(file_manager_->CorruptFile(backupdir_ + "/meta/3", 3));
  1474. }
  1475. }
  1476. CloseDBAndBackupEngine();
  1477. backupable_options_->max_valid_backups_to_open = 2;
  1478. backupable_options_->destroy_old_data = false;
  1479. BackupEngineReadOnly* read_only_backup_engine;
  1480. ASSERT_OK(BackupEngineReadOnly::Open(backup_chroot_env_.get(),
  1481. *backupable_options_,
  1482. &read_only_backup_engine));
  1483. std::vector<BackupInfo> backup_infos;
  1484. read_only_backup_engine->GetBackupInfo(&backup_infos);
  1485. ASSERT_EQ(2, backup_infos.size());
  1486. ASSERT_EQ(2, backup_infos[0].backup_id);
  1487. ASSERT_EQ(4, backup_infos[1].backup_id);
  1488. delete read_only_backup_engine;
  1489. }
  1490. TEST_F(BackupableDBTest, IgnoreLimitBackupsOpenedWhenNotReadOnly) {
  1491. // Verify the specified max_valid_backups_to_open is ignored if the engine
  1492. // is not read-only.
  1493. //
  1494. // Setup:
  1495. // - backups 1, 2, and 4 are valid
  1496. // - backup 3 is corrupt
  1497. // - max_valid_backups_to_open == 2
  1498. //
  1499. // Expectation: the engine opens backups 4, 2, and 1 since those are latest
  1500. // non-corrupt backups, by ignoring max_valid_backups_to_open == 2.
  1501. const int kNumKeys = 5000;
  1502. OpenDBAndBackupEngine(true);
  1503. for (int i = 1; i <= 4; ++i) {
  1504. FillDB(db_.get(), kNumKeys * i, kNumKeys * (i + 1));
  1505. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  1506. if (i == 3) {
  1507. ASSERT_OK(file_manager_->CorruptFile(backupdir_ + "/meta/3", 3));
  1508. }
  1509. }
  1510. CloseDBAndBackupEngine();
  1511. backupable_options_->max_valid_backups_to_open = 2;
  1512. OpenDBAndBackupEngine();
  1513. std::vector<BackupInfo> backup_infos;
  1514. backup_engine_->GetBackupInfo(&backup_infos);
  1515. ASSERT_EQ(3, backup_infos.size());
  1516. ASSERT_EQ(1, backup_infos[0].backup_id);
  1517. ASSERT_EQ(2, backup_infos[1].backup_id);
  1518. ASSERT_EQ(4, backup_infos[2].backup_id);
  1519. CloseDBAndBackupEngine();
  1520. DestroyDB(dbname_, options_);
  1521. }
  1522. TEST_F(BackupableDBTest, CreateWhenLatestBackupCorrupted) {
  1523. // we should pick an ID greater than corrupted backups' IDs so creation can
  1524. // succeed even when latest backup is corrupted.
  1525. const int kNumKeys = 5000;
  1526. OpenDBAndBackupEngine(true /* destroy_old_data */);
  1527. FillDB(db_.get(), 0 /* from */, kNumKeys);
  1528. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(),
  1529. true /* flush_before_backup */));
  1530. ASSERT_OK(file_manager_->CorruptFile(backupdir_ + "/meta/1",
  1531. 3 /* bytes_to_corrupt */));
  1532. CloseDBAndBackupEngine();
  1533. OpenDBAndBackupEngine();
  1534. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(),
  1535. true /* flush_before_backup */));
  1536. std::vector<BackupInfo> backup_infos;
  1537. backup_engine_->GetBackupInfo(&backup_infos);
  1538. ASSERT_EQ(1, backup_infos.size());
  1539. ASSERT_EQ(2, backup_infos[0].backup_id);
  1540. }
  1541. TEST_F(BackupableDBTest, WriteOnlyEngineNoSharedFileDeletion) {
  1542. // Verifies a write-only BackupEngine does not delete files belonging to valid
  1543. // backups when GarbageCollect, PurgeOldBackups, or DeleteBackup are called.
  1544. const int kNumKeys = 5000;
  1545. for (int i = 0; i < 3; ++i) {
  1546. OpenDBAndBackupEngine(i == 0 /* destroy_old_data */);
  1547. FillDB(db_.get(), i * kNumKeys, (i + 1) * kNumKeys);
  1548. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  1549. CloseDBAndBackupEngine();
  1550. backupable_options_->max_valid_backups_to_open = 0;
  1551. OpenDBAndBackupEngine();
  1552. switch (i) {
  1553. case 0:
  1554. ASSERT_OK(backup_engine_->GarbageCollect());
  1555. break;
  1556. case 1:
  1557. ASSERT_OK(backup_engine_->PurgeOldBackups(1 /* num_backups_to_keep */));
  1558. break;
  1559. case 2:
  1560. ASSERT_OK(backup_engine_->DeleteBackup(2 /* backup_id */));
  1561. break;
  1562. default:
  1563. assert(false);
  1564. }
  1565. CloseDBAndBackupEngine();
  1566. backupable_options_->max_valid_backups_to_open = port::kMaxInt32;
  1567. AssertBackupConsistency(i + 1, 0, (i + 1) * kNumKeys);
  1568. }
  1569. }
  1570. TEST_P(BackupableDBTestWithParam, BackupUsingDirectIO) {
  1571. // Tests direct I/O on the backup engine's reads and writes on the DB env and
  1572. // backup env
  1573. // We use ChrootEnv underneath so the below line checks for direct I/O support
  1574. // in the chroot directory, not the true filesystem root.
  1575. if (!test::IsDirectIOSupported(test_db_env_.get(), "/")) {
  1576. return;
  1577. }
  1578. const int kNumKeysPerBackup = 100;
  1579. const int kNumBackups = 3;
  1580. options_.use_direct_reads = true;
  1581. OpenDBAndBackupEngine(true /* destroy_old_data */);
  1582. for (int i = 0; i < kNumBackups; ++i) {
  1583. FillDB(db_.get(), i * kNumKeysPerBackup /* from */,
  1584. (i + 1) * kNumKeysPerBackup /* to */);
  1585. ASSERT_OK(db_->Flush(FlushOptions()));
  1586. // Clear the file open counters and then do a bunch of backup engine ops.
  1587. // For all ops, files should be opened in direct mode.
  1588. test_backup_env_->ClearFileOpenCounters();
  1589. test_db_env_->ClearFileOpenCounters();
  1590. CloseBackupEngine();
  1591. OpenBackupEngine();
  1592. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(),
  1593. false /* flush_before_backup */));
  1594. ASSERT_OK(backup_engine_->VerifyBackup(i + 1));
  1595. CloseBackupEngine();
  1596. OpenBackupEngine();
  1597. std::vector<BackupInfo> backup_infos;
  1598. backup_engine_->GetBackupInfo(&backup_infos);
  1599. ASSERT_EQ(static_cast<size_t>(i + 1), backup_infos.size());
  1600. // Verify backup engine always opened files with direct I/O
  1601. ASSERT_EQ(0, test_db_env_->num_writers());
  1602. ASSERT_EQ(0, test_db_env_->num_rand_readers());
  1603. ASSERT_GT(test_db_env_->num_direct_seq_readers(), 0);
  1604. // Currently the DB doesn't support reading WALs or manifest with direct
  1605. // I/O, so subtract two.
  1606. ASSERT_EQ(test_db_env_->num_seq_readers() - 2,
  1607. test_db_env_->num_direct_seq_readers());
  1608. ASSERT_EQ(0, test_db_env_->num_rand_readers());
  1609. }
  1610. CloseDBAndBackupEngine();
  1611. for (int i = 0; i < kNumBackups; ++i) {
  1612. AssertBackupConsistency(i + 1 /* backup_id */,
  1613. i * kNumKeysPerBackup /* start_exist */,
  1614. (i + 1) * kNumKeysPerBackup /* end_exist */,
  1615. (i + 2) * kNumKeysPerBackup /* end */);
  1616. }
  1617. }
  1618. } // anon namespace
  1619. } // namespace ROCKSDB_NAMESPACE
  1620. int main(int argc, char** argv) {
  1621. ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
  1622. ::testing::InitGoogleTest(&argc, argv);
  1623. return RUN_ALL_TESTS();
  1624. }
  1625. #else
  1626. #include <stdio.h>
  1627. int main(int /*argc*/, char** /*argv*/) {
  1628. fprintf(stderr, "SKIPPED as BackupableDB is not supported in ROCKSDB_LITE\n");
  1629. return 0;
  1630. }
  1631. #endif // !defined(ROCKSDB_LITE) && !defined(OS_WIN)