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/MultiProcessFileAppender.hpp"
00040 #include "blocxx/Format.hpp"
00041 #include "blocxx/Logger.hpp"
00042 #include "blocxx/LogMessage.hpp"
00043 #include "blocxx/FileSystem.hpp"
00044
00045 #include <fcntl.h>
00046 #ifdef BLOCXX_HAVE_SYS_STAT_H
00047 #include <sys/stat.h>
00048 #endif
00049
00050 namespace BLOCXX_NAMESPACE
00051 {
00052
00053 namespace
00054 {
00055 using namespace blocxx;
00056
00057 class FileLock
00058 {
00059 public:
00060 FileLock(File & file)
00061 : m_file(file)
00062 {
00063 m_ok = file.getLock() == 0;
00064 }
00065
00066 bool ok() const
00067 {
00068 return m_ok;
00069 }
00070
00071 ~FileLock()
00072 {
00073 if (m_ok)
00074 {
00075 m_file.unlock();
00076 }
00077 }
00078
00079 private:
00080 File & m_file;
00081 bool m_ok;
00082 };
00083
00084 typedef blocxx::MultiProcessFileAppender app_t;
00085
00086 UInt64 kbytesToBytes(UInt64 max_size)
00087 {
00088 UInt64 const oneK = 1024;
00089 UInt64 const biggest = UInt64(-1);
00090 return(
00091 max_size == app_t::NO_MAX_LOG_SIZE ? biggest
00092 : max_size > biggest / oneK ? biggest
00093 : max_size * oneK
00094 );
00095 }
00096
00097 }
00098
00099 MultiProcessFileAppender::MultiProcessFileAppender(
00100 const StringArray& components,
00101 const StringArray& categories,
00102 const String & filename,
00103 const String& pattern,
00104 UInt64 maxFileSize,
00105 UInt32 maxBackupIndex
00106 )
00107 : LogAppender(components, categories, pattern)
00108 , m_filename(filename)
00109 , m_maxFileSize(kbytesToBytes(maxFileSize))
00110 , m_maxBackupIndex(maxBackupIndex)
00111 {
00112 m_log = FileSystem::openForAppendOrCreateFile(filename);
00113 m_lock = FileSystem::openOrCreateFile(filename + ".lock");
00114
00115 if (!m_log)
00116 {
00117 String msg = "Cannot create log file " + filename;
00118 BLOCXX_THROW(LoggerException, msg.c_str());
00119 }
00120 if (!m_lock)
00121 {
00122 String msg = "Cannot create lock file for log file " + filename + ".lock";
00123 BLOCXX_THROW(LoggerException, msg.c_str());
00124 }
00125 }
00126
00127 MultiProcessFileAppender::~MultiProcessFileAppender()
00128 {
00129 }
00130
00131 void MultiProcessFileAppender::doProcessLogMessage(
00132 const String& formattedMessage, const LogMessage& message) const
00133 {
00134
00135
00136 if (!m_log || !m_lock)
00137 {
00138 return;
00139 }
00140
00141 FileLock lock(m_lock);
00142 if (!lock.ok())
00143 {
00144 return;
00145 }
00146
00147 UInt64 size = m_log.size();
00148
00149 if (size >= m_maxFileSize)
00150 {
00151
00152 File f = FileSystem::openForAppendOrCreateFile(m_filename);
00153 f.swap(m_log);
00154 if (!m_log)
00155 {
00156 return;
00157 }
00158 size = m_log.size();
00159 }
00160
00161 String s = formattedMessage + "\n";
00162 m_log.write(s.c_str(), s.length());
00163 m_log.flush();
00164 size += s.length();
00165
00166
00167 if (size >= m_maxFileSize)
00168 {
00169
00170 m_log.close();
00171
00172 if (m_maxBackupIndex > 0)
00173 {
00174
00175 FileSystem::removeFile(m_filename + '.' + String(m_maxBackupIndex));
00176
00177
00178 for (UInt32 i = m_maxBackupIndex - 1; i >= 1; --i)
00179 {
00180 FileSystem::renameFile(m_filename + '.' + String(i), m_filename + '.' + String(i + 1));
00181 }
00182
00183 if (!FileSystem::renameFile(m_filename, m_filename + ".1"))
00184 {
00185
00186 return;
00187 }
00188 }
00189
00190
00191 File f = FileSystem::openForAppendOrCreateFile(m_filename);
00192 f.swap(m_log);
00193 }
00194 }
00195
00196 }
00197
00198
00199
00200