15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef CONTENT_BROWSER_HISTOGRAM_SYNCHRONIZER_H_
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CONTENT_BROWSER_HISTOGRAM_SYNCHRONIZER_H_
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/callback.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/singleton.h"
14a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/synchronization/lock.h"
15ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/time/time.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/histogram_subscriber.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace base {
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class MessageLoop;
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This class maintains state that is used to upload histogram data from the
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// various child processes, into the browser process. Such transactions are
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// usually instigated by the browser. In general, a child process will respond
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// by gathering snapshots of all internal histograms, calculating what has
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// changed since its last upload, and transmitting a pickled collection of
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// deltas.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// There are actually two modes of update request.  One is synchronous (and
3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// blocks the UI thread, waiting to populate an about:histograms tab) and the
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// other is asynchronous, and used by the metrics services in preparation for a
34effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// log upload.
359ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch//
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// To assure that all the processes have responded, a counter is maintained to
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// indicate the number of pending (not yet responsive) processes. To avoid
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// confusion about a response (i.e., is the process responding to a current
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// request for an update, or to an old request for an update) we tag each group
40a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// of requests with a sequence number. When an update arrives we can ignore it
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// (relative to the counter) if it does not relate to a current outstanding
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sequence number.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
44effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// There is one final mode of use, where a renderer spontaneously decides to
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// transmit a collection of histogram data.  This is designed for use when the
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// renderer is terminating.  Unfortunately, renders may be terminated without
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// warning, and the best we can do is periodically acquire data from a tab, such
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as when a page load has completed.  In this mode, the renderer uses a
49effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// reserved sequence number, different from any sequence number that might be
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// specified by a browser request.  Since this sequence number can't match an
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// outstanding sequence number, the pickled data is accepted into the browser,
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// but there is no impact on the counters.
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class HistogramSynchronizer : public HistogramSubscriber {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum ProcessHistogramRequester {
57e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    UNKNOWN,
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASYNC_HISTOGRAMS,
59a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  };
60a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Return pointer to the singleton instance for the current process, or NULL
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if none.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static HistogramSynchronizer* GetInstance();
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Contact all processes, and get them to upload to the browser any/all
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // changes to histograms. This method is called from about:histograms.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void FetchHistograms();
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Contact all child processes, and get them to upload to the browser any/all
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // changes to histograms.  When all changes have been acquired, or when the
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // wait time expires (whichever is sooner), post the callback to the
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // specified message loop. Note the callback is posted exactly once.
7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  static void FetchHistogramsAsynchronously(base::MessageLoop* callback_thread,
7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                            const base::Closure& callback,
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                            base::TimeDelta wait_time);
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  friend struct DefaultSingletonTraits<HistogramSynchronizer>;
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  class RequestContext;
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  HistogramSynchronizer();
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual ~HistogramSynchronizer();
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Establish a new sequence number, and use it to notify all processes
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // (renderers, plugins, GPU, etc) of the need to supply, to the browser,
8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // any/all changes to their histograms. |wait_time| specifies the amount of
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // time to wait before cancelling the requests for non-responsive processes.
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void RegisterAndNotifyAllProcesses(ProcessHistogramRequester requester,
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                     base::TimeDelta wait_time);
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // -------------------------------------------------------
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // HistogramSubscriber methods for browser child processes
9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // -------------------------------------------------------
9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Update the number of pending processes for the given |sequence_number|.
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // This is called on UI thread.
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual void OnPendingProcesses(int sequence_number,
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                  int pending_processes,
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                  bool end) OVERRIDE;
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Send histogram_data back to caller and also record that we are waiting
10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // for one less histogram data from child process for the given sequence
10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // number. This method is accessible on UI thread.
10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual void OnHistogramDataCollected(
10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      int sequence_number,
10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      const std::vector<std::string>& pickled_histograms) OVERRIDE;
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Set the callback_thread_ and callback_ members. If these members already
11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // had values, then as a side effect, post the old callback_ to the old
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // callaback_thread_.  This side effect should not generally happen, but is in
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // place to assure correctness (that any tasks that were set, are eventually
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // called, and never merely discarded).
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void SetCallbackTaskAndThread(base::MessageLoop* callback_thread,
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                const base::Closure& callback);
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void ForceHistogramSynchronizationDoneCallback(int sequence_number);
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Internal helper function, to post task, and record callback stats.
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void InternalPostTask(base::MessageLoop* thread,
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        const base::Closure& callback);
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Gets a new sequence number to be sent to processes from browser process.
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int GetNextAvailableSequenceNumber(ProcessHistogramRequester requester);
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This lock_ protects access to all members.
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Lock lock_;
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // When a request is made to asynchronously update the histograms, we store
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the task and thread we use to post a completion notification in
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // callback_ and callback_thread_.
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Closure callback_;
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::MessageLoop* callback_thread_;
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We don't track the actual processes that are contacted for an update, only
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the count of the number of processes, and we can sometimes time-out and
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // give up on a "slow to respond" process.  We use a sequence_number to be
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // sure a response from a process is associated with the current round of
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // requests (and not merely a VERY belated prior response).
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // All sequence numbers used are non-negative.
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // last_used_sequence_number_ is the most recently used number (used to avoid
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // reuse for a long time).
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int last_used_sequence_number_;
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The sequence number used by the most recent asynchronous update request to
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // contact all processes.
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int async_sequence_number_;
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(HistogramSynchronizer);
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace content
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // CONTENT_BROWSER_HISTOGRAM_SYNCHRONIZER_H_
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)