Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / performance_monitor / database.h
blob87082cd7b9edd33c734e4eb58f2236cfa88c4cea
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.
5 #ifndef CHROME_BROWSER_PERFORMANCE_MONITOR_DATABASE_H_
6 #define CHROME_BROWSER_PERFORMANCE_MONITOR_DATABASE_H_
8 #include <set>
9 #include <string>
10 #include <vector>
12 #include "base/files/file_path.h"
13 #include "base/gtest_prod_util.h"
14 #include "base/memory/linked_ptr.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/time/time.h"
17 #include "chrome/browser/performance_monitor/constants.h"
18 #include "chrome/browser/performance_monitor/event.h"
19 #include "chrome/browser/performance_monitor/metric.h"
20 #include "third_party/leveldatabase/src/include/leveldb/db.h"
22 namespace performance_monitor {
24 struct TimeRange {
25 TimeRange();
26 TimeRange(base::Time start_time, base::Time end_time);
27 ~TimeRange();
29 base::Time start;
30 base::Time end;
33 class KeyBuilder;
34 class DatabaseTestHelper;
36 // The class supporting all performance monitor storage. This class wraps
37 // multiple leveldb::DB objects. All methods must be called from a background
38 // thread. Callers should use BrowserThread::PostBlockingPoolSequencedTask using
39 // performance_monitor::kDBSequenceToken as the sequence token.
41 // Different schemas are used for the different leveldb::DB's based off of the
42 // structure of the data and the common ways that it will need to be accessed.
43 // The following specifies the schema of each type of leveldb::DB. Delimiters
44 // are denoted with a '-'.
46 // State DB:
47 // Stores information about the configuration or 'state' of the browser. Things
48 // like browser version go in here.
49 // Key: Unique Identifier
50 // Value: State Value
52 // Active Interval DB:
53 // Stores information about when there is data in the database. When the
54 // database is constructed, the time is noted as the start of the active
55 // interval. Then, every write operation the current time is marked as the end
56 // of the current active interval. If the database has no write operations for
57 // a certain amount of time, then the database is considered inactive for that
58 // time period and a new start time is noted. Having the key be the beginning
59 // of the active interval allows for efficient upserts to the current active
60 // interval. If the end of the active interval was in the key, then every update
61 // to the active interval would have to remove a key and insert a new one.
62 // Key: Beginning of ActiveInterval
63 // Value: End of ActiveInterval
65 // Event DB:
66 // Stores all events. A time and type is enough to uniquely identify an event.
67 // Using the time that the event took place as the beginning of the key allows
68 // us to efficiently answer the question: "What are all the events that took
69 // place in this time range?".
70 // Key: Time - Type
71 // Value: Event in JSON
73 // Recent DB:
74 // Stores the most recent metric statistics to go into the database. There is
75 // only ever one entry per (metric, activity) pair. |recent_map_| keeps an
76 // in-memory version of this database with a mapping from a concatenation of
77 // metric and activity to the key used in the recent db. |recent_map_| allows us
78 // to quickly find the key that must be replaced in the recent db. This
79 // database becomes useful when it is necessary to find all the active metrics
80 // within a timerange. Without it, all the metric databases would need to be
81 // searched to see if that metric is active.
82 // Key: Time - Metric - Activity
83 // Value: Statistic
85 // Max Value DB:
86 // Stores the max metric statistics that have been inserted into the database.
87 // There is only ever one entry per (metric, activity) pair. |max_value_map_|
88 // keeps an in-memory version of this database with a mapping from a
89 // concatenation of metric and activity to the max metric.
90 // Key: Metric - Activity
91 // Value: Statistic
93 // Metric DB:
94 // Stores the statistics for different metrics. Having the time before the
95 // activity ensures that the search space can only be as large as the time
96 // interval.
97 // Key: Metric - Time - Activity
98 // Value: Statistic
99 class Database {
100 public:
101 typedef std::set<EventType> EventTypeSet;
102 typedef std::vector<linked_ptr<Event> > EventVector;
103 typedef std::set<MetricType> MetricTypeSet;
104 typedef std::vector<Metric> MetricVector;
105 typedef std::map<std::string, linked_ptr<MetricVector> > MetricVectorMap;
107 static const char kDatabaseSequenceToken[];
109 // The class that the database will use to infer time. Abstracting out the
110 // time mechanism allows for easy testing and mock data insetion.
111 class Clock {
112 public:
113 Clock() {}
114 virtual ~Clock() {}
115 virtual base::Time GetTime() = 0;
118 virtual ~Database();
120 static scoped_ptr<Database> Create(base::FilePath path);
122 // A "state" value is anything that can only have one value at a time, and
123 // usually describes the state of the browser eg. version.
124 bool AddStateValue(const std::string& key, const std::string& value);
126 std::string GetStateValue(const std::string& key);
128 // Add an event to the database.
129 bool AddEvent(const Event& event);
131 // Retrieve the events from the database. These methods populate the provided
132 // vector, and will search on the given criteria.
133 EventVector GetEvents(EventType type,
134 const base::Time& start,
135 const base::Time& end);
137 EventVector GetEvents(const base::Time& start, const base::Time& end) {
138 return GetEvents(EVENT_UNDEFINED, start, end);
141 EventVector GetEvents(EventType type) {
142 return GetEvents(type, base::Time(), clock_->GetTime());
145 EventVector GetEvents() {
146 return GetEvents(EVENT_UNDEFINED, base::Time(), clock_->GetTime());
149 EventTypeSet GetEventTypes(const base::Time& start, const base::Time& end);
151 EventTypeSet GetEventTypes() {
152 return GetEventTypes(base::Time(), clock_->GetTime());
155 // Add a metric instance to the database.
156 bool AddMetric(const std::string& activity, const Metric& metric);
158 bool AddMetric(const Metric& metric) {
159 return AddMetric(kProcessChromeAggregate, metric);
162 // Get the metrics that are active for the given process between |start|
163 // (inclusive) and |end| (exclusive).
164 MetricTypeSet GetActiveMetrics(const base::Time& start,
165 const base::Time& end);
167 // Get the activities that are active for the given metric after |start|.
168 std::set<std::string> GetActiveActivities(MetricType metric_type,
169 const base::Time& start);
171 // Get the max value for the given metric in the db.
172 double GetMaxStatsForActivityAndMetric(const std::string& activity,
173 MetricType metric_type);
174 double GetMaxStatsForActivityAndMetric(MetricType metric_type) {
175 return GetMaxStatsForActivityAndMetric(kProcessChromeAggregate,
176 metric_type);
179 // Populate info with the most recent activity. Return false if populate
180 // was unsuccessful.
181 bool GetRecentStatsForActivityAndMetric(const std::string& activity,
182 MetricType metric_type,
183 Metric* metric);
185 bool GetRecentStatsForActivityAndMetric(MetricType metric_type,
186 Metric* metric) {
187 return GetRecentStatsForActivityAndMetric(kProcessChromeAggregate,
188 metric_type,
189 metric);
192 // Query given |metric_type| and |activity|.
193 scoped_ptr<MetricVector> GetStatsForActivityAndMetric(
194 const std::string& activity,
195 MetricType metric_type,
196 const base::Time& start,
197 const base::Time& end);
199 scoped_ptr<MetricVector> GetStatsForActivityAndMetric(
200 MetricType metric_type, const base::Time& start, const base::Time& end) {
201 return GetStatsForActivityAndMetric(kProcessChromeAggregate, metric_type,
202 start, end);
205 scoped_ptr<MetricVector> GetStatsForActivityAndMetric(
206 const std::string& activity, MetricType metric_type) {
207 return GetStatsForActivityAndMetric(activity, metric_type, base::Time(),
208 clock_->GetTime());
211 scoped_ptr<MetricVector> GetStatsForActivityAndMetric(
212 MetricType metric_type) {
213 return GetStatsForActivityAndMetric(kProcessChromeAggregate, metric_type,
214 base::Time(), clock_->GetTime());
217 // Query given |metric_type|. The returned map is keyed by activity.
218 MetricVectorMap GetStatsForMetricByActivity(MetricType metric_type,
219 const base::Time& start,
220 const base::Time& end);
222 MetricVectorMap GetStatsForMetricByActivity(MetricType metric_type) {
223 return GetStatsForMetricByActivity(
224 metric_type, base::Time(), clock_->GetTime());
227 // Returns the active time intervals that overlap with the time interval
228 // defined by |start| and |end|.
229 std::vector<TimeRange> GetActiveIntervals(const base::Time& start,
230 const base::Time& end);
232 base::FilePath path() const { return path_; }
234 void set_clock(scoped_ptr<Clock> clock) {
235 clock_ = clock.Pass();
238 private:
239 friend class DatabaseTestHelper;
241 typedef std::map<std::string, std::string> RecentMap;
242 typedef std::map<std::string, double> MaxValueMap;
244 // By default, the database uses a clock that simply returns the current time.
245 class SystemClock : public Clock {
246 public:
247 SystemClock() {}
248 virtual ~SystemClock() {}
249 virtual base::Time GetTime() OVERRIDE;
252 explicit Database(const base::FilePath& path);
254 bool InitDBs();
256 // Attempts to open a database, and tries to fix it if it is corrupt or
257 // damaged (if |fix_if_damaged| is true). Returns a scoped_ptr to the
258 // database on success, or NULL on failure.
259 scoped_ptr<leveldb::DB> SafelyOpenDatabase(
260 const leveldb::Options& options,
261 const std::string& path,
262 bool fix_if_damaged);
264 bool Close();
266 // Load recent info from the db into recent_map_.
267 void LoadRecents();
268 // Load max values from the db into the max_value_map_.
269 void LoadMaxValues();
271 // Mark the database as being active for the current time.
272 void UpdateActiveInterval();
273 // Updates the max_value_map_ and max_value_db_ if the value is greater than
274 // the current max value for the given activity and metric.
275 bool UpdateMaxValue(const std::string& activity,
276 MetricType metric,
277 const std::string& value);
279 scoped_ptr<KeyBuilder> key_builder_;
281 // A mapping of id,metric to the last inserted key for those parameters
282 // is maintained to prevent having to search through the recent db every
283 // insert.
284 RecentMap recent_map_;
286 MaxValueMap max_value_map_;
288 // The directory where all the databases will reside.
289 base::FilePath path_;
291 // The key for the beginning of the active interval.
292 std::string start_time_key_;
294 // The last time the database had a transaction.
295 base::Time last_update_time_;
297 scoped_ptr<Clock> clock_;
299 scoped_ptr<leveldb::DB> recent_db_;
301 scoped_ptr<leveldb::DB> max_value_db_;
303 scoped_ptr<leveldb::DB> state_db_;
305 scoped_ptr<leveldb::DB> active_interval_db_;
307 scoped_ptr<leveldb::DB> metric_db_;
309 scoped_ptr<leveldb::DB> event_db_;
311 leveldb::ReadOptions read_options_;
312 leveldb::WriteOptions write_options_;
314 // Indicates whether or not the database successfully initialized. If false,
315 // the Create() call will return NULL.
316 bool valid_;
318 DISALLOW_COPY_AND_ASSIGN(Database);
321 } // namespace performance_monitor
323 #endif // CHROME_BROWSER_PERFORMANCE_MONITOR_DATABASE_H_