// 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 "content/browser/histogram_synchronizer.h"

#include <utility>

#include "base/bind.h"
#include "base/lazy_instance.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/metrics/histogram_delta_serialization.h"
#include "base/metrics/histogram_macros.h"
#include "base/pickle.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "content/browser/histogram_controller.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/histogram_fetcher.h"
#include "content/public/common/content_constants.h"

using base::Time;
using base::TimeDelta;
using base::TimeTicks;

namespace {

// Negative numbers are never used as sequence numbers.  We explicitly pick a
// negative number that is "so negative" that even when we add one (as is done
// when we generated the next sequence number) that it will still be negative.
// We have code that handles wrapping around on an overflow into negative
// territory.
static const int kNeverUsableSequenceNumber = -2;

}  // anonymous namespace

namespace content {

// The "RequestContext" structure describes an individual request received from
// the UI. All methods are accessible on UI thread.
class HistogramSynchronizer::RequestContext {
 public:
  // A map from sequence_number_ to the actual RequestContexts.
  typedef std::map<int, RequestContext*> RequestContextMap;

  RequestContext(const base::Closure& callback, int sequence_number)
      : callback_(callback),
        sequence_number_(sequence_number),
        received_process_group_count_(0),
        processes_pending_(0) {
  }
  ~RequestContext() {}

  void SetReceivedProcessGroupCount(bool done) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    received_process_group_count_ = done;
  }

  // Methods for book keeping of processes_pending_.
  void AddProcessesPending(int processes_pending) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    processes_pending_ += processes_pending;
  }

  void DecrementProcessesPending() {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    --processes_pending_;
  }

  // Records that we are waiting for one less histogram data from a process for
  // the given sequence number. If |received_process_group_count_| and
  // |processes_pending_| are zero, then delete the current object by calling
  // Unregister.
  void DeleteIfAllDone() {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);

    if (processes_pending_ <= 0 && received_process_group_count_)
      RequestContext::Unregister(sequence_number_);
  }

  // Register |callback| in |outstanding_requests_| map for the given
  // |sequence_number|.
  static void Register(const base::Closure& callback, int sequence_number) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);

    RequestContext* request = new RequestContext(callback, sequence_number);
    outstanding_requests_.Get()[sequence_number] = request;
  }

  // Find the |RequestContext| in |outstanding_requests_| map for the given
  // |sequence_number|.
  static RequestContext* GetRequestContext(int sequence_number) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);

    RequestContextMap::iterator it =
        outstanding_requests_.Get().find(sequence_number);
    if (it == outstanding_requests_.Get().end())
      return NULL;

    RequestContext* request = it->second;
    DCHECK_EQ(sequence_number, request->sequence_number_);
    return request;
  }

  // Delete the entry for the given |sequence_number| from
  // |outstanding_requests_| map. This method is called when all changes have
  // been acquired, or when the wait time expires (whichever is sooner).
  static void Unregister(int sequence_number) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);

    RequestContextMap::iterator it =
        outstanding_requests_.Get().find(sequence_number);
    if (it == outstanding_requests_.Get().end())
      return;

    RequestContext* request = it->second;
    DCHECK_EQ(sequence_number, request->sequence_number_);
    bool received_process_group_count = request->received_process_group_count_;
    int unresponsive_processes = request->processes_pending_;

    request->callback_.Run();

    delete request;
    outstanding_requests_.Get().erase(it);

    UMA_HISTOGRAM_BOOLEAN("Histogram.ReceivedProcessGroupCount",
                          received_process_group_count);
    UMA_HISTOGRAM_COUNTS("Histogram.PendingProcessNotResponding",
                         unresponsive_processes);
  }

  // Delete all the entries in |outstanding_requests_| map.
  static void OnShutdown() {
    // Just in case we have any pending tasks, clear them out.
    while (!outstanding_requests_.Get().empty()) {
      RequestContextMap::iterator it = outstanding_requests_.Get().begin();
      delete it->second;
      outstanding_requests_.Get().erase(it);
    }
  }

  // Requests are made to asynchronously send data to the |callback_|.
  base::Closure callback_;

  // The sequence number used by the most recent update request to contact all
  // processes.
  int sequence_number_;

  // Indicates if we have received all pending processes count.
  bool received_process_group_count_;

  // The number of pending processes (all renderer processes and browser child
  // processes) that have not yet responded to requests.
  int processes_pending_;

  // Map of all outstanding RequestContexts, from sequence_number_ to
  // RequestContext.
  static base::LazyInstance<RequestContextMap>::Leaky outstanding_requests_;
};

// static
base::LazyInstance
    <HistogramSynchronizer::RequestContext::RequestContextMap>::Leaky
        HistogramSynchronizer::RequestContext::outstanding_requests_ =
            LAZY_INSTANCE_INITIALIZER;

HistogramSynchronizer::HistogramSynchronizer()
    : lock_(),
      last_used_sequence_number_(kNeverUsableSequenceNumber),
      async_sequence_number_(kNeverUsableSequenceNumber) {
  HistogramController::GetInstance()->Register(this);
}

HistogramSynchronizer::~HistogramSynchronizer() {
  RequestContext::OnShutdown();

  // Just in case we have any pending tasks, clear them out.
  SetTaskRunnerAndCallback(nullptr, base::Closure());
}

HistogramSynchronizer* HistogramSynchronizer::GetInstance() {
  return base::Singleton<
      HistogramSynchronizer,
      base::LeakySingletonTraits<HistogramSynchronizer>>::get();
}

