Chromium Code Reviews| Index: third_party/leveldatabase/env_chromium.cc |
| diff --git a/third_party/leveldatabase/env_chromium.cc b/third_party/leveldatabase/env_chromium.cc |
| index b4daa541479b695c7b525c20973bc233a9d4da2c..510100599d7d935dfe044a7bf30a3c18c159117c 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) |
| @@ -21,9 +23,14 @@ |
| #include "base/strings/string_util.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/strings/utf_string_conversions.h" |
| +#include "base/strings/string_number_conversions.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/threading/thread_restrictions.h" |
| #include "base/trace_event/trace_event.h" |
| #include "third_party/leveldatabase/chromium_logger.h" |
| +#include "third_party/leveldatabase/src/include/leveldb/db.h" |
| #include "third_party/leveldatabase/src/include/leveldb/options.h" |
| #include "third_party/re2/src/re2/re2.h" |
| @@ -1071,6 +1078,153 @@ LevelDBStatusValue GetLevelDBStatusUMAValue(const leveldb::Status& s) { |
| return LEVELDB_STATUS_INVALID_ARGUMENT; |
| } |
| +class DBRegistry::DBProxy: public base::LinkNode<DBProxy>, public leveldb::DB { |
| + public: |
| + DBProxy(const leveldb::Options& options, const std::string name, leveldb::DB* db) |
| + : options_(options), name_(name), db_(db) { |
| + DBRegistry::GetInstance()->Register(this); |
| + } |
| + |
| + ~DBProxy() override { |
| + DBRegistry::GetInstance()->Unregister(this); |
| + } |
| + |
| + const leveldb::Options& options() const { return options_; }; |
| + |
| + const std::string& name() const { return name_; } |
| + |
| + Status Put(const leveldb::WriteOptions& options, |
| + const leveldb::Slice& key, |
| + const leveldb::Slice& value) override { |
| + return db_->Put(options, key, value); |
| + } |
| + |
| + Status Delete(const leveldb::WriteOptions& options, |
| + const leveldb::Slice& key) override { |
| + return db_->Delete(options, key); |
| + } |
| + |
| + Status Write(const leveldb::WriteOptions& options, leveldb::WriteBatch* updates) override { |
| + return db_->Write(options, updates); |
| + } |
| + |
| + Status Get(const leveldb::ReadOptions& options, const leveldb::Slice& key, std::string* value) override { |
| + return db_->Get(options, key, value); |
| + } |
| + |
| + leveldb::Iterator* NewIterator(const leveldb::ReadOptions& options) override { |
| + return db_->NewIterator(options); |
| + } |
| + |
| + 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); |
| + } |
| + |
| + private: |
| + leveldb::Options options_; |
| + std::string name_; |
| + std::unique_ptr<leveldb::DB> db_; |
| +}; |
| + |
| +class DBRegistry::MDP: public base::trace_event::MemoryDumpProvider { |
| + public: |
| + bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, |
|
ssid
2017/05/10 23:52:52
If we are adding all the databases here then we sh
|
| + base::trace_event::ProcessMemoryDump* pmd) override { |
| + auto db_dumper = [&](const leveldb::Options& options, |
| + const std::string& name, |
| + leveldb::DB* db) { |
| + std::string db_name; |
| + if (name.empty()) { |
| + db_name = "<in memory db>"; |
| + } else { |
| + // XXX: 'name' is actually a filesystem path - figure a way to extract |
| + // db name only (last component doesn't cut it). |
| + // |
| + // For now we show the path, but replace slashes with something |
| + // that looks like a slash, to make memory-infra show it as a |
| + // string (and not as a tree). |
| + base::ReplaceChars(name, "/", "\u2215", &db_name); |
| + } |
| + std::string dump_name = base::StringPrintf( |
| + "leveldatabase/%s (0x%" PRIXPTR ")", |
| + db_name.c_str(), |
| + reinterpret_cast<uintptr_t>(db)); |
| + auto* dump = pmd->CreateAllocatorDump(dump_name.c_str()); |
| + |
| + uint64_t memory_usage = 0; |
| + std::string memory_usage_string; |
| + bool got_memory_usage = |
| + db->GetProperty("leveldb.approximate-memory-usage", &memory_usage_string) && |
| + base::StringToUint64(memory_usage_string, &memory_usage); |
| + DCHECK(got_memory_usage); |
| + |
| + dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, |
| + base::trace_event::MemoryAllocatorDump::kUnitsBytes, |
| + memory_usage); |
| + }; |
| + |
| + DBRegistry::GetInstance()->Visit(db_dumper); |
| + |
| + return true; |
| + } |
| +}; |
| + |
| +DBRegistry::DBRegistry(): mdp_(new MDP()) { |
| + base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( |
| + mdp_.get(), "LevelDB", nullptr); |
| +} |
| + |
| +DBRegistry::~DBRegistry() = default; |
| + |
| +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()) { |
| + *dbptr = new DBProxy(options, name, *dbptr); |
| + } |
| + return status; |
| +} |
| + |
| +void DBRegistry::Visit(const Visitor& visitor) { |
| + base::AutoLock lock(lock_); |
| + for (auto* i = proxies_.head(); i != proxies_.end(); i = i->next()) { |
| + auto* proxy = i->value(); |
| + visitor(proxy->options(), proxy->name(), proxy); |
| + } |
| +} |
| + |
| +void DBRegistry::Register(DBProxy* proxy) { |
| + base::AutoLock lock(lock_); |
| + proxies_.Append(proxy); |
| +} |
| + |
| +void DBRegistry::Unregister(DBProxy* proxy) { |
| + base::AutoLock lock(lock_); |
| + proxy->RemoveFromList(); |
| +} |
| + |
| } // namespace leveldb_env |
| namespace leveldb { |