diff --git a/db/db_basic_test.cc b/db/db_basic_test.cc index 137817eef..6854c8467 100644 --- a/db/db_basic_test.cc +++ b/db/db_basic_test.cc @@ -524,6 +524,7 @@ TEST_F(DBBasicTest, Snapshot) { ASSERT_EQ(1U, GetNumSnapshots()); uint64_t time_snap1 = GetTimeOldestSnapshots(); ASSERT_GT(time_snap1, 0U); + ASSERT_EQ(GetSequenceOldestSnapshots(), s1->GetSequenceNumber()); Put(0, "foo", "0v2"); Put(1, "foo", "1v2"); @@ -532,6 +533,7 @@ TEST_F(DBBasicTest, Snapshot) { const Snapshot* s2 = db_->GetSnapshot(); ASSERT_EQ(2U, GetNumSnapshots()); ASSERT_EQ(time_snap1, GetTimeOldestSnapshots()); + ASSERT_EQ(GetSequenceOldestSnapshots(), s1->GetSequenceNumber()); Put(0, "foo", "0v3"); Put(1, "foo", "1v3"); @@ -539,6 +541,7 @@ TEST_F(DBBasicTest, Snapshot) { ManagedSnapshot s3(db_); ASSERT_EQ(3U, GetNumSnapshots()); ASSERT_EQ(time_snap1, GetTimeOldestSnapshots()); + ASSERT_EQ(GetSequenceOldestSnapshots(), s1->GetSequenceNumber()); Put(0, "foo", "0v4"); Put(1, "foo", "1v4"); @@ -554,6 +557,7 @@ TEST_F(DBBasicTest, Snapshot) { ASSERT_EQ(2U, GetNumSnapshots()); ASSERT_EQ(time_snap1, GetTimeOldestSnapshots()); + ASSERT_EQ(GetSequenceOldestSnapshots(), s1->GetSequenceNumber()); ASSERT_EQ("0v1", Get(0, "foo", s1)); ASSERT_EQ("1v1", Get(1, "foo", s1)); ASSERT_EQ("0v2", Get(0, "foo", s2)); @@ -568,9 +572,11 @@ TEST_F(DBBasicTest, Snapshot) { ASSERT_EQ("1v4", Get(1, "foo")); ASSERT_EQ(1U, GetNumSnapshots()); ASSERT_LT(time_snap1, GetTimeOldestSnapshots()); + ASSERT_EQ(GetSequenceOldestSnapshots(), s2->GetSequenceNumber()); db_->ReleaseSnapshot(s2); ASSERT_EQ(0U, GetNumSnapshots()); + ASSERT_EQ(GetSequenceOldestSnapshots(), 0); ASSERT_EQ("0v4", Get(0, "foo")); ASSERT_EQ("1v4", Get(1, "foo")); } while (ChangeOptions()); diff --git a/db/db_test.cc b/db/db_test.cc index 16d1a4dee..28d886208 100644 --- a/db/db_test.cc +++ b/db/db_test.cc @@ -1705,6 +1705,7 @@ TEST_F(DBTest, Snapshot) { ASSERT_EQ(1U, GetNumSnapshots()); uint64_t time_snap1 = GetTimeOldestSnapshots(); ASSERT_GT(time_snap1, 0U); + ASSERT_EQ(GetSequenceOldestSnapshots(), s1->GetSequenceNumber()); Put(0, "foo", "0v2"); Put(1, "foo", "1v2"); @@ -1713,6 +1714,7 @@ TEST_F(DBTest, Snapshot) { const Snapshot* s2 = db_->GetSnapshot(); ASSERT_EQ(2U, GetNumSnapshots()); ASSERT_EQ(time_snap1, GetTimeOldestSnapshots()); + ASSERT_EQ(GetSequenceOldestSnapshots(), s1->GetSequenceNumber()); Put(0, "foo", "0v3"); Put(1, "foo", "1v3"); @@ -1720,6 +1722,7 @@ TEST_F(DBTest, Snapshot) { ManagedSnapshot s3(db_); ASSERT_EQ(3U, GetNumSnapshots()); ASSERT_EQ(time_snap1, GetTimeOldestSnapshots()); + ASSERT_EQ(GetSequenceOldestSnapshots(), s1->GetSequenceNumber()); Put(0, "foo", "0v4"); Put(1, "foo", "1v4"); @@ -1735,6 +1738,7 @@ TEST_F(DBTest, Snapshot) { ASSERT_EQ(2U, GetNumSnapshots()); ASSERT_EQ(time_snap1, GetTimeOldestSnapshots()); + ASSERT_EQ(GetSequenceOldestSnapshots(), s1->GetSequenceNumber()); ASSERT_EQ("0v1", Get(0, "foo", s1)); ASSERT_EQ("1v1", Get(1, "foo", s1)); ASSERT_EQ("0v2", Get(0, "foo", s2)); @@ -1749,9 +1753,11 @@ TEST_F(DBTest, Snapshot) { ASSERT_EQ("1v4", Get(1, "foo")); ASSERT_EQ(1U, GetNumSnapshots()); ASSERT_LT(time_snap1, GetTimeOldestSnapshots()); + ASSERT_EQ(GetSequenceOldestSnapshots(), s2->GetSequenceNumber()); db_->ReleaseSnapshot(s2); ASSERT_EQ(0U, GetNumSnapshots()); + ASSERT_EQ(GetSequenceOldestSnapshots(), 0); ASSERT_EQ("0v4", Get(0, "foo")); ASSERT_EQ("1v4", Get(1, "foo")); } while (ChangeOptions()); diff --git a/db/db_test_util.cc b/db/db_test_util.cc index a6842b728..4594ab9af 100644 --- a/db/db_test_util.cc +++ b/db/db_test_util.cc @@ -867,6 +867,13 @@ uint64_t DBTestBase::GetTimeOldestSnapshots() { return int_num; } +uint64_t DBTestBase::GetSequenceOldestSnapshots() { + uint64_t int_num; + EXPECT_TRUE( + dbfull()->GetIntProperty("rocksdb.oldest-snapshot-sequence", &int_num)); + return int_num; +} + // Return a string that contains all key,value pairs in order, // formatted like "(k1->v1)(k2->v2)". std::string DBTestBase::Contents(int cf) { diff --git a/db/db_test_util.h b/db/db_test_util.h index c9678ee1c..4b36783cc 100644 --- a/db/db_test_util.h +++ b/db/db_test_util.h @@ -860,6 +860,8 @@ class DBTestBase : public testing::Test { uint64_t GetTimeOldestSnapshots(); + uint64_t GetSequenceOldestSnapshots(); + // Return a string that contains all key,value pairs in order, // formatted like "(k1->v1)(k2->v2)". std::string Contents(int cf = 0); diff --git a/db/internal_stats.cc b/db/internal_stats.cc index 94d9cd8ac..ced1c608e 100644 --- a/db/internal_stats.cc +++ b/db/internal_stats.cc @@ -231,6 +231,7 @@ static const std::string is_file_deletions_enabled = "is-file-deletions-enabled"; static const std::string num_snapshots = "num-snapshots"; static const std::string oldest_snapshot_time = "oldest-snapshot-time"; +static const std::string oldest_snapshot_sequence = "oldest-snapshot-sequence"; static const std::string num_live_versions = "num-live-versions"; static const std::string current_version_number = "current-super-version-number"; @@ -309,6 +310,8 @@ const std::string DB::Properties::kNumSnapshots = rocksdb_prefix + num_snapshots; const std::string DB::Properties::kOldestSnapshotTime = rocksdb_prefix + oldest_snapshot_time; +const std::string DB::Properties::kOldestSnapshotSequence = + rocksdb_prefix + oldest_snapshot_sequence; const std::string DB::Properties::kNumLiveVersions = rocksdb_prefix + num_live_versions; const std::string DB::Properties::kCurrentSuperVersionNumber = @@ -427,6 +430,9 @@ const std::unordered_map {DB::Properties::kOldestSnapshotTime, {false, nullptr, &InternalStats::HandleOldestSnapshotTime, nullptr, nullptr}}, + {DB::Properties::kOldestSnapshotSequence, + {false, nullptr, &InternalStats::HandleOldestSnapshotSequence, nullptr, + nullptr}}, {DB::Properties::kNumLiveVersions, {false, nullptr, &InternalStats::HandleNumLiveVersions, nullptr, nullptr}}, @@ -772,6 +778,12 @@ bool InternalStats::HandleOldestSnapshotTime(uint64_t* value, DBImpl* db, return true; } +bool InternalStats::HandleOldestSnapshotSequence(uint64_t* value, DBImpl* db, + Version* /*version*/) { + *value = static_cast(db->snapshots().GetOldestSnapshotSequence()); + return true; +} + bool InternalStats::HandleNumLiveVersions(uint64_t* value, DBImpl* /*db*/, Version* /*version*/) { *value = cfd_->GetNumLiveVersions(); diff --git a/db/internal_stats.h b/db/internal_stats.h index 24a8d98e6..aa4eda537 100644 --- a/db/internal_stats.h +++ b/db/internal_stats.h @@ -553,6 +553,8 @@ class InternalStats { bool HandleEstimateNumKeys(uint64_t* value, DBImpl* db, Version* version); bool HandleNumSnapshots(uint64_t* value, DBImpl* db, Version* version); bool HandleOldestSnapshotTime(uint64_t* value, DBImpl* db, Version* version); + bool HandleOldestSnapshotSequence(uint64_t* value, DBImpl* db, + Version* version); bool HandleNumLiveVersions(uint64_t* value, DBImpl* db, Version* version); bool HandleCurrentSuperVersionNumber(uint64_t* value, DBImpl* db, Version* version); diff --git a/db/snapshot_impl.h b/db/snapshot_impl.h index f1cf6f4b7..f6ee47628 100644 --- a/db/snapshot_impl.h +++ b/db/snapshot_impl.h @@ -148,6 +148,14 @@ class SnapshotList { } } + int64_t GetOldestSnapshotSequence() const { + if (empty()) { + return 0; + } else { + return oldest()->GetSequenceNumber(); + } + } + uint64_t count() const { return count_; } private: diff --git a/include/rocksdb/db.h b/include/rocksdb/db.h index e4bbe7871..cee86e99f 100644 --- a/include/rocksdb/db.h +++ b/include/rocksdb/db.h @@ -716,6 +716,10 @@ class DB { // timestamp of oldest unreleased snapshot. static const std::string kOldestSnapshotTime; + // "rocksdb.oldest-snapshot-sequence" - returns number representing + // sequence number of oldest unreleased snapshot. + static const std::string kOldestSnapshotSequence; + // "rocksdb.num-live-versions" - returns number of live versions. `Version` // is an internal data structure. See version_set.h for details. More // live versions often mean more SST files are held from being deleted,