Modify the policy of the buffered sink to flush its contents continuously instead of doing it once.

This commit is contained in:
faluco 2021-03-17 17:12:10 +01:00 committed by faluco
parent 0d91802495
commit eb27efd867
3 changed files with 98 additions and 111 deletions

View File

@ -11,7 +11,7 @@
*/
#include "srslte/srslog/event_trace.h"
#include "sinks/single_write_file_sink.h"
#include "sinks/buffered_file_sink.h"
#include "srslte/srslog/srslog.h"
#include <ctime>
@ -62,15 +62,13 @@ bool srslog::event_trace_init(const std::string& filename, std::size_t capacity)
return false;
}
auto tracer_sink = std::unique_ptr<sink>(new single_write_file_sink(
filename, capacity, get_default_log_formatter()));
auto tracer_sink = std::unique_ptr<sink>(new buffered_file_sink(filename, capacity, get_default_log_formatter()));
if (!install_custom_sink(sink_name, std::move(tracer_sink))) {
return false;
}
if (sink* s = find_sink(sink_name)) {
log_channel& c =
fetch_log_channel("event_trace_channel", *s, {"TRACE", '\0', false});
log_channel& c = fetch_log_channel("event_trace_channel", *s, {"TRACE", '\0', false});
tracer = &c;
return true;
}
@ -97,11 +95,7 @@ void trace_duration_begin(const std::string& category, const std::string& name)
char fmt_time[24];
format_time(fmt_time, sizeof(fmt_time));
(*tracer)("[%s] [TID:%0u] Entering \"%s\": %s",
fmt_time,
(unsigned)::pthread_self(),
category,
name);
(*tracer)("[%s] [TID:%0u] Entering \"%s\": %s", fmt_time, (unsigned)::pthread_self(), category, name);
}
void trace_duration_end(const std::string& category, const std::string& name)
@ -112,11 +106,7 @@ void trace_duration_end(const std::string& category, const std::string& name)
char fmt_time[24];
format_time(fmt_time, sizeof(fmt_time));
(*tracer)("[%s] [TID:%0u] Leaving \"%s\": %s",
fmt_time,
(unsigned)::pthread_self(),
category,
name);
(*tracer)("[%s] [TID:%0u] Leaving \"%s\": %s", fmt_time, (unsigned)::pthread_self(), category, name);
}
} // namespace srslog
@ -129,9 +119,7 @@ srslog::detail::scoped_complete_event::~scoped_complete_event()
}
auto end = std::chrono::steady_clock::now();
unsigned long long diff =
std::chrono::duration_cast<std::chrono::microseconds>(end - start)
.count();
unsigned long long diff = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
small_str_buffer str;
// Limit to the category and name strings to a predefined length so everything fits in a small string.

View File

@ -0,0 +1,89 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSLOG_BUFFERED_FILE_SINK_H
#define SRSLOG_BUFFERED_FILE_SINK_H
#include "file_utils.h"
#include "srslte/srslog/sink.h"
namespace srslog {
/// This class is a wrapper of a file handle that buffers the input data into an internal buffer and writes its contents
/// to the file once the buffer is full or in object destruction.
class buffered_file_sink : public sink
{
public:
buffered_file_sink(std::string filename, std::size_t capacity, std::unique_ptr<log_formatter> f) :
sink(std::move(f)), filename(std::move(filename))
{
buffer.reserve(capacity);
}
~buffered_file_sink() override { flush_buffer(); }
buffered_file_sink(const buffered_file_sink& other) = delete;
buffered_file_sink& operator=(const buffered_file_sink& other) = delete;
detail::error_string write(detail::memory_buffer input_buffer) override
{
// Create a new file the first time we hit this method.
if (!is_file_created) {
is_file_created = true;
assert(!handler && "No handler should be created yet");
if (auto err_str = handler.create(filename)) {
return err_str;
}
}
if (has_room_for(input_buffer.size())) {
buffer.insert(buffer.end(), input_buffer.begin(), input_buffer.end());
return {};
}
return flush_buffer();
}
detail::error_string flush() override
{
if (auto err = flush_buffer()) {
return err;
}
return handler.flush();
}
private:
/// Returns true if the internal buffer has room for the specified input size,
/// otherwise returns false.
bool has_room_for(std::size_t s) const { return s + buffer.size() < buffer.capacity(); }
/// Flushes the buffer contents into the file.
detail::error_string flush_buffer()
{
if (buffer.empty()) {
return {};
}
auto err = handler.write(detail::memory_buffer(buffer.data(), buffer.size()));
buffer.clear();
return err;
}
private:
const std::string filename;
file_utils::file handler;
std::vector<char> buffer;
bool is_file_created = false;
};
} // namespace srslog
#endif // SRSLOG_BUFFERED_FILE_SINK_H

View File

@ -1,90 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSLOG_SINGLE_WRITE_FILE_SINK_H
#define SRSLOG_SINGLE_WRITE_FILE_SINK_H
#include "file_utils.h"
#include "srslte/srslog/sink.h"
namespace srslog {
/// This class is a wrapper of a file handle that stores the input data into an
/// internal buffer and writes its contents to the file once the buffer is full
/// or in object destruction.
class single_write_file_sink : public sink
{
public:
single_write_file_sink(std::string filename,
std::size_t capacity,
std::unique_ptr<log_formatter> f) :
sink(std::move(f)), filename(std::move(filename))
{
buffer.reserve(capacity);
}
~single_write_file_sink() override
{
if (!is_written) {
write_contents();
}
}
single_write_file_sink(const single_write_file_sink& other) = delete;
single_write_file_sink&
operator=(const single_write_file_sink& other) = delete;
detail::error_string write(detail::memory_buffer input_buffer) override
{
// Nothing to do when the contents have been already written.
if (is_written) {
return {};
}
if (has_room_for(input_buffer.size())) {
buffer.insert(buffer.end(), input_buffer.begin(), input_buffer.end());
return {};
}
return write_contents();
}
detail::error_string flush() override { return handler.flush(); }
private:
/// Returns true if the internal buffer has room for the specified input size,
/// otherwise returns false.
bool has_room_for(std::size_t s) const
{
return s + buffer.size() < buffer.capacity();
}
/// Writes the buffer contents into the file.
detail::error_string write_contents()
{
is_written = true;
if (auto err_str = handler.create(filename)) {
return err_str;
}
return handler.write(detail::memory_buffer(buffer.data(), buffer.size()));
}
private:
const std::string filename;
file_utils::file handler;
std::vector<char> buffer;
bool is_written = false;
};
} // namespace srslog
#endif // SRSLOG_SINGLE_WRITE_FILE_SINK_H