- Added component locks
[public/netxms.git] / src / server / core / log.cpp
1 /*
2 ** Network Management System Core
3 ** Copyright (C) 2003 Victor Kirhenshtein
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 as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 **
19 ** $module: log.cpp
20 **
21 **/
22
23 #include "nms_core.h"
24
25
26 //
27 // Static data
28 //
29
30 #ifdef _WIN32
31 static HANDLE m_hEventLog = INVALID_HANDLE_VALUE;
32 #endif
33 static FILE *m_hLogFile = NULL;
34 static MUTEX m_mutexLogAccess = INVALID_MUTEX_HANDLE;
35
36
37 //
38 // Initialize log
39 //
40
41 void InitLog(void)
42 {
43 #ifdef _WIN32
44 if (g_dwFlags & AF_USE_EVENT_LOG)
45 {
46 m_hEventLog = RegisterEventSource(NULL, CORE_EVENT_SOURCE);
47 }
48 else
49 {
50 #endif
51 char szTimeBuf[32];
52 struct tm *loc;
53 time_t t;
54
55 m_hLogFile = fopen(g_szLogFile, "a");
56 t = time(NULL);
57 loc = localtime(&t);
58 strftime(szTimeBuf, 32, "%d-%b-%Y %H:%M:%S", loc);
59 fprintf(m_hLogFile, "**************************************************************\r\n[%s] Log file opened\r\n", szTimeBuf);
60
61 m_mutexLogAccess = MutexCreate();
62 #ifdef _WIN32
63 }
64 #endif
65 }
66
67
68 //
69 // Close log
70 //
71
72 void CloseLog(void)
73 {
74 #ifdef _WIN32
75 if (g_dwFlags & AF_USE_EVENT_LOG)
76 {
77 DeregisterEventSource(m_hEventLog);
78 }
79 else
80 {
81 #endif
82 if (m_hLogFile != NULL)
83 fclose(m_hLogFile);
84 if (m_mutexLogAccess != INVALID_MUTEX_HANDLE)
85 MutexDestroy(m_mutexLogAccess);
86 #ifdef _WIN32
87 }
88 #endif
89 }
90
91
92 //
93 // Write record to log file
94 //
95
96 static void WriteLogToFile(char *szMessage)
97 {
98 char szBuffer[64];
99 time_t t;
100 struct tm *loc;
101
102 // Prevent simultaneous write to log file
103 MutexLock(m_mutexLogAccess, INFINITE);
104
105 t = time(NULL);
106 loc = localtime(&t);
107 strftime(szBuffer, 32, "[%d-%b-%Y %H:%M:%S]", loc);
108 fprintf(m_hLogFile, "%s %s", szBuffer, szMessage);
109 if (IsStandalone())
110 printf("%s %s", szBuffer, szMessage);
111
112 MutexUnlock(m_mutexLogAccess);
113 }
114
115
116 //
117 // Write log record
118 // Parameters:
119 // msg - Message ID
120 // wType - Message type (see ReportEvent() for details)
121 // format - Parameter format string, each parameter represented by one character.
122 // The following format characters can be used:
123 // s - String
124 // d - Decimal integer
125 // x - Hex integer
126 // e - System error code (will appear in log as textual description)
127 // a - IP address in network byte order
128 //
129
130 void WriteLog(DWORD msg, WORD wType, char *format, ...)
131 {
132 va_list args;
133 char *strings[16], *msgBuf;
134 int numStrings = 0;
135 DWORD error;
136
137 memset(strings, 0, sizeof(char *) * 16);
138
139 if (format != NULL)
140 {
141 va_start(args, format);
142
143 for(; (format[numStrings] != 0) && (numStrings < 16); numStrings++)
144 {
145 switch(format[numStrings])
146 {
147 case 's':
148 strings[numStrings] = strdup(va_arg(args, char *));
149 break;
150 case 'd':
151 strings[numStrings] = (char *)malloc(16);
152 sprintf(strings[numStrings], "%d", va_arg(args, LONG));
153 break;
154 case 'x':
155 strings[numStrings] = (char *)malloc(16);
156 sprintf(strings[numStrings], "0x%08X", va_arg(args, DWORD));
157 break;
158 case 'a':
159 strings[numStrings] = (char *)malloc(20);
160 IpToStr(va_arg(args, DWORD), strings[numStrings]);
161 break;
162 case 'e':
163 error = va_arg(args, DWORD);
164 #ifdef _WIN32
165 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
166 FORMAT_MESSAGE_FROM_SYSTEM |
167 FORMAT_MESSAGE_IGNORE_INSERTS,
168 NULL, error,
169 MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), // Default language
170 (LPSTR)&msgBuf,0,NULL)>0)
171 {
172 msgBuf[strcspn(msgBuf,"\r\n")] = 0;
173 strings[numStrings]=(char *)malloc(strlen(msgBuf) + 1);
174 strcpy(strings[numStrings], msgBuf);
175 LocalFree(msgBuf);
176 }
177 else
178 {
179 strings[numStrings] = (char *)malloc(64);
180 sprintf(strings[numStrings], "MSG 0x%08X - Unable to find message text", error);
181 }
182 #else /* _WIN32 */
183 strings[numStrings] = strdup(strerror(error));
184 #endif
185 break;
186 default:
187 strings[numStrings] = (char *)malloc(32);
188 sprintf(strings[numStrings], "BAD FORMAT (0x%08X)", va_arg(args, DWORD));
189 break;
190 }
191 }
192 va_end(args);
193 }
194
195 #ifdef _WIN32
196 if (g_dwFlags & AF_USE_EVENT_LOG)
197 {
198 ReportEvent(m_hEventLog, wType, 0, msg, NULL, numStrings, 0, (const char **)strings, NULL);
199 }
200 else
201 {
202 LPVOID lpMsgBuf;
203
204 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ARGUMENT_ARRAY,
205 NULL, msg, 0, (LPTSTR)&lpMsgBuf, 0, strings)>0)
206 {
207 WriteLogToFile((char *)lpMsgBuf);
208 LocalFree(lpMsgBuf);
209 }
210 else
211 {
212 char message[64];
213
214 sprintf(message,"MSG 0x%08X - Unable to find message text\r\n",msg);
215 WriteLogToFile(message);
216 }
217 }
218 #else /* _WIN32 */
219
220 /* TODO: add event logging under UNIX */
221
222 #endif /* _WIN32 */
223
224 while(--numStrings >= 0)
225 free(strings[numStrings]);
226 }