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

Unified Diff: chrome/browser/performance_monitor/database.cc

Issue 10443092: Performance Monitor Database (Closed) Base URL: http://git.chromium.org/chromium/src.git@cpm_event_construction
Patch Set: Created 8 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: chrome/browser/performance_monitor/database.cc
diff --git a/chrome/browser/performance_monitor/database.cc b/chrome/browser/performance_monitor/database.cc
new file mode 100644
index 0000000000000000000000000000000000000000..9273ec7e767cb64ad848684c73792f21c644f9a9
--- /dev/null
+++ b/chrome/browser/performance_monitor/database.cc
@@ -0,0 +1,179 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/performance_monitor/database.h"
+
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/path_service.h"
+#include "base/string_number_conversions.h"
+#include "base/stringprintf.h"
+#include "base/time.h"
+#include "chrome/common/chrome_paths.h"
+#include "content/public/browser/browser_thread.h"
+#include "third_party/leveldatabase/src/include/leveldb/db.h"
+
+namespace {
+const char kDbDir[] = "Performance Monitor Databases";
+const char kRecentDb[] = "Recent Metrics";
+const char kEventDb[] = "Events";
+const char kStateDb[] = "Configuration";
+const char kActiveIntervalDb[] = "Active Interval";
+const char kDelimiter = '!';
+
+// If the db is quiet for this number of microseconds, then it is considered
+// down.
+const base::TimeDelta kActiveIntervalTimeout = base::TimeDelta::FromSeconds(5);
+
+// Create the key used for internal active interval monitoring.
+std::string CreateActiveIntervalKey(const base::Time& time) {
+ return StringPrintf("%016ld", time.ToInternalValue());
+}
+} // namespace
+
+namespace performance_monitor {
+
+TimeRange::TimeRange() {
+}
+
+TimeRange::TimeRange(base::Time start_time, base::Time end_time)
+ : start(start_time),
+ end(end_time) {
+}
+
+TimeRange::~TimeRange() {
+}
+
+base::Time Database::SystemClock::GetTime() {
+ return base::Time::Now();
+}
+bool Database::AddStateValueOnBackgroundThread(const std::string& key,
+ const std::string& value) {
+ CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ UpdateActiveIntervalOnBackgroundThread();
+ linked_ptr<leveldb::DB> state_db = FetchDBOnBackgroundThread(kStateDb);
+ leveldb::Status insert_status =
+ state_db->Put(write_options_, key, value);
+ return insert_status.ok();
+}
+
+std::string Database::GetStateValueOnBackgroundThread(const std::string& key) {
+ CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ std::string result;
+ linked_ptr<leveldb::DB> db = FetchDBOnBackgroundThread(kStateDb);
+ db->Get(read_options_, key, &result);
+ return result;
+}
+
+void Database::ClearOnBackgroundThread() {
+ CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ LevelDbMap::iterator db_iter;
+ databases_.clear();
+ // Recursively delete all the databases.
+ if (!file_util::Delete(path_, true /* recursive */) ||
+ !file_util::CreateDirectory(path_))
+ LOG(ERROR) << "Failed to clear the performance monitor databases.";
+}
+
+std::vector<TimeRange> Database::GetActiveIntervalOnBackgroundThread(
+ const base::Time& start, const base::Time& end) {
+ CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ std::vector<TimeRange> results;
+ std::string start_key = CreateActiveIntervalKey(start);
+ std::string end_key = CreateActiveIntervalKey(end);
+ linked_ptr<leveldb::DB> db = FetchDBOnBackgroundThread(kActiveIntervalDb);
+ scoped_ptr<leveldb::Iterator> it(db->NewIterator(read_options_));
+ it->Seek(start_key);
+ int64 start_time;
+ int64 end_time;
+ // Check the previous value in case we jumped in in the middle of an active
+ // interval.
+ it->Prev();
+ if (it->Valid() && it->value().ToString() > start_key) {
+ base::StringToInt64(it->key().ToString(), &start_time);
+ base::StringToInt64(it->value().ToString(), &end_time);
+ results.push_back(TimeRange(base::Time::FromInternalValue(start_time),
+ base::Time::FromInternalValue(end_time)));
+ }
+ for (it->Seek(start_key);
+ it->Valid() && it->key().ToString() < end_key;
+ it->Next()) {
+ base::StringToInt64(it->key().ToString(), &start_time);
+ base::StringToInt64(it->value().ToString(), &end_time);
+ results.push_back(TimeRange(base::Time::FromInternalValue(start_time),
+ base::Time::FromInternalValue(end_time)));
+ }
+ return results;
+}
+
+Database::Database(const FilePath& path, linked_ptr<Database::Clock> clock)
+ : path_(path),
+ clock_(clock),
+ read_options_(leveldb::ReadOptions()),
+ write_options_(leveldb::WriteOptions()) {
+ start_time_key_ = CreateActiveIntervalKey(clock_->GetTime());
+ last_update_time_ = clock->GetTime();
+}
+
+Database::~Database() {
+ CloseOnBackgroundThread();
+}
+
+// Static
+scoped_refptr<Database> Database::InitOnBackgroundThread(
+ FilePath path, linked_ptr<Database::Clock> clock) {
+ CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ if (path.empty()) {
+ CHECK(PathService::Get(chrome::DIR_USER_DATA, &path));
+ path = path.AppendASCII(kDbDir);
+ }
+ if (!file_util::DirectoryExists(path) && !file_util::CreateDirectory(path))
+ return scoped_refptr<Database>();
+ scoped_refptr<Database> db = new Database(path, clock);
+ return db;
+}
+
+bool Database::CloseOnBackgroundThread() {
+ CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ UpdateActiveIntervalOnBackgroundThread();
+ LevelDbMap::iterator db_iter;
+ databases_.clear();
+ return true;
+}
+
+linked_ptr<leveldb::DB> Database::FetchDBOnBackgroundThread(
+ const std::string& id) {
+ CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ LevelDbMap::iterator db_iter = databases_.find(id);
+ if (db_iter != databases_.end())
+ return db_iter->second;
+ leveldb::DB* new_db = NULL;
+ leveldb::Options open_options;
+ open_options.create_if_missing = true;
+ FilePath db_path = path_.AppendASCII(id);
+ leveldb::Status status = leveldb::DB::Open(open_options, db_path.value(),
+ &new_db);
+ databases_[id] = linked_ptr<leveldb::DB>(new_db);
+ return databases_[id];
+}
+
+// TODO(eriq): Only update the active interval under certian circumstances eg.
+// every 10 times or when forced.
+void Database::UpdateActiveIntervalOnBackgroundThread() {
+ CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ linked_ptr<leveldb::DB> active_interval_db =
+ FetchDBOnBackgroundThread(kActiveIntervalDb);
+ base::Time current_time = clock_->GetTime();
+ std::string end_time;
+ // If the last update was too long ago.
+ if (current_time - last_update_time_ > kActiveIntervalTimeout) {
+ start_time_key_ = CreateActiveIntervalKey(current_time);
+ end_time = start_time_key_;
+ } else {
+ end_time = CreateActiveIntervalKey(clock_->GetTime());
+ }
+ active_interval_db->Put(write_options_, start_time_key_, end_time);
+}
+} // namespace performance_monitor

Powered by Google App Engine
This is Rietveld 408576698