// 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,
                                             bool record_only_uma) {
  StatisticsRecorder::Histograms histograms;
  StatisticsRecorder::GetHistograms(&histograms);
  for (StatisticsRecorder::Histograms::const_iterator it = histograms.begin();
       histograms.end() != it;
       ++it) {
    (*it)->SetFlags(flag_to_set);
    if (record_only_uma &&
        0 == ((*it)->flags() & Histogram::kUmaTargetedHistogramFlag))
      continue;
    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
