OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/histogram_synchronizer.h" | 5 #include "content/browser/histogram_synchronizer.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/lazy_instance.h" | 8 #include "base/lazy_instance.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 | 43 |
44 RequestContext(const base::Closure& callback, int sequence_number) | 44 RequestContext(const base::Closure& callback, int sequence_number) |
45 : callback_(callback), | 45 : callback_(callback), |
46 sequence_number_(sequence_number), | 46 sequence_number_(sequence_number), |
47 received_process_group_count_(0), | 47 received_process_group_count_(0), |
48 processes_pending_(0) { | 48 processes_pending_(0) { |
49 } | 49 } |
50 ~RequestContext() {} | 50 ~RequestContext() {} |
51 | 51 |
52 void SetReceivedProcessGroupCount(bool done) { | 52 void SetReceivedProcessGroupCount(bool done) { |
53 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 53 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
54 received_process_group_count_ = done; | 54 received_process_group_count_ = done; |
55 } | 55 } |
56 | 56 |
57 // Methods for book keeping of processes_pending_. | 57 // Methods for book keeping of processes_pending_. |
58 void AddProcessesPending(int processes_pending) { | 58 void AddProcessesPending(int processes_pending) { |
59 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 59 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
60 processes_pending_ += processes_pending; | 60 processes_pending_ += processes_pending; |
61 } | 61 } |
62 | 62 |
63 void DecrementProcessesPending() { | 63 void DecrementProcessesPending() { |
64 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 64 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
65 --processes_pending_; | 65 --processes_pending_; |
66 } | 66 } |
67 | 67 |
68 // Records that we are waiting for one less histogram data from a process for | 68 // Records that we are waiting for one less histogram data from a process for |
69 // the given sequence number. If |received_process_group_count_| and | 69 // the given sequence number. If |received_process_group_count_| and |
70 // |processes_pending_| are zero, then delete the current object by calling | 70 // |processes_pending_| are zero, then delete the current object by calling |
71 // Unregister. | 71 // Unregister. |
72 void DeleteIfAllDone() { | 72 void DeleteIfAllDone() { |
73 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 73 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
74 | 74 |
75 if (processes_pending_ <= 0 && received_process_group_count_) | 75 if (processes_pending_ <= 0 && received_process_group_count_) |
76 RequestContext::Unregister(sequence_number_); | 76 RequestContext::Unregister(sequence_number_); |
77 } | 77 } |
78 | 78 |
79 // Register |callback| in |outstanding_requests_| map for the given | 79 // Register |callback| in |outstanding_requests_| map for the given |
80 // |sequence_number|. | 80 // |sequence_number|. |
81 static void Register(const base::Closure& callback, int sequence_number) { | 81 static void Register(const base::Closure& callback, int sequence_number) { |
82 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 82 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
83 | 83 |
84 RequestContext* request = new RequestContext(callback, sequence_number); | 84 RequestContext* request = new RequestContext(callback, sequence_number); |
85 outstanding_requests_.Get()[sequence_number] = request; | 85 outstanding_requests_.Get()[sequence_number] = request; |
86 } | 86 } |
87 | 87 |
88 // Find the |RequestContext| in |outstanding_requests_| map for the given | 88 // Find the |RequestContext| in |outstanding_requests_| map for the given |
89 // |sequence_number|. | 89 // |sequence_number|. |
90 static RequestContext* GetRequestContext(int sequence_number) { | 90 static RequestContext* GetRequestContext(int sequence_number) { |
91 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 91 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
92 | 92 |
93 RequestContextMap::iterator it = | 93 RequestContextMap::iterator it = |
94 outstanding_requests_.Get().find(sequence_number); | 94 outstanding_requests_.Get().find(sequence_number); |
95 if (it == outstanding_requests_.Get().end()) | 95 if (it == outstanding_requests_.Get().end()) |
96 return NULL; | 96 return NULL; |
97 | 97 |
98 RequestContext* request = it->second; | 98 RequestContext* request = it->second; |
99 DCHECK_EQ(sequence_number, request->sequence_number_); | 99 DCHECK_EQ(sequence_number, request->sequence_number_); |
100 return request; | 100 return request; |
101 } | 101 } |
102 | 102 |
103 // Delete the entry for the given |sequence_number| from | 103 // Delete the entry for the given |sequence_number| from |
104 // |outstanding_requests_| map. This method is called when all changes have | 104 // |outstanding_requests_| map. This method is called when all changes have |
105 // been acquired, or when the wait time expires (whichever is sooner). | 105 // been acquired, or when the wait time expires (whichever is sooner). |
106 static void Unregister(int sequence_number) { | 106 static void Unregister(int sequence_number) { |
107 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 107 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
108 | 108 |
109 RequestContextMap::iterator it = | 109 RequestContextMap::iterator it = |
110 outstanding_requests_.Get().find(sequence_number); | 110 outstanding_requests_.Get().find(sequence_number); |
111 if (it == outstanding_requests_.Get().end()) | 111 if (it == outstanding_requests_.Get().end()) |
112 return; | 112 return; |
113 | 113 |
114 RequestContext* request = it->second; | 114 RequestContext* request = it->second; |
115 DCHECK_EQ(sequence_number, request->sequence_number_); | 115 DCHECK_EQ(sequence_number, request->sequence_number_); |
116 bool received_process_group_count = request->received_process_group_count_; | 116 bool received_process_group_count = request->received_process_group_count_; |
117 int unresponsive_processes = request->processes_pending_; | 117 int unresponsive_processes = request->processes_pending_; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 } | 183 } |
184 | 184 |
185 // static | 185 // static |
186 void HistogramSynchronizer::FetchHistograms() { | 186 void HistogramSynchronizer::FetchHistograms() { |
187 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 187 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
188 BrowserThread::PostTask( | 188 BrowserThread::PostTask( |
189 BrowserThread::UI, FROM_HERE, | 189 BrowserThread::UI, FROM_HERE, |
190 base::Bind(&HistogramSynchronizer::FetchHistograms)); | 190 base::Bind(&HistogramSynchronizer::FetchHistograms)); |
191 return; | 191 return; |
192 } | 192 } |
193 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 193 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
194 | 194 |
195 HistogramSynchronizer* current_synchronizer = | 195 HistogramSynchronizer* current_synchronizer = |
196 HistogramSynchronizer::GetInstance(); | 196 HistogramSynchronizer::GetInstance(); |
197 if (current_synchronizer == NULL) | 197 if (current_synchronizer == NULL) |
198 return; | 198 return; |
199 | 199 |
200 current_synchronizer->RegisterAndNotifyAllProcesses( | 200 current_synchronizer->RegisterAndNotifyAllProcesses( |
201 HistogramSynchronizer::UNKNOWN, | 201 HistogramSynchronizer::UNKNOWN, |
202 base::TimeDelta::FromMinutes(1)); | 202 base::TimeDelta::FromMinutes(1)); |
203 } | 203 } |
(...skipping 18 matching lines...) Expand all Loading... |
222 current_synchronizer->SetCallbackTaskAndThread( | 222 current_synchronizer->SetCallbackTaskAndThread( |
223 callback_thread, callback); | 223 callback_thread, callback); |
224 | 224 |
225 current_synchronizer->RegisterAndNotifyAllProcesses( | 225 current_synchronizer->RegisterAndNotifyAllProcesses( |
226 HistogramSynchronizer::ASYNC_HISTOGRAMS, wait_time); | 226 HistogramSynchronizer::ASYNC_HISTOGRAMS, wait_time); |
227 } | 227 } |
228 | 228 |
229 void HistogramSynchronizer::RegisterAndNotifyAllProcesses( | 229 void HistogramSynchronizer::RegisterAndNotifyAllProcesses( |
230 ProcessHistogramRequester requester, | 230 ProcessHistogramRequester requester, |
231 base::TimeDelta wait_time) { | 231 base::TimeDelta wait_time) { |
232 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 232 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
233 | 233 |
234 int sequence_number = GetNextAvailableSequenceNumber(requester); | 234 int sequence_number = GetNextAvailableSequenceNumber(requester); |
235 | 235 |
236 base::Closure callback = base::Bind( | 236 base::Closure callback = base::Bind( |
237 &HistogramSynchronizer::ForceHistogramSynchronizationDoneCallback, | 237 &HistogramSynchronizer::ForceHistogramSynchronizationDoneCallback, |
238 base::Unretained(this), | 238 base::Unretained(this), |
239 sequence_number); | 239 sequence_number); |
240 | 240 |
241 RequestContext::Register(callback, sequence_number); | 241 RequestContext::Register(callback, sequence_number); |
242 | 242 |
243 // Get histogram data from renderer and browser child processes. | 243 // Get histogram data from renderer and browser child processes. |
244 HistogramController::GetInstance()->GetHistogramData(sequence_number); | 244 HistogramController::GetInstance()->GetHistogramData(sequence_number); |
245 | 245 |
246 // Post a task that would be called after waiting for wait_time. This acts | 246 // Post a task that would be called after waiting for wait_time. This acts |
247 // as a watchdog, to cancel the requests for non-responsive processes. | 247 // as a watchdog, to cancel the requests for non-responsive processes. |
248 BrowserThread::PostDelayedTask( | 248 BrowserThread::PostDelayedTask( |
249 BrowserThread::UI, FROM_HERE, | 249 BrowserThread::UI, FROM_HERE, |
250 base::Bind(&RequestContext::Unregister, sequence_number), | 250 base::Bind(&RequestContext::Unregister, sequence_number), |
251 wait_time); | 251 wait_time); |
252 } | 252 } |
253 | 253 |
254 void HistogramSynchronizer::OnPendingProcesses(int sequence_number, | 254 void HistogramSynchronizer::OnPendingProcesses(int sequence_number, |
255 int pending_processes, | 255 int pending_processes, |
256 bool end) { | 256 bool end) { |
257 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 257 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
258 | 258 |
259 RequestContext* request = RequestContext::GetRequestContext(sequence_number); | 259 RequestContext* request = RequestContext::GetRequestContext(sequence_number); |
260 if (!request) | 260 if (!request) |
261 return; | 261 return; |
262 request->AddProcessesPending(pending_processes); | 262 request->AddProcessesPending(pending_processes); |
263 request->SetReceivedProcessGroupCount(end); | 263 request->SetReceivedProcessGroupCount(end); |
264 request->DeleteIfAllDone(); | 264 request->DeleteIfAllDone(); |
265 } | 265 } |
266 | 266 |
267 void HistogramSynchronizer::OnHistogramDataCollected( | 267 void HistogramSynchronizer::OnHistogramDataCollected( |
268 int sequence_number, | 268 int sequence_number, |
269 const std::vector<std::string>& pickled_histograms) { | 269 const std::vector<std::string>& pickled_histograms) { |
270 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 270 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
271 | 271 |
272 base::HistogramDeltaSerialization::DeserializeAndAddSamples( | 272 base::HistogramDeltaSerialization::DeserializeAndAddSamples( |
273 pickled_histograms); | 273 pickled_histograms); |
274 | 274 |
275 RequestContext* request = RequestContext::GetRequestContext(sequence_number); | 275 RequestContext* request = RequestContext::GetRequestContext(sequence_number); |
276 if (!request) | 276 if (!request) |
277 return; | 277 return; |
278 | 278 |
279 // Delete request if we have heard back from all child processes. | 279 // Delete request if we have heard back from all child processes. |
280 request->DecrementProcessesPending(); | 280 request->DecrementProcessesPending(); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
334 kHistogramSynchronizerReservedSequenceNumber + 1; | 334 kHistogramSynchronizerReservedSequenceNumber + 1; |
335 } | 335 } |
336 DCHECK_NE(last_used_sequence_number_, | 336 DCHECK_NE(last_used_sequence_number_, |
337 kHistogramSynchronizerReservedSequenceNumber); | 337 kHistogramSynchronizerReservedSequenceNumber); |
338 if (requester == ASYNC_HISTOGRAMS) | 338 if (requester == ASYNC_HISTOGRAMS) |
339 async_sequence_number_ = last_used_sequence_number_; | 339 async_sequence_number_ = last_used_sequence_number_; |
340 return last_used_sequence_number_; | 340 return last_used_sequence_number_; |
341 } | 341 } |
342 | 342 |
343 } // namespace content | 343 } // namespace content |
OLD | NEW |