OLD | NEW |
---|---|
(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/path_service.h" | |
10 #include "base/string_number_conversions.h" | |
11 #include "base/stringprintf.h" | |
12 #include "base/time.h" | |
13 #include "chrome/common/chrome_paths.h" | |
14 #include "content/public/browser/browser_thread.h" | |
15 #include "third_party/leveldatabase/src/include/leveldb/db.h" | |
16 | |
17 namespace { | |
18 const char kDbDir[] = "performance_monitor_dbs"; | |
Aaron Boodman
2012/06/08 21:40:05
In Chrome, these files are normally named very hum
eaugusti
2012/06/08 22:52:08
Done.
| |
19 const char kRecentDb[] = "_performance_monitor_meta_recent"; | |
Aaron Boodman
2012/06/08 21:40:05
Since these are inside the directory, the 'perform
eaugusti
2012/06/08 22:52:08
Done.
| |
20 const char kEventDb[] = "_performance_monitor_meta_events"; | |
21 const char kStateDb[] = "_performance_monitor_meta_state"; | |
22 const char kUptimeDb[] = "_performance_monitor_meta_uptime"; | |
Aaron Boodman
2012/06/08 21:40:05
'uptime' has a well understood meaning that is dif
eaugusti
2012/06/08 22:52:08
How about Active Interval?
| |
23 const char kDelimiter = '!'; | |
24 | |
25 // If the db is quiet for this number of microseconds, then it is considered | |
26 // down. | |
27 const int kUptimeTimeout = 5 * base::Time::kMicrosecondsPerMinute; | |
Aaron Boodman
2012/06/08 19:33:56
Typically we either use base::TimeDelate, or encod
eaugusti
2012/06/08 22:52:08
Done.
| |
28 | |
29 // Create the key used for internal uptime monitoring. | |
30 std::string CreateUptimeKey(const base::Time& time) { | |
31 return StringPrintf("%016ld", time.ToInternalValue()); | |
32 } | |
33 } // namespace | |
34 | |
35 namespace performance_monitor { | |
36 | |
37 base::Time SystemClock::GetTime() { | |
38 return base::Time::Now(); | |
39 } | |
40 bool Database::AddStateValueOnBackgroundThread(const std::string& key, | |
41 const std::string& value) { | |
42 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
43 UpdateUptimeOnBackgroundThread(); | |
44 leveldb::DB* state_db = FetchDBOnBackgroundThread(std::string(kStateDb)); | |
Aaron Boodman
2012/06/08 19:33:56
There is implicit conversion from const char[] to
eaugusti
2012/06/08 22:52:08
Done.
| |
45 leveldb::Status insert_status = | |
46 state_db->Put(write_options_, key, value); | |
47 return insert_status.ok(); | |
48 } | |
49 | |
50 std::string Database::GetStateValueOnBackgroundThread(const std::string& key) { | |
51 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
52 UpdateUptimeOnBackgroundThread(); | |
53 std::string result; | |
54 leveldb::DB* db = FetchDBOnBackgroundThread(std::string(kStateDb)); | |
55 db->Get(read_options_, key, &result); | |
56 return result; | |
57 } | |
58 | |
59 void Database::ClearOnBackgroundThread() { | |
60 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
61 LevelDbMap::iterator db_iter; | |
62 for (db_iter = databases_.begin(); db_iter != databases_.end(); ++db_iter) | |
63 delete db_iter->second; | |
Aaron Boodman
2012/06/08 19:33:56
Use linked_ptr so that you don't need to do the de
eaugusti
2012/06/08 22:52:08
Done.
| |
64 databases_.clear(); | |
65 CHECK(file_util::Delete(path_, true)); | |
Aaron Boodman
2012/06/08 19:33:56
Document the magic boolean or use a named constant
Aaron Boodman
2012/06/08 19:33:56
CHECK means: if this condition is false, the code
eaugusti
2012/06/08 22:52:08
Done.
| |
66 CHECK(file_util::CreateDirectory(path_)); | |
67 } | |
68 | |
69 Database::TimePairs Database::GetUptimeOnBackgroundThread( | |
70 const base::Time& start, const base::Time& end) { | |
71 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
72 UpdateUptimeOnBackgroundThread(); | |
Aaron Boodman
2012/06/08 21:40:05
I think you probably don't want to update here.
eaugusti
2012/06/08 22:52:08
Done.
| |
73 TimePairs results; | |
74 std::string start_key = CreateUptimeKey(start); | |
75 std::string end_key = CreateUptimeKey(end); | |
76 leveldb::DB* db = FetchDBOnBackgroundThread(kUptimeDb); | |
77 leveldb::Iterator* it = db->NewIterator(read_options_); | |
78 it->Seek(start_key); | |
79 int64 start_time; | |
80 int64 end_time; | |
81 // Check the previous value in case we jumped in in the middle of an uptime. | |
82 it->Prev(); | |
83 if (it->Valid() && it->value().ToString() > start_key) { | |
Aaron Boodman
2012/06/08 21:40:05
Scary to compare lexographically. In this case it
eaugusti
2012/06/08 22:52:08
In key generation we pad with enough 0's to make l
| |
84 base::StringToInt64(it->key().ToString(), &start_time); | |
85 base::StringToInt64(it->value().ToString(), &end_time); | |
86 results.push_back(std::pair<base::Time, base::Time>( | |
87 base::Time::FromInternalValue(start_time), | |
88 base::Time::FromInternalValue(end_time))); | |
89 } | |
90 for (it->Seek(start_key); | |
91 it->Valid() && it->key().ToString() < end_key; | |
92 it->Next()) { | |
93 base::StringToInt64(it->key().ToString(), &start_time); | |
94 base::StringToInt64(it->value().ToString(), &end_time); | |
95 results.push_back(std::pair<base::Time, base::Time>( | |
96 base::Time::FromInternalValue(start_time), | |
97 base::Time::FromInternalValue(end_time))); | |
98 } | |
99 delete it; | |
Aaron Boodman
2012/06/08 21:40:05
scoped_ptr to avoid manual delete?
eaugusti
2012/06/08 22:52:08
Done.
| |
100 return results; | |
101 } | |
102 | |
103 Database::Database(const FilePath& path, scoped_refptr<DBClock> clock) | |
104 : path_(path), | |
105 clock_(clock), | |
106 read_options_(leveldb::ReadOptions()), | |
107 write_options_(leveldb::WriteOptions()) { | |
108 start_time_key_ = CreateUptimeKey(clock_->GetTime()); | |
109 last_update_time_ = clock->GetTime(); | |
110 uptime_threshold_ = base::TimeDelta::FromMicroseconds(kUptimeTimeout); | |
111 } | |
112 | |
113 Database::~Database() { | |
114 CloseOnBackgroundThread(); | |
115 } | |
116 | |
117 // Static | |
118 scoped_refptr<Database> Database::InitOnBackgroundThread( | |
119 FilePath path, scoped_refptr<DBClock> clock) { | |
120 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
121 if (path.empty()) { | |
122 CHECK(PathService::Get(chrome::DIR_USER_DATA, &path)); | |
123 path = path.AppendASCII(kDbDir); | |
124 } | |
125 if (!file_util::DirectoryExists(path) && !file_util::CreateDirectory(path)) | |
126 return scoped_refptr<Database>(); | |
127 scoped_refptr<Database> db = new Database(path, clock); | |
128 return db; | |
129 } | |
130 | |
131 bool Database::CloseOnBackgroundThread() { | |
132 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
133 UpdateUptimeOnBackgroundThread(); | |
134 LevelDbMap::iterator db_iter; | |
135 for (db_iter = databases_.begin(); db_iter != databases_.end(); ++db_iter) | |
136 delete db_iter->second; | |
137 databases_.clear(); | |
138 return true; | |
139 } | |
140 | |
141 leveldb::DB* Database::FetchDBOnBackgroundThread(const std::string& id) { | |
142 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
143 LevelDbMap::iterator db_iter = databases_.find(id); | |
144 if (db_iter != databases_.end()) | |
145 return db_iter->second; | |
146 leveldb::DB* new_db; | |
Aaron Boodman
2012/06/08 21:40:05
= NULL;
eaugusti
2012/06/08 22:52:08
Done.
| |
147 leveldb::Options open_options; | |
148 open_options.create_if_missing = true; | |
149 FilePath db_path = path_.AppendASCII(id); | |
150 leveldb::Status status = leveldb::DB::Open(open_options, db_path.value(), | |
151 &new_db); | |
152 databases_[id] = new_db; | |
153 return new_db; | |
154 } | |
155 | |
156 // TODO(eriq): Only update uptime under certian circumstances eg. every 10 | |
157 // times or when forced. | |
158 void Database::UpdateUptimeOnBackgroundThread() { | |
159 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
160 leveldb::DB* uptime_db = FetchDBOnBackgroundThread(kUptimeDb); | |
161 base::Time current_time = clock_->GetTime(); | |
162 std::string end_time; | |
163 // If the last update was too long ago. | |
164 if (current_time - last_update_time_ > uptime_threshold_) { | |
165 start_time_key_ = CreateUptimeKey(current_time); | |
166 end_time = start_time_key_; | |
167 } else { | |
168 end_time = CreateUptimeKey(clock_->GetTime()); | |
169 } | |
170 uptime_db->Put(write_options_, start_time_key_, end_time); | |
171 } | |
172 } // namespace performance_monitor | |
OLD | NEW |