1 // distribution boxbackup-0.11_trunk_2979 (svn version: 2979)
2 // Box Backup, http://www.boxbackup.org/
3 //
4 // Copyright (c) 2003-2010, Ben Summers and contributors.
5 // All rights reserved.
6 //
7 // Note that this project uses mixed licensing. Any file with this license
8 // attached, or where the code LICENSE-DUAL appears on the first line, falls
9 // under this license. See the file COPYING.txt for more information.
10 //
11 // This file is dual licensed. You may use and distribute it providing that you
12 // comply EITHER with the terms of the BSD license, OR the GPL license. It is
13 // not necessary to comply with both licenses, only one.
14 //
15 // The BSD license option follows:
16 //
17 // Redistribution and use in source and binary forms, with or without
18 // modification, are permitted provided that the following conditions are met:
19 //
20 // 1. Redistributions of source code must retain the above copyright
21 // notice, this list of conditions and the following disclaimer.
22 //
23 // 2. Redistributions in binary form must reproduce the above copyright
24 // notice, this list of conditions and the following disclaimer in the
25 // documentation and/or other materials provided with the distribution.
26 //
27 // 3. Neither the name of the Box Backup nor the names of its contributors may
28 // be used to endorse or promote products derived from this software without
29 // specific prior written permission.
30 //
31 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
32 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
35 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
36 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
38 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
40 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 //
42 // [http://en.wikipedia.org/wiki/BSD_licenses#3-clause_license_.28.22New_BSD_License.22.29]
43 //
44 // The GPL license option follows:
45 //
46 // This program is free software; you can redistribute it and/or
47 // modify it under the terms of the GNU General Public License
48 // as published by the Free Software Foundation; either version 2
49 // of the License, or (at your option) any later version.
50 //
51 // This program is distributed in the hope that it will be useful,
52 // but WITHOUT ANY WARRANTY; without even the implied warranty of
53 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
54 // GNU General Public License for more details.
55 //
56 // You should have received a copy of the GNU General Public License
57 // along with this program; if not, write to the Free Software
58 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
59 //
60 // [http://www.gnu.org/licenses/old-licenses/gpl-2.0.html#SEC4]
61 // --------------------------------------------------------------------------
62 //
63 // File
64 // Name: Logging.h
65 // Purpose: Generic logging core routines declarations and macros
66 // Created: 2006/12/16
67 //
68 // --------------------------------------------------------------------------
69
70 #ifndef LOGGING__H
71 #define LOGGING__H
72
73 #include <cerrno>
74 #include <cstring>
75 #include <iomanip>
76 #include <sstream>
77 #include <vector>
78
79 #include "FileStream.h"
80
81 #define BOX_LOG(level, stuff) \
82 { \
83 std::ostringstream _box_log_line; \
84 _box_log_line << stuff; \
85 Logging::Log(level, __FILE__, __LINE__, _box_log_line.str()); \
86 }
87
88 #define BOX_SYSLOG(level, stuff) \
89 { \
90 std::ostringstream _box_log_line; \
91 _box_log_line << stuff; \
92 Logging::LogToSyslog(level, __FILE__, __LINE__, _box_log_line.str()); \
93 }
94
95 #define BOX_FATAL(stuff) BOX_LOG(Log::FATAL, stuff)
96 #define BOX_ERROR(stuff) BOX_LOG(Log::ERROR, stuff)
97 #define BOX_WARNING(stuff) BOX_LOG(Log::WARNING, stuff)
98 #define BOX_NOTICE(stuff) BOX_LOG(Log::NOTICE, stuff)
99 #define BOX_INFO(stuff) BOX_LOG(Log::INFO, stuff)
100 #define BOX_TRACE(stuff) \
101 if (Logging::IsEnabled(Log::TRACE)) \
102 { BOX_LOG(Log::TRACE, stuff) }
103
104 #define BOX_SYS_ERRNO_MESSAGE(error_number, stuff) \
105 stuff << ": " << std::strerror(error_number) << \
106 " (" << error_number << ")"
107
108 #define BOX_FILE_MESSAGE(filename, message) \
109 message << ": " << filename
110
111 #define BOX_SYS_FILE_ERRNO_MESSAGE(filename, error_number, message) \
112 BOX_SYS_ERRNO_MESSAGE(error_number, BOX_FILE_MESSAGE(filename, message))
113
114 #define BOX_SYS_ERROR_MESSAGE(stuff) \
115 BOX_SYS_ERRNO_MESSAGE(errno, stuff)
116
117 #define BOX_LOG_SYS_WARNING(stuff) \
118 BOX_WARNING(BOX_SYS_ERROR_MESSAGE(stuff))
119 #define BOX_LOG_SYS_ERROR(stuff) \
120 BOX_ERROR(BOX_SYS_ERROR_MESSAGE(stuff))
121 #define BOX_LOG_SYS_ERRNO(error_number, stuff) \
122 BOX_ERROR(BOX_SYS_ERRNO_MESSAGE(error_number, stuff))
123 #define BOX_LOG_SYS_FATAL(stuff) \
124 BOX_FATAL(BOX_SYS_ERROR_MESSAGE(stuff))
125
126 #define THROW_SYS_ERROR_NUMBER(message, error_number, exception, subtype) \
127 THROW_EXCEPTION_MESSAGE(exception, subtype, \
128 BOX_SYS_ERRNO_MESSAGE(error_number, message))
129
130 #define THROW_SYS_ERROR(message, exception, subtype) \
131 THROW_SYS_ERROR_NUMBER(message, errno, exception, subtype)
132
133 #define THROW_SYS_FILE_ERROR(message, filename, exception, subtype) \
134 THROW_SYS_ERROR_NUMBER(BOX_FILE_MESSAGE(filename, message), \
135 errno, exception, subtype)
136
137 #define THROW_SYS_FILE_ERRNO(message, filename, error_number, exception, subtype) \
138 THROW_SYS_ERROR_NUMBER(BOX_FILE_MESSAGE(filename, message), \
139 error_number, exception, subtype)
140
141 #define THROW_FILE_ERROR(message, filename, exception, subtype) \
142 THROW_EXCEPTION_MESSAGE(exception, subtype, \
143 BOX_FILE_MESSAGE(filename, message))
144
GetNativeErrorMessage()145 inline std::string GetNativeErrorMessage()
146 {
147 #ifdef WIN32
148 return GetErrorMessage(GetLastError());
149 #else
150 std::ostringstream _box_log_line;
151 _box_log_line << std::strerror(errno) << " (" << errno << ")";
152 return _box_log_line.str();
153 #endif
154 }
155
156 #ifdef WIN32
157 #define BOX_LOG_WIN_ERROR(stuff) \
158 BOX_ERROR(stuff << ": " << GetErrorMessage(GetLastError()))
159 #define BOX_LOG_WIN_WARNING(stuff) \
160 BOX_WARNING(stuff << ": " << GetErrorMessage(GetLastError()))
161 #define BOX_LOG_WIN_ERROR_NUMBER(stuff, number) \
162 BOX_ERROR(stuff << ": " << GetErrorMessage(number))
163 #define BOX_LOG_WIN_WARNING_NUMBER(stuff, number) \
164 BOX_WARNING(stuff << ": " << GetErrorMessage(number))
165 #define BOX_LOG_NATIVE_ERROR(stuff) BOX_LOG_WIN_ERROR(stuff)
166 #define BOX_LOG_NATIVE_WARNING(stuff) BOX_LOG_WIN_WARNING(stuff)
167 #define BOX_WIN_ERRNO_MESSAGE(error_number, stuff) \
168 stuff << ": " << GetErrorMessage(error_number) << " (" << error_number << ")"
169 #define THROW_WIN_ERROR_NUMBER(message, error_number, exception, subtype) \
170 THROW_EXCEPTION_MESSAGE(exception, subtype, \
171 BOX_WIN_ERRNO_MESSAGE(error_number, message))
172 #define THROW_WIN_FILE_ERRNO(message, filename, error_number, exception, subtype) \
173 THROW_WIN_ERROR_NUMBER(BOX_FILE_MESSAGE(filename, message), \
174 error_number, exception, subtype)
175 #else
176 #define BOX_LOG_NATIVE_ERROR(stuff) BOX_LOG_SYS_ERROR(stuff)
177 #define BOX_LOG_NATIVE_WARNING(stuff) BOX_LOG_SYS_WARNING(stuff)
178 #endif
179
180 #define BOX_LOG_SOCKET_ERROR(_type, _name, _port, stuff) \
181 BOX_LOG_NATIVE_ERROR(stuff << " (type " << _type << ", name " << \
182 _name << ", port " << _port << ")")
183
184 #define BOX_FORMAT_HEX32(number) \
185 std::hex << \
186 std::showbase << \
187 std::internal << \
188 std::setw(10) << \
189 std::setfill('0') << \
190 (number) << \
191 std::dec
192
193 #define BOX_FORMAT_ACCOUNT(accno) \
194 BOX_FORMAT_HEX32(accno)
195
196 #define BOX_FORMAT_OBJECTID(objectid) \
197 std::hex << \
198 std::showbase << \
199 (objectid) << \
200 std::dec
201
202 #define BOX_FORMAT_TIMESPEC(timespec) \
203 timespec.tv_sec << \
204 std::setw(6) << \
205 timespec.tv_usec
206
207 #undef ERROR
208
209 namespace Log
210 {
211 enum Level
212 {
213 NOTHING = 1,
214 FATAL,
215 ERROR,
216 WARNING,
217 NOTICE,
218 INFO,
219 TRACE,
220 EVERYTHING,
221 INVALID = -1
222 };
223 }
224
225 // --------------------------------------------------------------------------
226 //
227 // Class
228 // Name: Logger
229 // Purpose: Abstract base class for log targets
230 // Created: 2006/12/16
231 //
232 // --------------------------------------------------------------------------
233
234 class Logger
235 {
236 private:
237 Log::Level mCurrentLevel;
238
239 public:
240 Logger();
241 Logger(Log::Level level);
242 virtual ~Logger();
243
244 virtual bool Log(Log::Level level, const std::string& rFile,
245 int line, std::string& rMessage) = 0;
246
Filter(Log::Level level)247 void Filter(Log::Level level)
248 {
249 mCurrentLevel = level;
250 }
251
252 virtual const char* GetType() = 0;
GetLevel()253 Log::Level GetLevel() { return mCurrentLevel; }
254
255 virtual void SetProgramName(const std::string& rProgramName) = 0;
256 };
257
258 // --------------------------------------------------------------------------
259 //
260 // Class
261 // Name: Console
262 // Purpose: Console logging target
263 // Created: 2006/12/16
264 //
265 // --------------------------------------------------------------------------
266
267 class Console : public Logger
268 {
269 private:
270 static bool sShowTag;
271 static bool sShowTime;
272 static bool sShowTimeMicros;
273 static bool sShowPID;
274 static std::string sTag;
275
276 public:
277 virtual bool Log(Log::Level level, const std::string& rFile,
278 int line, std::string& rMessage);
GetType()279 virtual const char* GetType() { return "Console"; }
280 virtual void SetProgramName(const std::string& rProgramName);
281
282 static void SetShowTag(bool enabled);
283 static void SetShowTime(bool enabled);
284 static void SetShowTimeMicros(bool enabled);
285 static void SetShowPID(bool enabled);
286 };
287
288 // --------------------------------------------------------------------------
289 //
290 // Class
291 // Name: Syslog
292 // Purpose: Syslog (or Windows Event Viewer) logging target
293 // Created: 2006/12/16
294 //
295 // --------------------------------------------------------------------------
296
297 class Syslog : public Logger
298 {
299 private:
300 std::string mName;
301 int mFacility;
302
303 public:
304 Syslog();
305 virtual ~Syslog();
306
307 virtual bool Log(Log::Level level, const std::string& rFile,
308 int line, std::string& rMessage);
GetType()309 virtual const char* GetType() { return "Syslog"; }
310 virtual void SetProgramName(const std::string& rProgramName);
311 virtual void SetFacility(int facility);
312 static int GetNamedFacility(const std::string& rFacility);
313 };
314
315 // --------------------------------------------------------------------------
316 //
317 // Class
318 // Name: Logging
319 // Purpose: Static logging helper, keeps track of enabled loggers
320 // and distributes log messages to them.
321 // Created: 2006/12/16
322 //
323 // --------------------------------------------------------------------------
324
325 class Logging
326 {
327 private:
328 static std::vector<Logger*> sLoggers;
329 static bool sLogToSyslog, sLogToConsole;
330 static std::string sContext;
331 static bool sContextSet;
332 static Console* spConsole;
333 static Syslog* spSyslog;
334 static Log::Level sGlobalLevel;
335 static Logging sGlobalLogging;
336 static std::string sProgramName;
337
338 public:
339 Logging ();
340 ~Logging();
341 static void ToSyslog (bool enabled);
342 static void ToConsole (bool enabled);
343 static void FilterSyslog (Log::Level level);
344 static void FilterConsole (Log::Level level);
345 static void Add (Logger* pNewLogger);
346 static void Remove (Logger* pOldLogger);
347 static void Log(Log::Level level, const std::string& rFile,
348 int line, const std::string& rMessage);
349 static void LogToSyslog(Log::Level level, const std::string& rFile,
350 int line, const std::string& rMessage);
351 static void SetContext(std::string context);
352 static void ClearContext();
SetGlobalLevel(Log::Level level)353 static void SetGlobalLevel(Log::Level level) { sGlobalLevel = level; }
GetGlobalLevel()354 static Log::Level GetGlobalLevel() { return sGlobalLevel; }
355 static Log::Level GetNamedLevel(const std::string& rName);
IsEnabled(Log::Level level)356 static bool IsEnabled(Log::Level level)
357 {
358 return (int)sGlobalLevel >= (int)level;
359 }
360 static void SetProgramName(const std::string& rProgramName);
GetProgramName()361 static std::string GetProgramName() { return sProgramName; }
362 static void SetFacility(int facility);
363
364 class Guard
365 {
366 private:
367 Log::Level mOldLevel;
368
369 public:
Guard(Log::Level newLevel)370 Guard(Log::Level newLevel)
371 {
372 mOldLevel = Logging::GetGlobalLevel();
373 Logging::SetGlobalLevel(newLevel);
374 }
~Guard()375 ~Guard()
376 {
377 Logging::SetGlobalLevel(mOldLevel);
378 }
379 };
380
381 class Tagger
382 {
383 private:
384 std::string mOldTag;
385
386 public:
Tagger(const std::string & rTempTag)387 Tagger(const std::string& rTempTag)
388 {
389 mOldTag = Logging::GetProgramName();
390 Logging::SetProgramName(mOldTag + " " + rTempTag);
391 }
~Tagger()392 ~Tagger()
393 {
394 Logging::SetProgramName(mOldTag);
395 }
396 };
397 };
398
399 class FileLogger : public Logger
400 {
401 private:
402 FileStream mLogFile;
FileLogger(const FileLogger & forbidden)403 FileLogger(const FileLogger& forbidden)
404 : mLogFile("") { /* do not call */ }
405
406 public:
FileLogger(const std::string & rFileName,Log::Level Level)407 FileLogger(const std::string& rFileName, Log::Level Level)
408 : Logger(Level),
409 mLogFile(rFileName, O_WRONLY | O_CREAT | O_APPEND)
410 { }
411
412 virtual bool Log(Log::Level Level, const std::string& rFile,
413 int Line, std::string& rMessage);
414
GetType()415 virtual const char* GetType() { return "FileLogger"; }
SetProgramName(const std::string & rProgramName)416 virtual void SetProgramName(const std::string& rProgramName) { }
417 };
418
419 class HideExceptionMessageGuard
420 {
421 public:
HideExceptionMessageGuard()422 HideExceptionMessageGuard()
423 {
424 mOldHiddenState = sHiddenState;
425 sHiddenState = true;
426 }
~HideExceptionMessageGuard()427 ~HideExceptionMessageGuard()
428 {
429 sHiddenState = mOldHiddenState;
430 }
ExceptionsHidden()431 static bool ExceptionsHidden() { return sHiddenState; }
432
433 private:
434 static bool sHiddenState;
435 bool mOldHiddenState;
436 };
437
438 std::string PrintEscapedBinaryData(const std::string& rInput);
439
440 #endif // LOGGING__H
441