| 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 |