leveldb: Have GetOrCreateAllocatorDump fail on untracked db.
The callers of DBTracker::GetOrCreateAllocatorDump assume that the DBTracker is dumping the passed |db|. Adding a DCHECK to detect adding an edge to a nonexistent dump. BUG=711518 Change-Id: I5b6fc966eb56d97436add9b24117f6b4539c2690 Reviewed-on: https://chromium-review.googlesource.com/650838 Commit-Queue: Chris Mumford <cmumford@chromium.org> Reviewed-by: Victor Costan <pwnall@chromium.org> Cr-Commit-Position: refs/heads/master@{#502019}
This commit is contained in:

committed by
Commit Bot

parent
14e8ff0851
commit
33b762b8f0
third_party/leveldatabase
30
third_party/leveldatabase/env_chromium.cc
vendored
30
third_party/leveldatabase/env_chromium.cc
vendored
@ -1338,6 +1338,7 @@ DBTracker::~DBTracker() {
|
||||
NOTREACHED(); // DBTracker is a singleton
|
||||
}
|
||||
|
||||
// static
|
||||
DBTracker* DBTracker::GetInstance() {
|
||||
static DBTracker* instance = new DBTracker();
|
||||
return instance;
|
||||
@ -1347,12 +1348,22 @@ DBTracker* DBTracker::GetInstance() {
|
||||
base::trace_event::MemoryAllocatorDump* DBTracker::GetOrCreateAllocatorDump(
|
||||
base::trace_event::ProcessMemoryDump* pmd,
|
||||
leveldb::DB* tracked_db) {
|
||||
DCHECK(GetInstance()->IsTrackedDB(tracked_db))
|
||||
<< std::hex << tracked_db << " is not tracked";
|
||||
return GetOrCreateAllocatorDump(pmd,
|
||||
reinterpret_cast<TrackedDB*>(tracked_db));
|
||||
}
|
||||
|
||||
// static
|
||||
base::trace_event::MemoryAllocatorDump* DBTracker::GetOrCreateAllocatorDump(
|
||||
base::trace_event::ProcessMemoryDump* pmd,
|
||||
TrackedDB* db) {
|
||||
if (pmd->dump_args().level_of_detail ==
|
||||
base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND) {
|
||||
return nullptr;
|
||||
}
|
||||
std::string dump_name = base::StringPrintf(
|
||||
"leveldatabase/0x%" PRIXPTR, reinterpret_cast<uintptr_t>(tracked_db));
|
||||
std::string dump_name = base::StringPrintf("leveldatabase/0x%" PRIXPTR,
|
||||
reinterpret_cast<uintptr_t>(db));
|
||||
auto* dump = pmd->GetAllocatorDump(dump_name);
|
||||
if (dump)
|
||||
return dump;
|
||||
@ -1360,9 +1371,9 @@ base::trace_event::MemoryAllocatorDump* DBTracker::GetOrCreateAllocatorDump(
|
||||
|
||||
uint64_t memory_usage = 0;
|
||||
std::string usage_string;
|
||||
bool success = tracked_db->GetProperty("leveldb.approximate-memory-usage",
|
||||
&usage_string) &&
|
||||
base::StringToUint64(usage_string, &memory_usage);
|
||||
bool success =
|
||||
db->GetProperty("leveldb.approximate-memory-usage", &usage_string) &&
|
||||
base::StringToUint64(usage_string, &memory_usage);
|
||||
DCHECK(success);
|
||||
dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
|
||||
base::trace_event::MemoryAllocatorDump::kUnitsBytes,
|
||||
@ -1376,6 +1387,15 @@ base::trace_event::MemoryAllocatorDump* DBTracker::GetOrCreateAllocatorDump(
|
||||
return dump;
|
||||
}
|
||||
|
||||
bool DBTracker::IsTrackedDB(const leveldb::DB* db) const {
|
||||
base::AutoLock lock(databases_lock_);
|
||||
for (auto* i = databases_.head(); i != databases_.end(); i = i->next()) {
|
||||
if (i->value() == db)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
leveldb::Status DBTracker::OpenDatabase(const leveldb::Options& options,
|
||||
const std::string& name,
|
||||
TrackedDB** dbptr) {
|
||||
|
25
third_party/leveldatabase/env_chromium.h
vendored
25
third_party/leveldatabase/env_chromium.h
vendored
@ -15,6 +15,7 @@
|
||||
#include "base/containers/linked_list.h"
|
||||
#include "base/files/file.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/gtest_prod_util.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/metrics/histogram.h"
|
||||
#include "leveldb/db.h"
|
||||
@ -280,8 +281,22 @@ class DBTracker {
|
||||
const std::string& name,
|
||||
TrackedDB** dbptr);
|
||||
|
||||
private:
|
||||
class MemoryDumpProvider;
|
||||
class TrackedDBImpl;
|
||||
|
||||
using DatabaseVisitor = base::RepeatingCallback<void(TrackedDB*)>;
|
||||
|
||||
friend class ChromiumEnvDBTrackerTest;
|
||||
FRIEND_TEST_ALL_PREFIXES(ChromiumEnvDBTrackerTest, IsTrackedDB);
|
||||
|
||||
DBTracker();
|
||||
~DBTracker();
|
||||
|
||||
static base::trace_event::MemoryAllocatorDump* GetOrCreateAllocatorDump(
|
||||
base::trace_event::ProcessMemoryDump* pmd,
|
||||
TrackedDB* db);
|
||||
|
||||
// Calls |visitor| for each live database. The database is live from the
|
||||
// point it was returned from OpenDatabase() and up until its instance is
|
||||
// destroyed.
|
||||
@ -290,19 +305,15 @@ class DBTracker {
|
||||
// destroyed (but doesn't lock the databases themselves).
|
||||
void VisitDatabases(const DatabaseVisitor& visitor);
|
||||
|
||||
private:
|
||||
class TrackedDBImpl;
|
||||
class MemoryDumpProvider;
|
||||
|
||||
DBTracker();
|
||||
~DBTracker();
|
||||
// Checks if |db| is tracked.
|
||||
bool IsTrackedDB(const leveldb::DB* db) const;
|
||||
|
||||
void DatabaseOpened(TrackedDBImpl* database);
|
||||
void DatabaseDestroyed(TrackedDBImpl* database);
|
||||
|
||||
std::unique_ptr<MemoryDumpProvider> mdp_;
|
||||
|
||||
base::Lock databases_lock_;
|
||||
mutable base::Lock databases_lock_;
|
||||
base::LinkedList<TrackedDBImpl> databases_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(DBTracker);
|
||||
|
@ -33,6 +33,8 @@ using leveldb_env::DBTracker;
|
||||
using leveldb_env::MethodID;
|
||||
using leveldb_env::Options;
|
||||
|
||||
namespace leveldb_env {
|
||||
|
||||
static const int kReadOnlyFileLimit = 4;
|
||||
|
||||
TEST(ErrorEncoding, OnlyAMethod) {
|
||||
@ -381,4 +383,29 @@ TEST_F(ChromiumEnvDBTrackerTest, OpenDBTracking) {
|
||||
ASSERT_EQ(db.get(), *visited_dbs.begin());
|
||||
}
|
||||
|
||||
TEST_F(ChromiumEnvDBTrackerTest, IsTrackedDB) {
|
||||
leveldb_env::Options options;
|
||||
options.create_if_missing = true;
|
||||
leveldb::DB* untracked_db;
|
||||
base::ScopedTempDir untracked_temp_dir;
|
||||
ASSERT_TRUE(untracked_temp_dir.CreateUniqueTempDir());
|
||||
leveldb::Status s = leveldb::DB::Open(
|
||||
options, untracked_temp_dir.GetPath().AsUTF8Unsafe(), &untracked_db);
|
||||
ASSERT_TRUE(s.ok());
|
||||
EXPECT_FALSE(DBTracker::GetInstance()->IsTrackedDB(untracked_db));
|
||||
|
||||
// Now a tracked db.
|
||||
std::unique_ptr<leveldb::DB> tracked_db;
|
||||
base::ScopedTempDir tracked_temp_dir;
|
||||
ASSERT_TRUE(tracked_temp_dir.CreateUniqueTempDir());
|
||||
s = leveldb_env::OpenDB(options, tracked_temp_dir.GetPath().AsUTF8Unsafe(),
|
||||
&tracked_db);
|
||||
ASSERT_TRUE(s.ok());
|
||||
EXPECT_TRUE(DBTracker::GetInstance()->IsTrackedDB(tracked_db.get()));
|
||||
|
||||
delete untracked_db;
|
||||
}
|
||||
|
||||
} // namespace leveldb_env
|
||||
|
||||
int main(int argc, char** argv) { return base::TestSuite(argc, argv).Run(); }
|
||||
|
Reference in New Issue
Block a user