summaryrefslogtreecommitdiff
path: root/libs/log/src/text_file_backend.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/log/src/text_file_backend.cpp')
-rw-r--r--libs/log/src/text_file_backend.cpp63
1 files changed, 51 insertions, 12 deletions
diff --git a/libs/log/src/text_file_backend.cpp b/libs/log/src/text_file_backend.cpp
index fda501937..6cd8a9b1a 100644
--- a/libs/log/src/text_file_backend.cpp
+++ b/libs/log/src/text_file_backend.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright Andrey Semashev 2007 - 2014.
+ * Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
@@ -31,6 +31,7 @@
#include <stdexcept>
#include <boost/ref.hpp>
#include <boost/bind.hpp>
+#include <boost/cstdint.hpp>
#include <boost/smart_ptr/make_shared_object.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/throw_exception.hpp>
@@ -1162,16 +1163,36 @@ BOOST_LOG_API void text_file_backend::auto_flush(bool f)
BOOST_LOG_API void text_file_backend::consume(record_view const& rec, string_type const& formatted_message)
{
typedef file_char_traits< string_type::value_type > traits_t;
- if
+
+ bool no_new_filename = false;
+ if (!m_pImpl->m_File.good())
+ {
+ // The file stream is not operational. One possible reason is that there is no more free space
+ // on the file system. In this case it is possible that this log record will fail to be written as well,
+ // leaving the newly creted file empty. Eventually this results in lots of empty log files.
+ // We should take precautions to avoid this. https://svn.boost.org/trac/boost/ticket/11016
+ close_file();
+
+ system::error_code ec;
+ uintmax_t size = filesystem::file_size(m_pImpl->m_FileName, ec);
+ if (!!ec || size == 0)
+ {
+ // To reuse the empty file avoid re-generating the new file name later
+ no_new_filename = true;
+ }
+ else if (!!m_pImpl->m_pFileCollector)
+ {
+ // Complete file rotation
+ m_pImpl->m_pFileCollector->store_file(m_pImpl->m_FileName);
+ }
+ }
+ else if
(
+ m_pImpl->m_File.is_open() &&
(
- m_pImpl->m_File.is_open() &&
- (
- m_pImpl->m_CharactersWritten + formatted_message.size() >= m_pImpl->m_FileRotationSize ||
- (!m_pImpl->m_TimeBasedRotation.empty() && m_pImpl->m_TimeBasedRotation())
- )
- ) ||
- !m_pImpl->m_File.good()
+ m_pImpl->m_CharactersWritten + formatted_message.size() >= m_pImpl->m_FileRotationSize ||
+ (!m_pImpl->m_TimeBasedRotation.empty() && m_pImpl->m_TimeBasedRotation())
+ )
)
{
rotate_file();
@@ -1179,9 +1200,11 @@ BOOST_LOG_API void text_file_backend::consume(record_view const& rec, string_typ
if (!m_pImpl->m_File.is_open())
{
- m_pImpl->m_FileName = m_pImpl->m_StorageDir / m_pImpl->m_FileNameGenerator(m_pImpl->m_FileCounter++);
+ if (!no_new_filename)
+ m_pImpl->m_FileName = m_pImpl->m_StorageDir / m_pImpl->m_FileNameGenerator(m_pImpl->m_FileCounter++);
filesystem::create_directories(m_pImpl->m_FileName.parent_path());
+
m_pImpl->m_File.open(m_pImpl->m_FileName, m_pImpl->m_FileOpenMode);
if (!m_pImpl->m_File.is_open())
{
@@ -1300,14 +1323,30 @@ BOOST_LOG_API void text_file_backend::set_file_name_pattern_internal(filesystem:
}
}
-//! The method rotates the file
-BOOST_LOG_API void text_file_backend::rotate_file()
+//! Closes the currently open file
+void text_file_backend::close_file()
{
if (!m_pImpl->m_CloseHandler.empty())
+ {
+ // Rationale: We should call the close handler even if the stream is !good() because
+ // writing the footer may not be the only thing the handler does. However, there is
+ // a chance that the file had become writable since the last failure (e.g. there was
+ // no space left to write the last record, but it got freed since then), so if the handler
+ // attempts to write a footer it may succeed now. For this reason we clear the stream state
+ // and let the handler have a try.
+ m_pImpl->m_File.clear();
m_pImpl->m_CloseHandler(m_pImpl->m_File);
+ }
m_pImpl->m_File.close();
m_pImpl->m_File.clear();
m_pImpl->m_CharactersWritten = 0;
+}
+
+//! The method rotates the file
+BOOST_LOG_API void text_file_backend::rotate_file()
+{
+ close_file();
+
if (!!m_pImpl->m_pFileCollector)
m_pImpl->m_pFileCollector->store_file(m_pImpl->m_FileName);
}