Eliminate duplicated property constants

Summary:
Before this diff, there were duplicated constants to refer to properties (user-
facing API had strings and InternalStats had an enum). I noticed these were
inconsistent in terms of which constants are provided, names of constants, and
documentation of constants. Overall it seemed annoying/error-prone to maintain
these duplicated constants.

So, this diff gets rid of InternalStats's constants and replaces them with a map
keyed on the user-facing constant. The value in that map contains a function
pointer to get the property value, so we don't need to do string matching while
holding db->mutex_. This approach has a side benefit of making many small
handler functions rather than a giant switch-statement.

Test Plan: db_properties_test passes, running "make commit-prereq -j32"

Reviewers: sdong, yhchiang, kradhakrishnan, IslamAbdelRahman, rven, anthony

Reviewed By: anthony

Subscribers: dhruba, leveldb

Differential Revision: https://reviews.facebook.net/D53253
This commit is contained in:
Andrew Kryczka 2016-02-02 19:14:56 -08:00
parent 94be872eab
commit 284aa613a7
6 changed files with 500 additions and 391 deletions

View File

@ -494,23 +494,22 @@ void DBImpl::MaybeDumpStats() {
last_stats_dump_time_microsec_ = now_micros; last_stats_dump_time_microsec_ = now_micros;
#ifndef ROCKSDB_LITE #ifndef ROCKSDB_LITE
bool tmp1 = false; const DBPropertyInfo* cf_property_info =
bool tmp2 = false; GetPropertyInfo(DB::Properties::kCFStats);
DBPropertyType cf_property_type = assert(cf_property_info != nullptr);
GetPropertyType(DB::Properties::kCFStats, &tmp1, &tmp2); const DBPropertyInfo* db_property_info =
DBPropertyType db_property_type = GetPropertyInfo(DB::Properties::kDBStats);
GetPropertyType(DB::Properties::kDBStats, &tmp1, &tmp2); assert(db_property_info != nullptr);
std::string stats; std::string stats;
{ {
InstrumentedMutexLock l(&mutex_); InstrumentedMutexLock l(&mutex_);
for (auto cfd : *versions_->GetColumnFamilySet()) { for (auto cfd : *versions_->GetColumnFamilySet()) {
cfd->internal_stats()->GetStringProperty(cf_property_type, cfd->internal_stats()->GetStringProperty(
DB::Properties::kCFStats, *cf_property_info, DB::Properties::kCFStats, &stats);
&stats);
} }
default_cf_internal_stats_->GetStringProperty(db_property_type, default_cf_internal_stats_->GetStringProperty(
DB::Properties::kDBStats, *db_property_info, DB::Properties::kDBStats, &stats);
&stats);
} }
Log(InfoLogLevel::WARN_LEVEL, Log(InfoLogLevel::WARN_LEVEL,
db_options_.info_log, "------- DUMPING STATS -------"); db_options_.info_log, "------- DUMPING STATS -------");
@ -4701,53 +4700,51 @@ const DBOptions& DBImpl::GetDBOptions() const { return db_options_; }
bool DBImpl::GetProperty(ColumnFamilyHandle* column_family, bool DBImpl::GetProperty(ColumnFamilyHandle* column_family,
const Slice& property, std::string* value) { const Slice& property, std::string* value) {
bool is_int_property = false; const DBPropertyInfo* property_info = GetPropertyInfo(property);
bool need_out_of_mutex = false;
DBPropertyType property_type =
GetPropertyType(property, &is_int_property, &need_out_of_mutex);
value->clear(); value->clear();
auto cfd = reinterpret_cast<ColumnFamilyHandleImpl*>(column_family)->cfd(); auto cfd = reinterpret_cast<ColumnFamilyHandleImpl*>(column_family)->cfd();
if (is_int_property) { if (property_info == nullptr) {
return false;
} else if (property_info->handle_int) {
uint64_t int_value; uint64_t int_value;
bool ret_value = GetIntPropertyInternal( bool ret_value =
cfd, property_type, need_out_of_mutex, false, &int_value); GetIntPropertyInternal(cfd, *property_info, false, &int_value);
if (ret_value) { if (ret_value) {
*value = ToString(int_value); *value = ToString(int_value);
} }
return ret_value; return ret_value;
} else { } else if (property_info->handle_string) {
InstrumentedMutexLock l(&mutex_); InstrumentedMutexLock l(&mutex_);
return cfd->internal_stats()->GetStringProperty(property_type, property, return cfd->internal_stats()->GetStringProperty(*property_info, property,
value); value);
} }
// Shouldn't reach here since exactly one of handle_string and handle_int
// should be non-nullptr.
assert(false);
return false;
} }
bool DBImpl::GetIntProperty(ColumnFamilyHandle* column_family, bool DBImpl::GetIntProperty(ColumnFamilyHandle* column_family,
const Slice& property, uint64_t* value) { const Slice& property, uint64_t* value) {
bool is_int_property = false; const DBPropertyInfo* property_info = GetPropertyInfo(property);
bool need_out_of_mutex = false; if (property_info == nullptr || property_info->handle_int == nullptr) {
DBPropertyType property_type =
GetPropertyType(property, &is_int_property, &need_out_of_mutex);
if (!is_int_property) {
return false; return false;
} }
auto cfd = reinterpret_cast<ColumnFamilyHandleImpl*>(column_family)->cfd(); auto cfd = reinterpret_cast<ColumnFamilyHandleImpl*>(column_family)->cfd();
return GetIntPropertyInternal(cfd, property_type, need_out_of_mutex, false, return GetIntPropertyInternal(cfd, *property_info, false, value);
value);
} }
bool DBImpl::GetIntPropertyInternal(ColumnFamilyData* cfd, bool DBImpl::GetIntPropertyInternal(ColumnFamilyData* cfd,
DBPropertyType property_type, const DBPropertyInfo& property_info,
bool need_out_of_mutex, bool is_locked, bool is_locked, uint64_t* value) {
uint64_t* value) { assert(property_info.handle_int != nullptr);
if (!need_out_of_mutex) { if (!property_info.need_out_of_mutex) {
if (is_locked) { if (is_locked) {
mutex_.AssertHeld(); mutex_.AssertHeld();
return cfd->internal_stats()->GetIntProperty(property_type, value, this); return cfd->internal_stats()->GetIntProperty(property_info, value, this);
} else { } else {
InstrumentedMutexLock l(&mutex_); InstrumentedMutexLock l(&mutex_);
return cfd->internal_stats()->GetIntProperty(property_type, value, this); return cfd->internal_stats()->GetIntProperty(property_info, value, this);
} }
} else { } else {
SuperVersion* sv = nullptr; SuperVersion* sv = nullptr;
@ -4758,7 +4755,7 @@ bool DBImpl::GetIntPropertyInternal(ColumnFamilyData* cfd,
} }
bool ret = cfd->internal_stats()->GetIntPropertyOutOfMutex( bool ret = cfd->internal_stats()->GetIntPropertyOutOfMutex(
property_type, sv->current, value); property_info, sv->current, value);
if (!is_locked) { if (!is_locked) {
ReturnAndCleanupSuperVersion(cfd, sv); ReturnAndCleanupSuperVersion(cfd, sv);
@ -4770,11 +4767,8 @@ bool DBImpl::GetIntPropertyInternal(ColumnFamilyData* cfd,
bool DBImpl::GetAggregatedIntProperty(const Slice& property, bool DBImpl::GetAggregatedIntProperty(const Slice& property,
uint64_t* aggregated_value) { uint64_t* aggregated_value) {
bool need_out_of_mutex; const DBPropertyInfo* property_info = GetPropertyInfo(property);
bool is_int_property; if (property_info == nullptr || property_info->handle_int == nullptr) {
DBPropertyType property_type =
GetPropertyType(property, &is_int_property, &need_out_of_mutex);
if (!is_int_property) {
return false; return false;
} }
@ -4784,8 +4778,7 @@ bool DBImpl::GetAggregatedIntProperty(const Slice& property,
InstrumentedMutexLock l(&mutex_); InstrumentedMutexLock l(&mutex_);
uint64_t value; uint64_t value;
for (auto* cfd : *versions_->GetColumnFamilySet()) { for (auto* cfd : *versions_->GetColumnFamilySet()) {
if (GetIntPropertyInternal(cfd, property_type, need_out_of_mutex, true, if (GetIntPropertyInternal(cfd, *property_info, true, &value)) {
&value)) {
sum += value; sum += value;
} else { } else {
return false; return false;

View File

@ -893,9 +893,8 @@ class DBImpl : public DB {
bool* value_found = nullptr); bool* value_found = nullptr);
bool GetIntPropertyInternal(ColumnFamilyData* cfd, bool GetIntPropertyInternal(ColumnFamilyData* cfd,
DBPropertyType property_type, const DBPropertyInfo& property_info,
bool need_out_of_mutex, bool is_locked, bool is_locked, uint64_t* value);
uint64_t* value);
bool HasPendingManualCompaction(); bool HasPendingManualCompaction();
bool HasExclusiveManualCompaction(); bool HasExclusiveManualCompaction();

View File

@ -226,6 +226,18 @@ void GetExpectedTableProperties(TableProperties* expected_tp,
} }
} // anonymous namespace } // anonymous namespace
TEST_F(DBPropertiesTest, ValidatePropertyInfo) {
for (const auto& ppt_name_and_info : InternalStats::ppt_name_to_info) {
// If C++ gets a std::string_literal, this would be better to check at
// compile-time using static_assert.
ASSERT_TRUE(ppt_name_and_info.first.empty() ||
!isdigit(ppt_name_and_info.first.back()));
ASSERT_TRUE((ppt_name_and_info.second.handle_string == nullptr) !=
(ppt_name_and_info.second.handle_int == nullptr));
}
}
TEST_F(DBPropertiesTest, AggregatedTableProperties) { TEST_F(DBPropertiesTest, AggregatedTableProperties) {
for (int kTableCount = 40; kTableCount <= 100; kTableCount += 30) { for (int kTableCount = 40; kTableCount <= 100; kTableCount += 30) {
const int kKeysPerTable = 100; const int kKeysPerTable = 100;

View File

@ -15,6 +15,7 @@
#include <inttypes.h> #include <inttypes.h>
#include <string> #include <string>
#include <algorithm> #include <algorithm>
#include <utility>
#include <vector> #include <vector>
#include "db/column_family.h" #include "db/column_family.h"
@ -81,7 +82,21 @@ void PrintLevelStats(char* buf, size_t len, const std::string& name,
stats.count == 0 ? 0 : stats.micros / kMicrosInSec / stats.count, stats.count == 0 ? 0 : stats.micros / kMicrosInSec / stats.count,
num_input_records.c_str(), num_dropped_records.c_str()); num_input_records.c_str(), num_dropped_records.c_str());
} }
// Assumes that trailing numbers represent an optional argument. This requires
// property names to not end with numbers.
std::pair<Slice, Slice> GetPropertyNameAndArg(const Slice& property) {
Slice name = property, arg = property;
size_t sfx_len = 0;
while (sfx_len < property.size() &&
isdigit(property[property.size() - sfx_len - 1])) {
++sfx_len;
}
name.remove_suffix(sfx_len);
arg.remove_prefix(property.size() - sfx_len);
return {name, arg};
} }
} // anonymous namespace
static const std::string rocksdb_prefix = "rocksdb."; static const std::string rocksdb_prefix = "rocksdb.";
@ -188,125 +203,111 @@ const std::string DB::Properties::kAggregatedTableProperties =
const std::string DB::Properties::kAggregatedTablePropertiesAtLevel = const std::string DB::Properties::kAggregatedTablePropertiesAtLevel =
rocksdb_prefix + aggregated_table_properties_at_level; rocksdb_prefix + aggregated_table_properties_at_level;
DBPropertyType GetPropertyType(const Slice& property, bool* is_int_property, const std::unordered_map<std::string,
bool* need_out_of_mutex) { DBPropertyInfo> InternalStats::ppt_name_to_info = {
assert(is_int_property != nullptr); {DB::Properties::kNumFilesAtLevelPrefix,
assert(need_out_of_mutex != nullptr); {false, &InternalStats::HandleNumFilesAtLevel, nullptr}},
Slice in = property; {DB::Properties::kLevelStats,
Slice prefix(rocksdb_prefix); {false, &InternalStats::HandleLevelStats, nullptr}},
*need_out_of_mutex = false; {DB::Properties::kStats, {false, &InternalStats::HandleStats, nullptr}},
*is_int_property = false; {DB::Properties::kCFStats, {false, &InternalStats::HandleCFStats, nullptr}},
if (!in.starts_with(prefix)) { {DB::Properties::kDBStats, {false, &InternalStats::HandleDBStats, nullptr}},
return kUnknown; {DB::Properties::kSSTables,
} {false, &InternalStats::HandleSsTables, nullptr}},
in.remove_prefix(prefix.size()); {DB::Properties::kAggregatedTableProperties,
{false, &InternalStats::HandleAggregatedTableProperties, nullptr}},
{DB::Properties::kAggregatedTablePropertiesAtLevel,
{false, &InternalStats::HandleAggregatedTablePropertiesAtLevel, nullptr}},
{DB::Properties::kNumImmutableMemTable,
{false, nullptr, &InternalStats::HandleNumImmutableMemTable}},
{DB::Properties::kNumImmutableMemTableFlushed,
{false, nullptr, &InternalStats::HandleNumImmutableMemTableFlushed}},
{DB::Properties::kMemTableFlushPending,
{false, nullptr, &InternalStats::HandleMemTableFlushPending}},
{DB::Properties::kCompactionPending,
{false, nullptr, &InternalStats::HandleCompactionPending}},
{DB::Properties::kBackgroundErrors,
{false, nullptr, &InternalStats::HandleBackgroundErrors}},
{DB::Properties::kCurSizeActiveMemTable,
{false, nullptr, &InternalStats::HandleCurSizeActiveMemTable}},
{DB::Properties::kCurSizeAllMemTables,
{false, nullptr, &InternalStats::HandleCurSizeAllMemTables}},
{DB::Properties::kSizeAllMemTables,
{false, nullptr, &InternalStats::HandleSizeAllMemTables}},
{DB::Properties::kNumEntriesActiveMemTable,
{false, nullptr, &InternalStats::HandleNumEntriesActiveMemTable}},
{DB::Properties::kNumEntriesImmMemTables,
{false, nullptr, &InternalStats::HandleNumEntriesImmMemTables}},
{DB::Properties::kNumDeletesActiveMemTable,
{false, nullptr, &InternalStats::HandleNumDeletesActiveMemTable}},
{DB::Properties::kNumDeletesImmMemTables,
{false, nullptr, &InternalStats::HandleNumDeletesImmMemTables}},
{DB::Properties::kEstimateNumKeys,
{false, nullptr, &InternalStats::HandleEstimateNumKeys}},
{DB::Properties::kEstimateTableReadersMem,
{true, nullptr, &InternalStats::HandleEstimateTableReadersMem}},
{DB::Properties::kIsFileDeletionsEnabled,
{false, nullptr, &InternalStats::HandleIsFileDeletionsEnabled}},
{DB::Properties::kNumSnapshots,
{false, nullptr, &InternalStats::HandleNumSnapshots}},
{DB::Properties::kOldestSnapshotTime,
{false, nullptr, &InternalStats::HandleOldestSnapshotTime}},
{DB::Properties::kNumLiveVersions,
{false, nullptr, &InternalStats::HandleNumLiveVersions}},
{DB::Properties::kEstimateLiveDataSize,
{true, nullptr, &InternalStats::HandleEstimateLiveDataSize}},
{DB::Properties::kBaseLevel,
{false, nullptr, &InternalStats::HandleBaseLevel}},
{DB::Properties::kTotalSstFilesSize,
{false, nullptr, &InternalStats::HandleTotalSstFilesSize}},
{DB::Properties::kEstimatePendingCompactionBytes,
{false, nullptr, &InternalStats::HandleEstimatePendingCompactionBytes}},
{DB::Properties::kNumRunningFlushes,
{false, nullptr, &InternalStats::HandleNumRunningFlushes}},
{DB::Properties::kNumRunningCompactions,
{false, nullptr, &InternalStats::HandleNumRunningCompactions}},
};
if (in.starts_with(num_files_at_level_prefix)) { const DBPropertyInfo* GetPropertyInfo(const Slice& property) {
return kNumFilesAtLevel; std::string ppt_name = GetPropertyNameAndArg(property).first.ToString();
} else if (in == levelstats) { auto ppt_info_iter = InternalStats::ppt_name_to_info.find(ppt_name);
return kLevelStats; if (ppt_info_iter == InternalStats::ppt_name_to_info.end()) {
} else if (in == allstats) { return nullptr;
return kStats;
} else if (in == cfstats) {
return kCFStats;
} else if (in == dbstats) {
return kDBStats;
} else if (in == sstables) {
return kSsTables;
} else if (in == aggregated_table_properties) {
return kAggregatedTableProperties;
} else if (in.starts_with(aggregated_table_properties_at_level)) {
return kAggregatedTablePropertiesAtLevel;
} }
return &ppt_info_iter->second;
*is_int_property = true;
if (in == num_immutable_mem_table) {
return kNumImmutableMemTable;
} else if (in == num_immutable_mem_table_flushed) {
return kNumImmutableMemTableFlushed;
} else if (in == mem_table_flush_pending) {
return kMemtableFlushPending;
} else if (in == compaction_pending) {
return kCompactionPending;
} else if (in == background_errors) {
return kBackgroundErrors;
} else if (in == cur_size_active_mem_table) {
return kCurSizeActiveMemTable;
} else if (in == cur_size_all_mem_tables) {
return kCurSizeAllMemTables;
} else if (in == size_all_mem_tables) {
return kSizeAllMemTables;
} else if (in == num_entries_active_mem_table) {
return kNumEntriesInMutableMemtable;
} else if (in == num_entries_imm_mem_tables) {
return kNumEntriesInImmutableMemtable;
} else if (in == num_deletes_active_mem_table) {
return kNumDeletesInMutableMemtable;
} else if (in == num_deletes_imm_mem_tables) {
return kNumDeletesInImmutableMemtable;
} else if (in == estimate_num_keys) {
return kEstimatedNumKeys;
} else if (in == estimate_table_readers_mem) {
*need_out_of_mutex = true;
return kEstimatedUsageByTableReaders;
} else if (in == is_file_deletions_enabled) {
return kIsFileDeletionEnabled;
} else if (in == num_snapshots) {
return kNumSnapshots;
} else if (in == oldest_snapshot_time) {
return kOldestSnapshotTime;
} else if (in == num_live_versions) {
return kNumLiveVersions;
} else if (in == estimate_live_data_size) {
*need_out_of_mutex = true;
return kEstimateLiveDataSize;
} else if (in == base_level) {
return kBaseLevel;
} else if (in == total_sst_files_size) {
return kTotalSstFilesSize;
} else if (in == estimate_pending_comp_bytes) {
return kEstimatePendingCompactionBytes;
} else if (in == num_running_flushes) {
return kNumRunningFlushes;
} else if (in == num_running_compactions) {
return kNumRunningCompactions;
}
return kUnknown;
} }
bool InternalStats::GetIntPropertyOutOfMutex(DBPropertyType property_type, bool InternalStats::GetStringProperty(const DBPropertyInfo& property_info,
Version* version,
uint64_t* value) const {
assert(value != nullptr);
const auto* vstorage = cfd_->current()->storage_info();
switch (property_type) {
case kEstimatedUsageByTableReaders:
*value = (version == nullptr) ?
0 : version->GetMemoryUsageByTableReaders();
return true;
case kEstimateLiveDataSize:
*value = vstorage->EstimateLiveDataSize();
return true;
default:
return false;
}
}
bool InternalStats::GetStringProperty(DBPropertyType property_type,
const Slice& property, const Slice& property,
std::string* value) { std::string* value) {
assert(value != nullptr); assert(value != nullptr);
auto* current = cfd_->current(); assert(property_info.handle_string != nullptr);
const auto* vstorage = current->storage_info(); Slice arg = GetPropertyNameAndArg(property).second;
Slice in = property; return (this->*(property_info.handle_string))(value, arg);
}
switch (property_type) { bool InternalStats::GetIntProperty(const DBPropertyInfo& property_info,
case kNumFilesAtLevel: { uint64_t* value, DBImpl* db) {
in.remove_prefix(strlen("rocksdb.num-files-at-level")); assert(value != nullptr);
assert(property_info.handle_int != nullptr &&
!property_info.need_out_of_mutex);
db->mutex_.AssertHeld();
return (this->*(property_info.handle_int))(value, db, nullptr /* version */);
}
bool InternalStats::GetIntPropertyOutOfMutex(
const DBPropertyInfo& property_info, Version* version, uint64_t* value) {
assert(value != nullptr);
assert(property_info.handle_int != nullptr &&
property_info.need_out_of_mutex);
return (this->*(property_info.handle_int))(value, nullptr /* db */, version);
}
bool InternalStats::HandleNumFilesAtLevel(std::string* value, Slice suffix) {
uint64_t level; uint64_t level;
bool ok = ConsumeDecimalNumber(&in, &level) && in.empty(); const auto* vstorage = cfd_->current()->storage_info();
if (!ok || (int)level >= number_levels_) { bool ok = ConsumeDecimalNumber(&suffix, &level) && suffix.empty();
if (!ok || static_cast<int>(level) >= number_levels_) {
return false; return false;
} else { } else {
char buf[100]; char buf[100];
@ -315,9 +316,11 @@ bool InternalStats::GetStringProperty(DBPropertyType property_type,
*value = buf; *value = buf;
return true; return true;
} }
} }
case kLevelStats: {
bool InternalStats::HandleLevelStats(std::string* value, Slice suffix) {
char buf[1000]; char buf[1000];
const auto* vstorage = cfd_->current()->storage_info();
snprintf(buf, sizeof(buf), snprintf(buf, sizeof(buf),
"Level Files Size(MB)\n" "Level Files Size(MB)\n"
"--------------------\n"); "--------------------\n");
@ -330,28 +333,36 @@ bool InternalStats::GetStringProperty(DBPropertyType property_type,
value->append(buf); value->append(buf);
} }
return true; return true;
} }
case kStats: {
if (!GetStringProperty(kCFStats, DB::Properties::kCFStats, value)) { bool InternalStats::HandleStats(std::string* value, Slice suffix) {
if (!HandleCFStats(value, suffix)) {
return false; return false;
} }
if (!GetStringProperty(kDBStats, DB::Properties::kDBStats, value)) { if (!HandleDBStats(value, suffix)) {
return false; return false;
} }
return true; return true;
} }
case kCFStats: {
bool InternalStats::HandleCFStats(std::string* value, Slice suffix) {
DumpCFStats(value); DumpCFStats(value);
return true; return true;
} }
case kDBStats: {
bool InternalStats::HandleDBStats(std::string* value, Slice suffix) {
DumpDBStats(value); DumpDBStats(value);
return true; return true;
} }
case kSsTables:
bool InternalStats::HandleSsTables(std::string* value, Slice suffix) {
auto* current = cfd_->current();
*value = current->DebugString(); *value = current->DebugString();
return true; return true;
case kAggregatedTableProperties: { }
bool InternalStats::HandleAggregatedTableProperties(std::string* value,
Slice suffix) {
std::shared_ptr<const TableProperties> tp; std::shared_ptr<const TableProperties> tp;
auto s = cfd_->current()->GetAggregatedTableProperties(&tp); auto s = cfd_->current()->GetAggregatedTableProperties(&tp);
if (!s.ok()) { if (!s.ok()) {
@ -359,12 +370,12 @@ bool InternalStats::GetStringProperty(DBPropertyType property_type,
} }
*value = tp->ToString(); *value = tp->ToString();
return true; return true;
} }
case kAggregatedTablePropertiesAtLevel: {
in.remove_prefix( bool InternalStats::HandleAggregatedTablePropertiesAtLevel(std::string* value,
DB::Properties::kAggregatedTablePropertiesAtLevel.length()); Slice suffix) {
uint64_t level; uint64_t level;
bool ok = ConsumeDecimalNumber(&in, &level) && in.empty(); bool ok = ConsumeDecimalNumber(&suffix, &level) && suffix.empty();
if (!ok || static_cast<int>(level) >= number_levels_) { if (!ok || static_cast<int>(level) >= number_levels_) {
return false; return false;
} }
@ -376,75 +387,111 @@ bool InternalStats::GetStringProperty(DBPropertyType property_type,
} }
*value = tp->ToString(); *value = tp->ToString();
return true; return true;
}
default:
return false;
}
} }
bool InternalStats::GetIntProperty(DBPropertyType property_type, bool InternalStats::HandleNumImmutableMemTable(uint64_t* value, DBImpl* db,
uint64_t* value, DBImpl* db) const { Version* version) {
db->mutex_.AssertHeld();
const auto* vstorage = cfd_->current()->storage_info();
switch (property_type) {
case kNumImmutableMemTable:
*value = cfd_->imm()->NumNotFlushed(); *value = cfd_->imm()->NumNotFlushed();
return true; return true;
case kNumImmutableMemTableFlushed: }
bool InternalStats::HandleNumImmutableMemTableFlushed(uint64_t* value,
DBImpl* db,
Version* version) {
*value = cfd_->imm()->NumFlushed(); *value = cfd_->imm()->NumFlushed();
return true; return true;
case kMemtableFlushPending: }
bool InternalStats::HandleMemTableFlushPending(uint64_t* value, DBImpl* db,
Version* version) {
// Return number of mem tables that are ready to flush (made immutable) // Return number of mem tables that are ready to flush (made immutable)
*value = (cfd_->imm()->IsFlushPending() ? 1 : 0); *value = (cfd_->imm()->IsFlushPending() ? 1 : 0);
return true; return true;
case kNumRunningFlushes: }
bool InternalStats::HandleNumRunningFlushes(uint64_t* value, DBImpl* db,
Version* version) {
*value = db->num_running_flushes(); *value = db->num_running_flushes();
return true; return true;
case kCompactionPending: }
bool InternalStats::HandleCompactionPending(uint64_t* value, DBImpl* db,
Version* version) {
// 1 if the system already determines at least one compaction is needed. // 1 if the system already determines at least one compaction is needed.
// 0 otherwise, // 0 otherwise,
const auto* vstorage = cfd_->current()->storage_info();
*value = (cfd_->compaction_picker()->NeedsCompaction(vstorage) ? 1 : 0); *value = (cfd_->compaction_picker()->NeedsCompaction(vstorage) ? 1 : 0);
return true; return true;
case kNumRunningCompactions: }
bool InternalStats::HandleNumRunningCompactions(uint64_t* value, DBImpl* db,
Version* version) {
*value = db->num_running_compactions_; *value = db->num_running_compactions_;
return true; return true;
case kBackgroundErrors: }
bool InternalStats::HandleBackgroundErrors(uint64_t* value, DBImpl* db,
Version* version) {
// Accumulated number of errors in background flushes or compactions. // Accumulated number of errors in background flushes or compactions.
*value = GetBackgroundErrorCount(); *value = GetBackgroundErrorCount();
return true; return true;
case kCurSizeActiveMemTable: }
bool InternalStats::HandleCurSizeActiveMemTable(uint64_t* value, DBImpl* db,
Version* version) {
// Current size of the active memtable // Current size of the active memtable
*value = cfd_->mem()->ApproximateMemoryUsage(); *value = cfd_->mem()->ApproximateMemoryUsage();
return true; return true;
case kCurSizeAllMemTables: }
bool InternalStats::HandleCurSizeAllMemTables(uint64_t* value, DBImpl* db,
Version* version) {
// Current size of the active memtable + immutable memtables // Current size of the active memtable + immutable memtables
*value = cfd_->mem()->ApproximateMemoryUsage() + *value = cfd_->mem()->ApproximateMemoryUsage() +
cfd_->imm()->ApproximateUnflushedMemTablesMemoryUsage(); cfd_->imm()->ApproximateUnflushedMemTablesMemoryUsage();
return true; return true;
case kSizeAllMemTables: }
bool InternalStats::HandleSizeAllMemTables(uint64_t* value, DBImpl* db,
Version* version) {
*value = cfd_->mem()->ApproximateMemoryUsage() + *value = cfd_->mem()->ApproximateMemoryUsage() +
cfd_->imm()->ApproximateMemoryUsage(); cfd_->imm()->ApproximateMemoryUsage();
return true; return true;
case kNumEntriesInMutableMemtable: }
bool InternalStats::HandleNumEntriesActiveMemTable(uint64_t* value, DBImpl* db,
Version* version) {
// Current number of entires in the active memtable // Current number of entires in the active memtable
*value = cfd_->mem()->num_entries(); *value = cfd_->mem()->num_entries();
return true; return true;
case kNumEntriesInImmutableMemtable: }
bool InternalStats::HandleNumEntriesImmMemTables(uint64_t* value, DBImpl* db,
Version* version) {
// Current number of entries in the immutable memtables // Current number of entries in the immutable memtables
*value = cfd_->imm()->current()->GetTotalNumEntries(); *value = cfd_->imm()->current()->GetTotalNumEntries();
return true; return true;
case kNumDeletesInMutableMemtable: }
bool InternalStats::HandleNumDeletesActiveMemTable(uint64_t* value, DBImpl* db,
Version* version) {
// Current number of entires in the active memtable // Current number of entires in the active memtable
*value = cfd_->mem()->num_deletes(); *value = cfd_->mem()->num_deletes();
return true; return true;
case kNumDeletesInImmutableMemtable: }
bool InternalStats::HandleNumDeletesImmMemTables(uint64_t* value, DBImpl* db,
Version* version) {
// Current number of entries in the immutable memtables // Current number of entries in the immutable memtables
*value = cfd_->imm()->current()->GetTotalNumDeletes(); *value = cfd_->imm()->current()->GetTotalNumDeletes();
return true; return true;
case kEstimatedNumKeys: }
bool InternalStats::HandleEstimateNumKeys(uint64_t* value, DBImpl* db,
Version* version) {
// 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();
*value = cfd_->mem()->num_entries() + *value = cfd_->mem()->num_entries() +
cfd_->imm()->current()->GetTotalNumEntries() - cfd_->imm()->current()->GetTotalNumEntries() -
(cfd_->mem()->num_deletes() + (cfd_->mem()->num_deletes() +
@ -452,30 +499,64 @@ bool InternalStats::GetIntProperty(DBPropertyType property_type,
2 + 2 +
vstorage->GetEstimatedActiveKeys(); vstorage->GetEstimatedActiveKeys();
return true; return true;
case kNumSnapshots: }
bool InternalStats::HandleNumSnapshots(uint64_t* value, DBImpl* db,
Version* version) {
*value = db->snapshots().count(); *value = db->snapshots().count();
return true; return true;
case kOldestSnapshotTime: }
bool InternalStats::HandleOldestSnapshotTime(uint64_t* value, DBImpl* db,
Version* version) {
*value = static_cast<uint64_t>(db->snapshots().GetOldestSnapshotTime()); *value = static_cast<uint64_t>(db->snapshots().GetOldestSnapshotTime());
return true; return true;
case kNumLiveVersions: }
bool InternalStats::HandleNumLiveVersions(uint64_t* value, DBImpl* db,
Version* version) {
*value = cfd_->GetNumLiveVersions(); *value = cfd_->GetNumLiveVersions();
return true; return true;
case kIsFileDeletionEnabled: }
bool InternalStats::HandleIsFileDeletionsEnabled(uint64_t* value, DBImpl* db,
Version* version) {
*value = db->IsFileDeletionsEnabled(); *value = db->IsFileDeletionsEnabled();
return true; return true;
case kBaseLevel: }
bool InternalStats::HandleBaseLevel(uint64_t* value, DBImpl* db,
Version* version) {
const auto* vstorage = cfd_->current()->storage_info();
*value = vstorage->base_level(); *value = vstorage->base_level();
return true; return true;
case kTotalSstFilesSize: }
bool InternalStats::HandleTotalSstFilesSize(uint64_t* value, DBImpl* db,
Version* version) {
*value = cfd_->GetTotalSstFilesSize(); *value = cfd_->GetTotalSstFilesSize();
return true; return true;
case kEstimatePendingCompactionBytes: }
bool InternalStats::HandleEstimatePendingCompactionBytes(uint64_t* value,
DBImpl* db,
Version* version) {
const auto* vstorage = cfd_->current()->storage_info();
*value = vstorage->estimated_compaction_needed_bytes(); *value = vstorage->estimated_compaction_needed_bytes();
return true; return true;
default: }
return false;
} bool InternalStats::HandleEstimateTableReadersMem(uint64_t* value, DBImpl* db,
Version* version) {
*value = (version == nullptr) ? 0 : version->GetMemoryUsageByTableReaders();
return true;
}
bool InternalStats::HandleEstimateLiveDataSize(uint64_t* value, DBImpl* db,
Version* version) {
const auto* vstorage = cfd_->current()->storage_info();
*value = vstorage->EstimateLiveDataSize();
return true;
} }
void InternalStats::DumpDBStats(std::string* value) { void InternalStats::DumpDBStats(std::string* value) {
@ -760,10 +841,7 @@ void InternalStats::DumpCFStats(std::string* value) {
#else #else
DBPropertyType GetPropertyType(const Slice& property, bool* is_int_property, const DBPropertyInfo* GetPropertyInfo(const Slice& property) { return nullptr; }
bool* need_out_of_mutex) {
return kUnknown;
}
#endif // !ROCKSDB_LITE #endif // !ROCKSDB_LITE

View File

@ -21,63 +21,29 @@ namespace rocksdb {
class MemTableList; class MemTableList;
class DBImpl; class DBImpl;
// IMPORTANT: If you add a new property here, also add it to the list in // Config for retrieving a property's value.
// include/rocksdb/db.h struct DBPropertyInfo {
enum DBPropertyType : uint32_t { bool need_out_of_mutex;
kUnknown,
kNumFilesAtLevel, // Number of files at a specific level // gcc had an internal error for initializing union of pointer-to-member-
kLevelStats, // Return number of files and total sizes of each level // functions. Workaround is to populate exactly one of the following function
kCFStats, // Return general statitistics of CF // pointers with a non-nullptr value.
kDBStats, // Return general statitistics of DB
kStats, // Return general statitistics of both DB and CF // @param value Value-result argument for storing the property's string value
kSsTables, // Return a human readable string of current SST files // @param suffix Argument portion of the property. For example, suffix would
kStartIntTypes, // ---- Dummy value to indicate the start of integer values // be "5" for the property "rocksdb.num-files-at-level5". So far, only
kNumImmutableMemTable, // Return number of immutable mem tables that // certain string properties take an argument.
// have not been flushed. bool (InternalStats::*handle_string)(std::string* value, Slice suffix);
kNumImmutableMemTableFlushed, // Return number of immutable mem tables
// in memory that have already been flushed // @param value Value-result argument for storing the property's uint64 value
kMemtableFlushPending, // Return 1 if mem table flushing is pending, // @param db Many of the int properties rely on DBImpl methods.
// otherwise 0. // @param version Version is needed in case the property is retrieved without
kNumRunningFlushes, // Return the number of currently running flushes. // holding db mutex, which is only supported for int properties.
kCompactionPending, // Return 1 if a compaction is pending. Otherwise 0. bool (InternalStats::*handle_int)(uint64_t* value, DBImpl* db,
kNumRunningCompactions, // Return the number of currently running Version* version);
// compactions.
kBackgroundErrors, // Return accumulated background errors encountered.
kCurSizeActiveMemTable, // Return current size of the active memtable
kCurSizeAllMemTables, // Return current size of unflushed
// (active + immutable) memtables
kSizeAllMemTables, // Return current size of all (active + immutable
// + pinned) memtables
kNumEntriesInMutableMemtable, // Return number of deletes in the mutable
// memtable.
kNumEntriesInImmutableMemtable, // Return sum of number of entries in all
// the immutable mem tables.
kNumDeletesInMutableMemtable, // Return number of deletion entries in the
// mutable memtable.
kNumDeletesInImmutableMemtable, // Return the total number of deletion
// entries in all the immutable mem tables.
kEstimatedNumKeys, // Estimated total number of keys in the database.
kEstimatedUsageByTableReaders, // Estimated memory by table readers.
kIsFileDeletionEnabled, // Equals disable_delete_obsolete_files_,
// 0 means file deletions enabled
kNumSnapshots, // Number of snapshots in the system
kOldestSnapshotTime, // Unix timestamp of the first snapshot
kNumLiveVersions,
kEstimateLiveDataSize, // Estimated amount of live data in bytes
kTotalSstFilesSize, // Total size of all sst files.
kBaseLevel, // The level that L0 data is compacted to
kEstimatePendingCompactionBytes, // Estimated bytes to compaction
kAggregatedTableProperties, // Return a string that contains the aggregated
// table properties.
kAggregatedTablePropertiesAtLevel, // Return a string that contains the
// aggregated
// table properties at the specified level.
}; };
extern DBPropertyType GetPropertyType(const Slice& property, extern const DBPropertyInfo* GetPropertyInfo(const Slice& property);
bool* is_int_property,
bool* need_out_of_mutex);
#ifndef ROCKSDB_LITE #ifndef ROCKSDB_LITE
class InternalStats { class InternalStats {
@ -248,14 +214,18 @@ class InternalStats {
uint64_t BumpAndGetBackgroundErrorCount() { return ++bg_error_count_; } uint64_t BumpAndGetBackgroundErrorCount() { return ++bg_error_count_; }
bool GetStringProperty(DBPropertyType property_type, const Slice& property, bool GetStringProperty(const DBPropertyInfo& property_info,
std::string* value); const Slice& property, std::string* value);
bool GetIntProperty(DBPropertyType property_type, uint64_t* value, bool GetIntProperty(const DBPropertyInfo& property_info, uint64_t* value,
DBImpl* db) const; DBImpl* db);
bool GetIntPropertyOutOfMutex(DBPropertyType property_type, Version* version, bool GetIntPropertyOutOfMutex(const DBPropertyInfo& property_info,
uint64_t* value) const; Version* version, uint64_t* value);
// Store a mapping from the user-facing DB::Properties string to our
// DBPropertyInfo struct used internally for retrieving properties.
static const std::unordered_map<std::string, DBPropertyInfo> ppt_name_to_info;
private: private:
void DumpDBStats(std::string* value); void DumpDBStats(std::string* value);
@ -321,6 +291,54 @@ class InternalStats {
seconds_up(0) {} seconds_up(0) {}
} db_stats_snapshot_; } db_stats_snapshot_;
// Handler functions for getting property values. They use "value" as a value-
// result argument, and return true upon successfully setting "value".
bool HandleNumFilesAtLevel(std::string* value, Slice suffix);
bool HandleLevelStats(std::string* value, Slice suffix);
bool HandleStats(std::string* value, Slice suffix);
bool HandleCFStats(std::string* value, Slice suffix);
bool HandleDBStats(std::string* value, Slice suffix);
bool HandleSsTables(std::string* value, Slice suffix);
bool HandleAggregatedTableProperties(std::string* value, Slice suffix);
bool HandleAggregatedTablePropertiesAtLevel(std::string* value, Slice suffix);
bool HandleNumImmutableMemTable(uint64_t* value, DBImpl* db,
Version* version);
bool HandleNumImmutableMemTableFlushed(uint64_t* value, DBImpl* db,
Version* version);
bool HandleMemTableFlushPending(uint64_t* value, DBImpl* db,
Version* version);
bool HandleNumRunningFlushes(uint64_t* value, DBImpl* db, Version* version);
bool HandleCompactionPending(uint64_t* value, DBImpl* db, Version* version);
bool HandleNumRunningCompactions(uint64_t* value, DBImpl* db,
Version* version);
bool HandleBackgroundErrors(uint64_t* value, DBImpl* db, Version* version);
bool HandleCurSizeActiveMemTable(uint64_t* value, DBImpl* db,
Version* version);
bool HandleCurSizeAllMemTables(uint64_t* value, DBImpl* db, Version* version);
bool HandleSizeAllMemTables(uint64_t* value, DBImpl* db, Version* version);
bool HandleNumEntriesActiveMemTable(uint64_t* value, DBImpl* db,
Version* version);
bool HandleNumEntriesImmMemTables(uint64_t* value, DBImpl* db,
Version* version);
bool HandleNumDeletesActiveMemTable(uint64_t* value, DBImpl* db,
Version* version);
bool HandleNumDeletesImmMemTables(uint64_t* value, DBImpl* db,
Version* version);
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 HandleNumLiveVersions(uint64_t* value, DBImpl* db, Version* version);
bool HandleIsFileDeletionsEnabled(uint64_t* value, DBImpl* db,
Version* version);
bool HandleBaseLevel(uint64_t* value, DBImpl* db, Version* version);
bool HandleTotalSstFilesSize(uint64_t* value, DBImpl* db, Version* version);
bool HandleEstimatePendingCompactionBytes(uint64_t* value, DBImpl* db,
Version* version);
bool HandleEstimateTableReadersMem(uint64_t* value, DBImpl* db,
Version* version);
bool HandleEstimateLiveDataSize(uint64_t* value, DBImpl* db,
Version* version);
// Total number of background errors encountered. Every time a flush task // Total number of background errors encountered. Every time a flush task
// or compaction task fails, this counter is incremented. The failure can // or compaction task fails, this counter is incremented. The failure can
// be caused by any possible reason, including file system errors, out of // be caused by any possible reason, including file system errors, out of
@ -402,14 +420,20 @@ class InternalStats {
uint64_t BumpAndGetBackgroundErrorCount() { return 0; } uint64_t BumpAndGetBackgroundErrorCount() { return 0; }
bool GetStringProperty(DBPropertyType property_type, const Slice& property, bool GetStringProperty(const DBPropertyInfo& property_info,
std::string* value) { return false; } const Slice& property, std::string* value) {
return false;
}
bool GetIntProperty(DBPropertyType property_type, uint64_t* value, bool GetIntProperty(const DBPropertyInfo& property_info, uint64_t* value,
DBImpl* db) const { return false; } DBImpl* db) const {
return false;
}
bool GetIntPropertyOutOfMutex(DBPropertyType property_type, Version* version, bool GetIntPropertyOutOfMutex(const DBPropertyInfo& property_info,
uint64_t* value) const { return false; } Version* version, uint64_t* value) const {
return false;
}
}; };
#endif // !ROCKSDB_LITE #endif // !ROCKSDB_LITE

View File

@ -329,6 +329,9 @@ class DB {
#ifndef ROCKSDB_LITE #ifndef ROCKSDB_LITE
// Contains all valid property arguments for GetProperty(). // Contains all valid property arguments for GetProperty().
//
// NOTE: Property names cannot end in numbers since those are interpreted as
// arguments, e.g., see kNumFilesAtLevelPrefix.
struct Properties { struct Properties {
// "rocksdb.num-files-at-level<N>" - returns string containing the number // "rocksdb.num-files-at-level<N>" - returns string containing the number
// of files at level <N>, where <N> is an ASCII representation of a // of files at level <N>, where <N> is an ASCII representation of a