Move StatisticsRecorder out of histogram.cc/h for further refactoring.

Review URL: https://chromiumcodereview.appspot.com/10703037

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@146659 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/base/metrics/histogram.cc b/base/metrics/histogram.cc
index 923ac9c..e176e8f 100644
--- a/base/metrics/histogram.cc
+++ b/base/metrics/histogram.cc
@@ -14,8 +14,8 @@
 #include <algorithm>
 #include <string>
 
-#include "base/debug/leak_annotations.h"
 #include "base/logging.h"
+#include "base/metrics/statistics_recorder.h"
 #include "base/pickle.h"
 #include "base/stringprintf.h"
 #include "base/synchronization/lock.h"
@@ -74,13 +74,6 @@
 // static
 const size_t Histogram::kBucketCount_MAX = 16384u;
 
-// Collect the number of histograms created.
-static uint32 number_of_histograms_ = 0;
-// Collect the number of vectors saved because of caching ranges.
-static uint32 number_of_vectors_saved_ = 0;
-// Collect the number of ranges_ elements saved because of caching ranges.
-static size_t saved_ranges_size_ = 0;
-
 Histogram* Histogram::FactoryGet(const std::string& name,
                                  Sample minimum,
                                  Sample maximum,
@@ -1037,265 +1030,6 @@
   return 1;
 }
 
