00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00038 #include "blocxx/BLOCXX_config.h"
00039 #include "blocxx/FileAppender.hpp"
00040 #include "blocxx/Format.hpp"
00041 #include "blocxx/Logger.hpp"
00042 #include "blocxx/LogMessage.hpp"
00043 #include "blocxx/Mutex.hpp"
00044 #include "blocxx/MutexLock.hpp"
00045 #include "blocxx/FileSystem.hpp"
00046 #include "blocxx/GlobalMutex.hpp"
00047
00048 #include <fstream>
00049
00050 namespace BLOCXX_NAMESPACE
00051 {
00052
00054 FileAppender::FileAppender(const StringArray& components,
00055 const StringArray& categories,
00056 const char* filename,
00057 const String& pattern,
00058 UInt64 maxFileSize,
00059 unsigned int maxBackupIndex,
00060 bool flushLog)
00061 : LogAppender(components, categories, pattern)
00062 , m_filename(filename)
00063 , m_maxFileSize(maxFileSize)
00064 , m_maxBackupIndex(maxBackupIndex)
00065 , m_flushLog(flushLog)
00066 {
00067 m_log.open(m_filename.c_str(), std::ios::out | std::ios::app);
00068 if (!m_log)
00069 {
00070 BLOCXX_THROW(LoggerException, Format("FileAppender: Unable to open file: %1", m_filename).toString().c_str() );
00071 }
00072 }
00073
00075 FileAppender::~FileAppender()
00076 {
00077 }
00078
00080 namespace
00081 {
00082 GlobalMutex fileGuard = BLOCXX_GLOBAL_MUTEX_INIT();
00083 }
00084 void
00085 FileAppender::doProcessLogMessage(const String& formattedMessage, const LogMessage& message) const
00086 {
00087 MutexLock lock(fileGuard);
00088
00089
00090 if (!FileSystem::exists(m_filename.c_str()))
00091 {
00092
00093 std::ofstream temp;
00094 temp.open(m_filename.c_str(), std::ios::out | std::ios::app);
00095 if (temp)
00096 {
00097 temp.close();
00098 m_log.close();
00099 m_log.open(m_filename.c_str(), std::ios::out | std::ios::app);
00100 }
00101 else
00102 {
00103 m_log << "FileAppender::doProcessLogMessage(): " << m_filename << " no longer exists and re-opening it failed!\n";
00104 }
00105 }
00106
00107 if (!m_log)
00108 {
00109
00110 return;
00111 }
00112
00113 m_log.write(formattedMessage.c_str(), formattedMessage.length());
00114 m_log << '\n';
00115
00116 if (m_flushLog)
00117 {
00118 m_log.flush();
00119 }
00120
00121
00122 if (m_maxFileSize != NO_MAX_LOG_SIZE && m_log.tellp() >= static_cast<std::streampos>(m_maxFileSize * 1024))
00123 {
00124
00125
00126 if (m_maxBackupIndex > 0)
00127 {
00128
00129 FileSystem::removeFile(m_filename + '.' + String(m_maxBackupIndex));
00130
00131
00132 for (unsigned int i = m_maxBackupIndex - 1; i >= 1; --i)
00133 {
00134 FileSystem::renameFile(m_filename + '.' + String(i), m_filename + '.' + String(i + 1));
00135 }
00136
00137 if (!FileSystem::renameFile(m_filename, m_filename + ".1"))
00138 {
00139
00140 m_log << "FileAppender::doProcessLogMessage(): Failed to rename " << m_filename << " to " << m_filename + ".1! Logging to this file STOPPED!\n";
00141 m_log.close();
00142 return;
00143 }
00144 }
00145
00146
00147 std::ofstream temp;
00148 temp.open(m_filename.c_str(), std::ios::out | std::ios::app);
00149 if (temp)
00150 {
00151 temp.close();
00152 m_log.close();
00153
00154 m_log.open(m_filename.c_str(), std::ios_base::out | std::ios_base::trunc);
00155 }
00156 else
00157 {
00158 m_log << "FileAppender::doProcessLogMessage(): Failed to open " << m_filename << "! Logging to this file STOPPED!\n";
00159 m_log.close();
00160 }
00161 }
00162 }
00163
00165 const GlobalString FileAppender::STR_DEFAULT_MESSAGE_PATTERN = BLOCXX_GLOBAL_STRING_INIT("%d{%a %b %d %H:%M:%S %Y} [%t]: %m");
00166
00167 }
00168
00169
00170
00171