1 /*
2    Copyright (C) 2003-2006, 2008 MySQL AB
3     All rights reserved. Use is subject to license terms.
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License, version 2.0,
7    as published by the Free Software Foundation.
8 
9    This program is also distributed with certain software (including
10    but not limited to OpenSSL) that is licensed under separate terms,
11    as designated in a particular file or component or in included license
12    documentation.  The authors of MySQL hereby grant you an additional
13    permission to link the program and your derivative works with the
14    separately licensed software that they have included with MySQL.
15 
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License, version 2.0, for more details.
20 
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
24 */
25 
26 #include "LogHandler.hpp"
27 
28 #include <NdbTick.h>
29 
30 //
31 // PUBLIC
32 //
LogHandler()33 LogHandler::LogHandler() :
34   m_pDateTimeFormat("%d-%.2d-%.2d %.2d:%.2d:%.2d"),
35   m_errorCode(0),
36   m_errorStr(NULL)
37 {
38   m_max_repeat_frequency= 3; // repeat messages maximum every 3 seconds
39   m_count_repeated_messages= 0;
40   m_last_category[0]= 0;
41   m_last_message[0]= 0;
42   m_last_log_time= 0;
43   m_now= 0;
44   m_last_level= (Logger::LoggerLevel)-1;
45 }
46 
~LogHandler()47 LogHandler::~LogHandler()
48 {
49 }
50 
51 void
append(const char * pCategory,Logger::LoggerLevel level,const char * pMsg)52 LogHandler::append(const char* pCategory, Logger::LoggerLevel level,
53 		   const char* pMsg)
54 {
55   time_t now;
56   now= ::time((time_t*)NULL);
57 
58   if (m_max_repeat_frequency == 0 ||
59       level != m_last_level ||
60       strcmp(pCategory, m_last_category) ||
61       strcmp(pMsg, m_last_message))
62   {
63     if (m_count_repeated_messages > 0) // print that message
64       append_impl(m_last_category, m_last_level, m_last_message);
65 
66     m_last_level= level;
67     strncpy(m_last_category, pCategory, sizeof(m_last_category));
68     strncpy(m_last_message, pMsg, sizeof(m_last_message));
69   }
70   else // repeated message
71   {
72     if (now < (time_t) (m_last_log_time+m_max_repeat_frequency))
73     {
74       m_count_repeated_messages++;
75       m_now= now;
76       return;
77     }
78   }
79 
80   m_now= now;
81 
82   append_impl(pCategory, level, pMsg);
83   m_last_log_time= now;
84 }
85 
86 void
append_impl(const char * pCategory,Logger::LoggerLevel level,const char * pMsg)87 LogHandler::append_impl(const char* pCategory, Logger::LoggerLevel level,
88 			const char* pMsg)
89 {
90   writeHeader(pCategory, level);
91   if (m_count_repeated_messages <= 1)
92     writeMessage(pMsg);
93   else
94   {
95     BaseString str(pMsg);
96     str.appfmt(" - Repeated %d times", m_count_repeated_messages);
97     writeMessage(str.c_str());
98   }
99   m_count_repeated_messages= 0;
100   writeFooter();
101 }
102 
103 const char*
getDefaultHeader(char * pStr,const char * pCategory,Logger::LoggerLevel level) const104 LogHandler::getDefaultHeader(char* pStr, const char* pCategory,
105 			     Logger::LoggerLevel level) const
106 {
107   char time[MAX_DATE_TIME_HEADER_LENGTH];
108   BaseString::snprintf(pStr, MAX_HEADER_LENGTH, "%s [%s] %s -- ",
109 	     getTimeAsString((char*)time),
110 	     pCategory,
111 	     Logger::LoggerLevelNames[level]);
112 
113   return pStr;
114 }
115 
116 
117 const char*
getDefaultFooter() const118 LogHandler::getDefaultFooter() const
119 {
120   return "\n";
121 }
122 
123 const char*
getDateTimeFormat() const124 LogHandler::getDateTimeFormat() const
125 {
126   return m_pDateTimeFormat;
127 }
128 
129 void
setDateTimeFormat(const char * pFormat)130 LogHandler::setDateTimeFormat(const char* pFormat)
131 {
132   m_pDateTimeFormat = (char*)pFormat;
133 }
134 
135 char*
getTimeAsString(char * pStr) const136 LogHandler::getTimeAsString(char* pStr) const
137 {
138   struct tm* tm_now;
139   tm_now = ::localtime(&m_now); //uses the "current" timezone
140 
141   BaseString::snprintf(pStr, MAX_DATE_TIME_HEADER_LENGTH,
142 	     m_pDateTimeFormat,
143 	     tm_now->tm_year + 1900,
144 	     tm_now->tm_mon + 1, //month is [0,11]. +1 -> [1,12]
145 	     tm_now->tm_mday,
146 	     tm_now->tm_hour,
147 	     tm_now->tm_min,
148 	     tm_now->tm_sec);
149 
150   return pStr;
151 }
152 
153 int
getErrorCode() const154 LogHandler::getErrorCode() const
155 {
156   return m_errorCode;
157 }
158 
159 void
setErrorCode(int code)160 LogHandler::setErrorCode(int code)
161 {
162   m_errorCode = code;
163 }
164 
165 
166 char*
getErrorStr()167 LogHandler::getErrorStr()
168 {
169   return m_errorStr;
170 }
171 
172 void
setErrorStr(const char * str)173 LogHandler::setErrorStr(const char* str)
174 {
175   m_errorStr= (char*) str;
176 }
177 
178 bool
parseParams(const BaseString & _params)179 LogHandler::parseParams(const BaseString &_params) {
180   Vector<BaseString> v_args;
181 
182   bool ret = true;
183 
184   _params.split(v_args, ",");
185   for(size_t i=0; i < v_args.size(); i++) {
186     Vector<BaseString> v_param_value;
187     if(v_args[i].split(v_param_value, "=", 2) != 2)
188     {
189       ret = false;
190       setErrorStr("Can't find key=value pair.");
191     }
192     else
193     {
194       v_param_value[0].trim(" \t");
195       if (!setParam(v_param_value[0], v_param_value[1]))
196       {
197         ret = false;
198       }
199     }
200   }
201 
202   if(!checkParams())
203     ret = false;
204   return ret;
205 }
206 
207 bool
checkParams()208 LogHandler::checkParams() {
209   return true;
210 }
211 
setRepeatFrequency(unsigned val)212 void LogHandler::setRepeatFrequency(unsigned val)
213 {
214   m_max_repeat_frequency= val;
215 }
216 
217 //
218 // PRIVATE
219 //
220