Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(755)

Side by Side Diff: webrtc/call/rtc_event_log_helper_thread.cc

Issue 2035483003: Hibernate the thread if there are no events in the queue. Wake it up when an event is added to the … (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Nit Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 18 matching lines...) Expand all
29 event_type == rtclog::Event::AUDIO_RECEIVER_CONFIG_EVENT || 29 event_type == rtclog::Event::AUDIO_RECEIVER_CONFIG_EVENT ||
30 event_type == rtclog::Event::AUDIO_SENDER_CONFIG_EVENT; 30 event_type == rtclog::Event::AUDIO_SENDER_CONFIG_EVENT;
31 } 31 }
32 } // namespace 32 } // namespace
33 33
34 // RtcEventLogImpl member functions. 34 // RtcEventLogImpl member functions.
35 RtcEventLogHelperThread::RtcEventLogHelperThread( 35 RtcEventLogHelperThread::RtcEventLogHelperThread(
36 SwapQueue<ControlMessage>* message_queue, 36 SwapQueue<ControlMessage>* message_queue,
37 SwapQueue<std::unique_ptr<rtclog::Event>>* event_queue, 37 SwapQueue<std::unique_ptr<rtclog::Event>>* event_queue,
38 rtc::Event* wake_up, 38 rtc::Event* wake_up,
39 rtc::Event* end_hibernation,
39 rtc::Event* stopped, 40 rtc::Event* stopped,
40 const Clock* const clock) 41 const Clock* const clock)
41 : message_queue_(message_queue), 42 : message_queue_(message_queue),
42 event_queue_(event_queue), 43 event_queue_(event_queue),
43 history_(kEventsInHistory), 44 history_(kEventsInHistory),
44 config_history_(), 45 config_history_(),
45 file_(FileWrapper::Create()), 46 file_(FileWrapper::Create()),
46 thread_(&ThreadOutputFunction, this, "RtcEventLog thread"), 47 thread_(&ThreadOutputFunction, this, "RtcEventLog thread"),
47 max_size_bytes_(std::numeric_limits<int64_t>::max()), 48 max_size_bytes_(std::numeric_limits<int64_t>::max()),
48 written_bytes_(0), 49 written_bytes_(0),
49 start_time_(0), 50 start_time_(0),
50 stop_time_(std::numeric_limits<int64_t>::max()), 51 stop_time_(std::numeric_limits<int64_t>::max()),
51 has_recent_event_(false), 52 has_recent_event_(false),
52 most_recent_event_(), 53 most_recent_event_(),
53 output_string_(), 54 output_string_(),
54 wake_up_(wake_up), 55 wake_up_(wake_up),
56 end_hibernation_(end_hibernation),
55 stopped_(stopped), 57 stopped_(stopped),
56 clock_(clock) { 58 clock_(clock) {
57 RTC_DCHECK(message_queue_); 59 RTC_DCHECK(message_queue_);
58 RTC_DCHECK(event_queue_); 60 RTC_DCHECK(event_queue_);
59 RTC_DCHECK(wake_up_); 61 RTC_DCHECK(wake_up_);
62 RTC_DCHECK(end_hibernation_);
60 RTC_DCHECK(stopped_); 63 RTC_DCHECK(stopped_);
61 RTC_DCHECK(clock_); 64 RTC_DCHECK(clock_);
62 thread_.Start(); 65 thread_.Start();
63 } 66 }
64 67
65 RtcEventLogHelperThread::~RtcEventLogHelperThread() { 68 RtcEventLogHelperThread::~RtcEventLogHelperThread() {
66 ControlMessage message; 69 ControlMessage message;
67 message.message_type = ControlMessage::TERMINATE_THREAD; 70 message.message_type = ControlMessage::TERMINATE_THREAD;
68 message.stop_time = clock_->TimeInMicroseconds(); 71 message.stop_time = clock_->TimeInMicroseconds();
69 while (!message_queue_->Insert(&message)) { 72 while (!message_queue_->Insert(&message)) {
70 // We can't destroy the event log until we have stopped the thread, 73 // We can't destroy the event log until we have stopped the thread,
71 // so clear the message queue and try again. Note that if we clear 74 // so clear the message queue and try again. Note that if we clear
72 // any STOP_FILE events, then the threads calling StopLogging would likely 75 // any STOP_FILE events, then the threads calling StopLogging would likely
73 // wait indefinitely. However, there should not be any such calls as we 76 // wait indefinitely. However, there should not be any such calls as we
74 // are executing the destructor. 77 // are executing the destructor.
75 LOG(LS_WARNING) << "Clearing message queue to terminate thread."; 78 LOG(LS_WARNING) << "Clearing message queue to terminate thread.";
76 message_queue_->Clear(); 79 message_queue_->Clear();
77 } 80 }
81 end_hibernation_->Set();
78 wake_up_->Set(); // Wake up the output thread. 82 wake_up_->Set(); // Wake up the output thread.
79 thread_.Stop(); // Wait for the thread to terminate. 83 thread_.Stop(); // Wait for the thread to terminate.
80 } 84 }
81 85
82 bool RtcEventLogHelperThread::AppendEventToString(rtclog::Event* event) { 86 bool RtcEventLogHelperThread::AppendEventToString(rtclog::Event* event) {
83 rtclog::EventStream event_stream; 87 rtclog::EventStream event_stream;
84 event_stream.add_stream(); 88 event_stream.add_stream();
85 event_stream.mutable_stream(0)->Swap(event); 89 event_stream.mutable_stream(0)->Swap(event);
86 // We create a new event stream per event but because of the way protobufs 90 // We create a new event stream per event but because of the way protobufs
87 // are encoded, events can be merged by concatenating them. Therefore, 91 // are encoded, events can be merged by concatenating them. Therefore,
88 // it will look like a single stream when we read it back from file. 92 // it will look like a single stream when we read it back from file.
89 bool stop = true; 93 bool stop = true;
90 if (written_bytes_ + static_cast<int64_t>(output_string_.size()) + 94 if (written_bytes_ + static_cast<int64_t>(output_string_.size()) +
91 event_stream.ByteSize() <= 95 event_stream.ByteSize() <=
92 max_size_bytes_) { 96 max_size_bytes_) {
93 event_stream.AppendToString(&output_string_); 97 event_stream.AppendToString(&output_string_);
94 stop = false; 98 stop = false;
95 } 99 }
96 // Swap the event back so that we don't mix event types in the queues. 100 // Swap the event back so that we don't mix event types in the queues.
97 event_stream.mutable_stream(0)->Swap(event); 101 event_stream.mutable_stream(0)->Swap(event);
98 return stop; 102 return stop;
99 } 103 }
100 104
101 void RtcEventLogHelperThread::LogToMemory() { 105 int RtcEventLogHelperThread::LogToMemory() {
102 RTC_DCHECK(!file_->Open()); 106 RTC_DCHECK(!file_->Open());
107 int message_received = 0;
103 108
104 // Process each event earlier than the current time and append it to the 109 // Process each event earlier than the current time and append it to the
105 // appropriate history_. 110 // appropriate history_.
106 int64_t current_time = clock_->TimeInMicroseconds(); 111 int64_t current_time = clock_->TimeInMicroseconds();
107 if (!has_recent_event_) { 112 if (!has_recent_event_) {
108 has_recent_event_ = event_queue_->Remove(&most_recent_event_); 113 has_recent_event_ = event_queue_->Remove(&most_recent_event_);
109 } 114 }
110 while (has_recent_event_ && 115 while (has_recent_event_ &&
111 most_recent_event_->timestamp_us() <= current_time) { 116 most_recent_event_->timestamp_us() <= current_time) {
112 if (IsConfigEvent(*most_recent_event_)) { 117 if (IsConfigEvent(*most_recent_event_)) {
113 config_history_.push_back(std::move(most_recent_event_)); 118 config_history_.push_back(std::move(most_recent_event_));
114 } else { 119 } else {
115 history_.push_back(std::move(most_recent_event_)); 120 history_.push_back(std::move(most_recent_event_));
116 } 121 }
117 has_recent_event_ = event_queue_->Remove(&most_recent_event_); 122 has_recent_event_ = event_queue_->Remove(&most_recent_event_);
123 message_received++;
stefan-webrtc 2016/06/03 08:55:44 ++message_received;
terelius 2016/06/08 11:47:29 Done.
118 } 124 }
125 return message_received;
119 } 126 }
120 127
121 void RtcEventLogHelperThread::StartLogFile() { 128 void RtcEventLogHelperThread::StartLogFile() {
122 RTC_DCHECK(file_->Open()); 129 RTC_DCHECK(file_->Open());
123 bool stop = false; 130 bool stop = false;
124 output_string_.clear(); 131 output_string_.clear();
125 132
126 // Create and serialize the LOG_START event. 133 // Create and serialize the LOG_START event.
127 rtclog::Event start_event; 134 rtclog::Event start_event;
128 start_event.set_timestamp_us(start_time_); 135 start_event.set_timestamp_us(start_time_);
(...skipping 26 matching lines...) Expand all
155 // space again. 162 // space again.
156 output_string_.clear(); 163 output_string_.clear();
157 output_string_.shrink_to_fit(); 164 output_string_.shrink_to_fit();
158 165
159 if (stop) { 166 if (stop) {
160 RTC_DCHECK(file_->Open()); 167 RTC_DCHECK(file_->Open());
161 StopLogFile(); 168 StopLogFile();
162 } 169 }
163 } 170 }
164 171
165 void RtcEventLogHelperThread::LogToFile() { 172 int RtcEventLogHelperThread::LogToFile() {
166 RTC_DCHECK(file_->Open()); 173 RTC_DCHECK(file_->Open());
167 output_string_.clear(); 174 output_string_.clear();
175 int message_received = 0;
168 176
169 // Append each event older than both the current time and the stop time 177 // Append each event older than both the current time and the stop time
170 // to the output_string_. 178 // to the output_string_.
171 int64_t current_time = clock_->TimeInMicroseconds(); 179 int64_t current_time = clock_->TimeInMicroseconds();
172 int64_t time_limit = std::min(current_time, stop_time_); 180 int64_t time_limit = std::min(current_time, stop_time_);
173 if (!has_recent_event_) { 181 if (!has_recent_event_) {
174 has_recent_event_ = event_queue_->Remove(&most_recent_event_); 182 has_recent_event_ = event_queue_->Remove(&most_recent_event_);
175 } 183 }
176 bool stop = false; 184 bool stop = false;
177 while (!stop && has_recent_event_ && 185 while (!stop && has_recent_event_ &&
178 most_recent_event_->timestamp_us() <= time_limit) { 186 most_recent_event_->timestamp_us() <= time_limit) {
179 stop = AppendEventToString(most_recent_event_.get()); 187 stop = AppendEventToString(most_recent_event_.get());
180 if (!stop) { 188 if (!stop) {
181 if (IsConfigEvent(*most_recent_event_)) { 189 if (IsConfigEvent(*most_recent_event_)) {
182 config_history_.push_back(std::move(most_recent_event_)); 190 config_history_.push_back(std::move(most_recent_event_));
183 } 191 }
184 has_recent_event_ = event_queue_->Remove(&most_recent_event_); 192 has_recent_event_ = event_queue_->Remove(&most_recent_event_);
185 } 193 }
194 message_received++;
stefan-webrtc 2016/06/03 08:55:44 ++...;
terelius 2016/06/08 11:47:29 Done.
186 } 195 }
187 196
188 // Write string to file. 197 // Write string to file.
189 if (!file_->Write(output_string_.data(), output_string_.size())) { 198 if (!file_->Write(output_string_.data(), output_string_.size())) {
190 LOG(LS_ERROR) << "FileWrapper failed to write WebRtcEventLog file."; 199 LOG(LS_ERROR) << "FileWrapper failed to write WebRtcEventLog file.";
191 // The current FileWrapper implementation closes the file on error. 200 // The current FileWrapper implementation closes the file on error.
192 RTC_DCHECK(!file_->Open()); 201 RTC_DCHECK(!file_->Open());
193 return; 202 return message_received;
194 } 203 }
195 written_bytes_ += output_string_.size(); 204 written_bytes_ += output_string_.size();
196 205
197 // We want to stop logging if we have reached the file size limit. We also 206 // We want to stop logging if we have reached the file size limit. We also
198 // want to stop logging if the remaining events are more recent than the 207 // want to stop logging if the remaining events are more recent than the
199 // time limit, or in other words if we have terminated the loop despite 208 // time limit, or in other words if we have terminated the loop despite
200 // having more events in the queue. 209 // having more events in the queue.
201 if ((has_recent_event_ && most_recent_event_->timestamp_us() > stop_time_) || 210 if ((has_recent_event_ && most_recent_event_->timestamp_us() > stop_time_) ||
202 stop) { 211 stop) {
203 RTC_DCHECK(file_->Open()); 212 RTC_DCHECK(file_->Open());
204 StopLogFile(); 213 StopLogFile();
205 } 214 }
215 return message_received;
206 } 216 }
207 217
208 void RtcEventLogHelperThread::StopLogFile() { 218 void RtcEventLogHelperThread::StopLogFile() {
209 RTC_DCHECK(file_->Open()); 219 RTC_DCHECK(file_->Open());
210 output_string_.clear(); 220 output_string_.clear();
211 221
212 rtclog::Event end_event; 222 rtclog::Event end_event;
213 end_event.set_timestamp_us(stop_time_); 223 end_event.set_timestamp_us(stop_time_);
214 end_event.set_type(rtclog::Event::LOG_END); 224 end_event.set_type(rtclog::Event::LOG_END);
215 AppendEventToString(&end_event); 225 AppendEventToString(&end_event);
(...skipping 10 matching lines...) Expand all
226 236
227 max_size_bytes_ = std::numeric_limits<int64_t>::max(); 237 max_size_bytes_ = std::numeric_limits<int64_t>::max();
228 written_bytes_ = 0; 238 written_bytes_ = 0;
229 start_time_ = 0; 239 start_time_ = 0;
230 stop_time_ = std::numeric_limits<int64_t>::max(); 240 stop_time_ = std::numeric_limits<int64_t>::max();
231 output_string_.clear(); 241 output_string_.clear();
232 file_->CloseFile(); 242 file_->CloseFile();
233 RTC_DCHECK(!file_->Open()); 243 RTC_DCHECK(!file_->Open());
234 } 244 }
235 245
236 void RtcEventLogHelperThread::WriteLog() { 246 void RtcEventLogHelperThread::ProcessEvents() {
237 ControlMessage message; 247 ControlMessage message;
248 int message_received; // Non-zero if we find new events in the queues.
238 249
239 while (true) { 250 while (true) {
251 message_received = 0;
240 // Process control messages. 252 // Process control messages.
241 while (message_queue_->Remove(&message)) { 253 while (message_queue_->Remove(&message)) {
242 switch (message.message_type) { 254 switch (message.message_type) {
243 case ControlMessage::START_FILE: 255 case ControlMessage::START_FILE:
244 if (!file_->Open()) { 256 if (!file_->Open()) {
245 max_size_bytes_ = message.max_size_bytes; 257 max_size_bytes_ = message.max_size_bytes;
246 start_time_ = message.start_time; 258 start_time_ = message.start_time;
247 stop_time_ = message.stop_time; 259 stop_time_ = message.stop_time;
248 file_.swap(message.file); 260 file_.swap(message.file);
249 StartLogFile(); 261 StartLogFile();
250 } else { 262 } else {
251 // Already started. Ignore message and close file handle. 263 // Already started. Ignore message and close file handle.
252 message.file->CloseFile(); 264 message.file->CloseFile();
253 } 265 }
266 message_received = 1;
254 break; 267 break;
255 case ControlMessage::STOP_FILE: 268 case ControlMessage::STOP_FILE:
256 if (file_->Open()) { 269 if (file_->Open()) {
257 stop_time_ = message.stop_time; 270 stop_time_ = message.stop_time;
258 LogToFile(); // Log remaining events from message queues. 271 LogToFile(); // Log remaining events from message queues.
259 } 272 }
260 // LogToFile might stop on it's own so we need to recheck the state. 273 // LogToFile might stop on it's own so we need to recheck the state.
261 if (file_->Open()) { 274 if (file_->Open()) {
262 StopLogFile(); 275 StopLogFile();
263 } 276 }
264 stopped_->Set(); 277 stopped_->Set();
278 message_received = 1;
265 break; 279 break;
266 case ControlMessage::TERMINATE_THREAD: 280 case ControlMessage::TERMINATE_THREAD:
267 if (file_->Open()) { 281 if (file_->Open()) {
268 StopLogFile(); 282 StopLogFile();
269 } 283 }
270 return; 284 return;
271 } 285 }
272 } 286 }
273 287
274 // Write events to file or memory 288 // Write events to file or memory
275 if (file_->Open()) { 289 if (file_->Open()) {
276 LogToFile(); 290 message_received += LogToFile();
277 } else { 291 } else {
278 LogToMemory(); 292 message_received += LogToMemory();
279 } 293 }
280 294
281 // Accumulate a new batch of events instead of processing them one at a 295 // Accumulate a new batch of events instead of processing them one at a
282 // time. 296 // time.
283 wake_up_->Wait(50); 297 if (message_received > 0) {
298 wake_up_->Wait(100);
299 } else {
300 end_hibernation_->Wait(rtc::Event::kForever);
301 }
284 } 302 }
285 } 303 }
286 304
287 bool RtcEventLogHelperThread::ThreadOutputFunction(void* obj) { 305 bool RtcEventLogHelperThread::ThreadOutputFunction(void* obj) {
288 RtcEventLogHelperThread* helper = static_cast<RtcEventLogHelperThread*>(obj); 306 RtcEventLogHelperThread* helper = static_cast<RtcEventLogHelperThread*>(obj);
289 helper->WriteLog(); 307 helper->ProcessEvents();
290 return false; 308 return false;
291 } 309 }
292 310
293 } // namespace webrtc 311 } // namespace webrtc
294 312
295 #endif // ENABLE_RTC_EVENT_LOG 313 #endif // ENABLE_RTC_EVENT_LOG
OLDNEW
« webrtc/call/rtc_event_log_helper_thread.h ('K') | « webrtc/call/rtc_event_log_helper_thread.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698