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

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

Issue 1687703002: Refactored CL for moving the output to a separate thread. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: No-op Created 4 years, 8 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
« no previous file with comments | « webrtc/call/rtc_event_log_helper_thread.h ('k') | webrtc/call/rtc_event_log_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 *
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
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "webrtc/call/rtc_event_log_helper_thread.h"
12
13 #include <algorithm>
14
15 #include "webrtc/base/checks.h"
16 #include "webrtc/system_wrappers/include/logging.h"
17
18 #ifdef ENABLE_RTC_EVENT_LOG
19
20 namespace webrtc {
21
22 namespace {
23 const int kEventsInHistory = 10000;
24
25 bool IsConfigEvent(const rtclog::Event& event) {
26 rtclog::Event_EventType event_type = event.type();
27 return event_type == rtclog::Event::VIDEO_RECEIVER_CONFIG_EVENT ||
28 event_type == rtclog::Event::VIDEO_SENDER_CONFIG_EVENT ||
29 event_type == rtclog::Event::AUDIO_RECEIVER_CONFIG_EVENT ||
30 event_type == rtclog::Event::AUDIO_SENDER_CONFIG_EVENT;
31 }
32 } // namespace
33
34 // RtcEventLogImpl member functions.
35 RtcEventLogHelperThread::RtcEventLogHelperThread(
36 SwapQueue<ControlMessage>* message_queue,
37 SwapQueue<std::unique_ptr<rtclog::Event>>* event_queue,
38 rtc::Event* wake_up,
39 rtc::Event* stopped,
40 const Clock* const clock)
41 : message_queue_(message_queue),
42 event_queue_(event_queue),
43 history_(kEventsInHistory),
44 config_history_(),
45 file_(FileWrapper::Create()),
46 thread_(&ThreadOutputFunction, this, "RtcEventLog thread"),
47 max_size_bytes_(std::numeric_limits<int64_t>::max()),
48 written_bytes_(0),
49 start_time_(0),
50 stop_time_(std::numeric_limits<int64_t>::max()),
51 has_recent_event_(false),
52 most_recent_event_(),
53 output_string_(),
54 wake_up_(wake_up),
55 stopped_(stopped),
56 clock_(clock) {
57 RTC_DCHECK(message_queue_);
58 RTC_DCHECK(event_queue_);
59 RTC_DCHECK(wake_up_);
60 RTC_DCHECK(stopped_);
61 RTC_DCHECK(clock_);
62 thread_.Start();
63 }
64
65 RtcEventLogHelperThread::~RtcEventLogHelperThread() {
66 ControlMessage message;
67 message.message_type = ControlMessage::TERMINATE_THREAD;
68 message.stop_time = clock_->TimeInMicroseconds();
69 while (!message_queue_->Insert(&message)) {
70 // 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
72 // any STOP_FILE events, then the threads calling StopLogging would likely
73 // wait indefinitely. However, there should not be any such calls as we
74 // are executing the destructor.
75 LOG(LS_WARNING) << "Clearing message queue to terminate thread.";
76 message_queue_->Clear();
77 }
78 wake_up_->Set(); // Wake up the output thread.
79 thread_.Stop(); // Wait for the thread to terminate.
80 }
81
82 bool RtcEventLogHelperThread::AppendEventToString(rtclog::Event* event) {
83 rtclog::EventStream event_stream;
84 event_stream.add_stream();
85 event_stream.mutable_stream(0)->Swap(event);
86 // 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,
88 // it will look like a single stream when we read it back from file.
89 bool stop = true;
90 if (written_bytes_ + static_cast<int64_t>(output_string_.size()) +
91 event_stream.ByteSize() <=
92 max_size_bytes_) {
93 event_stream.AppendToString(&output_string_);
94 stop = false;
95 }
96 // Swap the event back so that we don't mix event types in the queues.
97 event_stream.mutable_stream(0)->Swap(event);
98 return stop;
99 }
100
101 void RtcEventLogHelperThread::LogToMemory() {
102 RTC_DCHECK(!file_->Open());
103
104 // Process each event earlier than the current time and append it to the
105 // appropriate history_.
106 int64_t current_time = clock_->TimeInMicroseconds();
107 if (!has_recent_event_) {
108 has_recent_event_ = event_queue_->Remove(&most_recent_event_);
109 }
110 while (has_recent_event_ &&
111 most_recent_event_->timestamp_us() <= current_time) {
112 if (IsConfigEvent(*most_recent_event_)) {
113 config_history_.push_back(std::move(most_recent_event_));
114 } else {
115 history_.push_back(std::move(most_recent_event_));
116 }
117 has_recent_event_ = event_queue_->Remove(&most_recent_event_);
118 }
119 }
120
121 void RtcEventLogHelperThread::StartLogFile() {
122 RTC_DCHECK(file_->Open());
123 bool stop = false;
124 output_string_.clear();
125
126 // Create and serialize the LOG_START event.
127 rtclog::Event start_event;
128 start_event.set_timestamp_us(start_time_);
129 start_event.set_type(rtclog::Event::LOG_START);
130 AppendEventToString(&start_event);
131
132 // Serialize the config information for all old streams.
133 for (auto& event : config_history_) {
134 AppendEventToString(event.get());
135 }
136
137 // Serialize the events in the event queue.
138 while (!history_.empty() && !stop) {
139 stop = AppendEventToString(history_.front().get());
140 if (!stop) {
141 history_.pop_front();
142 }
143 }
144
145 // Write to file.
146 file_->Write(output_string_.data(), output_string_.size());
147 written_bytes_ += output_string_.size();
148
149 // Free the allocated memory since we probably won't need this amount of
150 // space again.
151 output_string_.clear();
152 output_string_.shrink_to_fit();
153
154 if (stop) {
155 RTC_DCHECK(file_->Open());
156 StopLogFile();
157 }
158 }
159
160 void RtcEventLogHelperThread::LogToFile() {
161 RTC_DCHECK(file_->Open());
162 output_string_.clear();
163
164 // Append each event older than both the current time and the stop time
165 // to the output_string_.
166 int64_t current_time = clock_->TimeInMicroseconds();
167 int64_t time_limit = std::min(current_time, stop_time_);
168 if (!has_recent_event_) {
169 has_recent_event_ = event_queue_->Remove(&most_recent_event_);
170 }
171 bool stop = false;
172 while (!stop && has_recent_event_ &&
173 most_recent_event_->timestamp_us() <= time_limit) {
174 stop = AppendEventToString(most_recent_event_.get());
175 if (!stop) {
176 if (IsConfigEvent(*most_recent_event_)) {
177 config_history_.push_back(std::move(most_recent_event_));
178 }
179 has_recent_event_ = event_queue_->Remove(&most_recent_event_);
180 }
181 }
182
183 // Write string to file.
184 file_->Write(output_string_.data(), output_string_.size());
185 written_bytes_ += output_string_.size();
186
187 if (!file_->Open()) {
188 LOG(LS_WARNING) << "WebRTC event log file closed by FileWrapper.";
189 }
190
191 // We want to stop logging if we have reached the file size limit. We also
192 // want to stop logging if the remaining events are more recent than the
193 // time limit, or in other words if we have terminated the loop despite
194 // having more events in the queue.
195 if ((has_recent_event_ && most_recent_event_->timestamp_us() > stop_time_) ||
196 stop) {
197 RTC_DCHECK(file_->Open());
198 StopLogFile();
199 }
200 }
201
202 void RtcEventLogHelperThread::StopLogFile() {
203 RTC_DCHECK(file_->Open());
204 output_string_.clear();
205
206 rtclog::Event end_event;
207 end_event.set_timestamp_us(stop_time_);
208 end_event.set_type(rtclog::Event::LOG_END);
209 AppendEventToString(&end_event);
210
211 if (written_bytes_ + static_cast<int64_t>(output_string_.size()) <=
212 max_size_bytes_) {
213 file_->Write(output_string_.data(), output_string_.size());
214 written_bytes_ += output_string_.size();
215 }
216
217 max_size_bytes_ = std::numeric_limits<int64_t>::max();
218 written_bytes_ = 0;
219 start_time_ = 0;
220 stop_time_ = std::numeric_limits<int64_t>::max();
221 output_string_.clear();
222 file_->CloseFile();
223 RTC_DCHECK(!file_->Open());
224 }
225
226 void RtcEventLogHelperThread::WriteLog() {
227 ControlMessage message;
228
229 while (true) {
230 // Process control messages.
231 while (message_queue_->Remove(&message)) {
232 switch (message.message_type) {
233 case ControlMessage::START_FILE:
234 if (!file_->Open()) {
235 max_size_bytes_ = message.max_size_bytes;
236 start_time_ = message.start_time;
237 stop_time_ = message.stop_time;
238 file_.swap(message.file);
239 StartLogFile();
240 } else {
241 // Already started. Ignore message and close file handle.
242 message.file->CloseFile();
243 }
244 break;
245 case ControlMessage::STOP_FILE:
246 if (file_->Open()) {
247 stop_time_ = message.stop_time;
248 LogToFile(); // Log remaining events from message queues.
249 }
250 // LogToFile might stop on it's own so we need to recheck the state.
251 if (file_->Open()) {
252 StopLogFile();
253 }
254 stopped_->Set();
255 break;
256 case ControlMessage::TERMINATE_THREAD:
257 if (file_->Open()) {
258 StopLogFile();
259 }
260 return;
261 }
262 }
263
264 // Write events to file or memory
265 if (file_->Open()) {
266 LogToFile();
267 } else {
268 LogToMemory();
269 }
270
271 // Accumulate a new batch of events instead of processing them one at a
272 // time.
273 wake_up_->Wait(50);
tommi 2016/05/24 21:47:04 Please see chromium:614192. Looks like this threa
274 }
275 }
276
277 bool RtcEventLogHelperThread::ThreadOutputFunction(void* obj) {
278 RtcEventLogHelperThread* helper = static_cast<RtcEventLogHelperThread*>(obj);
279 helper->WriteLog();
280 return false;
281 }
282
283 } // namespace webrtc
284
285 #endif // ENABLE_RTC_EVENT_LOG
OLDNEW
« no previous file with comments | « webrtc/call/rtc_event_log_helper_thread.h ('k') | webrtc/call/rtc_event_log_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698