srsRAN/lib/src/srslog/sinks/file_sink.h

108 lines
3.0 KiB
C++

/*
* Copyright 2013-2020 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#ifndef SRSLOG_FILE_SINK_H
#define SRSLOG_FILE_SINK_H
#include "file_utils.h"
#include "srslte/srslog/sink.h"
#include <cassert>
namespace srslog {
/// This sink implementation writes to files. Includes the optional feature of
/// file rotation: a new file is created when file size exceeds an established
/// threshold.
class file_sink : public sink
{
public:
file_sink(std::string name, size_t max_size) :
base_filename(std::move(name)),
max_size((max_size == 0) ? 0 : std::max<size_t>(max_size, 4 * 1024))
{}
file_sink(const file_sink& other) = delete;
file_sink& operator=(const file_sink& other) = delete;
~file_sink() override { handler.close(); }
detail::error_string write(detail::memory_buffer buffer) override
{
// Create a new file the first time we hit this method.
if (is_first_write()) {
assert(!handler && "No handler should be created yet");
if (auto err_str = create_file()) {
return err_str;
}
}
// Do not bother doing any work when the file was closed on a previous
// error.
if (!handler) {
return {};
}
if (auto err_str = handle_rotation(buffer.size())) {
return err_str;
}
return handler.write(buffer);
}
detail::error_string flush() override { return handler.flush(); }
private:
/// Returns true when the sink has never written data to a file, otherwise
/// returns false.
bool is_first_write() const { return file_index == 0; }
/// Creates a new file and increments the file index counter.
detail::error_string create_file()
{
return handler.create(
file_utils::build_filename_with_index(base_filename, file_index++));
}
/// Handles the file rotation feature when it is activated.
/// NOTE: The file handler must be valid.
detail::error_string handle_rotation(size_t size)
{
assert(handler && "Expected a valid file handle");
current_size += size;
if (max_size && current_size >= max_size) {
current_size = size;
return create_file();
}
return {};
}
private:
const size_t max_size;
const std::string base_filename;
file_utils::file handler;
size_t current_size = 0;
uint32_t file_index = 0;
};
} // namespace srslog
#endif // SRSLOG_FILE_SINK_H