blob: c037a502c4a2cc167723b35048a3907183321f2e [file] [log] [blame]
[email protected]83ab4a282012-07-12 18:19:451// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CONTENT_BROWSER_HISTOGRAM_SYNCHRONIZER_H_
6#define CONTENT_BROWSER_HISTOGRAM_SYNCHRONIZER_H_
7
8#include <string>
9#include <vector>
10
[email protected]83ab4a282012-07-12 18:19:4511#include "base/callback.h"
avib7348942015-12-25 20:57:1012#include "base/macros.h"
[email protected]83ab4a282012-07-12 18:19:4513#include "base/memory/singleton.h"
14#include "base/synchronization/lock.h"
fdoray0c755de2016-10-19 15:28:4415#include "base/task_runner.h"
[email protected]a43858f2013-06-28 15:18:3716#include "base/time/time.h"
[email protected]83ab4a282012-07-12 18:19:4517#include "content/browser/histogram_subscriber.h"
18
[email protected]83ab4a282012-07-12 18:19:4519namespace content {
20
21// This class maintains state that is used to upload histogram data from the
22// various child processes, into the browser process. Such transactions are
23// usually instigated by the browser. In general, a child process will respond
24// by gathering snapshots of all internal histograms, calculating what has
25// changed since its last upload, and transmitting a pickled collection of
26// deltas.
27//
28// There are actually two modes of update request. One is synchronous (and
29// blocks the UI thread, waiting to populate an about:histograms tab) and the
30// other is asynchronous, and used by the metrics services in preparation for a
31// log upload.
32//
33// To assure that all the processes have responded, a counter is maintained to
34// indicate the number of pending (not yet responsive) processes. To avoid
35// confusion about a response (i.e., is the process responding to a current
36// request for an update, or to an old request for an update) we tag each group
37// of requests with a sequence number. When an update arrives we can ignore it
38// (relative to the counter) if it does not relate to a current outstanding
39// sequence number.
40//
41// There is one final mode of use, where a renderer spontaneously decides to
42// transmit a collection of histogram data. This is designed for use when the
43// renderer is terminating. Unfortunately, renders may be terminated without
44// warning, and the best we can do is periodically acquire data from a tab, such
45// as when a page load has completed. In this mode, the renderer uses a
46// reserved sequence number, different from any sequence number that might be
47// specified by a browser request. Since this sequence number can't match an
48// outstanding sequence number, the pickled data is accepted into the browser,
49// but there is no impact on the counters.
50
[email protected]46488322012-10-30 03:22:2051class HistogramSynchronizer : public HistogramSubscriber {
[email protected]83ab4a282012-07-12 18:19:4552 public:
53 enum ProcessHistogramRequester {
54 UNKNOWN,
55 ASYNC_HISTOGRAMS,
56 };
57
58 // Return pointer to the singleton instance for the current process, or NULL
59 // if none.
60 static HistogramSynchronizer* GetInstance();
61
62 // Contact all processes, and get them to upload to the browser any/all
63 // changes to histograms. This method is called from about:histograms.
64 static void FetchHistograms();
65
66 // Contact all child processes, and get them to upload to the browser any/all
67 // changes to histograms. When all changes have been acquired, or when the
fdoray0c755de2016-10-19 15:28:4468 // wait time expires (whichever is sooner), post the callback to the specified
69 // TaskRunner. Note the callback is posted exactly once.
70 static void FetchHistogramsAsynchronously(
71 scoped_refptr<base::TaskRunner> task_runner,
72 const base::Closure& callback,
73 base::TimeDelta wait_time);
[email protected]83ab4a282012-07-12 18:19:4574
75 private:
olli.raula36aa8be2015-09-10 11:14:2276 friend struct base::DefaultSingletonTraits<HistogramSynchronizer>;
[email protected]83ab4a282012-07-12 18:19:4577
78 class RequestContext;
79
80 HistogramSynchronizer();
dchengc2282aa2014-10-21 12:07:5881 ~HistogramSynchronizer() override;
[email protected]83ab4a282012-07-12 18:19:4582
83 // Establish a new sequence number, and use it to notify all processes
84 // (renderers, plugins, GPU, etc) of the need to supply, to the browser,
85 // any/all changes to their histograms. |wait_time| specifies the amount of
86 // time to wait before cancelling the requests for non-responsive processes.
87 void RegisterAndNotifyAllProcesses(ProcessHistogramRequester requester,
88 base::TimeDelta wait_time);
89
90 // -------------------------------------------------------
91 // HistogramSubscriber methods for browser child processes
92 // -------------------------------------------------------
93
94 // Update the number of pending processes for the given |sequence_number|.
95 // This is called on UI thread.
dchengc2282aa2014-10-21 12:07:5896 void OnPendingProcesses(int sequence_number,
97 int pending_processes,
98 bool end) override;
[email protected]83ab4a282012-07-12 18:19:4599
100 // Send histogram_data back to caller and also record that we are waiting
101 // for one less histogram data from child process for the given sequence
102 // number. This method is accessible on UI thread.
dchengc2282aa2014-10-21 12:07:58103 void OnHistogramDataCollected(
[email protected]83ab4a282012-07-12 18:19:45104 int sequence_number,
mohan.reddy7fc3ac72014-10-09 05:24:13105 const std::vector<std::string>& pickled_histograms) override;
[email protected]83ab4a282012-07-12 18:19:45106
fdoray0c755de2016-10-19 15:28:44107 // Set the |callback_task_runner_| and |callback_| members. If these members
108 // already had values, then as a side effect, post the old |callback_| to the
109 // old |callback_task_runner_|. This side effect should not generally happen,
110 // but is in place to assure correctness (that any tasks that were set, are
111 // eventually called, and never merely discarded).
112 void SetTaskRunnerAndCallback(scoped_refptr<base::TaskRunner> task_runner,
[email protected]83ab4a282012-07-12 18:19:45113 const base::Closure& callback);
114
115 void ForceHistogramSynchronizationDoneCallback(int sequence_number);
116
117 // Internal helper function, to post task, and record callback stats.
fdoray0c755de2016-10-19 15:28:44118 void InternalPostTask(scoped_refptr<base::TaskRunner> task_runner,
[email protected]5e9e96a2013-03-31 02:29:20119 const base::Closure& callback);
[email protected]83ab4a282012-07-12 18:19:45120
121 // Gets a new sequence number to be sent to processes from browser process.
[email protected]053b14af2012-10-25 20:36:05122 int GetNextAvailableSequenceNumber(ProcessHistogramRequester requester);
[email protected]83ab4a282012-07-12 18:19:45123
124 // This lock_ protects access to all members.
125 base::Lock lock_;
126
127 // When a request is made to asynchronously update the histograms, we store
fdoray0c755de2016-10-19 15:28:44128 // the task and TaskRunner we use to post a completion notification in
129 // |callback_| and |callback_task_runner_|.
Lukasz Anforowicz40066f52018-09-21 21:14:41130 base::Closure callback_ GUARDED_BY(lock_);
131 scoped_refptr<base::TaskRunner> callback_task_runner_ GUARDED_BY(lock_);
[email protected]83ab4a282012-07-12 18:19:45132
133 // We don't track the actual processes that are contacted for an update, only
134 // the count of the number of processes, and we can sometimes time-out and
135 // give up on a "slow to respond" process. We use a sequence_number to be
136 // sure a response from a process is associated with the current round of
137 // requests (and not merely a VERY belated prior response).
138 // All sequence numbers used are non-negative.
139 // last_used_sequence_number_ is the most recently used number (used to avoid
140 // reuse for a long time).
Lukasz Anforowicz40066f52018-09-21 21:14:41141 int last_used_sequence_number_ GUARDED_BY(lock_);
[email protected]83ab4a282012-07-12 18:19:45142
143 // The sequence number used by the most recent asynchronous update request to
144 // contact all processes.
Lukasz Anforowicz40066f52018-09-21 21:14:41145 int async_sequence_number_ GUARDED_BY(lock_);
[email protected]83ab4a282012-07-12 18:19:45146
147 DISALLOW_COPY_AND_ASSIGN(HistogramSynchronizer);
148};
149
150} // namespace content
151
152#endif // CONTENT_BROWSER_HISTOGRAM_SYNCHRONIZER_H_