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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/performance_monitor/database.h"
6
7 #include "base/file_path.h"
8 #include "base/file_util.h"
9 #include "base/logging.h"
10 #include "base/path_service.h"
11 #include "base/string_number_conversions.h"
12 #include "base/stringprintf.h"
13 #include "base/time.h"
14 #include "chrome/common/chrome_paths.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "third_party/leveldatabase/src/include/leveldb/db.h"
17
18 namespace {
19 const char kDbDir[] = "Performance Monitor Databases";
20 const char kRecentDb[] = "Recent Metrics";
21 const char kEventDb[] = "Events";
22 const char kStateDb[] = "Configuration";
23 const char kActiveIntervalDb[] = "Active Interval";
24 const char kDelimiter = '!';
25
26 // If the db is quiet for this number of microseconds, then it is considered
27 // down.
28 const base::TimeDelta kActiveIntervalTimeout = base::TimeDelta::FromSeconds(5);
29
30 // Create the key used for internal active interval monitoring.
31 std::string CreateActiveIntervalKey(const base::Time& time) {
32 return StringPrintf("%016ld", time.ToInternalValue());
33 }
34 } // namespace
35
36 namespace performance_monitor {
37
38 TimeRange::TimeRange() {
39 }
40
41 TimeRange::TimeRange(base::Time start_time, base::Time end_time)
42 : start(start_time),
43 end(end_time) {
44 }
45
46 TimeRange::~TimeRange() {
47 }
48
49 base::Time Database::SystemClock::GetTime() {
50 return base::Time::Now();
51 }
52 bool Database::AddStateValueOnBackgroundThread(const std::string& key,
53 const std::string& value) {
54 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
55 UpdateActiveIntervalOnBackgroundThread();
56 linked_ptr<leveldb::DB> state_db = FetchDBOnBackgroundThread(kStateDb);
57 leveldb::Status insert_status =
58 state_db->Put(write_options_, key, value);
59 return insert_status.ok();
60 }
61
62 std::string Database::GetStateValueOnBackgroundThread(const std::string& key) {
63 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
64 std::string result;
65 linked_ptr<leveldb::DB> db = FetchDBOnBackgroundThread(kStateDb);
66 db->Get(read_options_, key, &result);
67 return result;
68 }
69
70 void Database::ClearOnBackgroundThread() {
71 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
72 LevelDbMap::iterator db_iter;
73 databases_.clear();
74 // Recursively delete all the databases.
75 if (!file_util::Delete(path_, true /* recursive */) ||
76 !file_util::CreateDirectory(path_))
77 LOG(ERROR) << "Failed to clear the performance monitor databases.";
78 }
79
80 std::vector<TimeRange> Database::GetActiveIntervalOnBackgroundThread(
81 const base::Time& start, const base::Time& end) {
82 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
83 std::vector<TimeRange> results;
84 std::string start_key = CreateActiveIntervalKey(start);
85 std::string end_key = CreateActiveIntervalKey(end);
86 linked_ptr<leveldb::DB> db = FetchDBOnBackgroundThread(kActiveIntervalDb);
87 scoped_ptr<leveldb::Iterator> it(db->NewIterator(read_options_));
88 it->Seek(start_key);
89 int64 start_time;
90 int64 end_time;
91 // Check the previous value in case we jumped in in the middle of an active
92 // interval.
93 it->Prev();
94 if (it->Valid() && it->value().ToString() > start_key) {
95 base::StringToInt64(it->key().ToString(), &start_time);
96 base::StringToInt64(it->value().ToString(), &end_time);
97 results.push_back(TimeRange(base::Time::FromInternalValue(start_time),
98 base::Time::FromInternalValue(end_time)));
99 }
100 for (it->Seek(start_key);
101 it->Valid() && it->key().ToString() < end_key;
102 it->Next()) {
103 base::StringToInt64(it->key().ToString(), &start_time);
104 base::StringToInt64(it->value().ToString(), &end_time);
105 results.push_back(TimeRange(base::Time::FromInternalValue(start_time),
106 base::Time::FromInternalValue(end_time)));
107 }
108 return results;
109 }
110
111 Database::Database(const FilePath& path, linked_ptr<Database::Clock> clock)
112 : path_(path),
113 clock_(clock),
114 read_options_(leveldb::ReadOptions()),
115 write_options_(leveldb::WriteOptions()) {
116 start_time_key_ = CreateActiveIntervalKey(clock_->GetTime());
117 last_update_time_ = clock->GetTime();
118 }
119
120 Database::~Database() {
121 CloseOnBackgroundThread();
122 }
123
124 // Static
125 scoped_refptr<Database> Database::InitOnBackgroundThread(
126 FilePath path, linked_ptr<Database::Clock> clock) {
127 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
128 if (path.empty()) {
129 CHECK(PathService::Get(chrome::DIR_USER_DATA, &path));
130 path = path.AppendASCII(kDbDir);
131 }
132 if (!file_util::DirectoryExists(path) && !file_util::CreateDirectory(path))
133 return scoped_refptr<Database>();
134 scoped_refptr<Database> db = new Database(path, clock);
135 return db;
136 }
137
138 bool Database::CloseOnBackgroundThread() {
139 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
140 UpdateActiveIntervalOnBackgroundThread();
141 LevelDbMap::iterator db_iter;
142 databases_.clear();
143 return true;
144 }
145
146 linked_ptr<leveldb::DB> Database::FetchDBOnBackgroundThread(
147 const std::string& id) {
148 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
149 LevelDbMap::iterator db_iter = databases_.find(id);
150 if (db_iter != databases_.end())
151 return db_iter->second;
152 leveldb::DB* new_db = NULL;
153 leveldb::Options open_options;
154 open_options.create_if_missing = true;
155 FilePath db_path = path_.AppendASCII(id);
156 leveldb::Status status = leveldb::DB::Open(open_options, db_path.value(),
157 &new_db);
158 databases_[id] = linked_ptr<leveldb::DB>(new_db);
159 return databases_[id];
160 }
161
162 // TODO(eriq): Only update the active interval under certian circumstances eg.
163 // every 10 times or when forced.
164 void Database::UpdateActiveIntervalOnBackgroundThread() {
165 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
166 linked_ptr<leveldb::DB> active_interval_db =
167 FetchDBOnBackgroundThread(kActiveIntervalDb);
168 base::Time current_time = clock_->GetTime();
169 std::string end_time;
170 // If the last update was too long ago.
171 if (current_time - last_update_time_ > kActiveIntervalTimeout) {
172 start_time_key_ = CreateActiveIntervalKey(current_time);
173 end_time = start_time_key_;
174 } else {
175 end_time = CreateActiveIntervalKey(clock_->GetTime());
176 }
177 active_interval_db->Put(write_options_, start_time_key_, end_time);
178 }
179 } // namespace performance_monitor
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698