Skip to content

Commit 4069afe

Browse files
jowlyzhangfacebook-github-bot
authored andcommitted
Add safeguarding from resurrected cutoff UDT from previous session (#13521)
Summary: Public APIs like `DB::GetFullHistoryTsLow` and `DB::IncreaseFullHistoryTsLow` have such safeguarding, allowing them to only be invoked when user defined timestamp is enabled. This PR adds safeguarding into related internal APIs in `ColumnFamilyData` to properly handle the case when the UDT feature are toggled. Pull Request resolved: #13521 Test Plan: ./db_with_timestamp_basic_test --gtest_filter="*EnableDisableUDT*" Reviewed By: cbi42 Differential Revision: D72475234 Pulled By: jowlyzhang fbshipit-source-id: 194c07287e3100da95450b04c76552c9d4a86c2d
1 parent 24e2b05 commit 4069afe

File tree

2 files changed

+88
-29
lines changed

2 files changed

+88
-29
lines changed

Diff for: db/column_family.h

+11
Original file line numberDiff line numberDiff line change
@@ -537,13 +537,24 @@ class ColumnFamilyData {
537537
assert(!ts_low.empty());
538538
const Comparator* ucmp = user_comparator();
539539
assert(ucmp);
540+
// Guard against resurrected full_history_ts_low persisted in MANIFEST
541+
// from previous DB sessions. This could happen if UDT was enabled and then
542+
// disabled.
543+
if (ucmp->timestamp_size() == 0) {
544+
return;
545+
}
540546
if (full_history_ts_low_.empty() ||
541547
ucmp->CompareTimestamp(ts_low, full_history_ts_low_) > 0) {
542548
full_history_ts_low_ = std::move(ts_low);
543549
}
544550
}
545551

546552
const std::string& GetFullHistoryTsLow() const {
553+
const Comparator* ucmp = user_comparator();
554+
assert(ucmp);
555+
if (ucmp->timestamp_size() == 0) {
556+
assert(full_history_ts_low_.empty());
557+
}
547558
return full_history_ts_low_;
548559
}
549560

Diff for: db/db_with_timestamp_basic_test.cc

+77-29
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@
1919
#include "utilities/merge_operators/string_append/stringappend2.h"
2020

2121
namespace ROCKSDB_NAMESPACE {
22+
namespace {
23+
std::string EncodeAsUint64(uint64_t v) {
24+
std::string dst;
25+
PutFixed64(&dst, v);
26+
return dst;
27+
}
28+
} // namespace
2229
class DBBasicTestWithTimestamp : public DBBasicTestWithTimestampBase {
2330
public:
2431
DBBasicTestWithTimestamp()
@@ -3746,17 +3753,42 @@ INSTANTIATE_TEST_CASE_P(
37463753
test::UserDefinedTimestampTestMode::kStripUserDefinedTimestamp,
37473754
test::UserDefinedTimestampTestMode::kNormal));
37483755

3749-
TEST_F(DBBasicTestWithTimestamp, EnableDisableUDT) {
3756+
// Test params:
3757+
// 1) whether to flush before close
3758+
class EnableDisableUDTTest : public DBBasicTestWithTimestampBase,
3759+
public testing::WithParamInterface<bool> {
3760+
public:
3761+
EnableDisableUDTTest()
3762+
: DBBasicTestWithTimestampBase("/enable_disable_udt") {}
3763+
};
3764+
3765+
INSTANTIATE_TEST_CASE_P(EnableDisableUDTTest, EnableDisableUDTTest,
3766+
::testing::Values(true, false));
3767+
3768+
TEST_P(EnableDisableUDTTest, Basic) {
37503769
Options options = CurrentOptions();
3770+
// Un-flushed data before close will involve a WAL replay on DB reopen.
3771+
bool flush_before_close = GetParam();
37513772
options.env = env_;
3752-
// Create a column family without user-defined timestamps.
37533773
options.comparator = BytewiseComparator();
37543774
options.persist_user_defined_timestamps = true;
37553775
DestroyAndReopen(options);
37563776

3777+
ReadOptions ropts;
3778+
std::string read_ts;
3779+
std::string value;
3780+
std::string key_ts;
3781+
37573782
// Create one SST file, its user keys have no user-defined timestamps.
3758-
ASSERT_OK(db_->Put(WriteOptions(), "foo", "val1"));
3759-
ASSERT_OK(Flush(0));
3783+
ASSERT_OK(db_->Put(WriteOptions(), "foo", "val0"));
3784+
ASSERT_OK(db_->Put(WriteOptions(), "bar", "val0"));
3785+
ASSERT_OK(db_->DeleteRange(WriteOptions(), "bar", "baz"));
3786+
ASSERT_OK(db_->Get(ReadOptions(), "foo", &value));
3787+
ASSERT_EQ("val0", value);
3788+
ASSERT_TRUE(db_->Get(ReadOptions(), "bar", &value).IsNotFound());
3789+
if (flush_before_close) {
3790+
ASSERT_OK(Flush(0));
3791+
}
37603792
Close();
37613793

37623794
// Reopen the existing column family and enable user-defined timestamps
@@ -3765,47 +3797,63 @@ TEST_F(DBBasicTestWithTimestamp, EnableDisableUDT) {
37653797
options.persist_user_defined_timestamps = false;
37663798
options.allow_concurrent_memtable_write = false;
37673799
Reopen(options);
3768-
3769-
std::string value;
3770-
ASSERT_TRUE(db_->Get(ReadOptions(), "foo", &value).IsInvalidArgument());
3771-
std::string read_ts;
3772-
PutFixed64(&read_ts, 0);
3773-
ReadOptions ropts;
3800+
// Read data from previous session before and after compaction.
3801+
read_ts = EncodeAsUint64(1);
37743802
Slice read_ts_slice = read_ts;
37753803
ropts.timestamp = &read_ts_slice;
3776-
std::string key_ts;
3777-
// Entries in pre-existing SST files are treated as if they have minimum
3778-
// user-defined timestamps.
3779-
ASSERT_OK(db_->Get(ropts, "foo", &value, &key_ts));
3780-
ASSERT_EQ("val1", value);
3781-
ASSERT_EQ(read_ts, key_ts);
3804+
for (int i = 0; i < 2; i++) {
3805+
ASSERT_TRUE(db_->Get(ReadOptions(), "foo", &value).IsInvalidArgument());
3806+
// Entries in pre-existing SST files are treated as if they have minimum
3807+
// user-defined timestamps.
3808+
ASSERT_OK(db_->Get(ropts, "foo", &value, &key_ts));
3809+
ASSERT_EQ("val0", value);
3810+
ASSERT_EQ(EncodeAsUint64(0), key_ts);
3811+
ASSERT_TRUE(db_->Get(ropts, "bar", &value, &key_ts).IsNotFound());
3812+
ASSERT_OK(db_->CompactRange(CompactRangeOptions(), nullptr, nullptr));
3813+
}
37823814

37833815
// Do timestamped read / write.
3784-
std::string write_ts;
3785-
PutFixed64(&write_ts, 1);
3786-
ASSERT_OK(db_->Put(WriteOptions(), "foo", write_ts, "val2"));
3787-
read_ts.clear();
3788-
PutFixed64(&read_ts, 1);
3816+
ASSERT_OK(db_->Put(WriteOptions(), "foo", EncodeAsUint64(1), "val1"));
3817+
ASSERT_OK(db_->Put(WriteOptions(), "bar", EncodeAsUint64(1), "val1"));
3818+
ASSERT_OK(db_->DeleteRange(WriteOptions(), "bar", "baz", EncodeAsUint64(2)));
37893819
ASSERT_OK(db_->Get(ropts, "foo", &value, &key_ts));
3790-
ASSERT_EQ("val2", value);
3791-
ASSERT_EQ(write_ts, key_ts);
3820+
ASSERT_EQ("val1", value);
3821+
ASSERT_EQ(EncodeAsUint64(1), key_ts);
3822+
ASSERT_OK(db_->Get(ropts, "bar", &value, &key_ts));
3823+
ASSERT_EQ("val1", value);
3824+
ASSERT_EQ(EncodeAsUint64(1), key_ts);
3825+
read_ts = EncodeAsUint64(2);
3826+
ASSERT_TRUE(db_->Get(ropts, "bar", &value, &key_ts).IsNotFound());
37923827
// The user keys in this SST file don't have user-defined timestamps either,
37933828
// because `persist_user_defined_timestamps` flag is set to false.
3794-
ASSERT_OK(Flush(0));
3829+
if (flush_before_close) {
3830+
ASSERT_OK(Flush(0));
3831+
}
37953832
Close();
37963833

37973834
// Reopen the existing column family while disabling user-defined timestamps.
37983835
options.comparator = BytewiseComparator();
37993836
Reopen(options);
38003837

3801-
ASSERT_TRUE(db_->Get(ropts, "foo", &value).IsInvalidArgument());
3802-
ASSERT_OK(db_->Get(ReadOptions(), "foo", &value));
3803-
ASSERT_EQ("val2", value);
3838+
// Read data from previous session before and after compaction.
3839+
for (int i = 0; i < 2; i++) {
3840+
ASSERT_TRUE(db_->Get(ropts, "foo", &value).IsInvalidArgument());
3841+
ASSERT_OK(db_->Get(ReadOptions(), "foo", &value));
3842+
ASSERT_EQ("val1", value);
3843+
ASSERT_TRUE(db_->Get(ReadOptions(), "bar", &value).IsNotFound());
3844+
ASSERT_OK(db_->CompactRange(CompactRangeOptions(), nullptr, nullptr));
3845+
}
38043846

38053847
// Continue to write / read the column family without user-defined timestamps.
3806-
ASSERT_OK(db_->Put(WriteOptions(), "foo", "val3"));
3848+
ASSERT_OK(db_->Put(WriteOptions(), "foo", "val2"));
3849+
ASSERT_OK(db_->Put(WriteOptions(), "bar", "val2"));
3850+
ASSERT_OK(db_->DeleteRange(WriteOptions(), "bar", "baz"));
38073851
ASSERT_OK(db_->Get(ReadOptions(), "foo", &value));
3808-
ASSERT_EQ("val3", value);
3852+
ASSERT_EQ("val2", value);
3853+
ASSERT_TRUE(db_->Get(ReadOptions(), "bar", &value).IsNotFound());
3854+
if (flush_before_close) {
3855+
ASSERT_OK(Flush(0));
3856+
}
38093857
Close();
38103858
}
38113859

0 commit comments

Comments
 (0)