db_readonly_with_timestamp_test.cc 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008
  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. #include "db/db_with_timestamp_test_util.h"
  10. #include "test_util/testutil.h"
  11. namespace ROCKSDB_NAMESPACE {
  12. class DBReadOnlyTestWithTimestamp : public DBBasicTestWithTimestampBase {
  13. public:
  14. DBReadOnlyTestWithTimestamp()
  15. : DBBasicTestWithTimestampBase("db_readonly_test_with_timestamp") {}
  16. protected:
  17. void CheckDBOpenedAsCompactedDBWithOneLevel0File() {
  18. VersionSet* const versions = dbfull()->GetVersionSet();
  19. ASSERT_NE(versions, nullptr);
  20. ColumnFamilyData* const cfd = versions->GetColumnFamilySet()->GetDefault();
  21. ASSERT_NE(cfd, nullptr);
  22. Version* const current = cfd->current();
  23. ASSERT_NE(current, nullptr);
  24. const VersionStorageInfo* const storage_info = current->storage_info();
  25. ASSERT_NE(storage_info, nullptr);
  26. // Only 1 L0 file.
  27. ASSERT_EQ(1, NumTableFilesAtLevel(0));
  28. // L0 is the max level.
  29. ASSERT_EQ(storage_info->num_non_empty_levels(), 1);
  30. }
  31. void CheckDBOpenedAsCompactedDBWithOnlyHighestNonEmptyLevelFiles() {
  32. VersionSet* const versions = dbfull()->GetVersionSet();
  33. ASSERT_NE(versions, nullptr);
  34. ColumnFamilyData* const cfd = versions->GetColumnFamilySet()->GetDefault();
  35. ASSERT_NE(cfd, nullptr);
  36. Version* const current = cfd->current();
  37. ASSERT_NE(current, nullptr);
  38. const VersionStorageInfo* const storage_info = current->storage_info();
  39. ASSERT_NE(storage_info, nullptr);
  40. // L0 has no files.
  41. ASSERT_EQ(0, NumTableFilesAtLevel(0));
  42. // All other levels have no files except the highest level with files.
  43. for (int i = 1; i < storage_info->num_non_empty_levels() - 1; ++i) {
  44. ASSERT_FALSE(storage_info->LevelFilesBrief(i).num_files > 0);
  45. }
  46. // The highest level with files have some files.
  47. int highest_non_empty_level = storage_info->num_non_empty_levels() - 1;
  48. ASSERT_TRUE(
  49. storage_info->LevelFilesBrief(highest_non_empty_level).num_files > 0);
  50. }
  51. };
  52. TEST_F(DBReadOnlyTestWithTimestamp, IteratorAndGetReadTimestampSizeMismatch) {
  53. const int kNumKeysPerFile = 128;
  54. const uint64_t kMaxKey = 1024;
  55. Options options = CurrentOptions();
  56. options.env = env_;
  57. options.create_if_missing = true;
  58. const size_t kTimestampSize = Timestamp(0, 0).size();
  59. TestComparator test_cmp(kTimestampSize);
  60. options.comparator = &test_cmp;
  61. options.memtable_factory.reset(
  62. test::NewSpecialSkipListFactory(kNumKeysPerFile));
  63. DestroyAndReopen(options);
  64. const std::string write_timestamp = Timestamp(1, 0);
  65. WriteOptions write_opts;
  66. for (uint64_t key = 0; key <= kMaxKey; ++key) {
  67. Status s = db_->Put(write_opts, Key1(key), write_timestamp,
  68. "value" + std::to_string(key));
  69. ASSERT_OK(s);
  70. }
  71. // Reopen the database in read only mode to test its timestamp support.
  72. Close();
  73. ASSERT_OK(ReadOnlyReopen(options));
  74. ReadOptions read_opts;
  75. std::string different_size_read_timestamp;
  76. PutFixed32(&different_size_read_timestamp, 2);
  77. Slice different_size_read_ts = different_size_read_timestamp;
  78. read_opts.timestamp = &different_size_read_ts;
  79. {
  80. std::unique_ptr<Iterator> iter(db_->NewIterator(read_opts));
  81. ASSERT_FALSE(iter->Valid());
  82. ASSERT_TRUE(iter->status().IsInvalidArgument());
  83. }
  84. for (uint64_t key = 0; key <= kMaxKey; ++key) {
  85. std::string value_from_get;
  86. std::string timestamp;
  87. ASSERT_TRUE(db_->Get(read_opts, Key1(key), &value_from_get, &timestamp)
  88. .IsInvalidArgument());
  89. }
  90. Close();
  91. }
  92. TEST_F(DBReadOnlyTestWithTimestamp,
  93. IteratorAndGetReadTimestampSpecifiedWithoutWriteTimestamp) {
  94. const int kNumKeysPerFile = 128;
  95. const uint64_t kMaxKey = 1024;
  96. Options options = CurrentOptions();
  97. options.env = env_;
  98. options.create_if_missing = true;
  99. options.memtable_factory.reset(
  100. test::NewSpecialSkipListFactory(kNumKeysPerFile));
  101. DestroyAndReopen(options);
  102. WriteOptions write_opts;
  103. for (uint64_t key = 0; key <= kMaxKey; ++key) {
  104. Status s = db_->Put(write_opts, Key1(key), "value" + std::to_string(key));
  105. ASSERT_OK(s);
  106. }
  107. // Reopen the database in read only mode to test its timestamp support.
  108. Close();
  109. ASSERT_OK(ReadOnlyReopen(options));
  110. ReadOptions read_opts;
  111. const std::string read_timestamp = Timestamp(2, 0);
  112. Slice read_ts = read_timestamp;
  113. read_opts.timestamp = &read_ts;
  114. {
  115. std::unique_ptr<Iterator> iter(db_->NewIterator(read_opts));
  116. ASSERT_FALSE(iter->Valid());
  117. ASSERT_TRUE(iter->status().IsInvalidArgument());
  118. }
  119. for (uint64_t key = 0; key <= kMaxKey; ++key) {
  120. std::string value_from_get;
  121. std::string timestamp;
  122. ASSERT_TRUE(db_->Get(read_opts, Key1(key), &value_from_get, &timestamp)
  123. .IsInvalidArgument());
  124. }
  125. Close();
  126. }
  127. TEST_F(DBReadOnlyTestWithTimestamp,
  128. IteratorAndGetWriteWithTimestampReadWithoutTimestamp) {
  129. const int kNumKeysPerFile = 128;
  130. const uint64_t kMaxKey = 1024;
  131. Options options = CurrentOptions();
  132. options.env = env_;
  133. options.create_if_missing = true;
  134. const size_t kTimestampSize = Timestamp(0, 0).size();
  135. TestComparator test_cmp(kTimestampSize);
  136. options.comparator = &test_cmp;
  137. options.memtable_factory.reset(
  138. test::NewSpecialSkipListFactory(kNumKeysPerFile));
  139. DestroyAndReopen(options);
  140. const std::string write_timestamp = Timestamp(1, 0);
  141. WriteOptions write_opts;
  142. for (uint64_t key = 0; key <= kMaxKey; ++key) {
  143. Status s = db_->Put(write_opts, Key1(key), write_timestamp,
  144. "value" + std::to_string(key));
  145. ASSERT_OK(s);
  146. }
  147. // Reopen the database in read only mode to test its timestamp support.
  148. Close();
  149. ASSERT_OK(ReadOnlyReopen(options));
  150. ReadOptions read_opts;
  151. {
  152. std::unique_ptr<Iterator> iter(db_->NewIterator(read_opts));
  153. ASSERT_FALSE(iter->Valid());
  154. ASSERT_TRUE(iter->status().IsInvalidArgument());
  155. }
  156. for (uint64_t key = 0; key <= kMaxKey; ++key) {
  157. std::string value_from_get;
  158. ASSERT_TRUE(
  159. db_->Get(read_opts, Key1(key), &value_from_get).IsInvalidArgument());
  160. }
  161. Close();
  162. }
  163. TEST_F(DBReadOnlyTestWithTimestamp, IteratorAndGet) {
  164. const int kNumKeysPerFile = 128;
  165. const uint64_t kMaxKey = 1024;
  166. Options options = CurrentOptions();
  167. options.env = env_;
  168. options.create_if_missing = true;
  169. const size_t kTimestampSize = Timestamp(0, 0).size();
  170. TestComparator test_cmp(kTimestampSize);
  171. options.comparator = &test_cmp;
  172. options.memtable_factory.reset(
  173. test::NewSpecialSkipListFactory(kNumKeysPerFile));
  174. DestroyAndReopen(options);
  175. const std::vector<uint64_t> start_keys = {1, 0};
  176. const std::vector<std::string> write_timestamps = {Timestamp(1, 0),
  177. Timestamp(3, 0)};
  178. const std::vector<std::string> read_timestamps = {Timestamp(2, 0),
  179. Timestamp(4, 0)};
  180. for (size_t i = 0; i < write_timestamps.size(); ++i) {
  181. WriteOptions write_opts;
  182. for (uint64_t key = start_keys[i]; key <= kMaxKey; ++key) {
  183. Status s = db_->Put(write_opts, Key1(key), write_timestamps[i],
  184. "value" + std::to_string(i));
  185. ASSERT_OK(s);
  186. }
  187. }
  188. // Reopen the database in read only mode to test its timestamp support.
  189. Close();
  190. ASSERT_OK(ReadOnlyReopen(options));
  191. auto get_value_and_check = [](DB* db, ReadOptions read_opts, Slice key,
  192. Slice expected_value, std::string expected_ts) {
  193. std::string value_from_get;
  194. std::string timestamp;
  195. ASSERT_OK(db->Get(read_opts, key.ToString(), &value_from_get, &timestamp));
  196. ASSERT_EQ(expected_value, value_from_get);
  197. ASSERT_EQ(expected_ts, timestamp);
  198. };
  199. for (size_t i = 0; i < read_timestamps.size(); ++i) {
  200. ReadOptions read_opts;
  201. Slice read_ts = read_timestamps[i];
  202. read_opts.timestamp = &read_ts;
  203. std::unique_ptr<Iterator> it(db_->NewIterator(read_opts));
  204. int count = 0;
  205. uint64_t key = 0;
  206. // Forward iterate.
  207. for (it->Seek(Key1(0)), key = start_keys[i]; it->Valid();
  208. it->Next(), ++count, ++key) {
  209. CheckIterUserEntry(it.get(), Key1(key), kTypeValue,
  210. "value" + std::to_string(i), write_timestamps[i]);
  211. get_value_and_check(db_, read_opts, it->key(), it->value(),
  212. write_timestamps[i]);
  213. }
  214. ASSERT_OK(it->status());
  215. size_t expected_count = kMaxKey - start_keys[i] + 1;
  216. ASSERT_EQ(expected_count, count);
  217. // Backward iterate.
  218. count = 0;
  219. for (it->SeekForPrev(Key1(kMaxKey)), key = kMaxKey; it->Valid();
  220. it->Prev(), ++count, --key) {
  221. CheckIterUserEntry(it.get(), Key1(key), kTypeValue,
  222. "value" + std::to_string(i), write_timestamps[i]);
  223. get_value_and_check(db_, read_opts, it->key(), it->value(),
  224. write_timestamps[i]);
  225. }
  226. ASSERT_OK(it->status());
  227. ASSERT_EQ(static_cast<size_t>(kMaxKey) - start_keys[i] + 1, count);
  228. // SeekToFirst()/SeekToLast() with lower/upper bounds.
  229. // Then iter with lower and upper bounds.
  230. uint64_t l = 0;
  231. uint64_t r = kMaxKey + 1;
  232. while (l < r) {
  233. std::string lb_str = Key1(l);
  234. Slice lb = lb_str;
  235. std::string ub_str = Key1(r);
  236. Slice ub = ub_str;
  237. read_opts.iterate_lower_bound = &lb;
  238. read_opts.iterate_upper_bound = &ub;
  239. it.reset(db_->NewIterator(read_opts));
  240. for (it->SeekToFirst(), key = std::max(l, start_keys[i]), count = 0;
  241. it->Valid(); it->Next(), ++key, ++count) {
  242. CheckIterUserEntry(it.get(), Key1(key), kTypeValue,
  243. "value" + std::to_string(i), write_timestamps[i]);
  244. get_value_and_check(db_, read_opts, it->key(), it->value(),
  245. write_timestamps[i]);
  246. }
  247. ASSERT_OK(it->status());
  248. ASSERT_EQ(r - std::max(l, start_keys[i]), count);
  249. for (it->SeekToLast(), key = std::min(r, kMaxKey + 1), count = 0;
  250. it->Valid(); it->Prev(), --key, ++count) {
  251. CheckIterUserEntry(it.get(), Key1(key - 1), kTypeValue,
  252. "value" + std::to_string(i), write_timestamps[i]);
  253. get_value_and_check(db_, read_opts, it->key(), it->value(),
  254. write_timestamps[i]);
  255. }
  256. ASSERT_OK(it->status());
  257. l += (kMaxKey / 100);
  258. r -= (kMaxKey / 100);
  259. }
  260. }
  261. Close();
  262. }
  263. TEST_F(DBReadOnlyTestWithTimestamp, Iterators) {
  264. const int kNumKeysPerFile = 128;
  265. const uint64_t kMaxKey = 1024;
  266. Options options = CurrentOptions();
  267. options.env = env_;
  268. options.create_if_missing = true;
  269. const size_t kTimestampSize = Timestamp(0, 0).size();
  270. TestComparator test_cmp(kTimestampSize);
  271. options.comparator = &test_cmp;
  272. options.memtable_factory.reset(
  273. test::NewSpecialSkipListFactory(kNumKeysPerFile));
  274. DestroyAndReopen(options);
  275. const std::string write_timestamp = Timestamp(1, 0);
  276. const std::string read_timestamp = Timestamp(2, 0);
  277. WriteOptions write_opts;
  278. for (uint64_t key = 0; key <= kMaxKey; ++key) {
  279. Status s = db_->Put(write_opts, Key1(key), write_timestamp,
  280. "value" + std::to_string(key));
  281. ASSERT_OK(s);
  282. }
  283. // Reopen the database in read only mode to test its timestamp support.
  284. Close();
  285. ASSERT_OK(ReadOnlyReopen(options));
  286. ReadOptions read_opts;
  287. Slice read_ts = read_timestamp;
  288. read_opts.timestamp = &read_ts;
  289. std::vector<Iterator*> iters;
  290. ASSERT_OK(db_->NewIterators(read_opts, {db_->DefaultColumnFamily()}, &iters));
  291. ASSERT_EQ(static_cast<uint64_t>(1), iters.size());
  292. int count = 0;
  293. uint64_t key = 0;
  294. // Forward iterate.
  295. for (iters[0]->Seek(Key1(0)), key = 0; iters[0]->Valid();
  296. iters[0]->Next(), ++count, ++key) {
  297. CheckIterUserEntry(iters[0], Key1(key), kTypeValue,
  298. "value" + std::to_string(key), write_timestamp);
  299. }
  300. ASSERT_OK(iters[0]->status());
  301. size_t expected_count = kMaxKey - 0 + 1;
  302. ASSERT_EQ(expected_count, count);
  303. delete iters[0];
  304. Close();
  305. }
  306. TEST_F(DBReadOnlyTestWithTimestamp, FullHistoryTsLowSanityCheckFail) {
  307. Options options = CurrentOptions();
  308. options.env = env_;
  309. options.comparator = test::BytewiseComparatorWithU64TsWrapper();
  310. // Use UDT in memtable only feature for this test, so we can control that
  311. // newly set `full_history_ts_low` collapse history when Flush happens.
  312. options.persist_user_defined_timestamps = false;
  313. options.allow_concurrent_memtable_write = false;
  314. DestroyAndReopen(options);
  315. std::string write_ts;
  316. PutFixed64(&write_ts, 1);
  317. ASSERT_OK(db_->Put(WriteOptions(), "foo", write_ts, "val1"));
  318. std::string full_history_ts_low;
  319. PutFixed64(&full_history_ts_low, 3);
  320. ASSERT_OK(db_->IncreaseFullHistoryTsLow(db_->DefaultColumnFamily(),
  321. full_history_ts_low));
  322. ASSERT_OK(Flush(0));
  323. // Reopen the database in read only mode to test its timestamp support.
  324. Close();
  325. ASSERT_OK(ReadOnlyReopen(options));
  326. // Reading below full_history_ts_low fails a sanity check.
  327. std::string read_ts;
  328. PutFixed64(&read_ts, 2);
  329. Slice read_ts_slice = read_ts;
  330. ReadOptions read_opts;
  331. read_opts.timestamp = &read_ts_slice;
  332. // Get()
  333. std::string value;
  334. ASSERT_TRUE(db_->Get(read_opts, "foo", &value).IsInvalidArgument());
  335. // NewIterator()
  336. std::unique_ptr<Iterator> iter(
  337. db_->NewIterator(read_opts, db_->DefaultColumnFamily()));
  338. ASSERT_TRUE(iter->status().IsInvalidArgument());
  339. // NewIterators()
  340. std::vector<ColumnFamilyHandle*> cfhs = {db_->DefaultColumnFamily()};
  341. std::vector<Iterator*> iterators;
  342. ASSERT_TRUE(
  343. db_->NewIterators(read_opts, cfhs, &iterators).IsInvalidArgument());
  344. Close();
  345. }
  346. TEST_F(DBReadOnlyTestWithTimestamp, IteratorsReadTimestampSizeMismatch) {
  347. const int kNumKeysPerFile = 128;
  348. const uint64_t kMaxKey = 1024;
  349. Options options = CurrentOptions();
  350. options.env = env_;
  351. options.create_if_missing = true;
  352. const size_t kTimestampSize = Timestamp(0, 0).size();
  353. TestComparator test_cmp(kTimestampSize);
  354. options.comparator = &test_cmp;
  355. options.memtable_factory.reset(
  356. test::NewSpecialSkipListFactory(kNumKeysPerFile));
  357. DestroyAndReopen(options);
  358. const std::string write_timestamp = Timestamp(1, 0);
  359. WriteOptions write_opts;
  360. for (uint64_t key = 0; key <= kMaxKey; ++key) {
  361. Status s = db_->Put(write_opts, Key1(key), write_timestamp,
  362. "value" + std::to_string(key));
  363. ASSERT_OK(s);
  364. }
  365. // Reopen the database in read only mode to test its timestamp support.
  366. Close();
  367. ASSERT_OK(ReadOnlyReopen(options));
  368. ReadOptions read_opts;
  369. std::string different_size_read_timestamp;
  370. PutFixed32(&different_size_read_timestamp, 2);
  371. Slice different_size_read_ts = different_size_read_timestamp;
  372. read_opts.timestamp = &different_size_read_ts;
  373. {
  374. std::vector<Iterator*> iters;
  375. ASSERT_TRUE(
  376. db_->NewIterators(read_opts, {db_->DefaultColumnFamily()}, &iters)
  377. .IsInvalidArgument());
  378. }
  379. Close();
  380. }
  381. TEST_F(DBReadOnlyTestWithTimestamp,
  382. IteratorsReadTimestampSpecifiedWithoutWriteTimestamp) {
  383. const int kNumKeysPerFile = 128;
  384. const uint64_t kMaxKey = 1024;
  385. Options options = CurrentOptions();
  386. options.env = env_;
  387. options.create_if_missing = true;
  388. options.memtable_factory.reset(
  389. test::NewSpecialSkipListFactory(kNumKeysPerFile));
  390. DestroyAndReopen(options);
  391. WriteOptions write_opts;
  392. for (uint64_t key = 0; key <= kMaxKey; ++key) {
  393. Status s = db_->Put(write_opts, Key1(key), "value" + std::to_string(key));
  394. ASSERT_OK(s);
  395. }
  396. // Reopen the database in read only mode to test its timestamp support.
  397. Close();
  398. ASSERT_OK(ReadOnlyReopen(options));
  399. ReadOptions read_opts;
  400. const std::string read_timestamp = Timestamp(2, 0);
  401. Slice read_ts = read_timestamp;
  402. read_opts.timestamp = &read_ts;
  403. {
  404. std::vector<Iterator*> iters;
  405. ASSERT_TRUE(
  406. db_->NewIterators(read_opts, {db_->DefaultColumnFamily()}, &iters)
  407. .IsInvalidArgument());
  408. }
  409. Close();
  410. }
  411. TEST_F(DBReadOnlyTestWithTimestamp,
  412. IteratorsWriteWithTimestampReadWithoutTimestamp) {
  413. const int kNumKeysPerFile = 128;
  414. const uint64_t kMaxKey = 1024;
  415. Options options = CurrentOptions();
  416. options.env = env_;
  417. options.create_if_missing = true;
  418. const size_t kTimestampSize = Timestamp(0, 0).size();
  419. TestComparator test_cmp(kTimestampSize);
  420. options.comparator = &test_cmp;
  421. options.memtable_factory.reset(
  422. test::NewSpecialSkipListFactory(kNumKeysPerFile));
  423. DestroyAndReopen(options);
  424. const std::string write_timestamp = Timestamp(1, 0);
  425. WriteOptions write_opts;
  426. for (uint64_t key = 0; key <= kMaxKey; ++key) {
  427. Status s = db_->Put(write_opts, Key1(key), write_timestamp,
  428. "value" + std::to_string(key));
  429. ASSERT_OK(s);
  430. }
  431. // Reopen the database in read only mode to test its timestamp support.
  432. Close();
  433. ASSERT_OK(ReadOnlyReopen(options));
  434. ReadOptions read_opts;
  435. {
  436. std::vector<Iterator*> iters;
  437. ASSERT_TRUE(
  438. db_->NewIterators(read_opts, {db_->DefaultColumnFamily()}, &iters)
  439. .IsInvalidArgument());
  440. }
  441. Close();
  442. }
  443. TEST_F(DBReadOnlyTestWithTimestamp, CompactedDBGetReadTimestampSizeMismatch) {
  444. const int kNumKeysPerFile = 1026;
  445. const uint64_t kMaxKey = 1024;
  446. Options options = CurrentOptions();
  447. options.env = env_;
  448. options.create_if_missing = true;
  449. options.disable_auto_compactions = true;
  450. const size_t kTimestampSize = Timestamp(0, 0).size();
  451. TestComparator test_cmp(kTimestampSize);
  452. options.comparator = &test_cmp;
  453. options.memtable_factory.reset(
  454. test::NewSpecialSkipListFactory(kNumKeysPerFile));
  455. DestroyAndReopen(options);
  456. std::string write_timestamp = Timestamp(1, 0);
  457. WriteOptions write_opts;
  458. for (uint64_t key = 0; key <= kMaxKey; ++key) {
  459. Status s = db_->Put(write_opts, Key1(key), write_timestamp,
  460. "value" + std::to_string(0));
  461. ASSERT_OK(s);
  462. }
  463. ASSERT_OK(db_->Flush(FlushOptions()));
  464. Close();
  465. // Reopen the database in read only mode as a Compacted DB to test its
  466. // timestamp support.
  467. options.max_open_files = -1;
  468. ASSERT_OK(ReadOnlyReopen(options));
  469. CheckDBOpenedAsCompactedDBWithOneLevel0File();
  470. ReadOptions read_opts;
  471. std::string different_size_read_timestamp;
  472. PutFixed32(&different_size_read_timestamp, 2);
  473. Slice different_size_read_ts = different_size_read_timestamp;
  474. read_opts.timestamp = &different_size_read_ts;
  475. for (uint64_t key = 0; key <= kMaxKey; ++key) {
  476. std::string value_from_get;
  477. std::string timestamp;
  478. ASSERT_TRUE(db_->Get(read_opts, Key1(key), &value_from_get, &timestamp)
  479. .IsInvalidArgument());
  480. }
  481. Close();
  482. }
  483. TEST_F(DBReadOnlyTestWithTimestamp,
  484. CompactedDBGetReadTimestampSpecifiedWithoutWriteTimestamp) {
  485. const int kNumKeysPerFile = 1026;
  486. const uint64_t kMaxKey = 1024;
  487. Options options = CurrentOptions();
  488. options.env = env_;
  489. options.create_if_missing = true;
  490. options.disable_auto_compactions = true;
  491. options.memtable_factory.reset(
  492. test::NewSpecialSkipListFactory(kNumKeysPerFile));
  493. DestroyAndReopen(options);
  494. WriteOptions write_opts;
  495. for (uint64_t key = 0; key <= kMaxKey; ++key) {
  496. Status s = db_->Put(write_opts, Key1(key), "value" + std::to_string(0));
  497. ASSERT_OK(s);
  498. }
  499. ASSERT_OK(db_->Flush(FlushOptions()));
  500. Close();
  501. // Reopen the database in read only mode as a Compacted DB to test its
  502. // timestamp support.
  503. options.max_open_files = -1;
  504. ASSERT_OK(ReadOnlyReopen(options));
  505. CheckDBOpenedAsCompactedDBWithOneLevel0File();
  506. ReadOptions read_opts;
  507. const std::string read_timestamp = Timestamp(2, 0);
  508. Slice read_ts = read_timestamp;
  509. read_opts.timestamp = &read_ts;
  510. for (uint64_t key = 0; key <= kMaxKey; ++key) {
  511. std::string value_from_get;
  512. std::string timestamp;
  513. ASSERT_TRUE(db_->Get(read_opts, Key1(key), &value_from_get, &timestamp)
  514. .IsInvalidArgument());
  515. }
  516. Close();
  517. }
  518. TEST_F(DBReadOnlyTestWithTimestamp,
  519. CompactedDBGetWriteWithTimestampReadWithoutTimestamp) {
  520. const int kNumKeysPerFile = 1026;
  521. const uint64_t kMaxKey = 1024;
  522. Options options = CurrentOptions();
  523. options.env = env_;
  524. options.create_if_missing = true;
  525. options.disable_auto_compactions = true;
  526. const size_t kTimestampSize = Timestamp(0, 0).size();
  527. TestComparator test_cmp(kTimestampSize);
  528. options.comparator = &test_cmp;
  529. options.memtable_factory.reset(
  530. test::NewSpecialSkipListFactory(kNumKeysPerFile));
  531. DestroyAndReopen(options);
  532. std::string write_timestamp = Timestamp(1, 0);
  533. WriteOptions write_opts;
  534. for (uint64_t key = 0; key <= kMaxKey; ++key) {
  535. Status s = db_->Put(write_opts, Key1(key), write_timestamp,
  536. "value" + std::to_string(0));
  537. ASSERT_OK(s);
  538. }
  539. ASSERT_OK(db_->Flush(FlushOptions()));
  540. Close();
  541. // Reopen the database in read only mode as a Compacted DB to test its
  542. // timestamp support.
  543. options.max_open_files = -1;
  544. ASSERT_OK(ReadOnlyReopen(options));
  545. CheckDBOpenedAsCompactedDBWithOneLevel0File();
  546. ReadOptions read_opts;
  547. for (uint64_t key = 0; key <= kMaxKey; ++key) {
  548. std::string value_from_get;
  549. ASSERT_TRUE(
  550. db_->Get(read_opts, Key1(key), &value_from_get).IsInvalidArgument());
  551. }
  552. Close();
  553. }
  554. TEST_F(DBReadOnlyTestWithTimestamp, CompactedDBGetWithOnlyOneL0File) {
  555. const int kNumKeysPerFile = 1026 * 2;
  556. const uint64_t kMaxKey = 1024;
  557. Options options = CurrentOptions();
  558. options.env = env_;
  559. options.create_if_missing = true;
  560. options.disable_auto_compactions = true;
  561. const size_t kTimestampSize = Timestamp(0, 0).size();
  562. TestComparator test_cmp(kTimestampSize);
  563. options.comparator = &test_cmp;
  564. options.memtable_factory.reset(
  565. test::NewSpecialSkipListFactory(kNumKeysPerFile));
  566. DestroyAndReopen(options);
  567. const std::vector<uint64_t> start_keys = {1, 0};
  568. const std::vector<std::string> write_timestamps = {Timestamp(1, 0),
  569. Timestamp(3, 0)};
  570. const std::vector<std::string> read_timestamps = {Timestamp(2, 0),
  571. Timestamp(4, 0)};
  572. for (size_t i = 0; i < write_timestamps.size(); ++i) {
  573. WriteOptions write_opts;
  574. for (uint64_t key = start_keys[i]; key <= kMaxKey; ++key) {
  575. Status s = db_->Put(write_opts, Key1(key), write_timestamps[i],
  576. "value" + std::to_string(i));
  577. ASSERT_OK(s);
  578. }
  579. }
  580. ASSERT_OK(db_->Flush(FlushOptions()));
  581. Close();
  582. // Reopen the database in read only mode as a Compacted DB to test its
  583. // timestamp support.
  584. options.max_open_files = -1;
  585. ASSERT_OK(ReadOnlyReopen(options));
  586. CheckDBOpenedAsCompactedDBWithOneLevel0File();
  587. for (size_t i = 0; i < read_timestamps.size(); ++i) {
  588. ReadOptions read_opts;
  589. Slice read_ts = read_timestamps[i];
  590. read_opts.timestamp = &read_ts;
  591. int count = 0;
  592. for (uint64_t key = start_keys[i]; key <= kMaxKey; ++key, ++count) {
  593. std::string value_from_get;
  594. std::string timestamp;
  595. ASSERT_OK(db_->Get(read_opts, Key1(key), &value_from_get, &timestamp));
  596. ASSERT_EQ("value" + std::to_string(i), value_from_get);
  597. ASSERT_EQ(write_timestamps[i], timestamp);
  598. }
  599. size_t expected_count = kMaxKey - start_keys[i] + 1;
  600. ASSERT_EQ(expected_count, count);
  601. }
  602. Close();
  603. }
  604. TEST_F(DBReadOnlyTestWithTimestamp,
  605. CompactedDBGetWithOnlyHighestNonEmptyLevelFiles) {
  606. const int kNumKeysPerFile = 128;
  607. const uint64_t kMaxKey = 1024;
  608. Options options = CurrentOptions();
  609. options.env = env_;
  610. options.create_if_missing = true;
  611. options.disable_auto_compactions = true;
  612. const size_t kTimestampSize = Timestamp(0, 0).size();
  613. TestComparator test_cmp(kTimestampSize);
  614. options.comparator = &test_cmp;
  615. options.memtable_factory.reset(
  616. test::NewSpecialSkipListFactory(kNumKeysPerFile));
  617. DestroyAndReopen(options);
  618. const std::vector<uint64_t> start_keys = {1, 0};
  619. const std::vector<std::string> write_timestamps = {Timestamp(1, 0),
  620. Timestamp(3, 0)};
  621. const std::vector<std::string> read_timestamps = {Timestamp(2, 0),
  622. Timestamp(4, 0)};
  623. for (size_t i = 0; i < write_timestamps.size(); ++i) {
  624. WriteOptions write_opts;
  625. for (uint64_t key = start_keys[i]; key <= kMaxKey; ++key) {
  626. Status s = db_->Put(write_opts, Key1(key), write_timestamps[i],
  627. "value" + std::to_string(i));
  628. ASSERT_OK(s);
  629. }
  630. }
  631. ASSERT_OK(db_->Flush(FlushOptions()));
  632. ASSERT_OK(db_->CompactRange(CompactRangeOptions(), nullptr, nullptr));
  633. Close();
  634. // Reopen the database in read only mode as a Compacted DB to test its
  635. // timestamp support.
  636. options.max_open_files = -1;
  637. ASSERT_OK(ReadOnlyReopen(options));
  638. CheckDBOpenedAsCompactedDBWithOnlyHighestNonEmptyLevelFiles();
  639. for (size_t i = 0; i < read_timestamps.size(); ++i) {
  640. ReadOptions read_opts;
  641. Slice read_ts = read_timestamps[i];
  642. read_opts.timestamp = &read_ts;
  643. int count = 0;
  644. for (uint64_t key = start_keys[i]; key <= kMaxKey; ++key, ++count) {
  645. std::string value_from_get;
  646. std::string timestamp;
  647. ASSERT_OK(db_->Get(read_opts, Key1(key), &value_from_get, &timestamp));
  648. ASSERT_EQ("value" + std::to_string(i), value_from_get);
  649. ASSERT_EQ(write_timestamps[i], timestamp);
  650. }
  651. size_t expected_count = kMaxKey - start_keys[i] + 1;
  652. ASSERT_EQ(expected_count, count);
  653. }
  654. Close();
  655. }
  656. TEST_F(DBReadOnlyTestWithTimestamp,
  657. CompactedDBMultiGetReadTimestampSizeMismatch) {
  658. const int kNumKeysPerFile = 1026;
  659. const uint64_t kMaxKey = 1024;
  660. Options options = CurrentOptions();
  661. options.env = env_;
  662. options.create_if_missing = true;
  663. options.disable_auto_compactions = true;
  664. const size_t kTimestampSize = Timestamp(0, 0).size();
  665. TestComparator test_cmp(kTimestampSize);
  666. options.comparator = &test_cmp;
  667. options.memtable_factory.reset(
  668. test::NewSpecialSkipListFactory(kNumKeysPerFile));
  669. DestroyAndReopen(options);
  670. std::string write_timestamp = Timestamp(1, 0);
  671. WriteOptions write_opts;
  672. for (uint64_t key = 0; key <= kMaxKey; ++key) {
  673. Status s = db_->Put(write_opts, Key1(key), write_timestamp,
  674. "value" + std::to_string(0));
  675. ASSERT_OK(s);
  676. }
  677. ASSERT_OK(db_->Flush(FlushOptions()));
  678. Close();
  679. // Reopen the database in read only mode as a Compacted DB to test its
  680. // timestamp support.
  681. options.max_open_files = -1;
  682. ASSERT_OK(ReadOnlyReopen(options));
  683. CheckDBOpenedAsCompactedDBWithOneLevel0File();
  684. ReadOptions read_opts;
  685. std::string different_size_read_timestamp;
  686. PutFixed32(&different_size_read_timestamp, 2);
  687. Slice different_size_read_ts = different_size_read_timestamp;
  688. read_opts.timestamp = &different_size_read_ts;
  689. std::vector<std::string> key_strs;
  690. std::vector<Slice> keys;
  691. for (uint64_t key = 0; key <= kMaxKey; ++key) {
  692. key_strs.push_back(Key1(key));
  693. }
  694. for (const auto& key_str : key_strs) {
  695. keys.emplace_back(key_str);
  696. }
  697. std::vector<std::string> values;
  698. std::vector<std::string> timestamps;
  699. std::vector<Status> status_list =
  700. db_->MultiGet(read_opts, keys, &values, &timestamps);
  701. for (const auto& status : status_list) {
  702. ASSERT_TRUE(status.IsInvalidArgument());
  703. }
  704. Close();
  705. }
  706. TEST_F(DBReadOnlyTestWithTimestamp,
  707. CompactedDBMultiGetReadTimestampSpecifiedWithoutWriteTimestamp) {
  708. const int kNumKeysPerFile = 1026;
  709. const uint64_t kMaxKey = 1024;
  710. Options options = CurrentOptions();
  711. options.env = env_;
  712. options.create_if_missing = true;
  713. options.disable_auto_compactions = true;
  714. options.memtable_factory.reset(
  715. test::NewSpecialSkipListFactory(kNumKeysPerFile));
  716. DestroyAndReopen(options);
  717. WriteOptions write_opts;
  718. for (uint64_t key = 0; key <= kMaxKey; ++key) {
  719. Status s = db_->Put(write_opts, Key1(key), "value" + std::to_string(0));
  720. ASSERT_OK(s);
  721. }
  722. ASSERT_OK(db_->Flush(FlushOptions()));
  723. Close();
  724. // Reopen the database in read only mode as a Compacted DB to test its
  725. // timestamp support.
  726. options.max_open_files = -1;
  727. ASSERT_OK(ReadOnlyReopen(options));
  728. CheckDBOpenedAsCompactedDBWithOneLevel0File();
  729. ReadOptions read_opts;
  730. std::string read_timestamp = Timestamp(2, 0);
  731. Slice read_ts = read_timestamp;
  732. read_opts.timestamp = &read_ts;
  733. std::vector<std::string> key_strs;
  734. std::vector<Slice> keys;
  735. for (uint64_t key = 0; key <= kMaxKey; ++key) {
  736. key_strs.push_back(Key1(key));
  737. }
  738. for (const auto& key_str : key_strs) {
  739. keys.emplace_back(key_str);
  740. }
  741. std::vector<std::string> values;
  742. std::vector<std::string> timestamps;
  743. std::vector<Status> status_list =
  744. db_->MultiGet(read_opts, keys, &values, &timestamps);
  745. for (const auto& status : status_list) {
  746. ASSERT_TRUE(status.IsInvalidArgument());
  747. }
  748. Close();
  749. }
  750. TEST_F(DBReadOnlyTestWithTimestamp,
  751. CompactedDBMultiGetWriteWithTimestampReadWithoutTimestamp) {
  752. const int kNumKeysPerFile = 1026;
  753. const uint64_t kMaxKey = 1024;
  754. Options options = CurrentOptions();
  755. options.env = env_;
  756. options.create_if_missing = true;
  757. options.disable_auto_compactions = true;
  758. const size_t kTimestampSize = Timestamp(0, 0).size();
  759. TestComparator test_cmp(kTimestampSize);
  760. options.comparator = &test_cmp;
  761. options.memtable_factory.reset(
  762. test::NewSpecialSkipListFactory(kNumKeysPerFile));
  763. DestroyAndReopen(options);
  764. std::string write_timestamp = Timestamp(1, 0);
  765. WriteOptions write_opts;
  766. for (uint64_t key = 0; key <= kMaxKey; ++key) {
  767. Status s = db_->Put(write_opts, Key1(key), write_timestamp,
  768. "value" + std::to_string(0));
  769. ASSERT_OK(s);
  770. }
  771. ASSERT_OK(db_->Flush(FlushOptions()));
  772. Close();
  773. // Reopen the database in read only mode as a Compacted DB to test its
  774. // timestamp support.
  775. options.max_open_files = -1;
  776. ASSERT_OK(ReadOnlyReopen(options));
  777. CheckDBOpenedAsCompactedDBWithOneLevel0File();
  778. ReadOptions read_opts;
  779. std::vector<std::string> key_strs;
  780. std::vector<Slice> keys;
  781. for (uint64_t key = 0; key <= kMaxKey; ++key) {
  782. key_strs.push_back(Key1(key));
  783. }
  784. for (const auto& key_str : key_strs) {
  785. keys.emplace_back(key_str);
  786. }
  787. std::vector<std::string> values;
  788. std::vector<Status> status_list = db_->MultiGet(read_opts, keys, &values);
  789. for (const auto& status : status_list) {
  790. ASSERT_TRUE(status.IsInvalidArgument());
  791. }
  792. Close();
  793. }
  794. TEST_F(DBReadOnlyTestWithTimestamp, CompactedDBMultiGetWithOnlyOneL0File) {
  795. const int kNumKeysPerFile = 1026 * 2;
  796. const uint64_t kMaxKey = 1024;
  797. Options options = CurrentOptions();
  798. options.env = env_;
  799. options.create_if_missing = true;
  800. options.disable_auto_compactions = true;
  801. const size_t kTimestampSize = Timestamp(0, 0).size();
  802. TestComparator test_cmp(kTimestampSize);
  803. options.comparator = &test_cmp;
  804. options.memtable_factory.reset(
  805. test::NewSpecialSkipListFactory(kNumKeysPerFile));
  806. DestroyAndReopen(options);
  807. const std::vector<uint64_t> start_keys = {1, 0};
  808. const std::vector<std::string> write_timestamps = {Timestamp(1, 0),
  809. Timestamp(3, 0)};
  810. const std::vector<std::string> read_timestamps = {Timestamp(2, 0),
  811. Timestamp(4, 0)};
  812. for (size_t i = 0; i < write_timestamps.size(); ++i) {
  813. WriteOptions write_opts;
  814. for (uint64_t key = start_keys[i]; key <= kMaxKey; ++key) {
  815. Status s = db_->Put(write_opts, Key1(key), write_timestamps[i],
  816. "value" + std::to_string(i));
  817. ASSERT_OK(s);
  818. }
  819. }
  820. ASSERT_OK(db_->Flush(FlushOptions()));
  821. Close();
  822. // Reopen the database in read only mode as a Compacted DB to test its
  823. // timestamp support.
  824. options.max_open_files = -1;
  825. ASSERT_OK(ReadOnlyReopen(options));
  826. CheckDBOpenedAsCompactedDBWithOneLevel0File();
  827. for (size_t i = 0; i < write_timestamps.size(); ++i) {
  828. ReadOptions read_opts;
  829. Slice read_ts = read_timestamps[i];
  830. read_opts.timestamp = &read_ts;
  831. std::vector<std::string> key_strs;
  832. std::vector<Slice> keys;
  833. for (uint64_t key = start_keys[i]; key <= kMaxKey; ++key) {
  834. key_strs.push_back(Key1(key));
  835. }
  836. for (const auto& key_str : key_strs) {
  837. keys.emplace_back(key_str);
  838. }
  839. size_t batch_size = kMaxKey - start_keys[i] + 1;
  840. std::vector<std::string> values;
  841. std::vector<std::string> timestamps;
  842. std::vector<Status> status_list =
  843. db_->MultiGet(read_opts, keys, &values, &timestamps);
  844. ASSERT_EQ(batch_size, values.size());
  845. ASSERT_EQ(batch_size, timestamps.size());
  846. for (uint64_t idx = 0; idx < values.size(); ++idx) {
  847. ASSERT_EQ("value" + std::to_string(i), values[idx]);
  848. ASSERT_EQ(write_timestamps[i], timestamps[idx]);
  849. ASSERT_OK(status_list[idx]);
  850. }
  851. }
  852. Close();
  853. }
  854. TEST_F(DBReadOnlyTestWithTimestamp,
  855. CompactedDBMultiGetWithOnlyHighestNonEmptyLevelFiles) {
  856. const int kNumKeysPerFile = 128;
  857. const uint64_t kMaxKey = 1024;
  858. Options options = CurrentOptions();
  859. options.env = env_;
  860. options.create_if_missing = true;
  861. options.disable_auto_compactions = true;
  862. const size_t kTimestampSize = Timestamp(0, 0).size();
  863. TestComparator test_cmp(kTimestampSize);
  864. options.comparator = &test_cmp;
  865. options.memtable_factory.reset(
  866. test::NewSpecialSkipListFactory(kNumKeysPerFile));
  867. DestroyAndReopen(options);
  868. const std::vector<uint64_t> start_keys = {1, 0};
  869. const std::vector<std::string> write_timestamps = {Timestamp(1, 0),
  870. Timestamp(3, 0)};
  871. const std::vector<std::string> read_timestamps = {Timestamp(2, 0),
  872. Timestamp(4, 0)};
  873. for (size_t i = 0; i < write_timestamps.size(); ++i) {
  874. WriteOptions write_opts;
  875. for (uint64_t key = start_keys[i]; key <= kMaxKey; ++key) {
  876. Status s = db_->Put(write_opts, Key1(key), write_timestamps[i],
  877. "value" + std::to_string(i));
  878. ASSERT_OK(s);
  879. }
  880. }
  881. ASSERT_OK(db_->Flush(FlushOptions()));
  882. ASSERT_OK(db_->CompactRange(CompactRangeOptions(), nullptr, nullptr));
  883. Close();
  884. // Reopen the database in read only mode as a Compacted DB to test its
  885. // timestamp support.
  886. options.max_open_files = -1;
  887. ASSERT_OK(ReadOnlyReopen(options));
  888. CheckDBOpenedAsCompactedDBWithOnlyHighestNonEmptyLevelFiles();
  889. for (size_t i = 0; i < write_timestamps.size(); ++i) {
  890. ReadOptions read_opts;
  891. Slice read_ts = read_timestamps[i];
  892. read_opts.timestamp = &read_ts;
  893. std::vector<std::string> key_strs;
  894. std::vector<Slice> keys;
  895. for (uint64_t key = start_keys[i]; key <= kMaxKey; ++key) {
  896. key_strs.push_back(Key1(key));
  897. }
  898. for (const auto& key_str : key_strs) {
  899. keys.emplace_back(key_str);
  900. }
  901. size_t batch_size = kMaxKey - start_keys[i] + 1;
  902. std::vector<std::string> values;
  903. std::vector<std::string> timestamps;
  904. std::vector<Status> status_list =
  905. db_->MultiGet(read_opts, keys, &values, &timestamps);
  906. ASSERT_EQ(batch_size, values.size());
  907. ASSERT_EQ(batch_size, timestamps.size());
  908. for (uint64_t idx = 0; idx < values.size(); ++idx) {
  909. ASSERT_EQ("value" + std::to_string(i), values[idx]);
  910. ASSERT_EQ(write_timestamps[i], timestamps[idx]);
  911. ASSERT_OK(status_list[idx]);
  912. }
  913. }
  914. Close();
  915. }
  916. } // namespace ROCKSDB_NAMESPACE
  917. int main(int argc, char** argv) {
  918. ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
  919. ::testing::InitGoogleTest(&argc, argv);
  920. RegisterCustomObjects(argc, argv);
  921. return RUN_ALL_TESTS();
  922. }