-//------------------------------------------------------------------------------
-// The next section handles global (central) support for all histograms, as well
-// as startup/teardown of this service.
-//------------------------------------------------------------------------------
-
-// This singleton instance should be started during the single threaded portion
-// of main(), and hence it is not thread safe.  It initializes globals to
-// provide support for all future calls.
-StatisticsRecorder::StatisticsRecorder() {
-  DCHECK(!histograms_);
-  if (lock_ == NULL) {
-    // This will leak on purpose. It's the only way to make sure we won't race
-    // against the static uninitialization of the module while one of our
-    // static methods relying on the lock get called at an inappropriate time
-    // during the termination phase. Since it's a static data member, we will
-    // leak one per process, which would be similar to the instance allocated
-    // during static initialization and released only on  process termination.
-    lock_ = new base::Lock;
-  }
-  base::AutoLock auto_lock(*lock_);
-  histograms_ = new HistogramMap;
-  ranges_ = new RangesMap;
-}
-
-StatisticsRecorder::~StatisticsRecorder() {
-  DCHECK(histograms_ && lock_);
-
-  if (dump_on_exit_) {
-    std::string output;
-    WriteGraph("", &output);
-    DLOG(INFO) << output;
-  }
-  // Clean up.
-  HistogramMap* histograms = NULL;
-  {
-    base::AutoLock auto_lock(*lock_);
-    histograms = histograms_;
-    histograms_ = NULL;
-  }
-  RangesMap* ranges = NULL;
-  {
-    base::AutoLock auto_lock(*lock_);
-    ranges = ranges_;
-    ranges_ = NULL;
-  }
-  // We are going to leak the histograms and the ranges.
-  delete histograms;
-  delete ranges;
-  // We don't delete lock_ on purpose to avoid having to properly protect
-  // against it going away after we checked for NULL in the static methods.
-}
-
-// static
-bool StatisticsRecorder::IsActive() {
-  if (lock_ == NULL)
-    return false;
-  base::AutoLock auto_lock(*lock_);
-  return NULL != histograms_;
-}
-
-Histogram* StatisticsRecorder::RegisterOrDeleteDuplicate(Histogram* histogram) {
-  // As per crbug.com/79322 the histograms are intentionally leaked, so we need
-  // to annotate them. Because ANNOTATE_LEAKING_OBJECT_PTR may be used only once
-  // for an object, the duplicates should not be annotated.
-  // Callers are responsible for not calling RegisterOrDeleteDuplicate(ptr)
-  // twice if (lock_ == NULL) || (!histograms_).
-  DCHECK(histogram->HasValidRangeChecksum());
-  if (lock_ == NULL) {
-    ANNOTATE_LEAKING_OBJECT_PTR(histogram);  // see crbug.com/79322
-    return histogram;
-  }
-  base::AutoLock auto_lock(*lock_);
-  if (!histograms_) {
-    ANNOTATE_LEAKING_OBJECT_PTR(histogram);  // see crbug.com/79322
-    return histogram;
-  }
-  const std::string name = histogram->histogram_name();
-  HistogramMap::iterator it = histograms_->find(name);
-  // Avoid overwriting a previous registration.
-  if (histograms_->end() == it) {
-    (*histograms_)[name] = histogram;
-    ANNOTATE_LEAKING_OBJECT_PTR(histogram);  // see crbug.com/79322
-    RegisterOrDeleteDuplicateRanges(histogram);
-    ++number_of_histograms_;
-  } else {
-    delete histogram;  // We already have one by this name.
-    histogram = it->second;
-  }
-  return histogram;
-}
-
-// static
-void StatisticsRecorder::RegisterOrDeleteDuplicateRanges(Histogram* histogram) {
-  DCHECK(histogram);
-  CachedRanges* histogram_ranges = histogram->cached_ranges();
-  DCHECK(histogram_ranges);
-  uint32 checksum = histogram->range_checksum();
-  histogram_ranges->SetRangeChecksum(checksum);
-
-  RangesMap::iterator ranges_it = ranges_->find(checksum);
-  if (ranges_->end() == ranges_it) {
-    // Register the new CachedRanges.
-    std::list<CachedRanges*>* checksum_matching_list(
-        new std::list<CachedRanges*>());
-    checksum_matching_list->push_front(histogram_ranges);
-    (*ranges_)[checksum] = checksum_matching_list;
-    return;
-  }
-
-  // Use the registered CachedRanges if the registered CachedRanges has same
-  // ranges_ as |histogram|'s CachedRanges.
-  std::list<CachedRanges*>* checksum_matching_list = ranges_it->second;
-  std::list<CachedRanges*>::iterator checksum_matching_list_it;
-  for (checksum_matching_list_it = checksum_matching_list->begin();
-       checksum_matching_list_it != checksum_matching_list->end();
-       ++checksum_matching_list_it) {
-    CachedRanges* existing_histogram_ranges = *checksum_matching_list_it;
-    DCHECK(existing_histogram_ranges);
-    if (existing_histogram_ranges->Equals(histogram_ranges)) {
-      histogram->set_cached_ranges(existing_histogram_ranges);
-      ++number_of_vectors_saved_;
-      saved_ranges_size_ += histogram_ranges->size();
-      delete histogram_ranges;
-      return;
-    }
-  }
-
-  // We haven't found a CachedRanges which has the same ranges. Register the
-  // new CachedRanges.
-  DCHECK(checksum_matching_list_it == checksum_matching_list->end());
-  checksum_matching_list->push_front(histogram_ranges);
-}
-
-// static
-void StatisticsRecorder::CollectHistogramStats(const std::string& suffix) {
-  static int uma_upload_attempt = 0;
-  ++uma_upload_attempt;
-  if (uma_upload_attempt == 1) {
-    UMA_HISTOGRAM_COUNTS_10000(
-        "Histogram.SharedRange.Count.FirstUpload." + suffix,
-        number_of_histograms_);
-    UMA_HISTOGRAM_COUNTS_10000(
-        "Histogram.SharedRange.RangesSaved.FirstUpload." + suffix,
-        number_of_vectors_saved_);
-    UMA_HISTOGRAM_COUNTS(
-        "Histogram.SharedRange.ElementsSaved.FirstUpload." + suffix,
-        static_cast<int>(saved_ranges_size_));
-    number_of_histograms_ = 0;
-    number_of_vectors_saved_ = 0;
-    saved_ranges_size_ = 0;
-    return;
-  }
-  if (uma_upload_attempt == 2) {
-    UMA_HISTOGRAM_COUNTS_10000(
-        "Histogram.SharedRange.Count.SecondUpload." + suffix,
-        number_of_histograms_);
-    UMA_HISTOGRAM_COUNTS_10000(
-        "Histogram.SharedRange.RangesSaved.SecondUpload." + suffix,
-        number_of_vectors_saved_);
-    UMA_HISTOGRAM_COUNTS(
-        "Histogram.SharedRange.ElementsSaved.SecondUpload." + suffix,
-        static_cast<int>(saved_ranges_size_));
-    number_of_histograms_ = 0;
-    number_of_vectors_saved_ = 0;
-    saved_ranges_size_ = 0;
-    return;
-  }
-  UMA_HISTOGRAM_COUNTS_10000(
-      "Histogram.SharedRange.Count.RestOfUploads." + suffix,
-      number_of_histograms_);
-  UMA_HISTOGRAM_COUNTS_10000(
-      "Histogram.SharedRange.RangesSaved.RestOfUploads." + suffix,
-      number_of_vectors_saved_);
-  UMA_HISTOGRAM_COUNTS(
-      "Histogram.SharedRange.ElementsSaved.RestOfUploads." + suffix,
-      static_cast<int>(saved_ranges_size_));
-}
-
-// static
-void StatisticsRecorder::WriteHTMLGraph(const std::string& query,
-                                        std::string* output) {
-  if (!IsActive())
-    return;
-
-  Histograms snapshot;
-  GetSnapshot(query, &snapshot);
-  for (Histograms::iterator it = snapshot.begin();
-       it != snapshot.end();
-       ++it) {
-    (*it)->WriteHTMLGraph(output);
-    output->append("<br><hr><br>");
-  }
-}
-
-// static
-void StatisticsRecorder::WriteGraph(const std::string& query,
-                                    std::string* output) {
-  if (!IsActive())
-    return;
-  if (query.length())
-    StringAppendF(output, "Collections of histograms for %s\n", query.c_str());
-  else
-    output->append("Collections of all histograms\n");
-
-  Histograms snapshot;
-  GetSnapshot(query, &snapshot);
-  for (Histograms::iterator it = snapshot.begin();
-       it != snapshot.end();
-       ++it) {
-    (*it)->WriteAscii(true, "\n", output);
-    output->append("\n");
-  }
-}
-
-// static
-void StatisticsRecorder::GetHistograms(Histograms* output) {
-  if (lock_ == NULL)
-    return;
-  base::AutoLock auto_lock(*lock_);
-  if (!histograms_)
-    return;
-  for (HistogramMap::iterator it = histograms_->begin();
-       histograms_->end() != it;
-       ++it) {
-    DCHECK_EQ(it->first, it->second->histogram_name());
-    output->push_back(it->second);
-  }
-}
-
-bool StatisticsRecorder::FindHistogram(const std::string& name,
-                                       Histogram** histogram) {
-  if (lock_ == NULL)
-    return false;
-  base::AutoLock auto_lock(*lock_);
-  if (!histograms_)
-    return false;
-  HistogramMap::iterator it = histograms_->find(name);
-  if (histograms_->end() == it)
-    return false;
-  *histogram = it->second;
-  return true;
-}
-
-// private static
-void StatisticsRecorder::GetSnapshot(const std::string& query,
-                                     Histograms* snapshot) {
-  if (lock_ == NULL)
-    return;
-  base::AutoLock auto_lock(*lock_);
-  if (!histograms_)
-    return;
-  for (HistogramMap::iterator it = histograms_->begin();
-       histograms_->end() != it;
-       ++it) {
-    if (it->first.find(query) != std::string::npos)
-      snapshot->push_back(it->second);
-  }
-}
-
 CachedRanges::CachedRanges(size_t bucket_count, int initial_value)
     : ranges_(bucket_count, initial_value),
       range_checksum_(0) {
@@ -1322,12 +1056,4 @@
   return true;
 }
 
-// static
-StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL;
-// static
-StatisticsRecorder::RangesMap* StatisticsRecorder::ranges_ = NULL;
-// static
-base::Lock* StatisticsRecorder::lock_ = NULL;
-// static
-bool StatisticsRecorder::dump_on_exit_ = false;
 }  // namespace base