OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |