file_indexer_test.cc 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  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/file_indexer.h"
  10. #include <string>
  11. #include "db/dbformat.h"
  12. #include "db/version_edit.h"
  13. #include "port/stack_trace.h"
  14. #include "rocksdb/comparator.h"
  15. #include "test_util/testharness.h"
  16. #include "test_util/testutil.h"
  17. namespace ROCKSDB_NAMESPACE {
  18. class IntComparator : public Comparator {
  19. public:
  20. int Compare(const Slice& a, const Slice& b) const override {
  21. assert(a.size() == 8);
  22. assert(b.size() == 8);
  23. int64_t diff = *reinterpret_cast<const int64_t*>(a.data()) -
  24. *reinterpret_cast<const int64_t*>(b.data());
  25. if (diff < 0) {
  26. return -1;
  27. } else if (diff == 0) {
  28. return 0;
  29. } else {
  30. return 1;
  31. }
  32. }
  33. const char* Name() const override { return "IntComparator"; }
  34. void FindShortestSeparator(std::string* /*start*/,
  35. const Slice& /*limit*/) const override {}
  36. void FindShortSuccessor(std::string* /*key*/) const override {}
  37. };
  38. class FileIndexerTest : public testing::Test {
  39. public:
  40. FileIndexerTest()
  41. : kNumLevels(4), files(new std::vector<FileMetaData*>[kNumLevels]) {}
  42. ~FileIndexerTest() override {
  43. ClearFiles();
  44. delete[] files;
  45. }
  46. void AddFile(int level, int64_t smallest, int64_t largest) {
  47. auto* f = new FileMetaData();
  48. f->smallest = IntKey(smallest);
  49. f->largest = IntKey(largest);
  50. files[level].push_back(f);
  51. }
  52. InternalKey IntKey(int64_t v) {
  53. return InternalKey(Slice(reinterpret_cast<char*>(&v), 8), 0, kTypeValue);
  54. }
  55. void ClearFiles() {
  56. for (uint32_t i = 0; i < kNumLevels; ++i) {
  57. for (auto* f : files[i]) {
  58. delete f;
  59. }
  60. files[i].clear();
  61. }
  62. }
  63. void GetNextLevelIndex(const uint32_t level, const uint32_t file_index,
  64. const int cmp_smallest, const int cmp_largest, int32_t* left_index,
  65. int32_t* right_index) {
  66. *left_index = 100;
  67. *right_index = 100;
  68. indexer->GetNextLevelIndex(level, file_index, cmp_smallest, cmp_largest,
  69. left_index, right_index);
  70. }
  71. int32_t left = 100;
  72. int32_t right = 100;
  73. const uint32_t kNumLevels;
  74. IntComparator ucmp;
  75. FileIndexer* indexer;
  76. std::vector<FileMetaData*>* files;
  77. };
  78. // Case 0: Empty
  79. TEST_F(FileIndexerTest, Empty) {
  80. Arena arena;
  81. indexer = new FileIndexer(&ucmp);
  82. indexer->UpdateIndex(&arena, 0, files);
  83. delete indexer;
  84. }
  85. // Case 1: no overlap, files are on the left of next level files
  86. TEST_F(FileIndexerTest, no_overlap_left) {
  87. Arena arena;
  88. indexer = new FileIndexer(&ucmp);
  89. // level 1
  90. AddFile(1, 100, 200);
  91. AddFile(1, 300, 400);
  92. AddFile(1, 500, 600);
  93. // level 2
  94. AddFile(2, 1500, 1600);
  95. AddFile(2, 1601, 1699);
  96. AddFile(2, 1700, 1800);
  97. // level 3
  98. AddFile(3, 2500, 2600);
  99. AddFile(3, 2601, 2699);
  100. AddFile(3, 2700, 2800);
  101. indexer->UpdateIndex(&arena, kNumLevels, files);
  102. for (uint32_t level = 1; level < 3; ++level) {
  103. for (uint32_t f = 0; f < 3; ++f) {
  104. GetNextLevelIndex(level, f, -1, -1, &left, &right);
  105. ASSERT_EQ(0, left);
  106. ASSERT_EQ(-1, right);
  107. GetNextLevelIndex(level, f, 0, -1, &left, &right);
  108. ASSERT_EQ(0, left);
  109. ASSERT_EQ(-1, right);
  110. GetNextLevelIndex(level, f, 1, -1, &left, &right);
  111. ASSERT_EQ(0, left);
  112. ASSERT_EQ(-1, right);
  113. GetNextLevelIndex(level, f, 1, 0, &left, &right);
  114. ASSERT_EQ(0, left);
  115. ASSERT_EQ(-1, right);
  116. GetNextLevelIndex(level, f, 1, 1, &left, &right);
  117. ASSERT_EQ(0, left);
  118. ASSERT_EQ(2, right);
  119. }
  120. }
  121. delete indexer;
  122. ClearFiles();
  123. }
  124. // Case 2: no overlap, files are on the right of next level files
  125. TEST_F(FileIndexerTest, no_overlap_right) {
  126. Arena arena;
  127. indexer = new FileIndexer(&ucmp);
  128. // level 1
  129. AddFile(1, 2100, 2200);
  130. AddFile(1, 2300, 2400);
  131. AddFile(1, 2500, 2600);
  132. // level 2
  133. AddFile(2, 1500, 1600);
  134. AddFile(2, 1501, 1699);
  135. AddFile(2, 1700, 1800);
  136. // level 3
  137. AddFile(3, 500, 600);
  138. AddFile(3, 501, 699);
  139. AddFile(3, 700, 800);
  140. indexer->UpdateIndex(&arena, kNumLevels, files);
  141. for (uint32_t level = 1; level < 3; ++level) {
  142. for (uint32_t f = 0; f < 3; ++f) {
  143. GetNextLevelIndex(level, f, -1, -1, &left, &right);
  144. ASSERT_EQ(f == 0 ? 0 : 3, left);
  145. ASSERT_EQ(2, right);
  146. GetNextLevelIndex(level, f, 0, -1, &left, &right);
  147. ASSERT_EQ(3, left);
  148. ASSERT_EQ(2, right);
  149. GetNextLevelIndex(level, f, 1, -1, &left, &right);
  150. ASSERT_EQ(3, left);
  151. ASSERT_EQ(2, right);
  152. GetNextLevelIndex(level, f, 1, -1, &left, &right);
  153. ASSERT_EQ(3, left);
  154. ASSERT_EQ(2, right);
  155. GetNextLevelIndex(level, f, 1, 0, &left, &right);
  156. ASSERT_EQ(3, left);
  157. ASSERT_EQ(2, right);
  158. GetNextLevelIndex(level, f, 1, 1, &left, &right);
  159. ASSERT_EQ(3, left);
  160. ASSERT_EQ(2, right);
  161. }
  162. }
  163. delete indexer;
  164. }
  165. // Case 3: empty L2
  166. TEST_F(FileIndexerTest, empty_L2) {
  167. Arena arena;
  168. indexer = new FileIndexer(&ucmp);
  169. for (uint32_t i = 1; i < kNumLevels; ++i) {
  170. ASSERT_EQ(0U, indexer->LevelIndexSize(i));
  171. }
  172. // level 1
  173. AddFile(1, 2100, 2200);
  174. AddFile(1, 2300, 2400);
  175. AddFile(1, 2500, 2600);
  176. // level 3
  177. AddFile(3, 500, 600);
  178. AddFile(3, 501, 699);
  179. AddFile(3, 700, 800);
  180. indexer->UpdateIndex(&arena, kNumLevels, files);
  181. for (uint32_t f = 0; f < 3; ++f) {
  182. GetNextLevelIndex(1, f, -1, -1, &left, &right);
  183. ASSERT_EQ(0, left);
  184. ASSERT_EQ(-1, right);
  185. GetNextLevelIndex(1, f, 0, -1, &left, &right);
  186. ASSERT_EQ(0, left);
  187. ASSERT_EQ(-1, right);
  188. GetNextLevelIndex(1, f, 1, -1, &left, &right);
  189. ASSERT_EQ(0, left);
  190. ASSERT_EQ(-1, right);
  191. GetNextLevelIndex(1, f, 1, -1, &left, &right);
  192. ASSERT_EQ(0, left);
  193. ASSERT_EQ(-1, right);
  194. GetNextLevelIndex(1, f, 1, 0, &left, &right);
  195. ASSERT_EQ(0, left);
  196. ASSERT_EQ(-1, right);
  197. GetNextLevelIndex(1, f, 1, 1, &left, &right);
  198. ASSERT_EQ(0, left);
  199. ASSERT_EQ(-1, right);
  200. }
  201. delete indexer;
  202. ClearFiles();
  203. }
  204. // Case 4: mixed
  205. TEST_F(FileIndexerTest, mixed) {
  206. Arena arena;
  207. indexer = new FileIndexer(&ucmp);
  208. // level 1
  209. AddFile(1, 100, 200);
  210. AddFile(1, 250, 400);
  211. AddFile(1, 450, 500);
  212. // level 2
  213. AddFile(2, 100, 150); // 0
  214. AddFile(2, 200, 250); // 1
  215. AddFile(2, 251, 300); // 2
  216. AddFile(2, 301, 350); // 3
  217. AddFile(2, 500, 600); // 4
  218. // level 3
  219. AddFile(3, 0, 50);
  220. AddFile(3, 100, 200);
  221. AddFile(3, 201, 250);
  222. indexer->UpdateIndex(&arena, kNumLevels, files);
  223. // level 1, 0
  224. GetNextLevelIndex(1, 0, -1, -1, &left, &right);
  225. ASSERT_EQ(0, left);
  226. ASSERT_EQ(0, right);
  227. GetNextLevelIndex(1, 0, 0, -1, &left, &right);
  228. ASSERT_EQ(0, left);
  229. ASSERT_EQ(0, right);
  230. GetNextLevelIndex(1, 0, 1, -1, &left, &right);
  231. ASSERT_EQ(0, left);
  232. ASSERT_EQ(1, right);
  233. GetNextLevelIndex(1, 0, 1, 0, &left, &right);
  234. ASSERT_EQ(1, left);
  235. ASSERT_EQ(1, right);
  236. GetNextLevelIndex(1, 0, 1, 1, &left, &right);
  237. ASSERT_EQ(1, left);
  238. ASSERT_EQ(4, right);
  239. // level 1, 1
  240. GetNextLevelIndex(1, 1, -1, -1, &left, &right);
  241. ASSERT_EQ(1, left);
  242. ASSERT_EQ(1, right);
  243. GetNextLevelIndex(1, 1, 0, -1, &left, &right);
  244. ASSERT_EQ(1, left);
  245. ASSERT_EQ(1, right);
  246. GetNextLevelIndex(1, 1, 1, -1, &left, &right);
  247. ASSERT_EQ(1, left);
  248. ASSERT_EQ(3, right);
  249. GetNextLevelIndex(1, 1, 1, 0, &left, &right);
  250. ASSERT_EQ(4, left);
  251. ASSERT_EQ(3, right);
  252. GetNextLevelIndex(1, 1, 1, 1, &left, &right);
  253. ASSERT_EQ(4, left);
  254. ASSERT_EQ(4, right);
  255. // level 1, 2
  256. GetNextLevelIndex(1, 2, -1, -1, &left, &right);
  257. ASSERT_EQ(4, left);
  258. ASSERT_EQ(3, right);
  259. GetNextLevelIndex(1, 2, 0, -1, &left, &right);
  260. ASSERT_EQ(4, left);
  261. ASSERT_EQ(3, right);
  262. GetNextLevelIndex(1, 2, 1, -1, &left, &right);
  263. ASSERT_EQ(4, left);
  264. ASSERT_EQ(4, right);
  265. GetNextLevelIndex(1, 2, 1, 0, &left, &right);
  266. ASSERT_EQ(4, left);
  267. ASSERT_EQ(4, right);
  268. GetNextLevelIndex(1, 2, 1, 1, &left, &right);
  269. ASSERT_EQ(4, left);
  270. ASSERT_EQ(4, right);
  271. // level 2, 0
  272. GetNextLevelIndex(2, 0, -1, -1, &left, &right);
  273. ASSERT_EQ(0, left);
  274. ASSERT_EQ(1, right);
  275. GetNextLevelIndex(2, 0, 0, -1, &left, &right);
  276. ASSERT_EQ(1, left);
  277. ASSERT_EQ(1, right);
  278. GetNextLevelIndex(2, 0, 1, -1, &left, &right);
  279. ASSERT_EQ(1, left);
  280. ASSERT_EQ(1, right);
  281. GetNextLevelIndex(2, 0, 1, 0, &left, &right);
  282. ASSERT_EQ(1, left);
  283. ASSERT_EQ(1, right);
  284. GetNextLevelIndex(2, 0, 1, 1, &left, &right);
  285. ASSERT_EQ(1, left);
  286. ASSERT_EQ(2, right);
  287. // level 2, 1
  288. GetNextLevelIndex(2, 1, -1, -1, &left, &right);
  289. ASSERT_EQ(1, left);
  290. ASSERT_EQ(1, right);
  291. GetNextLevelIndex(2, 1, 0, -1, &left, &right);
  292. ASSERT_EQ(1, left);
  293. ASSERT_EQ(1, right);
  294. GetNextLevelIndex(2, 1, 1, -1, &left, &right);
  295. ASSERT_EQ(1, left);
  296. ASSERT_EQ(2, right);
  297. GetNextLevelIndex(2, 1, 1, 0, &left, &right);
  298. ASSERT_EQ(2, left);
  299. ASSERT_EQ(2, right);
  300. GetNextLevelIndex(2, 1, 1, 1, &left, &right);
  301. ASSERT_EQ(2, left);
  302. ASSERT_EQ(2, right);
  303. // level 2, [2 - 4], no overlap
  304. for (uint32_t f = 2; f <= 4; ++f) {
  305. GetNextLevelIndex(2, f, -1, -1, &left, &right);
  306. ASSERT_EQ(f == 2 ? 2 : 3, left);
  307. ASSERT_EQ(2, right);
  308. GetNextLevelIndex(2, f, 0, -1, &left, &right);
  309. ASSERT_EQ(3, left);
  310. ASSERT_EQ(2, right);
  311. GetNextLevelIndex(2, f, 1, -1, &left, &right);
  312. ASSERT_EQ(3, left);
  313. ASSERT_EQ(2, right);
  314. GetNextLevelIndex(2, f, 1, 0, &left, &right);
  315. ASSERT_EQ(3, left);
  316. ASSERT_EQ(2, right);
  317. GetNextLevelIndex(2, f, 1, 1, &left, &right);
  318. ASSERT_EQ(3, left);
  319. ASSERT_EQ(2, right);
  320. }
  321. delete indexer;
  322. ClearFiles();
  323. }
  324. } // namespace ROCKSDB_NAMESPACE
  325. int main(int argc, char** argv) {
  326. ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
  327. ::testing::InitGoogleTest(&argc, argv);
  328. return RUN_ALL_TESTS();
  329. }