// 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 "base/metrics/histogram_snapshot_manager.h"

#include "base/memory/scoped_ptr.h"
#include "base/metrics/histogram_flattener.h"
#include "base/metrics/histogram_samples.h"
#include "base/metrics/statistics_recorder.h"
#include "base/stl_util.h"

using std::map;
using std::string;

namespace base {

HistogramSnapshotManager::HistogramSnapshotManager(
    HistogramFlattener* histogram_flattener)
    : histogram_flattener_(histogram_flattener) {
  DCHECK(histogram_flattener_);
}

HistogramSnapshotManager::~HistogramSnapshotManager() {
  STLDeleteValues(&logged_samples_);
}

void HistogramSnapshotManager::PrepareDeltas(
    HistogramBase::Flags flag_to_set,
    HistogramBase::Flags required_flags) {
  StatisticsRecorder::Histograms histograms;
  StatisticsRecorder::GetHistograms(&histograms);
  for (StatisticsRecorder::Histograms::const_iterator it = histograms.begin();
       histograms.end() != it;
       ++it) {
    (*it)->SetFlags(flag_to_set);
    if (((*it)->flags() & required_flags) == required_flags)
      PrepareDelta(**it);
  }
}

void HistogramSnapshotManager::PrepareDelta(const HistogramBase& histogram) {
  DCHECK(histogram_flattener_);

  // Get up-to-date snapshot of sample stats.
  scoped_ptr<HistogramSamples> snapshot(histogram.SnapshotSamples());
  const std::string& histogram_name = histogram.histogram_name();

  int corruption = histogram.FindCorruption(*snapshot);

  // Crash if we detect that our histograms have been overwritten.  This may be
  // a fair distance from the memory smasher, but we hope to correlate these
  // crashes with other events, such as plugins, or usage patterns, etc.
  if (HistogramBase::BUCKET_ORDER_ERROR & corruption) {
    // The checksum should have caught this, so crash separately if it didn't.
    CHECK_NE(0, HistogramBase::RANGE_CHECKSUM_ERROR & corruption);
    CHECK(false);  // Crash for the bucket order corruption.
  }
  // Checksum corruption might not have caused order corruption.
  CHECK_EQ(0, HistogramBase::RANGE_CHECKSUM_ERROR & corruption);

  // Note, at this point corruption can only be COUNT_HIGH_ERROR or
  // COUNT_LOW_ERROR and they never arise together, so we don't need to extract
  // bits from corruption.
  if (corruption) {
    DLOG(ERROR) << "Histogram: " << histogram_name
                << " has data corruption: " << corruption;
    histogram_flattener_->InconsistencyDetected(
        static_cast<HistogramBase::Inconsistency>(corruption));
    // Don't record corrupt data to metrics services.
    int old_corruption = inconsistencies_[histogram_name];
    if (old_corruption == (corruption | old_corruption))
      return;  // We've already seen this corruption for this histogram.
    inconsistencies_[histogram_name] |= corruption;
    histogram_flattener_->UniqueInconsistencyDetected(
        static_cast<HistogramBase::Inconsistency>(corruption));
    return;
  }

  HistogramSamples* to_log;
  map<string, HistogramSamples*>::iterator it =
      logged_samples_.find(histogram_name);
  if (it == logged_samples_.end()) {
    to_log = snapshot.release();

    // This histogram has not been logged before, add a new entry.
    logged_samples_[histogram_name] = to_log;
  } else {
    HistogramSamples* already_logged = it->second;
    InspectLoggedSamplesInconsistency(*snapshot, already_logged);
    snapshot->Subtract(*already_logged);
    already_logged->Add(*snapshot);
    to_log = snapshot.get();
  }

  if (to_log->TotalCount() > 0)
    histogram_flattener_->RecordDelta(histogram, *to_log);
}

void HistogramSnapshotManager::InspectLoggedSamplesInconsistency(
      const HistogramSamples& new_snapshot,
      HistogramSamples* logged_samples) {
  HistogramBase::Count discrepancy =
      logged_samples->TotalCount() - logged_samples->redundant_count();
  if (!discrepancy)
    return;

  histogram_flattener_->InconsistencyDetectedInLoggedCount(discrepancy);
  if (discrepancy > Histogram::kCommonRaceBasedCountMismatch) {
    // Fix logged_samples.
    logged_samples->Subtract(*logged_samples);
    logged_samples->Add(new_snapshot);
  }
}

}  // namespace base
