| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/prefs/json_pref_store.h" | 5 #include "base/prefs/json_pref_store.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/callback.h" | 10 #include "base/callback.h" |
| 11 #include "base/files/file_path.h" | 11 #include "base/files/file_path.h" |
| 12 #include "base/files/file_util.h" | 12 #include "base/files/file_util.h" |
| 13 #include "base/json/json_file_value_serializer.h" | 13 #include "base/json/json_file_value_serializer.h" |
| 14 #include "base/json/json_string_value_serializer.h" | 14 #include "base/json/json_string_value_serializer.h" |
| 15 #include "base/memory/ref_counted.h" | 15 #include "base/memory/ref_counted.h" |
| 16 #include "base/metrics/histogram.h" | 16 #include "base/metrics/histogram.h" |
| 17 #include "base/prefs/pref_filter.h" | 17 #include "base/prefs/pref_filter.h" |
| 18 #include "base/sequenced_task_runner.h" | 18 #include "base/sequenced_task_runner.h" |
| 19 #include "base/strings/string_number_conversions.h" |
| 19 #include "base/strings/string_util.h" | 20 #include "base/strings/string_util.h" |
| 20 #include "base/task_runner_util.h" | 21 #include "base/task_runner_util.h" |
| 21 #include "base/threading/sequenced_worker_pool.h" | 22 #include "base/threading/sequenced_worker_pool.h" |
| 23 #include "base/time/default_clock.h" |
| 22 #include "base/values.h" | 24 #include "base/values.h" |
| 23 | 25 |
| 24 // Result returned from internal read tasks. | 26 // Result returned from internal read tasks. |
| 25 struct JsonPrefStore::ReadResult { | 27 struct JsonPrefStore::ReadResult { |
| 26 public: | 28 public: |
| 27 ReadResult(); | 29 ReadResult(); |
| 28 ~ReadResult(); | 30 ~ReadResult(); |
| 29 | 31 |
| 30 scoped_ptr<base::Value> value; | 32 scoped_ptr<base::Value> value; |
| 31 PrefReadError error; | 33 PrefReadError error; |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 149 const scoped_refptr<base::SequencedTaskRunner>& sequenced_task_runner, | 151 const scoped_refptr<base::SequencedTaskRunner>& sequenced_task_runner, |
| 150 scoped_ptr<PrefFilter> pref_filter) | 152 scoped_ptr<PrefFilter> pref_filter) |
| 151 : path_(filename), | 153 : path_(filename), |
| 152 sequenced_task_runner_(sequenced_task_runner), | 154 sequenced_task_runner_(sequenced_task_runner), |
| 153 prefs_(new base::DictionaryValue()), | 155 prefs_(new base::DictionaryValue()), |
| 154 read_only_(false), | 156 read_only_(false), |
| 155 writer_(filename, sequenced_task_runner), | 157 writer_(filename, sequenced_task_runner), |
| 156 pref_filter_(pref_filter.Pass()), | 158 pref_filter_(pref_filter.Pass()), |
| 157 initialized_(false), | 159 initialized_(false), |
| 158 filtering_in_progress_(false), | 160 filtering_in_progress_(false), |
| 159 read_error_(PREF_READ_ERROR_NONE) { | 161 read_error_(PREF_READ_ERROR_NONE), |
| 162 write_count_histogram_(writer_.commit_interval(), path_) { |
| 160 DCHECK(!path_.empty()); | 163 DCHECK(!path_.empty()); |
| 161 } | 164 } |
| 162 | 165 |
| 163 JsonPrefStore::JsonPrefStore( | 166 JsonPrefStore::JsonPrefStore( |
| 164 const base::FilePath& filename, | 167 const base::FilePath& filename, |
| 165 const base::FilePath& alternate_filename, | 168 const base::FilePath& alternate_filename, |
| 166 const scoped_refptr<base::SequencedTaskRunner>& sequenced_task_runner, | 169 const scoped_refptr<base::SequencedTaskRunner>& sequenced_task_runner, |
| 167 scoped_ptr<PrefFilter> pref_filter) | 170 scoped_ptr<PrefFilter> pref_filter) |
| 168 : path_(filename), | 171 : path_(filename), |
| 169 alternate_path_(alternate_filename), | 172 alternate_path_(alternate_filename), |
| 170 sequenced_task_runner_(sequenced_task_runner), | 173 sequenced_task_runner_(sequenced_task_runner), |
| 171 prefs_(new base::DictionaryValue()), | 174 prefs_(new base::DictionaryValue()), |
| 172 read_only_(false), | 175 read_only_(false), |
| 173 writer_(filename, sequenced_task_runner), | 176 writer_(filename, sequenced_task_runner), |
| 174 pref_filter_(pref_filter.Pass()), | 177 pref_filter_(pref_filter.Pass()), |
| 175 initialized_(false), | 178 initialized_(false), |
| 176 filtering_in_progress_(false), | 179 filtering_in_progress_(false), |
| 177 read_error_(PREF_READ_ERROR_NONE) { | 180 read_error_(PREF_READ_ERROR_NONE), |
| 181 write_count_histogram_(writer_.commit_interval(), path_) { |
| 178 DCHECK(!path_.empty()); | 182 DCHECK(!path_.empty()); |
| 179 } | 183 } |
| 180 | 184 |
| 181 bool JsonPrefStore::GetValue(const std::string& key, | 185 bool JsonPrefStore::GetValue(const std::string& key, |
| 182 const base::Value** result) const { | 186 const base::Value** result) const { |
| 183 DCHECK(CalledOnValidThread()); | 187 DCHECK(CalledOnValidThread()); |
| 184 | 188 |
| 185 base::Value* tmp = NULL; | 189 base::Value* tmp = NULL; |
| 186 if (!prefs_->Get(key, &tmp)) | 190 if (!prefs_->Get(key, &tmp)) |
| 187 return false; | 191 return false; |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 387 } | 391 } |
| 388 } | 392 } |
| 389 | 393 |
| 390 JsonPrefStore::~JsonPrefStore() { | 394 JsonPrefStore::~JsonPrefStore() { |
| 391 CommitPendingWrite(); | 395 CommitPendingWrite(); |
| 392 } | 396 } |
| 393 | 397 |
| 394 bool JsonPrefStore::SerializeData(std::string* output) { | 398 bool JsonPrefStore::SerializeData(std::string* output) { |
| 395 DCHECK(CalledOnValidThread()); | 399 DCHECK(CalledOnValidThread()); |
| 396 | 400 |
| 401 write_count_histogram_.RecordWriteOccured(); |
| 402 |
| 397 if (pref_filter_) | 403 if (pref_filter_) |
| 398 pref_filter_->FilterSerializeData(prefs_.get()); | 404 pref_filter_->FilterSerializeData(prefs_.get()); |
| 399 | 405 |
| 400 JSONStringValueSerializer serializer(output); | 406 JSONStringValueSerializer serializer(output); |
| 401 // Not pretty-printing prefs shrinks pref file size by ~30%. To obtain | 407 // Not pretty-printing prefs shrinks pref file size by ~30%. To obtain |
| 402 // readable prefs for debugging purposes, you can dump your prefs into any | 408 // readable prefs for debugging purposes, you can dump your prefs into any |
| 403 // command-line or online JSON pretty printing tool. | 409 // command-line or online JSON pretty printing tool. |
| 404 serializer.set_pretty_print(false); | 410 serializer.set_pretty_print(false); |
| 405 return serializer.Serialize(*prefs_); | 411 return serializer.Serialize(*prefs_); |
| 406 } | 412 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 428 | 434 |
| 429 if (error_delegate_ && read_error_ != PREF_READ_ERROR_NONE) | 435 if (error_delegate_ && read_error_ != PREF_READ_ERROR_NONE) |
| 430 error_delegate_->OnError(read_error_); | 436 error_delegate_->OnError(read_error_); |
| 431 | 437 |
| 432 FOR_EACH_OBSERVER(PrefStore::Observer, | 438 FOR_EACH_OBSERVER(PrefStore::Observer, |
| 433 observers_, | 439 observers_, |
| 434 OnInitializationCompleted(true)); | 440 OnInitializationCompleted(true)); |
| 435 | 441 |
| 436 return; | 442 return; |
| 437 } | 443 } |
| 444 |
| 445 // NOTE: This value should NOT be changed without renaming the histogram |
| 446 // otherwise it will create incompatible buckets. |
| 447 const int32_t |
| 448 JsonPrefStore::WriteCountHistogram::kHistogramWriteReportIntervalMins = 5; |
| 449 |
| 450 JsonPrefStore::WriteCountHistogram::WriteCountHistogram( |
| 451 const base::TimeDelta& commit_interval, |
| 452 const base::FilePath& path) |
| 453 : WriteCountHistogram(commit_interval, |
| 454 path, |
| 455 scoped_ptr<base::Clock>(new base::DefaultClock)) { |
| 456 } |
| 457 |
| 458 JsonPrefStore::WriteCountHistogram::WriteCountHistogram( |
| 459 const base::TimeDelta& commit_interval, |
| 460 const base::FilePath& path, |
| 461 scoped_ptr<base::Clock> clock) |
| 462 : commit_interval_(commit_interval), |
| 463 path_(path), |
| 464 clock_(clock.release()), |
| 465 report_interval_( |
| 466 base::TimeDelta::FromMinutes(kHistogramWriteReportIntervalMins)), |
| 467 last_report_time_(clock_->Now()), |
| 468 writes_since_last_report_(0) { |
| 469 } |
| 470 |
| 471 JsonPrefStore::WriteCountHistogram::~WriteCountHistogram() { |
| 472 ReportOutstandingWrites(); |
| 473 } |
| 474 |
| 475 void JsonPrefStore::WriteCountHistogram::RecordWriteOccured() { |
| 476 ReportOutstandingWrites(); |
| 477 |
| 478 ++writes_since_last_report_; |
| 479 } |
| 480 |
| 481 void JsonPrefStore::WriteCountHistogram::ReportOutstandingWrites() { |
| 482 base::Time current_time = clock_->Now(); |
| 483 base::TimeDelta time_since_last_report = current_time - last_report_time_; |
| 484 |
| 485 if (time_since_last_report <= report_interval_) |
| 486 return; |
| 487 |
| 488 // If the time since the last report exceeds the report interval, report all |
| 489 // the writes since the last report. They must have all occurred in the same |
| 490 // report interval. |
| 491 base::HistogramBase* histogram = GetHistogram(); |
| 492 histogram->Add(writes_since_last_report_); |
| 493 |
| 494 // There may be several report intervals that elapsed that don't have any |
| 495 // writes in them. Report these too. |
| 496 int64 total_num_intervals_elapsed = |
| 497 (time_since_last_report / report_interval_); |
| 498 for (int64 i = 0; i < total_num_intervals_elapsed - 1; ++i) |
| 499 histogram->Add(0); |
| 500 |
| 501 writes_since_last_report_ = 0; |
| 502 last_report_time_ += total_num_intervals_elapsed * report_interval_; |
| 503 } |
| 504 |
| 505 base::HistogramBase* JsonPrefStore::WriteCountHistogram::GetHistogram() { |
| 506 std::string spaceless_basename; |
| 507 base::ReplaceChars(path_.BaseName().MaybeAsASCII(), " ", "_", |
| 508 &spaceless_basename); |
| 509 std::string histogram_name = |
| 510 "Settings.JsonDataWriteCount." + spaceless_basename; |
| 511 |
| 512 // The min value for a histogram is 1. The max value is the maximum number of |
| 513 // writes that can occur in the window being recorded. The number of buckets |
| 514 // used is the max value (plus the underflow/overflow buckets). |
| 515 int32_t min_value = 1; |
| 516 int32_t max_value = report_interval_ / commit_interval_; |
| 517 int32_t num_buckets = max_value + 1; |
| 518 |
| 519 // NOTE: These values should NOT be changed without renaming the histogram |
| 520 // otherwise it will create incompatible buckets. |
| 521 DCHECK_EQ(30, max_value); |
| 522 DCHECK_EQ(31, num_buckets); |
| 523 |
| 524 // The histogram below is an expansion of the UMA_HISTOGRAM_CUSTOM_COUNTS |
| 525 // macro adapted to allow for a dynamically suffixed histogram name. |
| 526 // Note: The factory creates and owns the histogram. |
| 527 base::HistogramBase* histogram = base::Histogram::FactoryGet( |
| 528 histogram_name, min_value, max_value, num_buckets, |
| 529 base::HistogramBase::kUmaTargetedHistogramFlag); |
| 530 return histogram; |
| 531 } |
| OLD | NEW |