| Index: chrome/browser/metrics/tracking_synchronizer.cc
|
| diff --git a/chrome/browser/metrics/tracking_synchronizer.cc b/chrome/browser/metrics/tracking_synchronizer.cc
|
| deleted file mode 100644
|
| index fd4505a3a63c400a1ba3789a759ff9853fba3ccb..0000000000000000000000000000000000000000
|
| --- a/chrome/browser/metrics/tracking_synchronizer.cc
|
| +++ /dev/null
|
| @@ -1,297 +0,0 @@
|
| -// 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 "chrome/browser/metrics/tracking_synchronizer.h"
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/metrics/histogram.h"
|
| -#include "base/threading/thread.h"
|
| -#include "base/tracked_objects.h"
|
| -#include "chrome/browser/metrics/tracking_synchronizer_observer.h"
|
| -#include "content/public/browser/browser_thread.h"
|
| -#include "content/public/browser/profiler_controller.h"
|
| -#include "content/public/common/process_type.h"
|
| -
|
| -using base::TimeTicks;
|
| -using content::BrowserThread;
|
| -
|
| -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.
|
| -const int kNeverUsableSequenceNumber = -2;
|
| -
|
| -// This singleton instance should be started during the single threaded
|
| -// portion of main(). It initializes globals to provide support for all future
|
| -// calls. This object is created on the UI thread, and it is destroyed after
|
| -// all the other threads have gone away. As a result, it is ok to call it
|
| -// from the UI thread, or for about:profiler.
|
| -static chrome_browser_metrics::TrackingSynchronizer* g_tracking_synchronizer =
|
| - NULL;
|
| -
|
| -} // anonymous namespace
|
| -
|
| -namespace chrome_browser_metrics {
|
| -
|
| -// The "RequestContext" structure describes an individual request received
|
| -// from the UI. All methods are accessible on UI thread.
|
| -class TrackingSynchronizer::RequestContext {
|
| - public:
|
| - // A map from sequence_number_ to the actual RequestContexts.
|
| - typedef std::map<int, RequestContext*> RequestContextMap;
|
| -
|
| - RequestContext(
|
| - const base::WeakPtr<TrackingSynchronizerObserver>& callback_object,
|
| - int sequence_number)
|
| - : callback_object_(callback_object),
|
| - sequence_number_(sequence_number),
|
| - received_process_group_count_(0),
|
| - processes_pending_(0) {
|
| - }
|
| - ~RequestContext() {}
|
| -
|
| - void SetReceivedProcessGroupCount(bool done) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - received_process_group_count_ = done;
|
| - }
|
| -
|
| - // Methods for book keeping of processes_pending_.
|
| - void IncrementProcessesPending() {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - ++processes_pending_;
|
| - }
|
| -
|
| - void AddProcessesPending(int processes_pending) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - processes_pending_ += processes_pending;
|
| - }
|
| -
|
| - void DecrementProcessesPending() {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - --processes_pending_;
|
| - }
|
| -
|
| - // Records that we are waiting for one less tracking 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(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| -
|
| - if (processes_pending_ <= 0 && received_process_group_count_)
|
| - RequestContext::Unregister(sequence_number_);
|
| - }
|
| -
|
| - // Register |callback_object| in |outstanding_requests_| map for the given
|
| - // |sequence_number|.
|
| - static RequestContext* Register(
|
| - int sequence_number,
|
| - const base::WeakPtr<TrackingSynchronizerObserver>& callback_object) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| -
|
| - RequestContext* request = new RequestContext(
|
| - callback_object, sequence_number);
|
| - outstanding_requests_.Get()[sequence_number] = request;
|
| -
|
| - return request;
|
| - }
|
| -
|
| - // Find the |RequestContext| in |outstanding_requests_| map for the given
|
| - // |sequence_number|.
|
| - static RequestContext* GetRequestContext(int sequence_number) {
|
| - DCHECK(BrowserThread::CurrentlyOn(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(BrowserThread::CurrentlyOn(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_;
|
| -
|
| - if (request->callback_object_.get())
|
| - request->callback_object_->FinishedReceivingProfilerData();
|
| -
|
| - delete request;
|
| - outstanding_requests_.Get().erase(it);
|
| -
|
| - UMA_HISTOGRAM_BOOLEAN("Profiling.ReceivedProcessGroupCount",
|
| - received_process_group_count);
|
| - UMA_HISTOGRAM_COUNTS("Profiling.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_object_|.
|
| - base::WeakPtr<TrackingSynchronizerObserver> callback_object_;
|
| -
|
| - // 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 (browser, 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
|
| - <TrackingSynchronizer::RequestContext::RequestContextMap>::Leaky
|
| - TrackingSynchronizer::RequestContext::outstanding_requests_ =
|
| - LAZY_INSTANCE_INITIALIZER;
|
| -
|
| -// TrackingSynchronizer methods and members.
|
| -
|
| -TrackingSynchronizer::TrackingSynchronizer()
|
| - : last_used_sequence_number_(kNeverUsableSequenceNumber) {
|
| - DCHECK(!g_tracking_synchronizer);
|
| - g_tracking_synchronizer = this;
|
| - content::ProfilerController::GetInstance()->Register(this);
|
| -}
|
| -
|
| -TrackingSynchronizer::~TrackingSynchronizer() {
|
| - content::ProfilerController::GetInstance()->Unregister(this);
|
| -
|
| - // Just in case we have any pending tasks, clear them out.
|
| - RequestContext::OnShutdown();
|
| -
|
| - g_tracking_synchronizer = NULL;
|
| -}
|
| -
|
| -// static
|
| -void TrackingSynchronizer::FetchProfilerDataAsynchronously(
|
| - const base::WeakPtr<TrackingSynchronizerObserver>& callback_object) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| -
|
| - if (!g_tracking_synchronizer) {
|
| - // System teardown is happening.
|
| - return;
|
| - }
|
| -
|
| - int sequence_number = g_tracking_synchronizer->RegisterAndNotifyAllProcesses(
|
| - callback_object);
|
| -
|
| - // 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),
|
| - base::TimeDelta::FromMinutes(1));
|
| -}
|
| -
|
| -void TrackingSynchronizer::OnPendingProcesses(int sequence_number,
|
| - int pending_processes,
|
| - bool end) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| -
|
| - RequestContext* request = RequestContext::GetRequestContext(sequence_number);
|
| - if (!request)
|
| - return;
|
| - request->AddProcessesPending(pending_processes);
|
| - request->SetReceivedProcessGroupCount(end);
|
| - request->DeleteIfAllDone();
|
| -}
|
| -
|
| -void TrackingSynchronizer::OnProfilerDataCollected(
|
| - int sequence_number,
|
| - const tracked_objects::ProcessDataSnapshot& profiler_data,
|
| - int process_type) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - DecrementPendingProcessesAndSendData(sequence_number, profiler_data,
|
| - process_type);
|
| -}
|
| -
|
| -int TrackingSynchronizer::RegisterAndNotifyAllProcesses(
|
| - const base::WeakPtr<TrackingSynchronizerObserver>& callback_object) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| -
|
| - int sequence_number = GetNextAvailableSequenceNumber();
|
| -
|
| - RequestContext* request =
|
| - RequestContext::Register(sequence_number, callback_object);
|
| -
|
| - // Increment pending process count for sending browser's profiler data.
|
| - request->IncrementProcessesPending();
|
| -
|
| - // Get profiler data from renderer and browser child processes.
|
| - content::ProfilerController::GetInstance()->GetProfilerData(sequence_number);
|
| -
|
| - // Send profiler_data from browser process.
|
| - tracked_objects::ProcessDataSnapshot process_data;
|
| - tracked_objects::ThreadData::Snapshot(false, &process_data);
|
| - DecrementPendingProcessesAndSendData(sequence_number, process_data,
|
| - content::PROCESS_TYPE_BROWSER);
|
| -
|
| - return sequence_number;
|
| -}
|
| -
|
| -void TrackingSynchronizer::DecrementPendingProcessesAndSendData(
|
| - int sequence_number,
|
| - const tracked_objects::ProcessDataSnapshot& profiler_data,
|
| - int process_type) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| -
|
| - RequestContext* request = RequestContext::GetRequestContext(sequence_number);
|
| - if (!request)
|
| - return;
|
| -
|
| - if (request->callback_object_.get()) {
|
| - request->callback_object_
|
| - ->ReceivedProfilerData(profiler_data, process_type);
|
| - }
|
| -
|
| - // Delete request if we have heard back from all child processes.
|
| - request->DecrementProcessesPending();
|
| - request->DeleteIfAllDone();
|
| -}
|
| -
|
| -int TrackingSynchronizer::GetNextAvailableSequenceNumber() {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| -
|
| - ++last_used_sequence_number_;
|
| -
|
| - // Watch out for wrapping to a negative number.
|
| - if (last_used_sequence_number_ < 0)
|
| - last_used_sequence_number_ = 1;
|
| - return last_used_sequence_number_;
|
| -}
|
| -
|
| -} // namespace chrome_browser_metrics
|
|
|