| Index: chrome/browser/performance_monitor/database.cc
|
| diff --git a/chrome/browser/performance_monitor/database.cc b/chrome/browser/performance_monitor/database.cc
|
| index 27108e319b010b9969c25573ba90bc199a644942..e67ab9c20545eb0ba2048d84b7f9eff3c54b7cd5 100644
|
| --- a/chrome/browser/performance_monitor/database.cc
|
| +++ b/chrome/browser/performance_monitor/database.cc
|
| @@ -18,6 +18,8 @@
|
| #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 {
|
| @@ -50,6 +52,17 @@ double StringToDouble(const std::string& s) {
|
| 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) {
|
| + Value* value = base::JSONReader::Read(data);
|
| + DictionaryValue* dict = NULL;
|
| + if (!value || !value->GetAsDictionary(&dict))
|
| + return scoped_ptr<Event>();
|
| +
|
| + return Event::FromValue(scoped_ptr<DictionaryValue>(dict));
|
| +}
|
| +
|
| } // namespace
|
|
|
| const char Database::kDatabaseSequenceToken[] =
|
| @@ -145,6 +158,7 @@ Database::EventVector Database::GetEvents(EventType type,
|
| 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;
|
| @@ -155,18 +169,17 @@ Database::EventVector Database::GetEvents(EventType type,
|
| if (key_type != type)
|
| continue;
|
| }
|
| - base::DictionaryValue* dict = NULL;
|
| - if (!base::JSONReader::Read(
|
| - it->value().ToString())->GetAsDictionary(&dict)) {
|
| - LOG(ERROR) << "Unable to convert database event to JSON.";
|
| + 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;
|
| }
|
| - scoped_ptr<Event> event =
|
| - Event::FromValue(scoped_ptr<base::DictionaryValue>(dict));
|
| - if (!event.get())
|
| - continue;
|
| events.push_back(linked_ptr<Event>(event.release()));
|
| }
|
| + event_db_->Write(write_options_, &invalid_entries);
|
| return events;
|
| }
|
|
|
| @@ -190,28 +203,34 @@ Database::EventTypeSet Database::GetEventTypes(const base::Time& start,
|
| }
|
|
|
| bool Database::AddMetric(const std::string& activity,
|
| - MetricType metric,
|
| - const std::string& value) {
|
| + const Metric& metric) {
|
| CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
| + if (!metric.IsValid()) {
|
| + LOG(ERROR) << "Metric to be added is invalid. Type: " << metric.type
|
| + << ", Time: " << metric.time.ToInternalValue()
|
| + << ", Value: " << metric.value << ". Ignoring.";
|
| + return false;
|
| + }
|
| +
|
| UpdateActiveInterval();
|
| - base::Time timestamp = clock_->GetTime();
|
| std::string recent_key =
|
| - key_builder_->CreateRecentKey(timestamp, metric, activity);
|
| + key_builder_->CreateRecentKey(metric.time, metric.type, activity);
|
| std::string metric_key =
|
| - key_builder_->CreateMetricKey(timestamp, metric, activity);
|
| + key_builder_->CreateMetricKey(metric.time, metric.type, activity);
|
| std::string recent_map_key =
|
| - key_builder_->CreateRecentMapKey(metric, activity);
|
| + 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, value);
|
| + recent_db_->Put(write_options_, recent_key, metric.ValueAsString());
|
| leveldb::Status metric_status =
|
| - metric_db_->Put(write_options_, metric_key, value);
|
| + metric_db_->Put(write_options_, metric_key, metric.ValueAsString());
|
|
|
| - bool max_value_success = UpdateMaxValue(activity, metric, value);
|
| + bool max_value_success =
|
| + UpdateMaxValue(activity, metric.type, metric.ValueAsString());
|
| return recent_status.ok() && metric_status.ok() && max_value_success;
|
| }
|
|
|
| @@ -321,7 +340,9 @@ bool Database::GetRecentStatsForActivityAndMetric(const std::string& activity,
|
| std::string result;
|
| leveldb::Status status = recent_db_->Get(read_options_, recent_key, &result);
|
| if (status.ok())
|
| - *metric = Metric(key_builder_->SplitRecentKey(recent_key).time, result);
|
| + *metric = Metric(metric_type,
|
| + key_builder_->SplitRecentKey(recent_key).time,
|
| + result);
|
| return status.ok();
|
| }
|
|
|
| @@ -336,15 +357,27 @@ Database::MetricVector Database::GetStatsForActivityAndMetric(
|
| 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)
|
| - results.push_back(Metric(split_key.time, it->value().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;
|
| }
|
|
|
| @@ -358,6 +391,7 @@ Database::MetricVectorMap Database::GetStatsForMetricByActivity(
|
| 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;
|
| @@ -367,9 +401,18 @@ Database::MetricVectorMap Database::GetStatsForMetricByActivity(
|
| results[split_key.activity] =
|
| linked_ptr<MetricVector >(new MetricVector());
|
| }
|
| - results[split_key.activity]->push_back(
|
| - Metric(split_key.time, it->value().ToString()));
|
| + 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;
|
| }
|
|
|
|
|