1 /*
2    Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 #include <ndb_global.h>
26 
27 #include "Logger.hpp"
28 
29 #include <LogHandler.hpp>
30 #include <ConsoleLogHandler.hpp>
31 #include <FileLogHandler.hpp>
32 #include "LogHandlerList.hpp"
33 
34 #ifdef _WIN32
35 #include "EventLogHandler.hpp"
36 #else
37 #include <SysLogHandler.hpp>
38 #endif
39 
40 #include <portlib/ndb_localtime.h>
41 
42 const char* Logger::LoggerLevelNames[] = { "ON      ",
43 					   "DEBUG   ",
44 					   "INFO    ",
45 					   "WARNING ",
46 					   "ERROR   ",
47 					   "CRITICAL",
48 					   "ALERT   ",
49 					   "ALL     "
50 					 };
Logger()51 Logger::Logger() :
52   m_pCategory("Logger"),
53   m_pConsoleHandler(NULL),
54   m_pFileHandler(NULL),
55   m_pSyslogHandler(NULL)
56 {
57   m_pHandlerList = new LogHandlerList();
58   m_mutex= NdbMutex_Create();
59   m_handler_mutex= NdbMutex_Create();
60   disable(LL_ALL);
61   enable(LL_ON);
62   enable(LL_INFO);
63 }
64 
~Logger()65 Logger::~Logger()
66 {
67   removeAllHandlers();
68   delete m_pHandlerList;
69   NdbMutex_Destroy(m_handler_mutex);
70   NdbMutex_Destroy(m_mutex);
71 }
72 
73 void
setCategory(const char * pCategory)74 Logger::setCategory(const char* pCategory)
75 {
76   Guard g(m_mutex);
77   m_pCategory = pCategory;
78 }
79 
80 bool
createConsoleHandler(NdbOut & out)81 Logger::createConsoleHandler(NdbOut &out)
82 {
83   Guard g(m_handler_mutex);
84 
85   if (m_pConsoleHandler)
86     return true; // Ok, already exist
87 
88   LogHandler* log_handler = new ConsoleLogHandler(out);
89   if (!log_handler)
90     return false;
91 
92   if (!addHandler(log_handler))
93   {
94     delete log_handler;
95     return false;
96   }
97 
98   m_pConsoleHandler = log_handler;
99   return true;
100 }
101 
102 void
removeConsoleHandler()103 Logger::removeConsoleHandler()
104 {
105   Guard g(m_handler_mutex);
106   if (removeHandler(m_pConsoleHandler))
107   {
108     m_pConsoleHandler = NULL;
109   }
110 }
111 
112 bool
createEventLogHandler(const char * source_name)113 Logger::createEventLogHandler(const char* source_name)
114 {
115 #ifdef _WIN32
116   Guard g(m_handler_mutex);
117 
118   LogHandler* log_handler = new EventLogHandler(source_name);
119   if (!log_handler)
120     return false;
121 
122   if (!addHandler(log_handler))
123   {
124     delete log_handler;
125     return false;
126   }
127 
128   return true;
129 #else
130   return false;
131 #endif
132 }
133 
134 bool
createFileHandler(char * filename)135 Logger::createFileHandler(char*filename)
136 {
137   Guard g(m_handler_mutex);
138 
139   if (m_pFileHandler)
140     return true; // Ok, already exist
141 
142   LogHandler* log_handler = new FileLogHandler(filename);
143   if (!log_handler)
144     return false;
145 
146   if (!addHandler(log_handler))
147   {
148     delete log_handler;
149     return false;
150   }
151 
152   m_pFileHandler = log_handler;
153   return true;
154 }
155 
156 void
removeFileHandler()157 Logger::removeFileHandler()
158 {
159   Guard g(m_handler_mutex);
160   if (removeHandler(m_pFileHandler))
161   {
162     m_pFileHandler = NULL;
163   }
164 }
165 
166 bool
createSyslogHandler()167 Logger::createSyslogHandler()
168 {
169 #ifdef _WIN32
170   return false;
171 #else
172   Guard g(m_handler_mutex);
173 
174   if (m_pSyslogHandler)
175     return true; // Ok, already exist
176 
177   LogHandler* log_handler = new SysLogHandler();
178   if (!log_handler)
179     return false;
180 
181   if (!addHandler(log_handler))
182   {
183     delete log_handler;
184     return false;
185   }
186 
187   m_pSyslogHandler = log_handler;
188   return true;
189 #endif
190 }
191 
192 void
removeSyslogHandler()193 Logger::removeSyslogHandler()
194 {
195   Guard g(m_handler_mutex);
196   if (removeHandler(m_pSyslogHandler))
197   {
198     m_pSyslogHandler = NULL;
199   }
200 }
201 
202 bool
addHandler(LogHandler * pHandler)203 Logger::addHandler(LogHandler* pHandler)
204 {
205   Guard g(m_mutex);
206   assert(pHandler != NULL);
207 
208   if (!pHandler->is_open() &&
209       !pHandler->open())
210   {
211     // Failed to open
212     return false;
213   }
214 
215   if (!m_pHandlerList->add(pHandler))
216     return false;
217 
218   return true;
219 }
220 
221 
222 bool
removeHandler(LogHandler * pHandler)223 Logger::removeHandler(LogHandler* pHandler)
224 {
225   Guard g(m_mutex);
226   int rc = false;
227   if (pHandler != NULL)
228   {
229     if (pHandler == m_pConsoleHandler)
230       m_pConsoleHandler= NULL;
231     if (pHandler == m_pFileHandler)
232       m_pFileHandler= NULL;
233     if (pHandler == m_pSyslogHandler)
234       m_pSyslogHandler= NULL;
235 
236     rc = m_pHandlerList->remove(pHandler);
237   }
238 
239   return rc;
240 }
241 
242 void
removeAllHandlers()243 Logger::removeAllHandlers()
244 {
245   Guard g(m_mutex);
246   m_pHandlerList->removeAll();
247 
248   m_pConsoleHandler= NULL;
249   m_pFileHandler= NULL;
250   m_pSyslogHandler= NULL;
251 }
252 
253 bool
isEnable(LoggerLevel logLevel) const254 Logger::isEnable(LoggerLevel logLevel) const
255 {
256   Guard g(m_mutex);
257   if (logLevel == LL_ALL)
258   {
259     for (unsigned i = 1; i < MAX_LOG_LEVELS; i++)
260       if (!m_logLevels[i])
261 	return false;
262     return true;
263   }
264   return m_logLevels[logLevel];
265 }
266 
267 void
enable(LoggerLevel logLevel)268 Logger::enable(LoggerLevel logLevel)
269 {
270   Guard g(m_mutex);
271   if (logLevel == LL_ALL)
272   {
273     for (unsigned i = 0; i < MAX_LOG_LEVELS; i++)
274     {
275       m_logLevels[i] = true;
276     }
277   }
278   else
279   {
280     m_logLevels[logLevel] = true;
281   }
282 }
283 
284 void
enable(LoggerLevel fromLogLevel,LoggerLevel toLogLevel)285 Logger::enable(LoggerLevel fromLogLevel, LoggerLevel toLogLevel)
286 {
287   Guard g(m_mutex);
288   if (fromLogLevel > toLogLevel)
289   {
290     LoggerLevel tmp = toLogLevel;
291     toLogLevel = fromLogLevel;
292     fromLogLevel = tmp;
293   }
294 
295   for (int i = fromLogLevel; i <= toLogLevel; i++)
296   {
297     m_logLevels[i] = true;
298   }
299 }
300 
301 void
disable(LoggerLevel logLevel)302 Logger::disable(LoggerLevel logLevel)
303 {
304   Guard g(m_mutex);
305   if (logLevel == LL_ALL)
306   {
307     for (unsigned i = 0; i < MAX_LOG_LEVELS; i++)
308     {
309       m_logLevels[i] = false;
310     }
311   }
312   else
313   {
314     m_logLevels[logLevel] = false;
315   }
316 }
317 
318 void
alert(const char * pMsg,...) const319 Logger::alert(const char* pMsg, ...) const
320 {
321   va_list ap;
322   va_start(ap, pMsg);
323   log(LL_ALERT, pMsg, ap);
324   va_end(ap);
325 }
326 
327 void
critical(const char * pMsg,...) const328 Logger::critical(const char* pMsg, ...) const
329 {
330   va_list ap;
331   va_start(ap, pMsg);
332   log(LL_CRITICAL, pMsg, ap);
333   va_end(ap);
334 }
335 void
error(const char * pMsg,...) const336 Logger::error(const char* pMsg, ...) const
337 {
338   va_list ap;
339   va_start(ap, pMsg);
340   log(LL_ERROR, pMsg, ap);
341   va_end(ap);
342 }
343 void
warning(const char * pMsg,...) const344 Logger::warning(const char* pMsg, ...) const
345 {
346   va_list ap;
347   va_start(ap, pMsg);
348   log(LL_WARNING, pMsg, ap);
349   va_end(ap);
350 }
351 
352 void
info(const char * pMsg,...) const353 Logger::info(const char* pMsg, ...) const
354 {
355   va_list ap;
356   va_start(ap, pMsg);
357   log(LL_INFO, pMsg, ap);
358   va_end(ap);
359 }
360 
361 void
debug(const char * pMsg,...) const362 Logger::debug(const char* pMsg, ...) const
363 {
364   va_list ap;
365   va_start(ap, pMsg);
366   log(LL_DEBUG, pMsg, ap);
367   va_end(ap);
368 }
369 
370 void
log(LoggerLevel logLevel,const char * pMsg,va_list ap) const371 Logger::log(LoggerLevel logLevel, const char* pMsg, va_list ap) const
372 {
373   Guard g(m_mutex);
374   if (m_logLevels[LL_ON] && m_logLevels[logLevel])
375   {
376     char buf[MAX_LOG_MESSAGE_SIZE];
377     BaseString::vsnprintf(buf, sizeof(buf), pMsg, ap);
378     LogHandler* pHandler = NULL;
379     while ( (pHandler = m_pHandlerList->next()) != NULL)
380     {
381       pHandler->append(m_pCategory, logLevel, buf);
382     }
383   }
384 }
385 
setRepeatFrequency(unsigned val)386 void Logger::setRepeatFrequency(unsigned val)
387 {
388   LogHandler* pHandler;
389   while ((pHandler = m_pHandlerList->next()) != NULL)
390   {
391     pHandler->setRepeatFrequency(val);
392   }
393 }
394 
395 
396 void
format_timestamp(const time_t epoch,char * str,size_t len)397 Logger::format_timestamp(const time_t epoch,
398                          char* str, size_t len)
399 {
400   assert(len > 0); // Assume buffer has size
401 
402   // convert to local timezone
403   tm tm_buf;
404   if (ndb_localtime_r(&epoch, &tm_buf) == NULL)
405   {
406     // Failed to convert to local timezone.
407     // Fill with bogus time stamp value in order
408     // to ensure buffer can be safely printed
409     strncpy(str, "2001-01-01 00:00:00", len);
410     str[len-1] = 0;
411     return;
412   }
413 
414   // Print the broken down time in timestamp format
415   // to the string buffer
416   BaseString::snprintf(str, len,
417                        "%d-%.2d-%.2d %.2d:%.2d:%.2d",
418                        tm_buf.tm_year + 1900,
419                        tm_buf.tm_mon + 1, //month is [0,11]. +1 -> [1,12]
420                        tm_buf.tm_mday,
421                        tm_buf.tm_hour,
422                        tm_buf.tm_min,
423                        tm_buf.tm_sec);
424   str[len-1] = 0;
425   return;
426 }
427