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