Add method to encode a batch of RtcEvents.
Bug: webrtc:8111
Change-Id: Ieb3ff6b817a6bc068b358d49e6d6df07e3ec8d8b
Reviewed-on: https://webrtc-review.googlesource.com/32720
Commit-Queue: Björn Terelius <terelius@webrtc.org>
Reviewed-by: Elad Alon <eladalon@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#21286}diff --git a/logging/rtc_event_log/encoder/rtc_event_log_encoder.h b/logging/rtc_event_log/encoder/rtc_event_log_encoder.h
index 3580d9c..dfa59ed 100644
--- a/logging/rtc_event_log/encoder/rtc_event_log_encoder.h
+++ b/logging/rtc_event_log/encoder/rtc_event_log_encoder.h
@@ -11,6 +11,8 @@
#ifndef LOGGING_RTC_EVENT_LOG_ENCODER_RTC_EVENT_LOG_ENCODER_H_
#define LOGGING_RTC_EVENT_LOG_ENCODER_RTC_EVENT_LOG_ENCODER_H_
+#include <deque>
+#include <memory>
#include <string>
#include "logging/rtc_event_log/events/rtc_event.h"
@@ -21,6 +23,10 @@
virtual ~RtcEventLogEncoder() = default;
virtual std::string Encode(const RtcEvent& event) = 0;
+
+ virtual std::string EncodeBatch(
+ std::deque<std::unique_ptr<RtcEvent>>::const_iterator begin,
+ std::deque<std::unique_ptr<RtcEvent>>::const_iterator end) = 0;
};
} // namespace webrtc
diff --git a/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.cc b/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.cc
index dd4abd9..0f3f3be 100644
--- a/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.cc
+++ b/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.cc
@@ -107,6 +107,18 @@
}
} // namespace
+std::string RtcEventLogEncoderLegacy::EncodeBatch(
+ std::deque<std::unique_ptr<RtcEvent>>::const_iterator begin,
+ std::deque<std::unique_ptr<RtcEvent>>::const_iterator end) {
+ std::string encoded_output;
+ for (auto it = begin; it != end; ++it) {
+ // TODO(terelius): Can we avoid the slight inefficiency of reallocating the
+ // string?
+ encoded_output += Encode(**it);
+ }
+ return encoded_output;
+}
+
std::string RtcEventLogEncoderLegacy::Encode(const RtcEvent& event) {
switch (event.GetType()) {
case RtcEvent::Type::AudioNetworkAdaptation: {
diff --git a/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.h b/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.h
index f4d3355..9f795a6 100644
--- a/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.h
+++ b/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.h
@@ -11,6 +11,7 @@
#ifndef LOGGING_RTC_EVENT_LOG_ENCODER_RTC_EVENT_LOG_ENCODER_LEGACY_H_
#define LOGGING_RTC_EVENT_LOG_ENCODER_RTC_EVENT_LOG_ENCODER_LEGACY_H_
+#include <deque>
#include <memory>
#include <string>
@@ -51,6 +52,10 @@
std::string Encode(const RtcEvent& event) override;
+ std::string EncodeBatch(
+ std::deque<std::unique_ptr<RtcEvent>>::const_iterator begin,
+ std::deque<std::unique_ptr<RtcEvent>>::const_iterator end) override;
+
private:
// Encoding entry-point for the various RtcEvent subclasses.
std::string EncodeAlrState(const RtcEventAlrState& event);
diff --git a/logging/rtc_event_log/rtc_event_log.cc b/logging/rtc_event_log/rtc_event_log.cc
index 9bbccaf..c6323c0 100644
--- a/logging/rtc_event_log/rtc_event_log.cc
+++ b/logging/rtc_event_log/rtc_event_log.cc
@@ -95,22 +95,14 @@
void Log(std::unique_ptr<RtcEvent> event) override;
private:
- // Appends an event to the output protobuf string, returning true on success.
- // Fails and returns false in case the limit on output size prevents the
- // event from being added; in this case, the output string is left unchanged.
- // The event is encoded before being appended.
- // We could have avoided this, because the output repeats the check, but this
- // way, we minimize the number of lock acquisitions, task switches, etc.,
- // that might be associated with each call to RtcEventLogOutput::Write().
- bool AppendEventToString(const RtcEvent& event,
- std::string* output_string) RTC_WARN_UNUSED_RESULT;
-
void LogToMemory(std::unique_ptr<RtcEvent> event) RTC_RUN_ON(&task_queue_);
-
void LogEventsFromMemoryToOutput() RTC_RUN_ON(&task_queue_);
- void LogToOutput(std::unique_ptr<RtcEvent> event) RTC_RUN_ON(&task_queue_);
+
void StopOutput() RTC_RUN_ON(&task_queue_);
+ void WriteConfigsAndHistoryToOutput(const std::string& encoded_configs,
+ const std::string& encoded_history)
+ RTC_RUN_ON(&task_queue_);
void WriteToOutput(const std::string& output_string) RTC_RUN_ON(&task_queue_);
void StopLoggingInternal() RTC_RUN_ON(&task_queue_);
@@ -196,7 +188,7 @@
RTC_DCHECK(output->IsActive());
event_output_ = std::move(output);
num_config_events_written_ = 0;
- LogToOutput(rtc::MakeUnique<RtcEventLoggingStarted>(start_event));
+ WriteToOutput(event_encoder_->Encode(start_event));
LogEventsFromMemoryToOutput();
};
@@ -279,26 +271,6 @@
}
}
-bool RtcEventLogImpl::AppendEventToString(const RtcEvent& event,
- std::string* output_string) {
- RTC_DCHECK_RUN_ON(&task_queue_);
-
- std::string encoded_event = event_encoder_->Encode(event);
-
- bool appended;
- size_t potential_new_size =
- written_bytes_ + output_string->size() + encoded_event.length();
- if (potential_new_size <= max_size_bytes_) {
- // TODO(eladalon): This is inefficient; fix this in a separate CL.
- *output_string += encoded_event;
- appended = true;
- } else {
- appended = false;
- }
-
- return appended;
-}
-
void RtcEventLogImpl::LogToMemory(std::unique_ptr<RtcEvent> event) {
std::deque<std::unique_ptr<RtcEvent>>& container =
event->IsConfigEvent() ? config_history_ : history_;
@@ -316,65 +288,46 @@
RTC_DCHECK(event_output_ && event_output_->IsActive());
last_output_ms_ = rtc::TimeMillis();
- std::string output_string;
-
// Serialize all stream configurations that haven't already been written to
// this output. |num_config_events_written_| is used to track which configs we
// have already written. (Note that the config may have been written to
// previous outputs; configs are not discarded.)
- bool appended = true;
- while (num_config_events_written_ < config_history_.size()) {
- appended = AppendEventToString(*config_history_[num_config_events_written_],
- &output_string);
- if (!appended)
- break;
- ++num_config_events_written_;
+ std::string encoded_configs;
+ RTC_DCHECK_LE(num_config_events_written_, config_history_.size());
+ if (num_config_events_written_ < config_history_.size()) {
+ const auto begin = config_history_.begin() + num_config_events_written_;
+ const auto end = config_history_.end();
+ encoded_configs = event_encoder_->EncodeBatch(begin, end);
+ num_config_events_written_ = config_history_.size();
}
- // Serialize the events in the event queue.
- while (appended && !history_.empty()) {
- appended = AppendEventToString(*history_.front(), &output_string);
- if (appended) {
- // Known issue - if writing to the output fails, these events will have
- // been lost. If we try to open a new output, these events will be missing
- // from it.
- history_.pop_front();
- }
- }
+ // Serialize the events in the event queue. Note that the write may fail,
+ // for example if we are writing to a file and have reached the maximum limit.
+ // We don't get any feedback if this happens, so we still remove the events
+ // from the event log history. This is normally not a problem, but if another
+ // log is started immediately after the first one becomes full, then one
+ // cannot rely on the second log to contain everything that isn't in the first
+ // log; one batch of events might be missing.
+ std::string encoded_history =
+ event_encoder_->EncodeBatch(history_.begin(), history_.end());
+ history_.clear();
- WriteToOutput(output_string);
-
- if (!appended) {
- // Successful partial write to the output. Some events could not be written;
- // the output should be closed, to avoid gaps.
- StopOutput();
- }
+ WriteConfigsAndHistoryToOutput(encoded_configs, encoded_history);
}
-void RtcEventLogImpl::LogToOutput(std::unique_ptr<RtcEvent> event) {
- RTC_DCHECK(event_output_ && event_output_->IsActive());
-
- std::string output_string;
-
- bool appended = AppendEventToString(*event, &output_string);
-
- if (event->IsConfigEvent()) {
- // Config events need to be kept in memory too, so that they may be
- // rewritten into future outputs, too.
- config_history_.push_back(std::move(event));
+void RtcEventLogImpl::WriteConfigsAndHistoryToOutput(
+ const std::string& encoded_configs,
+ const std::string& encoded_history) {
+ // This function is used to merge the strings instead of calling the output
+ // object twice with small strings. The function also avoids copying any
+ // strings in the typical case where there are no config events.
+ if (encoded_configs.size() == 0) {
+ WriteToOutput(encoded_history); // Typical case.
+ } else if (encoded_history.size() == 0) {
+ WriteToOutput(encoded_configs); // Very unusual case.
+ } else {
+ WriteToOutput(encoded_configs + encoded_history);
}
-
- if (!appended) {
- if (!event->IsConfigEvent()) {
- // This event will not fit into the output; push it into |history_|
- // instead, so that it might be logged into the next output (if any).
- history_.push_back(std::move(event));
- }
- StopOutput();
- return;
- }
-
- WriteToOutput(output_string);
}
void RtcEventLogImpl::StopOutput() {
@@ -386,8 +339,8 @@
void RtcEventLogImpl::StopLoggingInternal() {
if (event_output_) {
RTC_DCHECK(event_output_->IsActive());
- event_output_->Write(
- event_encoder_->Encode(*rtc::MakeUnique<RtcEventLoggingStopped>()));
+ RtcEventLoggingStopped stop_event;
+ event_output_->Write(event_encoder_->Encode(stop_event));
}
StopOutput();
}