Fix rocksdb.estimate-num-keys DB property underflow

Summary:
rocksdb.estimate-num-keys is compute from `estimate_num_keys - 2 * estimate_num_deletes`. If  `2 * estimate_num_deletes > estimate_num_keys` it will underflow. Fixing it.
Closes https://github.com/facebook/rocksdb/pull/2348

Differential Revision: D5109272

Pulled By: yiwu-arbug

fbshipit-source-id: e1bfb91346a59b7282a282b615002507e9d7c246
This commit is contained in:
Yi Wu 2017-05-23 10:32:02 -07:00
parent 4646cd45c4
commit 0ccaba2a05
2 changed files with 20 additions and 6 deletions

View File

@ -1300,6 +1300,18 @@ TEST_F(DBPropertiesTest, NeedCompactHintPersistentTest) {
SetPerfLevel(kDisable); SetPerfLevel(kDisable);
} }
} }
TEST_F(DBPropertiesTest, EstimateNumKeysUnderflow) {
Options options;
Reopen(options);
Put("foo", "bar");
Delete("foo");
Delete("foo");
uint64_t num_keys = 0;
ASSERT_TRUE(dbfull()->GetIntProperty("rocksdb.estimate-num-keys", &num_keys));
ASSERT_EQ(0, num_keys);
}
#endif // ROCKSDB_LITE #endif // ROCKSDB_LITE
} // namespace rocksdb } // namespace rocksdb

View File

@ -677,12 +677,14 @@ bool InternalStats::HandleEstimateNumKeys(uint64_t* value, DBImpl* db,
// Estimate number of entries in the column family: // Estimate number of entries in the column family:
// Use estimated entries in tables + total entries in memtables. // Use estimated entries in tables + total entries in memtables.
const auto* vstorage = cfd_->current()->storage_info(); const auto* vstorage = cfd_->current()->storage_info();
*value = cfd_->mem()->num_entries() + uint64_t estimate_keys = cfd_->mem()->num_entries() +
cfd_->imm()->current()->GetTotalNumEntries() - cfd_->imm()->current()->GetTotalNumEntries() +
(cfd_->mem()->num_deletes() +
cfd_->imm()->current()->GetTotalNumDeletes()) *
2 +
vstorage->GetEstimatedActiveKeys(); vstorage->GetEstimatedActiveKeys();
uint64_t estimate_deletes =
cfd_->mem()->num_deletes() + cfd_->imm()->current()->GetTotalNumDeletes();
*value = estimate_keys > estimate_deletes * 2
? estimate_keys - (estimate_deletes * 2)
: 0;
return true; return true;
} }