Home | History | Annotate | Download | only in performance_monitor
      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 #ifndef CHROME_BROWSER_PERFORMANCE_MONITOR_DATABASE_H_
      6 #define CHROME_BROWSER_PERFORMANCE_MONITOR_DATABASE_H_
      7 
      8 #include <set>
      9 #include <string>
     10 #include <vector>
     11 
     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"
     21 
     22 namespace performance_monitor {
     23 
     24 struct TimeRange {
     25   TimeRange();
     26   TimeRange(base::Time start_time, base::Time end_time);
     27   ~TimeRange();
     28 
     29   base::Time start;
     30   base::Time end;
     31 };
     32 
     33 class KeyBuilder;
     34 class DatabaseTestHelper;
     35 
     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.
     40 //
     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 '-'.
     45 //
     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
     51 //
     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
     64 //
     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
     72 //
     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
     84 //
     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
     92 //
     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;
    106 
    107   static const char kDatabaseSequenceToken[];
    108 
    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;
    116   };
    117 
    118   virtual ~Database();
    119 
    120   static scoped_ptr<Database> Create(base::FilePath path);
    121 
    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);
    125 
    126   std::string GetStateValue(const std::string& key);
    127 
    128   // Add an event to the database.
    129   bool AddEvent(const Event& event);
    130 
    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);
    136 
    137   EventVector GetEvents(const base::Time& start, const base::Time& end) {
    138     return GetEvents(EVENT_UNDEFINED, start, end);
    139   }
    140 
    141   EventVector GetEvents(EventType type) {
    142     return GetEvents(type, base::Time(), clock_->GetTime());
    143   }
    144 
    145   EventVector GetEvents() {
    146     return GetEvents(EVENT_UNDEFINED, base::Time(), clock_->GetTime());
    147   }
    148 
    149   EventTypeSet GetEventTypes(const base::Time& start, const base::Time& end);
    150 
    151   EventTypeSet GetEventTypes() {
    152     return GetEventTypes(base::Time(), clock_->GetTime());
    153   }
    154 
    155   // Add a metric instance to the database.
    156   bool AddMetric(const std::string& activity, const Metric& metric);
    157 
    158   bool AddMetric(const Metric& metric) {
    159     return AddMetric(kProcessChromeAggregate, metric);
    160   }
    161 
    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);
    166 
    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);
    170 
    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);
    177   }
    178 
    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);
    184 
    185   bool GetRecentStatsForActivityAndMetric(MetricType metric_type,
    186                                            Metric* metric) {
    187     return GetRecentStatsForActivityAndMetric(kProcessChromeAggregate,
    188                                               metric_type,
    189                                               metric);
    190   }
    191 
    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);
    198 
    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);
    203   }
    204 
    205   scoped_ptr<MetricVector> GetStatsForActivityAndMetric(
    206       const std::string& activity, MetricType metric_type) {
    207     return GetStatsForActivityAndMetric(activity, metric_type, base::Time(),
    208                                         clock_->GetTime());
    209   }
    210 
    211   scoped_ptr<MetricVector> GetStatsForActivityAndMetric(
    212       MetricType metric_type) {
    213     return GetStatsForActivityAndMetric(kProcessChromeAggregate, metric_type,
    214                                         base::Time(), clock_->GetTime());
    215   }
    216 
    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);
    221 
    222   MetricVectorMap GetStatsForMetricByActivity(MetricType metric_type) {
    223     return GetStatsForMetricByActivity(
    224         metric_type, base::Time(), clock_->GetTime());
    225   }
    226 
    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);
    231 
    232   base::FilePath path() const { return path_; }
    233 
    234   void set_clock(scoped_ptr<Clock> clock) {
    235     clock_ = clock.Pass();
    236   }
    237 
    238  private:
    239   friend class DatabaseTestHelper;
    240 
    241   typedef std::map<std::string, std::string> RecentMap;
    242   typedef std::map<std::string, double> MaxValueMap;
    243 
    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;
    250   };
    251 
    252   explicit Database(const base::FilePath& path);
    253 
    254   bool InitDBs();
    255 
    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);
    263 
    264   bool Close();
    265 
    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();
    270 
    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);
    278 
    279   scoped_ptr<KeyBuilder> key_builder_;
    280 
    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_;
    285 
    286   MaxValueMap max_value_map_;
    287 
    288   // The directory where all the databases will reside.
    289   base::FilePath path_;
    290 
    291   // The key for the beginning of the active interval.
    292   std::string start_time_key_;
    293 
    294   // The last time the database had a transaction.
    295   base::Time last_update_time_;
    296 
    297   scoped_ptr<Clock> clock_;
    298 
    299   scoped_ptr<leveldb::DB> recent_db_;
    300 
    301   scoped_ptr<leveldb::DB> max_value_db_;
    302 
    303   scoped_ptr<leveldb::DB> state_db_;
    304 
    305   scoped_ptr<leveldb::DB> active_interval_db_;
    306 
    307   scoped_ptr<leveldb::DB> metric_db_;
    308 
    309   scoped_ptr<leveldb::DB> event_db_;
    310 
    311   leveldb::ReadOptions read_options_;
    312   leveldb::WriteOptions write_options_;
    313 
    314   // Indicates whether or not the database successfully initialized. If false,
    315   // the Create() call will return NULL.
    316   bool valid_;
    317 
    318   DISALLOW_COPY_AND_ASSIGN(Database);
    319 };
    320 
    321 }  // namespace performance_monitor
    322 
    323 #endif  // CHROME_BROWSER_PERFORMANCE_MONITOR_DATABASE_H_
    324