blocxx
MultiProcessFileAppender.cpp
Go to the documentation of this file.
1/*******************************************************************************
2* Copyright (C) 2005, Quest Software, 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* Quest Software, 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
38#include "blocxx/BLOCXX_config.h"
40#include "blocxx/Format.hpp"
41#include "blocxx/Logger.hpp"
42#include "blocxx/LogMessage.hpp"
43#include "blocxx/FileSystem.hpp"
44
45#include <fcntl.h>
46#ifdef BLOCXX_HAVE_SYS_STAT_H
47#include <sys/stat.h>
48#endif
49
50namespace BLOCXX_NAMESPACE
51{
52
53namespace
54{
55 using namespace blocxx;
56
57 class FileLock
58 {
59 public:
60 FileLock(File & file)
61 : m_file(file)
62 {
63 m_ok = file.getLock() == 0;
64 }
65
66 bool ok() const
67 {
68 return m_ok;
69 }
70
71 ~FileLock()
72 {
73 if (m_ok)
74 {
75 m_file.unlock(); // nowhere to report error if unlock fails...
76 }
77 }
78
79 private:
80 File & m_file;
81 bool m_ok;
82 };
83
84 typedef blocxx::MultiProcessFileAppender app_t;
85
86 UInt64 kbytesToBytes(UInt64 max_size)
87 {
88 UInt64 const oneK = 1024;
89 UInt64 const biggest = UInt64(-1); // largest possible UInt64
90 return(
91 max_size == app_t::NO_MAX_LOG_SIZE ? biggest
92 : max_size > biggest / oneK ? biggest
93 : max_size * oneK
94 );
95 }
96
97}
98
100 const StringArray& components,
101 const StringArray& categories,
102 const String & filename,
103 const String& pattern,
104 UInt64 maxFileSize,
105 UInt32 maxBackupIndex
106)
107 : LogAppender(components, categories, pattern)
108 , m_filename(filename)
109 , m_maxFileSize(kbytesToBytes(maxFileSize))
110 , m_maxBackupIndex(maxBackupIndex)
111{
113 m_lock = FileSystem::openOrCreateFile(filename + ".lock");
114
115 if (!m_log)
116 {
117 String msg = "Cannot create log file " + filename;
119 }
120 if (!m_lock)
121 {
122 String msg = "Cannot create lock file for log file " + filename + ".lock";
124 }
125}
126
130
132 const String& formattedMessage, const LogMessage& message) const
133{
134 // On error, we just return, since doProcessLogMessage should not throw
135
136 if (!m_log || !m_lock)
137 {
138 return;
139 }
140
141 FileLock lock(m_lock);
142 if (!lock.ok())
143 {
144 return;
145 }
146
147 UInt64 size = m_log.size();
148
149 if (size >= m_maxFileSize)
150 {
151 // Log file has been rotated
153 f.swap(m_log);
154 if (!m_log)
155 {
156 return;
157 }
158 size = m_log.size();
159 }
160
161 String s = formattedMessage + "\n";
162 m_log.write(s.c_str(), s.length());
163 m_log.flush();
164 size += s.length();
165
166 // handle log rotation
167 if (size >= m_maxFileSize)
168 {
169 // do the roll over
170 m_log.close();
171
172 if (m_maxBackupIndex > 0)
173 {
174 // delete the oldest file first, if it exists
176
177 // increment the numbers on all the files, if they exist
178 for (UInt32 i = m_maxBackupIndex - 1; i >= 1; --i)
179 {
181 }
182
184 {
185 // if we can't rename it, at least don't write to it anymore
186 return;
187 }
188 }
189
190 // open new log file
192 f.swap(m_log);
193 }
194}
195
196} // end namespace BLOCXX_NAMESPACE
197
198
199
200
#define BLOCXX_THROW(exType, msg)
Throw an exception using FILE and LINE.
The purpose of the File class is to provide an abstraction layer over the platform dependant function...
Definition File.hpp:55
int close()
Close the underlying file object.
Definition File.hpp:171
int flush()
Flush any buffered data to the file.
Definition File.hpp:185
size_t write(const void *bfr, size_t numberOfBytes, Int64 offset=-1L)
Write to the underlying file.
Definition File.hpp:127
void swap(File &x)
Definition File.hpp:98
UInt64 size() const
Current size of file.
Definition File.hpp:163
MultiProcessFileAppender(const StringArray &components, const StringArray &categories, const String &filename, const String &pattern, UInt64 maxFileSize, UInt32 maxBackupIndex)
All processes that log to filename must use the same values for maxFileSize and maxBackupIndex.
virtual void doProcessLogMessage(const String &formattedMessage, const LogMessage &message) const
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 File openForAppendOrCreateFile(const String &path)
Opens the file for the given name to append data or create if it does not exist.
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.
BLOCXX_COMMON_API File openOrCreateFile(const String &path)
Opens or creates the file for the given name.
Taken from RFC 1321.