|
9 | 9 | #include "db/version_edit.h"
|
10 | 10 | #include "port/port.h"
|
11 | 11 | #include "port/stack_trace.h"
|
| 12 | +#include "rocksdb/advanced_options.h" |
| 13 | +#include "rocksdb/options.h" |
12 | 14 | #include "rocksdb/sst_file_writer.h"
|
13 | 15 | #include "test_util/testharness.h"
|
14 | 16 | #include "test_util/testutil.h"
|
@@ -1292,6 +1294,80 @@ TEST_F(ExternalSSTFileBasicTest, VerifyChecksumReadahead) {
|
1292 | 1294 | Destroy(options);
|
1293 | 1295 | }
|
1294 | 1296 |
|
| 1297 | +TEST_F(ExternalSSTFileBasicTest, ReadOldValueOfIngestedKeyBug) { |
| 1298 | + Options options = CurrentOptions(); |
| 1299 | + options.compaction_style = kCompactionStyleUniversal; |
| 1300 | + options.disable_auto_compactions = true; |
| 1301 | + options.num_levels = 3; |
| 1302 | + options.preserve_internal_time_seconds = 36000; |
| 1303 | + DestroyAndReopen(options); |
| 1304 | + |
| 1305 | + // To create the following LSM tree to trigger the bug: |
| 1306 | + // L0 |
| 1307 | + // L1 with seqno [1, 2] |
| 1308 | + // L2 with seqno [3, 4] |
| 1309 | + |
| 1310 | + // To create L1 shape |
| 1311 | + ASSERT_OK( |
| 1312 | + db_->Put(WriteOptions(), db_->DefaultColumnFamily(), "k1", "seqno1")); |
| 1313 | + ASSERT_OK(db_->Flush(FlushOptions())); |
| 1314 | + ASSERT_OK( |
| 1315 | + db_->Put(WriteOptions(), db_->DefaultColumnFamily(), "k1", "seqno2")); |
| 1316 | + ASSERT_OK(db_->Flush(FlushOptions())); |
| 1317 | + ColumnFamilyMetaData meta_1; |
| 1318 | + db_->GetColumnFamilyMetaData(&meta_1); |
| 1319 | + auto& files_1 = meta_1.levels[0].files; |
| 1320 | + ASSERT_EQ(files_1.size(), 2); |
| 1321 | + std::string file1 = files_1[0].db_path + files_1[0].name; |
| 1322 | + std::string file2 = files_1[1].db_path + files_1[1].name; |
| 1323 | + ASSERT_OK(db_->CompactFiles(CompactionOptions(), {file1, file2}, 1)); |
| 1324 | + // To confirm L1 shape |
| 1325 | + ColumnFamilyMetaData meta_2; |
| 1326 | + db_->GetColumnFamilyMetaData(&meta_2); |
| 1327 | + ASSERT_EQ(meta_2.levels[0].files.size(), 0); |
| 1328 | + ASSERT_EQ(meta_2.levels[1].files.size(), 1); |
| 1329 | + // Seqno starts from non-zero due to seqno reservation for |
| 1330 | + // preserve_internal_time_seconds greater than 0; |
| 1331 | + ASSERT_EQ(meta_2.levels[1].files[0].largest_seqno, 102); |
| 1332 | + ASSERT_EQ(meta_2.levels[2].files.size(), 0); |
| 1333 | + // To create L2 shape |
| 1334 | + ASSERT_OK(db_->Put(WriteOptions(), db_->DefaultColumnFamily(), "k2overlap", |
| 1335 | + "old_value")); |
| 1336 | + ASSERT_OK(db_->Flush(FlushOptions())); |
| 1337 | + ASSERT_OK(db_->Put(WriteOptions(), db_->DefaultColumnFamily(), "k2overlap", |
| 1338 | + "old_value")); |
| 1339 | + ASSERT_OK(db_->Flush(FlushOptions())); |
| 1340 | + ColumnFamilyMetaData meta_3; |
| 1341 | + db_->GetColumnFamilyMetaData(&meta_3); |
| 1342 | + auto& files_3 = meta_3.levels[0].files; |
| 1343 | + std::string file3 = files_3[0].db_path + files_3[0].name; |
| 1344 | + std::string file4 = files_3[1].db_path + files_3[1].name; |
| 1345 | + ASSERT_OK(db_->CompactFiles(CompactionOptions(), {file3, file4}, 2)); |
| 1346 | + // To confirm L2 shape |
| 1347 | + ColumnFamilyMetaData meta_4; |
| 1348 | + db_->GetColumnFamilyMetaData(&meta_4); |
| 1349 | + ASSERT_EQ(meta_4.levels[0].files.size(), 0); |
| 1350 | + ASSERT_EQ(meta_4.levels[1].files.size(), 1); |
| 1351 | + ASSERT_EQ(meta_4.levels[2].files.size(), 1); |
| 1352 | + ASSERT_EQ(meta_4.levels[2].files[0].largest_seqno, 104); |
| 1353 | + |
| 1354 | + // Ingest a file with new value of the key "k2overlap" |
| 1355 | + SstFileWriter sst_file_writer(EnvOptions(), options); |
| 1356 | + std::string f = sst_files_dir_ + "f.sst"; |
| 1357 | + ASSERT_OK(sst_file_writer.Open(f)); |
| 1358 | + ASSERT_OK(sst_file_writer.Put("k2overlap", "new_value")); |
| 1359 | + ExternalSstFileInfo f_info; |
| 1360 | + ASSERT_OK(sst_file_writer.Finish(&f_info)); |
| 1361 | + ASSERT_OK(db_->IngestExternalFile({f}, IngestExternalFileOptions())); |
| 1362 | + |
| 1363 | + // To verify new value of the key "k2overlap" is correctly returned |
| 1364 | + ASSERT_OK(db_->CompactRange(CompactRangeOptions(), nullptr, nullptr)); |
| 1365 | + std::string value; |
| 1366 | + ASSERT_OK(db_->Get(ReadOptions(), "k2overlap", &value)); |
| 1367 | + // Before the fix, the value would be "old_value" and assertion failed |
| 1368 | + ASSERT_EQ(value, "new_value"); |
| 1369 | +} |
| 1370 | + |
1295 | 1371 | TEST_F(ExternalSSTFileBasicTest, IngestRangeDeletionTombstoneWithGlobalSeqno) {
|
1296 | 1372 | for (int i = 5; i < 25; i++) {
|
1297 | 1373 | ASSERT_OK(db_->Put(WriteOptions(), db_->DefaultColumnFamily(), Key(i),
|
|
0 commit comments