Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions include/spdlog/details/file_helper-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <cstdio>
#include <string>
#include <tuple>
#include <vector>

SPDLOG_NAMESPACE_BEGIN
namespace details {
Expand Down Expand Up @@ -48,6 +49,7 @@ SPDLOG_INLINE void file_helper::open(const filename_t &fname, bool truncate) {
std::fclose(tmp);
}
if (!os::fopen_s(&fd_, fname, mode)) {
apply_buffer_();
if (event_handlers_.after_open) {
event_handlers_.after_open(filename_, fd_);
}
Expand All @@ -61,6 +63,37 @@ SPDLOG_INLINE void file_helper::open(const filename_t &fname, bool truncate) {
errno);
}

SPDLOG_INLINE void file_helper::set_buffer(std::size_t size) {
if (size == 0) {
if (fd_ != nullptr) {
if (std::setvbuf(fd_, nullptr, _IOFBF, BUFSIZ) != 0) {
throw_spdlog_ex("Failed setvbuf on file " + os::filename_to_str(filename_), errno);
}
}
buffer_.clear();
return;
}

// Detach any previous user buffer before resizing (avoids dangling FILE* buffer ptr).
if (fd_ != nullptr && !buffer_.empty()) {
if (std::setvbuf(fd_, nullptr, _IOFBF, BUFSIZ) != 0) {
throw_spdlog_ex("Failed setvbuf on file " + os::filename_to_str(filename_), errno);
}
}

buffer_.resize(size);
apply_buffer_();
}

SPDLOG_INLINE void file_helper::apply_buffer_() {
if (fd_ == nullptr || buffer_.empty()) {
return;
}
if (std::setvbuf(fd_, buffer_.data(), _IOFBF, buffer_.size()) != 0) {
throw_spdlog_ex("Failed setvbuf on file " + os::filename_to_str(filename_), errno);
}
}

SPDLOG_INLINE void file_helper::reopen(bool truncate) {
if (filename_.empty()) {
throw_spdlog_ex("Failed re opening file - was not opened before");
Expand Down
9 changes: 9 additions & 0 deletions include/spdlog/details/file_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include <spdlog/common.h>
#include <tuple>
#include <vector>

SPDLOG_NAMESPACE_BEGIN
namespace details {
Expand All @@ -31,6 +32,11 @@ class SPDLOG_API file_helper {
size_t size() const;
const filename_t &filename() const;

// Set custom FILE stream buffer size via setvbuf(_IOFBF).
// size == 0 clears the custom buffer and restores default buffering if the file is open.
// Re-applied automatically on open/reopen when size > 0.
void set_buffer(std::size_t size);

//
// return file path and its extension:
//
Expand All @@ -47,11 +53,14 @@ class SPDLOG_API file_helper {
static std::tuple<filename_t, filename_t> split_by_extension(const filename_t &fname);

private:
void apply_buffer_();

const int open_tries_ = 5;
const unsigned int open_interval_ = 10;
std::FILE *fd_{nullptr};
filename_t filename_;
file_event_handlers event_handlers_;
std::vector<char> buffer_;
};
} // namespace details
SPDLOG_NAMESPACE_END
Expand Down
12 changes: 11 additions & 1 deletion include/spdlog/sinks/basic_file_sink-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@ namespace sinks {
template <typename Mutex>
SPDLOG_INLINE basic_file_sink<Mutex>::basic_file_sink(const filename_t &filename,
bool truncate,
const file_event_handlers &event_handlers)
const file_event_handlers &event_handlers,
std::size_t buffer_size)
: file_helper_{event_handlers} {
if (buffer_size > 0) {
file_helper_.set_buffer(buffer_size);
}
file_helper_.open(filename, truncate);
}

Expand All @@ -32,6 +36,12 @@ SPDLOG_INLINE void basic_file_sink<Mutex>::truncate() {
file_helper_.reopen(true);
}

template <typename Mutex>
SPDLOG_INLINE void basic_file_sink<Mutex>::set_buffer(std::size_t size) {
std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);
file_helper_.set_buffer(size);
}

template <typename Mutex>
SPDLOG_INLINE void basic_file_sink<Mutex>::sink_it_(const details::log_msg &msg) {
memory_buf_t formatted;
Expand Down
14 changes: 9 additions & 5 deletions include/spdlog/sinks/basic_file_sink.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ class basic_file_sink final : public base_sink<Mutex> {
public:
explicit basic_file_sink(const filename_t &filename,
bool truncate = false,
const file_event_handlers &event_handlers = {});
const file_event_handlers &event_handlers = {},
std::size_t buffer_size = 0);
const filename_t &filename() const;
void truncate();
void set_buffer(std::size_t size);

protected:
void sink_it_(const details::log_msg &msg) override;
Expand All @@ -45,18 +47,20 @@ template <typename Factory = synchronous_factory>
inline std::shared_ptr<logger> basic_logger_mt(const std::string &logger_name,
const filename_t &filename,
bool truncate = false,
const file_event_handlers &event_handlers = {}) {
const file_event_handlers &event_handlers = {},
std::size_t buffer_size = 0) {
return Factory::template create<sinks::basic_file_sink_mt>(logger_name, filename, truncate,
event_handlers);
event_handlers, buffer_size);
}

template <typename Factory = synchronous_factory>
inline std::shared_ptr<logger> basic_logger_st(const std::string &logger_name,
const filename_t &filename,
bool truncate = false,
const file_event_handlers &event_handlers = {}) {
const file_event_handlers &event_handlers = {},
std::size_t buffer_size = 0) {
return Factory::template create<sinks::basic_file_sink_st>(logger_name, filename, truncate,
event_handlers);
event_handlers, buffer_size);
}

SPDLOG_NAMESPACE_END
Expand Down
12 changes: 11 additions & 1 deletion include/spdlog/sinks/rotating_file_sink-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ SPDLOG_INLINE rotating_file_sink<Mutex>::rotating_file_sink(
std::size_t max_size,
std::size_t max_files,
bool rotate_on_open,
const file_event_handlers &event_handlers)
const file_event_handlers &event_handlers,
std::size_t buffer_size)
: base_filename_(std::move(base_filename)),
max_size_(max_size),
max_files_(max_files),
Expand All @@ -40,6 +41,9 @@ SPDLOG_INLINE rotating_file_sink<Mutex>::rotating_file_sink(
if (max_files > MaxFiles) {
throw_spdlog_ex("rotating sink constructor: max_files arg cannot exceed MaxFiles");
}
if (buffer_size > 0) {
file_helper_.set_buffer(buffer_size);
}
file_helper_.open(calc_filename(base_filename_, 0));
current_size_ = file_helper_.size(); // expensive. called only once
if (rotate_on_open && current_size_ > 0) {
Expand Down Expand Up @@ -109,6 +113,12 @@ std::size_t rotating_file_sink<Mutex>::get_current_size() {
return current_size_;
}

template <typename Mutex>
SPDLOG_INLINE void rotating_file_sink<Mutex>::set_buffer(std::size_t size) {
std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);
file_helper_.set_buffer(size);
}

template <typename Mutex>
SPDLOG_INLINE void rotating_file_sink<Mutex>::sink_it_(const details::log_msg &msg) {
memory_buf_t formatted;
Expand Down
16 changes: 11 additions & 5 deletions include/spdlog/sinks/rotating_file_sink.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ class rotating_file_sink final : public base_sink<Mutex> {
std::size_t max_size,
std::size_t max_files,
bool rotate_on_open = false,
const file_event_handlers &event_handlers = {});
const file_event_handlers &event_handlers = {},
std::size_t buffer_size = 0);
static filename_t calc_filename(const filename_t &filename, std::size_t index);
filename_t filename();
void rotate_now();
Expand All @@ -34,6 +35,7 @@ class rotating_file_sink final : public base_sink<Mutex> {
void set_max_files(std::size_t max_files);
std::size_t get_max_files();
std::size_t get_current_size();
void set_buffer(std::size_t size);

protected:
void sink_it_(const details::log_msg &msg) override;
Expand Down Expand Up @@ -72,9 +74,11 @@ std::shared_ptr<logger> rotating_logger_mt(const std::string &logger_name,
size_t max_file_size,
size_t max_files,
bool rotate_on_open = false,
const file_event_handlers &event_handlers = {}) {
const file_event_handlers &event_handlers = {},
std::size_t buffer_size = 0) {
return Factory::template create<sinks::rotating_file_sink_mt>(
logger_name, filename, max_file_size, max_files, rotate_on_open, event_handlers);
logger_name, filename, max_file_size, max_files, rotate_on_open, event_handlers,
buffer_size);
}

template <typename Factory = synchronous_factory>
Expand All @@ -83,9 +87,11 @@ std::shared_ptr<logger> rotating_logger_st(const std::string &logger_name,
size_t max_file_size,
size_t max_files,
bool rotate_on_open = false,
const file_event_handlers &event_handlers = {}) {
const file_event_handlers &event_handlers = {},
std::size_t buffer_size = 0) {
return Factory::template create<sinks::rotating_file_sink_st>(
logger_name, filename, max_file_size, max_files, rotate_on_open, event_handlers);
logger_name, filename, max_file_size, max_files, rotate_on_open, event_handlers,
buffer_size);
}
SPDLOG_NAMESPACE_END

Expand Down