1 // -*- c++ -*-
2 //------------------------------------------------------------------------------
3 // Logger_Impl.h
4 //------------------------------------------------------------------------------
5 // $Id: Logger_Impl.h,v 1.12 2012/05/21 03:20:39 vlg Exp $
6 //------------------------------------------------------------------------------
7 // Copyright (c) 2001 Vladislav Grinchenko
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Library General Public
11 // License as published by the Free Software Foundation; either
12 // version 2 of the License, or (at your option) any later version.
13 //------------------------------------------------------------------------------
14 #ifndef LOGGER_IMPL_H
15 #define LOGGER_IMPL_H
16
17 #include <errno.h>
18 #include <string>
19 #include <stdio.h>
20
21 #if defined(sun)
22 #include <sys/varargs.h> // va_list
23 #endif
24
25 #if defined (__CYGWIN32__) || defined (__NetBSD__) || defined (WIN32) || defined (__GLIBC__)
26 # include <stdarg.h>
27 #endif
28
29 #if defined(WIN32)
30 # include <winsock2.h> /* select(3) */
31 #endif
32
33 /* Also defined in winsock.h, winsock2.h, gmon.h and in cygwin's sys/types
34 */
35 #if !defined ( _BSDTYPES_DEFINED )
36
37 typedef unsigned char u_char;
38 typedef unsigned short u_short;
39 typedef unsigned int u_int;
40 typedef unsigned long u_long;
41
42 #define _BSDTYPES_DEFINED
43
44 #endif /* ! def _BSDTYPES_DEFINED */
45
46 using std::string;
47 using std::ostream;
48
49 #include "assa/LogMask.h"
50
51 /** Sort out WIN32/mingw oddities
52 */
53 #if defined (WIN32)
54
55 typedef SOCKET handler_t;
56 #define BAD_HANDLER INVALID_SOCKET
57
58 /** Map win32 error names
59 */
60 #define EINPROGRESS WSAEINPROGRESS /* A blocking Winsock call is in
61 * progress, or the service provider
62 * is still process a callback function.
63 */
64 #define EWOULDBLOCK WSAEWOULDBLOCK /* The socket is marked as nonblocking
65 * and the connection cannot be completed
66 * immediately.
67 */
68 #define EISCONN WSAEISCONN
69
70 #define ENOTSOCK WSAENOTSOCK /* The descriptor is not a socket.
71 */
72 #define ECONNREFUSED WSAECONNREFUSED /* The attempt to connect was
73 * forcefully rejected.
74 */
75 #define ETIMEDOUT WSAETIMEDOUT /* An attempt to connect timed out
76 * without establishing connection.
77 */
78 #else /*--- POSIX ---*/
79
80 #define BAD_HANDLER -1
81 typedef int handler_t;
82
83 #endif // ifdef WIN32
84
85
86 namespace ASSA {
87
88 class Reactor;
89
90 //---------------------------------------------------------------------------
91 // Utilities that don't fit anywhere else
92 //---------------------------------------------------------------------------
93
94 /** Detect socket() error in a portable way.
95 *
96 * @return true if socket is in valid range;
97 * false otherwise.
98 */
is_valid_handler(handler_t socket_)99 inline bool is_valid_handler (handler_t socket_)
100 {
101 return (socket_ != BAD_HANDLER);
102 }
103
104 /** Set socket descriptor to invalid value in a portable way.
105 * socket_ is set to the value out of valid range.
106 */
disable_handler(handler_t & socket_)107 inline void disable_handler (handler_t& socket_)
108 {
109 socket_ = BAD_HANDLER;
110 }
111
112 /** Fetch error number in a portable way.
113 */
get_errno()114 inline int get_errno ()
115 {
116 int myerrno;
117 #if defined (WIN32)
118 myerrno = WSAGetLastError ();
119 #else
120 myerrno = errno;
121 #endif
122 return myerrno;
123 }
124
125 /** Set error number in a portable way.
126 */
set_errno(int new_errno_)127 inline void set_errno (int new_errno_)
128 {
129 #if defined (WIN32)
130 WSASetLastError (new_errno_);
131 #else
132 errno = new_errno_;
133 #endif
134 }
135
136 //---------------------------------------------------------------------------
137 // Class Logger_Impl
138 //---------------------------------------------------------------------------
139
140 class Logger_Impl {
141 public:
142 /**
143 Maximum length of the formatted message. The size is selected
144 based on the maximum number of bytes transmitted through Socketbuf
145 which is 1416. This is at most the bytes dumped with MemDump -
146 (1416/16 + 2) * 74 = 6660. See MemDump.cpp comments for details.
147 */
148 static const unsigned int LOGGER_MAXLINE = 6660;
149
150 public:
151 Logger_Impl ();
~Logger_Impl()152 virtual ~Logger_Impl () { /* empty */ }
153
enable_group(Group g_)154 void enable_group (Group g_) { m_groups |= g_; }
disable_group(Group g_)155 void disable_group (Group g_) { m_groups &= ~g_; }
156
enable_groups(u_long g_)157 void enable_groups (u_long g_) { m_groups |= g_; }
disable_groups(u_long g_)158 void disable_groups (u_long g_) { m_groups &= ~g_; }
159
enable_all_groups(void)160 void enable_all_groups (void) { m_groups = ASSA::ALL; }
disable_all_groups(void)161 void disable_all_groups (void) { m_groups = 0; }
162
group_enabled(Group g_)163 bool group_enabled (Group g_) const { return (m_groups & g_); }
164
enable_timestamp(void)165 void enable_timestamp (void) { m_tmflg = true; }
disable_timestamp(void)166 void disable_timestamp (void) { m_tmflg = false; }
timestamp_enabled(void)167 bool timestamp_enabled (void) const { return m_tmflg; }
set_timezone(int zone_)168 void set_timezone (int zone_) { m_tz = zone_; }
169
set_indent_step(u_short step_)170 void set_indent_step (u_short step_) { m_indent_step = step_; }
get_indent_step(void)171 u_short get_indent_step (void) const { return m_indent_step; }
172
173 /// Open StdErr Logger
174 virtual int log_open (u_long groups_);
175
176 /// Open File Logger
177 virtual int log_open (const char* logfname_,
178 u_long groups_,
179 u_long maxsize_);
180
181 /// Open connection with Log Server
182 virtual int log_open (const char* appname_,
183 const char* logfname_,
184 u_long groups_,
185 u_long maxsize_,
186 Reactor* reactor_);
187
188 virtual int log_close (void) = 0;
log_resync(void)189 virtual void log_resync (void) { /* empty */ }
190
191 virtual int log_msg (Group g_,
192 size_t indent_level_,
193 const string& func_name_,
194 size_t expected_sz_,
195 const char* fmt_,
196 va_list) = 0;
197
198 virtual int log_func (Group g_,
199 size_t indent_level_,
200 const string& func_name_,
201 marker_t type_) = 0;
202 protected:
203 virtual u_short add_timestamp (ostream& sink_);
204 virtual u_short indent_func_name (ostream& sink_,
205 const string& funcname_,
206 size_t indent_level_,
207 marker_t type_);
208
209 /** Format and put the message in the buffer. If expected size
210 is smaller then LOGGER_MAXLINE, formatted message is written
211 to the static buffer and release_ is set to false.
212 Otherwise, this function allocates a buffer on the heap big
213 enough to hold the message and set release_ to true. In this
214 case caller is responsible for releasing the memory by calling
215 delete [].
216
217 @param expected_sz_ Expected size of the formatted message
218 @param fmt_ printf()-like format string
219 @param vap_ variable argument parameters list
220 @param release_ [OUT] if true, caller is responsible for memory
221 deallocation.
222 @return Pointer to the formatted message buffer. If formatting
223 failed, NULL is returned.
224 */
225 char* format_msg (size_t expected_sz_,
226 const char* fmt_,
227 va_list vap_,
228 bool& release_);
229
230 protected:
231 /// Static buffer for formatted message
232 static char m_msgbuf [LOGGER_MAXLINE];
233
234 /// Indentation step
235 u_short m_indent_step;
236
237 /// Enabled groups
238 u_long m_groups;
239
240 /// Log file name
241 string m_logfname;
242
243 /// Timestamp on/off flag
244 bool m_tmflg;
245
246 /// Timezone: 0-GMT, 1-Local
247 int m_tz;
248 };
249
250 inline
251 Logger_Impl::
Logger_Impl()252 Logger_Impl ()
253 : m_indent_step (1),
254 m_groups (0),
255 m_tmflg (false),
256 m_tz (1)
257 {
258 /* no-op */
259 }
260
261 inline int
262 Logger_Impl::
log_open(u_long)263 log_open (u_long /* groups_ */)
264 {
265 errno = ENOSYS;
266 return -1;
267 }
268
269 inline int
270 Logger_Impl::
log_open(const char *,u_long,u_long)271 log_open (const char*, /* logfname_ */
272 u_long, /* groups_ */
273 u_long /* maxsize_ */)
274 {
275 errno = ENOSYS;
276 return -1;
277 }
278
279 inline int
280 Logger_Impl::
log_open(const char *,const char *,u_long,u_long,Reactor *)281 log_open (const char*, /* appname_ */
282 const char*, /* logfname_ */
283 u_long, /* groups_ */
284 u_long, /* maxsize_ */
285 Reactor* /* reactor_ */)
286 {
287 errno = ENOSYS;
288 return -1;
289 }
290
291 } // end namespace ASSA
292
293 #endif /* LOGGER_IMPL_H */
294