Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(19)

Unified Diff: third_party/leveldatabase/env_chromium.cc

Issue 2855953002: leveldb: Add DBTracker for exposing databases to Chrome's memory-infra. (Closed)
Patch Set: Add unittests Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/leveldatabase/env_chromium.cc
diff --git a/third_party/leveldatabase/env_chromium.cc b/third_party/leveldatabase/env_chromium.cc
index 124689256368a042c35b39cf336cb69e8bbf387e..a65a70d513edda8ae425ff0b9620e6ec3ab36104 100644
--- a/third_party/leveldatabase/env_chromium.cc
+++ b/third_party/leveldatabase/env_chromium.cc
@@ -4,6 +4,8 @@
#include "third_party/leveldatabase/env_chromium.h"
+#include <inttypes.h>
+
#include <utility>
#if defined(OS_POSIX)
@@ -18,10 +20,14 @@
#include "base/metrics/histogram_functions.h"
#include "base/process/process_metrics.h"
#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_restrictions.h"
+#include "base/trace_event/memory_dump_manager.h"
+#include "base/trace_event/memory_dump_provider.h"
+#include "base/trace_event/process_memory_dump.h"
#include "base/trace_event/trace_event.h"
#include "third_party/leveldatabase/chromium_logger.h"
#include "third_party/leveldatabase/src/include/leveldb/options.h"
@@ -1095,6 +1101,159 @@ LevelDBStatusValue GetLevelDBStatusUMAValue(const leveldb::Status& s) {
return LEVELDB_STATUS_INVALID_ARGUMENT;
}
+// DBRegistry's leveldb::DB wrapper. Forwards all calls to the underlying
+// leveldb::DB instance. Registers / unregisters itself in the registry.
+class DBRegistry::DBWrapperImpl : public base::LinkNode<DBWrapperImpl>,
+ public DBWrapper {
+ public:
+ DBWrapperImpl(const std::string name, leveldb::DB* db)
+ : name_(name), db_(db) {
+ DBRegistry::GetInstance()->RegisterDatabase(this);
+ }
+
+ ~DBWrapperImpl() override {
+ DBRegistry::GetInstance()->UnregisterDatabase(this);
+ }
+
+ const std::string& name() const override { return name_; }
+
+ leveldb::Status Put(const leveldb::WriteOptions& options,
+ const leveldb::Slice& key,
+ const leveldb::Slice& value) override {
+ return db_->Put(options, key, value);
+ }
+
+ leveldb::Status Delete(const leveldb::WriteOptions& options,
+ const leveldb::Slice& key) override {
+ return db_->Delete(options, key);
+ }
+
+ leveldb::Status Write(const leveldb::WriteOptions& options,
+ leveldb::WriteBatch* updates) override {
+ return db_->Write(options, updates);
+ }
+
+ leveldb::Status Get(const leveldb::ReadOptions& options,
+ const leveldb::Slice& key,
+ std::string* value) override {
+ return db_->Get(options, key, value);
+ }
+
+ const leveldb::Snapshot* GetSnapshot() override { return db_->GetSnapshot(); }
+
+ void ReleaseSnapshot(const leveldb::Snapshot* snapshot) override {
+ return db_->ReleaseSnapshot(snapshot);
+ }
+
+ bool GetProperty(const leveldb::Slice& property,
+ std::string* value) override {
+ return db_->GetProperty(property, value);
+ }
+
+ void GetApproximateSizes(const leveldb::Range* range,
+ int n,
+ uint64_t* sizes) override {
+ return db_->GetApproximateSizes(range, n, sizes);
+ }
+
+ void CompactRange(const leveldb::Slice* begin,
+ const leveldb::Slice* end) override {
+ return db_->CompactRange(begin, end);
+ }
+
+ leveldb::Iterator* NewIterator(const leveldb::ReadOptions& options) override {
+ return db_->NewIterator(options);
+ }
+
+ private:
+ std::string name_;
+ std::unique_ptr<leveldb::DB> db_;
+};
+
+// DBRegistry MemoryDumpProvider implementation. Declared here to minimize
+// dependencies in the header file.
+class DBRegistry::MDP : public base::trace_event::MemoryDumpProvider {
+ public:
+ bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
+ base::trace_event::ProcessMemoryDump* pmd) override {
+ auto db_visitor = [&](DBWrapper* db) {
+ std::string db_dump_name = base::StringPrintf(
+ "leveldatabase/0x%" PRIXPTR, reinterpret_cast<uintptr_t>(db));
Marijn Kruisselbrink 2017/06/20 23:38:52 nit: should this be leveldb/ something to be consi
ssid 2017/06/20 23:52:13 I think it is intentional. How about leveldb_regis
DmitrySkiba 2017/06/20 23:59:21 Yes, the name is intentionally different. Some of
+ auto* db_dump = pmd->CreateAllocatorDump(db_dump_name.c_str());
+
+ uint64_t db_memory_usage = 0;
+ {
+ std::string usage_string;
+ bool success = db->GetProperty("leveldb.approximate-memory-usage",
+ &usage_string) &&
+ base::StringToUint64(usage_string, &db_memory_usage);
+ DCHECK(success);
+ }
+ db_dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ db_memory_usage);
+
+ if (args.level_of_detail !=
+ base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND) {
+ db_dump->AddString("name", "", db->name());
+ }
+
+ const char* system_allocator_name =
+ base::trace_event::MemoryDumpManager::GetInstance()
+ ->system_allocator_pool_name();
+ if (system_allocator_name) {
+ pmd->AddSuballocation(db_dump->guid(), system_allocator_name);
+ }
+ };
+
+ DBRegistry::GetInstance()->VisitDatabases(db_visitor);
+ return true;
+ }
+};
+
+DBRegistry::DBRegistry() : mdp_(new MDP()) {
+ base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
+ mdp_.get(), "LevelDB", nullptr);
+}
+
+DBRegistry::~DBRegistry() {
+ base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
ssid 2017/06/20 23:52:13 You cannot unregister dump providers without task
DmitrySkiba 2017/06/21 01:08:06 Ouch, I didn't know about that. I wonder if Unregi
+ mdp_.get());
+}
+
+DBRegistry* DBRegistry::GetInstance() {
+ static DBRegistry* instance = new DBRegistry();
+ return instance;
+}
+
+leveldb::Status DBRegistry::Open(const leveldb::Options& options,
+ const std::string& name,
+ leveldb::DB** dbptr) {
+ auto status = leveldb::DB::Open(options, name, dbptr);
+ if (status.ok()) {
+ // DBWrapperImpl ctor registers the instance in DBRegistry
+ *dbptr = new DBWrapperImpl(name, *dbptr);
+ }
+ return status;
+}
+
+void DBRegistry::VisitDatabases(const DatabaseVisitor& visitor) {
+ base::AutoLock lock(databases_lock_);
+ for (auto* i = databases_.head(); i != databases_.end(); i = i->next()) {
+ visitor(i->value());
+ }
+}
+
+void DBRegistry::RegisterDatabase(DBWrapperImpl* database) {
+ base::AutoLock lock(databases_lock_);
+ databases_.Append(database);
+}
+
+void DBRegistry::UnregisterDatabase(DBWrapperImpl* database) {
+ base::AutoLock lock(databases_lock_);
+ database->RemoveFromList();
+}
+
} // namespace leveldb_env
namespace leveldb {

Powered by Google App Engine
This is Rietveld 408576698