blocxx
FileAppender.cpp
Go to the documentation of this file.
1/*******************************************************************************
2* Copyright (C) 2005, Vintela, Inc. All rights reserved.
3* Copyright (C) 2006, Novell, Inc. All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without
6* modification, are permitted provided that the following conditions are met:
7*
8* * Redistributions of source code must retain the above copyright notice,
9* this list of conditions and the following disclaimer.
10* * Redistributions in binary form must reproduce the above copyright
11* notice, this list of conditions and the following disclaimer in the
12* documentation and/or other materials provided with the distribution.
13* * Neither the name of
14* Vintela, Inc.,
15* nor Novell, Inc.,
16* nor the names of its contributors or employees may be used to
17* endorse or promote products derived from this software without
18* specific prior written permission.
19*
20* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30* POSSIBILITY OF SUCH DAMAGE.
31*******************************************************************************/
32
33
37
38#include "blocxx/BLOCXX_config.h"
40#include "blocxx/Format.hpp"
41#include "blocxx/Logger.hpp"
42#include "blocxx/LogMessage.hpp"
43#include "blocxx/Mutex.hpp"
44#include "blocxx/MutexLock.hpp"
45#include "blocxx/FileSystem.hpp"
47
48#include <fstream>
49
50namespace BLOCXX_NAMESPACE
51{
52
55 const StringArray& categories,
56 const char* filename,
57 const String& pattern,
58 UInt64 maxFileSize,
59 unsigned int maxBackupIndex,
60 bool flushLog)
61 : LogAppender(components, categories, pattern)
62 , m_filename(filename)
63 , m_maxFileSize(maxFileSize)
64 , m_maxBackupIndex(maxBackupIndex)
65 , m_flushLog(flushLog)
66{
67 m_log.open(m_filename.c_str(), std::ios::out | std::ios::app);
68 if (!m_log)
69 {
70 BLOCXX_THROW(LoggerException, Format("FileAppender: Unable to open file: %1", m_filename).toString().c_str() );
71 }
72}
73
78
80namespace
81{
83}
84void
85FileAppender::doProcessLogMessage(const String& formattedMessage, const LogMessage& message) const
86{
87 MutexLock lock(fileGuard);
88
89 // take into account external log rotators, if the file we have open no longer exists, then reopen it.
90 if (!FileSystem::exists(m_filename.c_str()))
91 {
92 // make sure we can re-open the log file before we close it
93 std::ofstream temp;
94 temp.open(m_filename.c_str(), std::ios::out | std::ios::app);
95 if (temp)
96 {
97 temp.close();
98 m_log.close();
99 m_log.open(m_filename.c_str(), std::ios::out | std::ios::app);
100 }
101 else
102 {
103 m_log << "FileAppender::doProcessLogMessage(): " << m_filename << " no longer exists and re-opening it failed!\n";
104 }
105 }
106
107 if (!m_log)
108 {
109 // hmm, not much we can do here. doProcessLogMessage can't throw.
110 return;
111 }
112
113 m_log.write(formattedMessage.c_str(), formattedMessage.length());
114 m_log << '\n';
115
116 if (m_flushLog)
117 {
118 m_log.flush();
119 }
120
121 // handle log rotation
122 if (m_maxFileSize != NO_MAX_LOG_SIZE && m_log.tellp() >= static_cast<std::streampos>(m_maxFileSize * 1024))
123 {
124 // do the roll over
125
126 if (m_maxBackupIndex > 0)
127 {
128 // Delete the oldest file first - this may or may not exist; we try anyway.
130
131 // increment the numbers on all the files - some may exist or not, but try anyway.
132 for (unsigned int i = m_maxBackupIndex - 1; i >= 1; --i)
133 {
134 FileSystem::renameFile(m_filename + '.' + String(i), m_filename + '.' + String(i + 1));
135 }
136
138 {
139 // if we can't rename it, avoid truncating it.
140 m_log << "FileAppender::doProcessLogMessage(): Failed to rename " << m_filename << " to " << m_filename + ".1! Logging to this file STOPPED!\n";
141 m_log.close();
142 return;
143 }
144 }
145
146 // make sure we can re-open the log file before we close it
147 std::ofstream temp;
148 temp.open(m_filename.c_str(), std::ios::out | std::ios::app);
149 if (temp)
150 {
151 temp.close();
152 m_log.close();
153 // truncate the existing one
154 m_log.open(m_filename.c_str(), std::ios_base::out | std::ios_base::trunc);
155 }
156 else
157 {
158 m_log << "FileAppender::doProcessLogMessage(): Failed to open " << m_filename << "! Logging to this file STOPPED!\n";
159 m_log.close();
160 }
161 }
162}
163
165const GlobalString FileAppender::STR_DEFAULT_MESSAGE_PATTERN = BLOCXX_GLOBAL_STRING_INIT("%d{%a %b %d %H:%M:%S %Y} [%t]: %m");
166
167} // end namespace BLOCXX_NAMESPACE
168
169
170
171
#define BLOCXX_THROW(exType, msg)
Throw an exception using FILE and LINE.
#define BLOCXX_GLOBAL_MUTEX_INIT()
#define BLOCXX_GLOBAL_STRING_INIT(str)
static const GlobalString STR_DEFAULT_MESSAGE_PATTERN
static UInt64 const NO_MAX_LOG_SIZE
virtual void doProcessLogMessage(const String &formattedMessage, const LogMessage &message) const
FileAppender(const StringArray &components, const StringArray &categories, const char *filename, const String &pattern, UInt64 maxFileSize, unsigned int maxBackupIndex, bool flushLog=true)
LogAppender(const StringArray &components=ALL_COMPONENTS, const StringArray &categories=ALL_CATEGORIES, const String &pattern=STR_TTCC_MESSAGE_FORMAT)
This String class is an abstract data type that represents as NULL terminated string of characters.
Definition String.hpp:67
const char * c_str() const
Definition String.cpp:905
size_t length() const
Definition String.cpp:354
BLOCXX_COMMON_API bool exists(const String &path)
BLOCXX_COMMON_API bool removeFile(const String &path)
Remove the given file.
BLOCXX_COMMON_API bool renameFile(const String &oldFileName, const String &newFileName)
Rename the given file to the new name.
Taken from RFC 1321.
LazyGlobal< String, char const *const > GlobalString
Array< String > StringArray
Definition CommonFwd.hpp:73
LazyGlobal< Mutex, int, GlobalMutexFactory > GlobalMutex