// 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/sparse_histogram.h"

#include <utility>

#include "base/memory/ptr_util.h"
#include "base/metrics/metrics_hashes.h"
#include "base/metrics/persistent_histogram_allocator.h"
#include "base/metrics/persistent_sample_map.h"
#include "base/metrics/sample_map.h"
#include "base/metrics/statistics_recorder.h"
#include "base/pickle.h"
#include "base/strings/stringprintf.h"
#include "base/synchronization/lock.h"

namespace base {

typedef HistogramBase::Count Count;
typedef HistogramBase::Sample Sample;

// static
HistogramBase* SparseHistogram::FactoryGet(const std::string& name,
                                           int32_t flags) {
  HistogramBase* histogram = StatisticsRecorder::FindHistogram(name);
  if (!histogram) {
    // Try to create the histogram using a "persistent" allocator. As of
    // 2016-02-25, the availability of such is controlled by a base::Feature
    // that is off by default. If the allocator doesn't exist or if
    // allocating from it fails, code below will allocate the histogram from
    // the process heap.
    PersistentMemoryAllocator::Reference histogram_ref = 0;
    std::unique_ptr<HistogramBase> tentative_histogram;
    PersistentHistogramAllocator* allocator = GlobalHistogramAllocator::Get();
    if (allocator) {
      tentative_histogram = allocator->AllocateHistogram(
          SPARSE_HISTOGRAM, name, 0, 0, nullptr, flags, &histogram_ref);
    }

    // Handle the case where no persistent allocator is present or the
    // persistent allocation fails (perhaps because it is full).
    if (!tentative_histogram) {
      DCHECK(!histogram_ref);  // Should never have been set.
      DCHECK(!allocator);      // Shouldn't have failed.
      flags &= ~HistogramBase::kIsPersistent;
      tentative_histogram.reset(new SparseHistogram(name));
      tentative_histogram->SetFlags(flags);
    }

    // Register this histogram with the StatisticsRecorder. Keep a copy of
    // the pointer value to tell later whether the locally created histogram
    // was registered or deleted. The type is "void" because it could point
    // to released memory after the following line.
    const void* tentative_histogram_ptr = tentative_histogram.get();
    histogram = StatisticsRecorder::RegisterOrDeleteDuplicate(
        tentative_histogram.release());

    // Persistent histograms need some follow-up processing.
    if (histogram_ref) {
      allocator->FinalizeHistogram(histogram_ref,
                                   histogram == tentative_histogram_ptr);
    }

    ReportHistogramActivity(*histogram, HISTOGRAM_CREATED);
  } else {
    ReportHistogramActivity(*histogram, HISTOGRAM_LOOKUP);
  }

  DCHECK_EQ(SPARSE_HISTOGRAM, histogram->GetHistogramType());
  return histogram;
}

// static
std::unique_ptr<HistogramBase> SparseHistogram::PersistentCreate(
    PersistentHistogramAllocator* allocator,
    const std::string& name,
    HistogramSamples::Metadata* meta,
    HistogramSamples::Metadata* logged_meta) {
  return WrapUnique(
      new SparseHistogram(allocator, name, meta, logged_meta));
}

SparseHistogram::~SparseHistogram() {}

uint64_t SparseHistogram::name_hash() const {
  return samples_->id();
}

HistogramType SparseHistogram::GetHistogramType() const {
  return SPARSE_HISTOGRAM;
}

bool SparseHistogram::HasConstructionArguments(
    Sample /*expected_minimum*/,
    Sample /*expected_maximum*/,
    uint32_t /*expected_bucket_count*/) const {
  // SparseHistogram never has min/max/bucket_count limit.
  return false;
}

void SparseHistogram::Add(Sample value) {
  AddCount(value, 1);
}

void SparseHistogram::AddCount(Sample value, int count) {
  if (count <= 0) {
    NOTREACHED();
    return;
  }
  {
    base::AutoLock auto_lock(lock_);
    samples_->Accumulate(value, count);
  }

  FindAndRunCallback(value);
}

std::unique_ptr<HistogramSamples> SparseHistogram::SnapshotSamples() const {
  std::unique_ptr<SampleMap> snapshot(new SampleMap(name_hash()));

  base::AutoLock auto_lock(lock_);
  snapshot->Add(*samples_);
  return std::move(snapshot);
}

std::unique_ptr<HistogramSamples> SparseHistogram::SnapshotDelta() {
  DCHECK(!final_delta_created_);

  std::unique_ptr<SampleMap> snapshot(new SampleMap(name_hash()));
  base::AutoLock auto_lock(lock_);
  snapshot->Add(*samples_);

  // Subtract what was previously logged and update that information.
  snapshot->Subtract(*logged_samples_);
  logged_samples_->Add(*snapshot);
  return std::move(snapshot);
}

std::unique_ptr<HistogramSamples> SparseHistogram::SnapshotFinalDelta() const {
  DCHECK(!final_delta_created_);
  final_delta_created_ = true;

  std::unique_ptr<SampleMap> snapshot(new SampleMap(name_hash()));
  base::AutoLock auto_lock(lock_);
  snapshot->Add(*samples_);

  // Subtract what was previously logged and then return.
  snapshot->Subtract(*logged_samples_);
  return std::move(snapshot);
}

void SparseHistogram::AddSamples(const HistogramSamples& samples) {
  base::AutoLock auto_lock(lock_);
  samples_->Add(samples);
}

bool SparseHistogram::AddSamplesFromPickle(PickleIterator* iter) {
  base::AutoLock auto_lock(lock_);
  return samples_->AddFromPickle(iter);
}

void SparseHistogram::WriteHTMLGraph(std::string* output) const {
  output->append("<PRE>");
  WriteAsciiImpl(true, "<br>", output);
  output->append("</PRE>");
}

void SparseHistogram::WriteAscii(std::string* output) const {
  WriteAsciiImpl(true, "\n", output);
}

bool SparseHistogram::SerializeInfoImpl(Pickle* pickle) const {
  return pickle->WriteString(histogram_name()) && pickle->WriteInt(flags());
}

SparseHistogram::SparseHistogram(const std::string& name)
    : HistogramBase(name),
      samples_(new SampleMap(HashMetricName(name))),
      logged_samples_(new SampleMap(samples_->id())) {}

SparseHistogram::SparseHistogram(PersistentHistogramAllocator* allocator,
                                 const std::string& name,
                                 HistogramSamples::Metadata* meta,
                                 HistogramSamples::Metadata* logged_meta)
    : HistogramBase(name),
      // While other histogram types maintain a static vector of values with
      // sufficient space for both "active" and "logged" samples, with each
      // SampleVector being given the appropriate half, sparse histograms
      // have no such initial allocation. Each sample has its own record
      // attached to a single PersistentSampleMap by a common 64-bit identifier.
      // Since a sparse histogram has two sample maps (active and logged),
      // there must be two sets of sample records with diffent IDs. The
      // "active" samples use, for convenience purposes, an ID matching
      // that of the histogram while the "logged" samples use that number
      // plus 1.
      samples_(new PersistentSampleMap(HashMetricName(name), allocator, meta)),
      logged_samples_(
          new PersistentSampleMap(samples_->id() + 1, allocator, logged_meta)) {
}

HistogramBase* SparseHistogram::DeserializeInfoImpl(PickleIterator* iter) {
  std::string histogram_name;
  int flags;
  if (!iter->ReadString(&histogram_name) || !iter->ReadInt(&flags)) {
    DLOG(ERROR) << "Pickle error decoding Histogram: " << histogram_name;
    return NULL;
  }

  flags &= ~HistogramBase::kIPCSerializationSourceFlag;

  return SparseHistogram::FactoryGet(histogram_name, flags);
}

void SparseHistogram::GetParameters(DictionaryValue* /*params*/) const {
  // TODO(kaiwang): Implement. (See HistogramBase::WriteJSON.)
}

void SparseHistogram::GetCountAndBucketData(Count* /*count*/,
                                            int64_t* /*sum*/,
                                            ListValue* /*buckets*/) const {
  // TODO(kaiwang): Implement. (See HistogramBase::WriteJSON.)
}

void SparseHistogram::WriteAsciiImpl(bool graph_it,
                                     const std::string& newline,
                                     std::string* output) const {
  // Get a local copy of the data so we are consistent.
  std::unique_ptr<HistogramSamples> snapshot = SnapshotSamples();
  Count total_count = snapshot->TotalCount();
  double scaled_total_count = total_count / 100.0;

  WriteAsciiHeader(total_count, output);
  output->append(newline);

  // Determine how wide the largest bucket range is (how many digits to print),
  // so that we'll be able to right-align starts for the graphical bars.
  // Determine which bucket has the largest sample count so that we can
  // normalize the graphical bar-width relative to that sample count.
  Count largest_count = 0;
  Sample largest_sample = 0;
  std::unique_ptr<SampleCountIterator> it = snapshot->Iterator();
  while (!it->Done()) {
    Sample min;
    Sample max;
    Count count;
    it->Get(&min, &max, &count);
    if (min > largest_sample)
      largest_sample = min;
    if (count > largest_count)
      largest_count = count;
    it->Next();
  }
  size_t print_width = GetSimpleAsciiBucketRange(largest_sample).size() + 1;

  // iterate over each item and display them
  it = snapshot->Iterator();
  while (!it->Done()) {
    Sample min;
    Sample max;
    Count count;
    it->Get(&min, &max, &count);

    // value is min, so display it
    std::string range = GetSimpleAsciiBucketRange(min);
    output->append(range);
    for (size_t j = 0; range.size() + j < print_width + 1; ++j)
      output->push_back(' ');

    if (graph_it)
      WriteAsciiBucketGraph(count, largest_count, output);
    WriteAsciiBucketValue(count, scaled_total_count, output);
    output->append(newline);
    it->Next();
  }
}

void SparseHistogram::WriteAsciiHeader(const Count total_count,
                                       std::string* output) const {
  StringAppendF(output,
                "Histogram: %s recorded %d samples",
                histogram_name().c_str(),
                total_count);
  if (flags() & ~kHexRangePrintingFlag)
    StringAppendF(output, " (flags = 0x%x)", flags() & ~kHexRangePrintingFlag);
}

}  // namespace base
