| Index: chrome/browser/performance_monitor/database.cc
|
| diff --git a/chrome/browser/performance_monitor/database.cc b/chrome/browser/performance_monitor/database.cc
|
| deleted file mode 100644
|
| index f3522d20e48838ed4c91636a8d7b5e6d2fff9cbc..0000000000000000000000000000000000000000
|
| --- a/chrome/browser/performance_monitor/database.cc
|
| +++ /dev/null
|
| @@ -1,590 +0,0 @@
|
| -// 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/files/file_path.h"
|
| -#include "base/files/file_util.h"
|
| -#include "base/json/json_reader.h"
|
| -#include "base/json/json_writer.h"
|
| -#include "base/logging.h"
|
| -#include "base/path_service.h"
|
| -#include "base/stl_util.h"
|
| -#include "base/strings/string_number_conversions.h"
|
| -#include "base/strings/utf_string_conversions.h"
|
| -#include "base/time/time.h"
|
| -#include "chrome/browser/performance_monitor/key_builder.h"
|
| -#include "chrome/common/chrome_paths.h"
|
| -#include "content/public/browser/browser_thread.h"
|
| -#include "third_party/leveldatabase/src/include/leveldb/db.h"
|
| -#include "third_party/leveldatabase/src/include/leveldb/iterator.h"
|
| -#include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
|
| -
|
| -namespace performance_monitor {
|
| -namespace {
|
| -const char kDbDir[] = "Performance Monitor Databases";
|
| -const char kRecentDb[] = "Recent Metrics";
|
| -const char kMaxValueDb[] = "Max Value Metrics";
|
| -const char kEventDb[] = "Events";
|
| -const char kStateDb[] = "Configuration";
|
| -const char kActiveIntervalDb[] = "Active Interval";
|
| -const char kMetricDb[] = "Metrics";
|
| -const double kDefaultMaxValue = 0.0;
|
| -
|
| -// If the db is quiet for this number of minutes, then it is considered down.
|
| -const base::TimeDelta kActiveIntervalTimeout() {
|
| - return base::TimeDelta::FromMinutes(5);
|
| -}
|
| -
|
| -TimeRange ActiveIntervalToTimeRange(const std::string& start_time,
|
| - const std::string& end_time) {
|
| - int64 start_time_int = 0;
|
| - int64 end_time_int = 0;
|
| - base::StringToInt64(start_time, &start_time_int);
|
| - base::StringToInt64(end_time, &end_time_int);
|
| - return TimeRange(base::Time::FromInternalValue(start_time_int),
|
| - base::Time::FromInternalValue(end_time_int));
|
| -}
|
| -
|
| -double StringToDouble(const std::string& s) {
|
| - double value = 0.0;
|
| - if (!base::StringToDouble(s, &value))
|
| - LOG(ERROR) << "Failed to convert " << s << " to double.";
|
| - return value;
|
| -}
|
| -
|
| -// Returns an event from the given JSON string; the scoped_ptr will be NULL if
|
| -// we are unable to properly parse the JSON.
|
| -scoped_ptr<Event> EventFromJSON(const std::string& data) {
|
| - base::Value* value = base::JSONReader::Read(data);
|
| - base::DictionaryValue* dict = NULL;
|
| - if (!value || !value->GetAsDictionary(&dict))
|
| - return scoped_ptr<Event>();
|
| -
|
| - return Event::FromValue(scoped_ptr<base::DictionaryValue>(dict));
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -const char Database::kDatabaseSequenceToken[] =
|
| - "_performance_monitor_db_sequence_token_";
|
| -
|
| -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();
|
| -}
|
| -
|
| -// Static
|
| -scoped_ptr<Database> Database::Create(base::FilePath path) {
|
| - CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
| - if (path.empty()) {
|
| - CHECK(PathService::Get(chrome::DIR_USER_DATA, &path));
|
| - path = path.AppendASCII(kDbDir);
|
| - }
|
| - scoped_ptr<Database> database;
|
| - if (!base::DirectoryExists(path) && !base::CreateDirectory(path))
|
| - return database.Pass();
|
| - database.reset(new Database(path));
|
| -
|
| - // If the database did not initialize correctly, return a NULL scoped_ptr.
|
| - if (!database->valid_)
|
| - database.reset();
|
| - return database.Pass();
|
| -}
|
| -
|
| -bool Database::AddStateValue(const std::string& key, const std::string& value) {
|
| - CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
| - UpdateActiveInterval();
|
| - leveldb::Status insert_status = state_db_->Put(write_options_, key, value);
|
| - return insert_status.ok();
|
| -}
|
| -
|
| -std::string Database::GetStateValue(const std::string& key) {
|
| - CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
| - std::string result;
|
| - state_db_->Get(read_options_, key, &result);
|
| - return result;
|
| -}
|
| -
|
| -bool Database::AddEvent(const Event& event) {
|
| - CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
| - UpdateActiveInterval();
|
| - std::string value;
|
| - base::JSONWriter::Write(event.data(), &value);
|
| - std::string key = key_builder_->CreateEventKey(event.time(), event.type());
|
| - leveldb::Status status = event_db_->Put(write_options_, key, value);
|
| - return status.ok();
|
| -}
|
| -
|
| -std::vector<TimeRange> Database::GetActiveIntervals(const base::Time& start,
|
| - const base::Time& end) {
|
| - CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
| - std::vector<TimeRange> results;
|
| - std::string start_key = key_builder_->CreateActiveIntervalKey(start);
|
| - std::string end_key = key_builder_->CreateActiveIntervalKey(end);
|
| - scoped_ptr<leveldb::Iterator> it(active_interval_db_->NewIterator(
|
| - read_options_));
|
| - it->Seek(start_key);
|
| - // If the interator is valid, we check the previous value in case we jumped
|
| - // into the middle of an active interval. If the iterator is not valid, then
|
| - // the key may be in the current active interval.
|
| - if (it->Valid())
|
| - it->Prev();
|
| - else
|
| - it->SeekToLast();
|
| - if (it->Valid() && it->value().ToString() > start_key) {
|
| - results.push_back(ActiveIntervalToTimeRange(it->key().ToString(),
|
| - it->value().ToString()));
|
| - }
|
| -
|
| - for (it->Seek(start_key);
|
| - it->Valid() && it->key().ToString() < end_key;
|
| - it->Next()) {
|
| - results.push_back(ActiveIntervalToTimeRange(it->key().ToString(),
|
| - it->value().ToString()));
|
| - }
|
| - return results;
|
| -}
|
| -
|
| -Database::EventVector Database::GetEvents(EventType type,
|
| - const base::Time& start,
|
| - const base::Time& end) {
|
| - CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
| - EventVector events;
|
| - std::string start_key =
|
| - key_builder_->CreateEventKey(start, EVENT_UNDEFINED);
|
| - std::string end_key =
|
| - key_builder_->CreateEventKey(end, EVENT_NUMBER_OF_EVENTS);
|
| - leveldb::WriteBatch invalid_entries;
|
| - scoped_ptr<leveldb::Iterator> it(event_db_->NewIterator(read_options_));
|
| - for (it->Seek(start_key);
|
| - it->Valid() && it->key().ToString() <= end_key;
|
| - it->Next()) {
|
| - if (type != EVENT_UNDEFINED) {
|
| - EventType key_type =
|
| - key_builder_->EventKeyToEventType(it->key().ToString());
|
| - if (key_type != type)
|
| - continue;
|
| - }
|
| - scoped_ptr<Event> event = EventFromJSON(it->value().ToString());
|
| - if (!event.get()) {
|
| - invalid_entries.Delete(it->key());
|
| - LOG(ERROR) << "Found invalid event in the database. JSON: '"
|
| - << it->value().ToString()
|
| - << "'. Erasing event from the database.";
|
| - continue;
|
| - }
|
| - events.push_back(linked_ptr<Event>(event.release()));
|
| - }
|
| - event_db_->Write(write_options_, &invalid_entries);
|
| - return events;
|
| -}
|
| -
|
| -Database::EventTypeSet Database::GetEventTypes(const base::Time& start,
|
| - const base::Time& end) {
|
| - CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
| - EventTypeSet results;
|
| - std::string start_key =
|
| - key_builder_->CreateEventKey(start, EVENT_UNDEFINED);
|
| - std::string end_key =
|
| - key_builder_->CreateEventKey(end, EVENT_NUMBER_OF_EVENTS);
|
| - scoped_ptr<leveldb::Iterator> it(event_db_->NewIterator(read_options_));
|
| - for (it->Seek(start_key);
|
| - it->Valid() && it->key().ToString() <= end_key;
|
| - it->Next()) {
|
| - EventType key_type =
|
| - key_builder_->EventKeyToEventType(it->key().ToString());
|
| - results.insert(key_type);
|
| - }
|
| - return results;
|
| -}
|
| -
|
| -bool Database::AddMetric(const std::string& activity,
|
| - const Metric& metric) {
|
| - CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
| - if (!metric.IsValid()) {
|
| - DLOG(ERROR) << "Metric to be added is invalid. Type: " << metric.type
|
| - << ", Time: " << metric.time.ToInternalValue()
|
| - << ", Value: " << metric.value << ". Ignoring.";
|
| - return false;
|
| - }
|
| -
|
| - UpdateActiveInterval();
|
| - std::string recent_key =
|
| - key_builder_->CreateRecentKey(metric.time, metric.type, activity);
|
| - std::string metric_key =
|
| - key_builder_->CreateMetricKey(metric.time, metric.type, activity);
|
| - std::string recent_map_key =
|
| - key_builder_->CreateRecentMapKey(metric.type, activity);
|
| - // Use recent_map_ to quickly find the key that must be removed.
|
| - RecentMap::iterator old_it = recent_map_.find(recent_map_key);
|
| - if (old_it != recent_map_.end())
|
| - recent_db_->Delete(write_options_, old_it->second);
|
| - recent_map_[recent_map_key] = recent_key;
|
| - leveldb::Status recent_status =
|
| - recent_db_->Put(write_options_, recent_key, metric.ValueAsString());
|
| - leveldb::Status metric_status =
|
| - metric_db_->Put(write_options_, metric_key, metric.ValueAsString());
|
| -
|
| - bool max_value_success =
|
| - UpdateMaxValue(activity, metric.type, metric.ValueAsString());
|
| - return recent_status.ok() && metric_status.ok() && max_value_success;
|
| -}
|
| -
|
| -bool Database::UpdateMaxValue(const std::string& activity,
|
| - MetricType metric,
|
| - const std::string& value) {
|
| - std::string max_value_key(
|
| - key_builder_->CreateMaxValueKey(metric, activity));
|
| - bool has_key = ContainsKey(max_value_map_, max_value_key);
|
| - if ((has_key && StringToDouble(value) > max_value_map_[max_value_key]) ||
|
| - !has_key) {
|
| - max_value_map_[max_value_key] = StringToDouble(value);
|
| - return max_value_db_->Put(write_options_, max_value_key, value).ok();
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -Database::MetricTypeSet Database::GetActiveMetrics(const base::Time& start,
|
| - const base::Time& end) {
|
| - CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
| - std::string recent_start_key = key_builder_->CreateRecentKey(
|
| - start, static_cast<MetricType>(0), std::string());
|
| - std::string recent_end_key = key_builder_->CreateRecentKey(
|
| - end, METRIC_NUMBER_OF_METRICS, std::string());
|
| - std::string recent_end_of_time_key = key_builder_->CreateRecentKey(
|
| - clock_->GetTime(), METRIC_NUMBER_OF_METRICS, std::string());
|
| -
|
| - MetricTypeSet active_metrics;
|
| - // Get all the guaranteed metrics.
|
| - scoped_ptr<leveldb::Iterator> recent_it(
|
| - recent_db_->NewIterator(read_options_));
|
| - for (recent_it->Seek(recent_start_key);
|
| - recent_it->Valid() && recent_it->key().ToString() <= recent_end_key;
|
| - recent_it->Next()) {
|
| - RecentKey split_key =
|
| - key_builder_->SplitRecentKey(recent_it->key().ToString());
|
| - active_metrics.insert(split_key.type);
|
| - }
|
| - // Get all the possible metrics (metrics that may have been updated after
|
| - // |end|).
|
| - MetricTypeSet possible_metrics;
|
| - for (recent_it->Seek(recent_end_key);
|
| - recent_it->Valid() &&
|
| - recent_it->key().ToString() <= recent_end_of_time_key;
|
| - recent_it->Next()) {
|
| - RecentKey split_key =
|
| - key_builder_->SplitRecentKey(recent_it->key().ToString());
|
| - possible_metrics.insert(split_key.type);
|
| - }
|
| - MetricTypeSet::iterator possible_it;
|
| - scoped_ptr<leveldb::Iterator> metric_it(
|
| - metric_db_->NewIterator(read_options_));
|
| - for (possible_it = possible_metrics.begin();
|
| - possible_it != possible_metrics.end();
|
| - ++possible_it) {
|
| - std::string metric_start_key =
|
| - key_builder_->CreateMetricKey(start, *possible_it,std::string());
|
| - std::string metric_end_key =
|
| - key_builder_->CreateMetricKey(end, *possible_it, std::string());
|
| - metric_it->Seek(metric_start_key);
|
| - // Stats in the timerange from any activity makes the metric active.
|
| - if (metric_it->Valid() && metric_it->key().ToString() <= metric_end_key) {
|
| - active_metrics.insert(*possible_it);
|
| - }
|
| - }
|
| -
|
| - return active_metrics;
|
| -}
|
| -
|
| -std::set<std::string> Database::GetActiveActivities(MetricType metric_type,
|
| - const base::Time& start) {
|
| - CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
| - std::set<std::string> results;
|
| - std::string start_key = key_builder_->CreateRecentKey(
|
| - start, static_cast<MetricType>(0), std::string());
|
| - scoped_ptr<leveldb::Iterator> it(recent_db_->NewIterator(read_options_));
|
| - for (it->Seek(start_key); it->Valid(); it->Next()) {
|
| - RecentKey split_key =
|
| - key_builder_->SplitRecentKey(it->key().ToString());
|
| - if (split_key.type == metric_type)
|
| - results.insert(split_key.activity);
|
| - }
|
| - return results;
|
| -}
|
| -
|
| -double Database::GetMaxStatsForActivityAndMetric(const std::string& activity,
|
| - MetricType metric) {
|
| - CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
| - std::string max_value_key(
|
| - key_builder_->CreateMaxValueKey(metric, activity));
|
| - if (ContainsKey(max_value_map_, max_value_key))
|
| - return max_value_map_[max_value_key];
|
| - return kDefaultMaxValue;
|
| -}
|
| -
|
| -bool Database::GetRecentStatsForActivityAndMetric(const std::string& activity,
|
| - MetricType metric_type,
|
| - Metric* metric) {
|
| - CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
| - std::string recent_map_key =
|
| - key_builder_->CreateRecentMapKey(metric_type, activity);
|
| - if (!ContainsKey(recent_map_, recent_map_key))
|
| - return false;
|
| - std::string recent_key = recent_map_[recent_map_key];
|
| -
|
| - std::string result;
|
| - leveldb::Status status = recent_db_->Get(read_options_, recent_key, &result);
|
| - if (status.ok())
|
| - *metric = Metric(metric_type,
|
| - key_builder_->SplitRecentKey(recent_key).time,
|
| - result);
|
| - return status.ok();
|
| -}
|
| -
|
| -scoped_ptr<Database::MetricVector> Database::GetStatsForActivityAndMetric(
|
| - const std::string& activity,
|
| - MetricType metric_type,
|
| - const base::Time& start,
|
| - const base::Time& end) {
|
| - CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
| - scoped_ptr<MetricVector> results(new MetricVector());
|
| - std::string start_key =
|
| - key_builder_->CreateMetricKey(start, metric_type, activity);
|
| - std::string end_key =
|
| - key_builder_->CreateMetricKey(end, metric_type, activity);
|
| - leveldb::WriteBatch invalid_entries;
|
| - scoped_ptr<leveldb::Iterator> it(metric_db_->NewIterator(read_options_));
|
| - for (it->Seek(start_key);
|
| - it->Valid() && it->key().ToString() <= end_key;
|
| - it->Next()) {
|
| - MetricKey split_key =
|
| - key_builder_->SplitMetricKey(it->key().ToString());
|
| - if (split_key.activity == activity) {
|
| - Metric metric(metric_type, split_key.time, it->value().ToString());
|
| - if (!metric.IsValid()) {
|
| - invalid_entries.Delete(it->key());
|
| - LOG(ERROR) << "Found bad metric in the database. Type: "
|
| - << metric.type << ", Time: " << metric.time.ToInternalValue()
|
| - << ", Value: " << metric.value
|
| - << ". Erasing metric from database.";
|
| - continue;
|
| - }
|
| - results->push_back(metric);
|
| - }
|
| - }
|
| - metric_db_->Write(write_options_, &invalid_entries);
|
| - return results.Pass();
|
| -}
|
| -
|
| -Database::MetricVectorMap Database::GetStatsForMetricByActivity(
|
| - MetricType metric_type,
|
| - const base::Time& start,
|
| - const base::Time& end) {
|
| - CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
| - MetricVectorMap results;
|
| - std::string start_key =
|
| - key_builder_->CreateMetricKey(start, metric_type, std::string());
|
| - std::string end_key =
|
| - key_builder_->CreateMetricKey(end, metric_type, std::string());
|
| - leveldb::WriteBatch invalid_entries;
|
| - scoped_ptr<leveldb::Iterator> it(metric_db_->NewIterator(read_options_));
|
| - for (it->Seek(start_key);
|
| - it->Valid() && it->key().ToString() <= end_key;
|
| - it->Next()) {
|
| - MetricKey split_key = key_builder_->SplitMetricKey(it->key().ToString());
|
| - if (!results[split_key.activity].get()) {
|
| - results[split_key.activity] =
|
| - linked_ptr<MetricVector >(new MetricVector());
|
| - }
|
| - Metric metric(metric_type, split_key.time, it->value().ToString());
|
| - if (!metric.IsValid()) {
|
| - invalid_entries.Delete(it->key());
|
| - LOG(ERROR) << "Found bad metric in the database. Type: "
|
| - << metric.type << ", Time: " << metric.time.ToInternalValue()
|
| - << ", Value: " << metric.value
|
| - << ". Erasing metric from database.";
|
| - continue;
|
| - }
|
| - results[split_key.activity]->push_back(metric);
|
| - }
|
| - metric_db_->Write(write_options_, &invalid_entries);
|
| - return results;
|
| -}
|
| -
|
| -Database::Database(const base::FilePath& path)
|
| - : key_builder_(new KeyBuilder()),
|
| - path_(path),
|
| - read_options_(leveldb::ReadOptions()),
|
| - write_options_(leveldb::WriteOptions()),
|
| - valid_(false) {
|
| - if (!InitDBs())
|
| - return;
|
| - LoadRecents();
|
| - LoadMaxValues();
|
| - clock_ = scoped_ptr<Clock>(new SystemClock());
|
| - valid_ = true;
|
| -}
|
| -
|
| -Database::~Database() {
|
| -}
|
| -
|
| -bool Database::InitDBs() {
|
| - CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
| - leveldb::Options open_options;
|
| - open_options.max_open_files = 0; // Use minimum.
|
| - open_options.create_if_missing = true;
|
| -
|
| - // TODO (rdevlin.cronin): This code is ugly. Fix it.
|
| - recent_db_ = SafelyOpenDatabase(open_options,
|
| - kRecentDb,
|
| - true); // fix if damaged
|
| - max_value_db_ = SafelyOpenDatabase(open_options,
|
| - kMaxValueDb,
|
| - true); // fix if damaged
|
| - state_db_ = SafelyOpenDatabase(open_options,
|
| - kStateDb,
|
| - true); // fix if damaged
|
| - active_interval_db_ = SafelyOpenDatabase(open_options,
|
| - kActiveIntervalDb,
|
| - true); // fix if damaged
|
| - metric_db_ = SafelyOpenDatabase(open_options,
|
| - kMetricDb,
|
| - true); // fix if damaged
|
| - event_db_ = SafelyOpenDatabase(open_options,
|
| - kEventDb,
|
| - true); // fix if damaged
|
| - return recent_db_ && max_value_db_ && state_db_ &&
|
| - active_interval_db_ && metric_db_ && event_db_;
|
| -}
|
| -
|
| -scoped_ptr<leveldb::DB> Database::SafelyOpenDatabase(
|
| - const leveldb::Options& options,
|
| - const std::string& path,
|
| - bool fix_if_damaged) {
|
| -#if defined(OS_POSIX)
|
| - std::string name = path_.AppendASCII(path).value();
|
| -#elif defined(OS_WIN)
|
| - std::string name = base::WideToUTF8(path_.AppendASCII(path).value());
|
| -#endif
|
| -
|
| - leveldb::DB* database;
|
| - leveldb::Status status = leveldb::DB::Open(options, name, &database);
|
| - // If all goes well, return the database.
|
| - if (status.ok())
|
| - return scoped_ptr<leveldb::DB>(database);
|
| -
|
| - // Return NULL and print the error if we either didn't find the database and
|
| - // don't want to create it, or if we don't want to try to fix it.
|
| - if ((status.IsNotFound() && !options.create_if_missing) || !fix_if_damaged) {
|
| - LOG(ERROR) << status.ToString();
|
| - return scoped_ptr<leveldb::DB>();
|
| - }
|
| - // Otherwise, we have an error (corruption, io error, or a not found error
|
| - // even if we tried to create it).
|
| - //
|
| - // First, we try again.
|
| - LOG(ERROR) << "Database error: " << status.ToString() << ". Trying again.";
|
| - status = leveldb::DB::Open(options, name, &database);
|
| - // If we fail on corruption, we can try to repair it.
|
| - if (status.IsCorruption()) {
|
| - LOG(ERROR) << "Database corrupt (second attempt). Trying to repair.";
|
| - status = leveldb::RepairDB(name, options);
|
| - // If the repair succeeds and we can open the database, return the
|
| - // database. Otherwise, continue on.
|
| - if (status.ok()) {
|
| - status = leveldb::DB::Open(options, name, &database);
|
| - if (status.ok())
|
| - return scoped_ptr<leveldb::DB>(database);
|
| - }
|
| - LOG(ERROR) << "Repair failed. Deleting database.";
|
| - }
|
| - // Next, try to delete and recreate the database. Return NULL if we fail
|
| - // on either of these steps.
|
| - status = leveldb::DestroyDB(name, options);
|
| - if (!status.ok()) {
|
| - LOG(ERROR) << "Failed to delete database. " << status.ToString();
|
| - return scoped_ptr<leveldb::DB>();
|
| - }
|
| - // If we don't have the create_if_missing option, add it (it's safe to
|
| - // assume this is okay, since we have permission to |fix_if_damaged|).
|
| - if (!options.create_if_missing) {
|
| - leveldb::Options create_options(options);
|
| - create_options.create_if_missing = true;
|
| - status = leveldb::DB::Open(create_options, name, &database);
|
| - } else {
|
| - status = leveldb::DB::Open(options, name, &database);
|
| - }
|
| - // There's nothing else we can try at this point.
|
| - if (status.ok())
|
| - return scoped_ptr<leveldb::DB>(database);
|
| - // Return the database if we succeeded, or NULL on failure.
|
| - LOG(ERROR) << "Failed to recreate database. " << status.ToString();
|
| - return scoped_ptr<leveldb::DB>();
|
| -}
|
| -
|
| -bool Database::Close() {
|
| - CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
| - metric_db_.reset();
|
| - event_db_.reset();
|
| - recent_db_.reset();
|
| - max_value_db_.reset();
|
| - state_db_.reset();
|
| - active_interval_db_.reset();
|
| - start_time_key_.clear();
|
| - return true;
|
| -}
|
| -
|
| -void Database::LoadRecents() {
|
| - CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
| - recent_map_.clear();
|
| - scoped_ptr<leveldb::Iterator> it(recent_db_->NewIterator(read_options_));
|
| - for (it->SeekToFirst(); it->Valid(); it->Next()) {
|
| - RecentKey split_key = key_builder_->SplitRecentKey(it->key().ToString());
|
| - recent_map_[key_builder_->
|
| - CreateRecentMapKey(split_key.type, split_key.activity)] =
|
| - it->key().ToString();
|
| - }
|
| -}
|
| -
|
| -void Database::LoadMaxValues() {
|
| - CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
| - max_value_map_.clear();
|
| - scoped_ptr<leveldb::Iterator> it(max_value_db_->NewIterator(read_options_));
|
| - for (it->SeekToFirst(); it->Valid(); it->Next()) {
|
| - max_value_map_[it->key().ToString()] =
|
| - StringToDouble(it->value().ToString());
|
| - }
|
| -}
|
| -
|
| -// TODO(chebert): Only update the active interval under certian circumstances
|
| -// eg. every 10 times or when forced.
|
| -void Database::UpdateActiveInterval() {
|
| - CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
| - base::Time current_time = clock_->GetTime();
|
| - std::string end_time;
|
| - // If the last update was too long ago.
|
| - if (start_time_key_.empty() ||
|
| - current_time - last_update_time_ > kActiveIntervalTimeout()) {
|
| - start_time_key_ = key_builder_->CreateActiveIntervalKey(current_time);
|
| - end_time = start_time_key_;
|
| - } else {
|
| - end_time = key_builder_->CreateActiveIntervalKey(clock_->GetTime());
|
| - }
|
| - last_update_time_ = current_time;
|
| - active_interval_db_->Put(write_options_, start_time_key_, end_time);
|
| -}
|
| -
|
| -} // namespace performance_monitor
|
|
|