// static
void HistogramSynchronizer::FetchHistograms() {
  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
    BrowserThread::PostTask(
        BrowserThread::UI, FROM_HERE,
        base::Bind(&HistogramSynchronizer::FetchHistograms));
    return;
  }
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  HistogramSynchronizer* current_synchronizer =
      HistogramSynchronizer::GetInstance();
  if (current_synchronizer == NULL)
    return;

  current_synchronizer->RegisterAndNotifyAllProcesses(
      HistogramSynchronizer::UNKNOWN,
      base::TimeDelta::FromMinutes(1));
}

void FetchHistogramsAsynchronously(scoped_refptr<base::TaskRunner> task_runner,
                                   const base::Closure& callback,
                                   base::TimeDelta wait_time) {
  HistogramSynchronizer::FetchHistogramsAsynchronously(std::move(task_runner),
                                                       callback, wait_time);
}

// static
void HistogramSynchronizer::FetchHistogramsAsynchronously(
    scoped_refptr<base::TaskRunner> task_runner,
    const base::Closure& callback,
    base::TimeDelta wait_time) {
  DCHECK(task_runner);
  DCHECK(!callback.is_null());

  HistogramSynchronizer* current_synchronizer =
      HistogramSynchronizer::GetInstance();
  current_synchronizer->SetTaskRunnerAndCallback(std::move(task_runner),
                                                 callback);

  current_synchronizer->RegisterAndNotifyAllProcesses(
      HistogramSynchronizer::ASYNC_HISTOGRAMS, wait_time);
}

void HistogramSynchronizer::RegisterAndNotifyAllProcesses(
    ProcessHistogramRequester requester,
    base::TimeDelta wait_time) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  int sequence_number = GetNextAvailableSequenceNumber(requester);

  base::Closure callback = base::Bind(
      &HistogramSynchronizer::ForceHistogramSynchronizationDoneCallback,
      base::Unretained(this),
      sequence_number);

  RequestContext::Register(callback, sequence_number);

  // Get histogram data from renderer and browser child processes.
  HistogramController::GetInstance()->GetHistogramData(sequence_number);

  // Post a task that would be called after waiting for wait_time.  This acts
  // as a watchdog, to cancel the requests for non-responsive processes.
  BrowserThread::PostDelayedTask(
      BrowserThread::UI, FROM_HERE,
      base::Bind(&RequestContext::Unregister, sequence_number),
      wait_time);
}

void HistogramSynchronizer::OnPendingProcesses(int sequence_number,
                                               int pending_processes,
                                               bool end) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  RequestContext* request = RequestContext::GetRequestContext(sequence_number);
  if (!request)
    return;
  request->AddProcessesPending(pending_processes);
  request->SetReceivedProcessGroupCount(end);
  request->DeleteIfAllDone();
}

void HistogramSynchronizer::OnHistogramDataCollected(
    int sequence_number,
    const std::vector<std::string>& pickled_histograms) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  base::HistogramDeltaSerialization::DeserializeAndAddSamples(
      pickled_histograms);

  RequestContext* request = RequestContext::GetRequestContext(sequence_number);
  if (!request)
    return;

  // Delete request if we have heard back from all child processes.
  request->DecrementProcessesPending();
  request->DeleteIfAllDone();
}

void HistogramSynchronizer::SetTaskRunnerAndCallback(
    scoped_refptr<base::TaskRunner> task_runner,
    const base::Closure& callback) {
  base::Closure old_callback;
  scoped_refptr<base::TaskRunner> old_task_runner;
  {
    base::AutoLock auto_lock(lock_);
    old_callback = callback_;
    callback_ = callback;
    old_task_runner = std::move(callback_task_runner_);
    callback_task_runner_ = std::move(task_runner);
    // Prevent premature calling of our new callbacks.
    async_sequence_number_ = kNeverUsableSequenceNumber;
  }
  // Just in case there was a task pending....
  InternalPostTask(std::move(old_task_runner), old_callback);
}

void HistogramSynchronizer::ForceHistogramSynchronizationDoneCallback(
    int sequence_number) {
  base::Closure callback;
  scoped_refptr<base::TaskRunner> task_runner;
  {
    base::AutoLock lock(lock_);
    if (sequence_number != async_sequence_number_)
      return;
    callback = callback_;
    task_runner = std::move(callback_task_runner_);
    callback_.Reset();
  }
  InternalPostTask(std::move(task_runner), callback);
}

void HistogramSynchronizer::InternalPostTask(
    scoped_refptr<base::TaskRunner> task_runner,
    const base::Closure& callback) {
  if (callback.is_null() || !task_runner)
    return;
  task_runner->PostTask(FROM_HERE, callback);
}

int HistogramSynchronizer::GetNextAvailableSequenceNumber(
    ProcessHistogramRequester requester) {
  base::AutoLock auto_lock(lock_);
  ++last_used_sequence_number_;
  // Watch out for wrapping to a negative number.
  if (last_used_sequence_number_ < 0) {
    // Bypass the reserved number, which is used when a renderer spontaneously
    // decides to send some histogram data.
    last_used_sequence_number_ =
        kHistogramSynchronizerReservedSequenceNumber + 1;
  }
  DCHECK_NE(last_used_sequence_number_,
            kHistogramSynchronizerReservedSequenceNumber);
  if (requester == ASYNC_HISTOGRAMS)
    async_sequence_number_ = last_used_sequence_number_;
  return last_used_sequence_number_;
}

}  // namespace content
