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)