(file) Return to log.c CVS log (file) (dir) Up to [OMI] / omi / base

  1 mike  1.1 /*
  2           **==============================================================================
  3           **
  4           ** Open Management Infrastructure (OMI)
  5           **
  6           ** Copyright (c) Microsoft Corporation
  7           ** 
  8           ** Licensed under the Apache License, Version 2.0 (the "License"); you may not 
  9           ** use this file except in compliance with the License. You may obtain a copy 
 10           ** of the License at 
 11           **
 12           **     http://www.apache.org/licenses/LICENSE-2.0 
 13           **
 14           ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15           ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
 16           ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
 17           ** MERCHANTABLITY OR NON-INFRINGEMENT. 
 18           **
 19           ** See the Apache 2 License for the specific language governing permissions 
 20           ** and limitations under the License.
 21           **
 22 mike  1.1 **==============================================================================
 23           */
 24           
 25 krisbash 1.3 #include "logbase.h"
 26 mike     1.1 
 27              #if defined(CONFIG_OS_WINDOWS)
 28              # include <windows.h>
 29              # include <time.h>
 30              #else
 31              # include <unistd.h>
 32              # include <sys/time.h>
 33              # include <sys/types.h>
 34              # include <time.h>
 35 krisbash 1.3 # if defined(linux)
 36              #  include <syscall.h>
 37              # endif
 38 mike     1.1 #endif
 39              
 40 krisbash 1.3 // Disable this by default as it slows down performance (by about 12% in tests with 2 threads)
 41              // it can be re-activated if intermingled traces become too difficult to read and it doesnt affect repro in that particular case
 42              // Note though that It will not prevent the case of different executables logging to the same files
 43              //#define LOGC_USES_LOCK
 44              
 45              #include <pal/strings.h>
 46              #include <pal/format.h>
 47              #include <pal/process.h>
 48              #include <pal/thread.h>
 49              #ifdef LOGC_USES_LOCK
 50              #include <pal/lock.h>
 51              #endif
 52 mike     1.1 
 53              /*
 54              **==============================================================================
 55              **
 56              ** Local definitions:
 57              **
 58              **==============================================================================
 59              */
 60              
 61              static FILE* _os;
 62 krisbash 1.3 #ifdef LOGC_USES_LOCK
 63              static Lock _logLock;
 64              #endif
 65              static Log_Level _level = OMI_WARNING;
 66              
 67 mike     1.1 
 68              static const char* _levelStrings[] =
 69              {
 70                  "FATAL",
 71                  "ERROR",
 72                  "WARNING",
 73                  "INFO",
 74                  "DEBUG",
 75 krisbash 1.3     "VERBOSE",
 76 mike     1.1 };
 77              
 78 krisbash 1.3 PAL_INLINE PAL_Boolean _ShouldLog(int level)
 79              {
 80                  if (level > Log_GetLevel())
 81                      return PAL_FALSE;
 82                  else
 83                      return PAL_TRUE;
 84              }
 85              
 86              #define FMTSIZE 1024
 87              void FilePutLog(
 88                  int priority,
 89                  int eventId,
 90                  const char * file,
 91                  int line,
 92                  const PAL_Char* format,
 93                  ...)
 94              {
 95                  if ((unsigned int)priority > OMI_VERBOSE)
 96                      return;
 97              
 98                  if (_ShouldLog(priority))
 99 krisbash 1.3     {
100                      TChar fmt[FMTSIZE];
101                      va_list ap;
102              
103                      Stprintf(fmt, FMTSIZE, PAL_T("EventId=%d Priority=%s "), eventId, _levelStrings[priority]);
104                      Tcslcat(fmt, format, FMTSIZE);
105                              
106                      va_start(ap, format);
107                      Log_VPut((Log_Level)priority, file, line, fmt, ap);
108                      va_end(ap);        
109                  }    
110              }
111 mike     1.1 
112 krisbash 1.3 int _GetCurrentTimeInUsec(MI_Uint64* usec)
113 mike     1.1 {
114              #if defined(CONFIG_OS_WINDOWS)
115                  FILETIME ft;
116                  ULARGE_INTEGER tmp;
117              
118                  GetSystemTimeAsFileTime(&ft);
119                  tmp.u.LowPart = ft.dwLowDateTime;
120                  tmp.u.HighPart = ft.dwHighDateTime;
121                  tmp.QuadPart -= 0X19DB1DED53E8000;
122                  *usec = tmp.QuadPart / (UINT64)10;
123              
124                  return 0;
125              #else
126                  struct timeval tv;
127                  struct timezone tz;
128                  memset(&tv, 0, sizeof(tv));
129                  memset(&tz, 0, sizeof(tz));
130              
131                  if (gettimeofday(&tv, &tz) != 0)
132                      return -1;
133              
134 mike     1.1     *usec = (MI_Uint64)tv.tv_sec * (MI_Uint64)1000000 + (MI_Uint64)tv.tv_usec;
135                  return 0;
136              #endif
137              }
138              
139              #define TIMESTAMP_SIZE 128
140              
141 krisbash 1.3 static int _GetTimeStamp(_Pre_writable_size_(TIMESTAMP_SIZE) char buf[TIMESTAMP_SIZE])
142 mike     1.1 {
143 krisbash 1.3 #if defined(CONFIG_OS_WINDOWS)
144                  {
145                      SYSTEMTIME systime;
146                      GetLocalTime(&systime);
147              
148                      sprintf_s(
149                          buf,
150                          TIMESTAMP_SIZE,
151                          "%02u/%02u/%02u %02u:%02u:%02u",
152                          systime.wYear,
153                          systime.wMonth,
154                          systime.wDay,
155                          systime.wHour,
156                          systime.wMinute,
157                          systime.wSecond);
158                  }
159              #else
160 mike     1.1     MI_Uint64 usec;
161              
162                  if (_GetCurrentTimeInUsec(&usec) != 0)
163                  {
164                      buf[0] = '\0';
165                      return -1;
166                  }
167              
168                  {
169                      time_t t = usec / 1000000;
170                      struct tm tm;
171                      localtime_r(&t, &tm);
172                      sprintf(
173                          buf,
174                          "%02u/%02u/%02u %02u:%02u:%02u",
175                          tm.tm_year + 1900,
176                          tm.tm_mon + 1,
177                          tm.tm_mday,
178                          tm.tm_hour,
179                          tm.tm_min,
180                          tm.tm_sec);
181 mike     1.1     }
182              #endif
183              
184                  return 0;
185              }
186              
187              static void _PutHeader(
188                  FILE* os, 
189                  const char* file, 
190                  unsigned int line, 
191                  Log_Level level)
192              {
193                  char buf[TIMESTAMP_SIZE];
194              
195                  _GetTimeStamp(buf);
196 krisbash 1.3     Ftprintf(os, ZT("%s "), scs(buf));
197                  Ftprintf(os, ZT("[%u,%lu] "), (unsigned int)Process_ID(), (unsigned long)Thread_TID());
198                  Ftprintf(os, ZT("%s: "), scs(_levelStrings[(int)level]));
199              
200                  if (file)
201                      Ftprintf(os, ZT("%s(%u): "), scs(file), line);
202 mike     1.1 }
203              
204              /*
205              **==============================================================================
206              **
207              ** Public definitions:
208              **
209              **==============================================================================
210              */
211              
212 krisbash 1.3 MI_Boolean Log_IsOpen()
213              {
214                  return (_os != NULL);
215              }
216              
217              #if defined(CONFIG_OS_WINDOWS)
218              #include <share.h>
219              #endif
220              
221 mike     1.1 MI_Result Log_Open(
222 krisbash 1.3     const ZChar* path)
223 mike     1.1 {
224                  if (!path || _os)
225                      return MI_RESULT_FAILED;
226              
227 krisbash 1.3 #ifdef LOGC_USES_LOCK
228                  Lock_Init(&_logLock);
229              #endif
230              
231 mike     1.1 #if defined(CONFIG_OS_WINDOWS)
232              # if (MI_CHAR_TYPE == 1)
233                  {
234 krisbash 1.3         _os = _fsopen(path, "a", _SH_DENYWR);
235                      if (_os == NULL)
236 mike     1.1             return MI_RESULT_FAILED;
237              
238                      return MI_RESULT_OK;
239                  }
240              # else
241                  {
242 krisbash 1.3         _os = _wfsopen(path, L"a", _SH_DENYWR);
243                      if (_os == NULL)
244 mike     1.1             return MI_RESULT_FAILED;
245              
246                      return MI_RESULT_OK;
247                  }
248              # endif
249              #else
250              # if (MI_CHAR_TYPE == 1)
251                  {
252                      _os = fopen(path, "a");
253 krisbash 1.3 
254 mike     1.1         if (!_os)
255                          return MI_RESULT_FAILED;
256              
257                      return MI_RESULT_OK;
258                  }
259              # else
260                  {
261 krisbash 1.3         char path7[PAL_MAX_PATH_SIZE];
262                      if (StrWcslcpy(path7, path, PAL_MAX_PATH_SIZE) >= PAL_MAX_PATH_SIZE)
263 mike     1.1             return MI_RESULT_FAILED;
264                      
265 krisbash 1.3         _os = fopen(path7, "a");
266 mike     1.1 
267                      if (!_os)
268                      {
269                          return MI_RESULT_FAILED;
270                      }
271              
272                      return MI_RESULT_OK;
273                  }
274              # endif
275              #endif
276              }
277              
278              MI_Result Log_OpenFD(
279                  int fd)
280              {
281              #if defined(CONFIG_OS_WINDOWS)
282                  MI_UNUSED(fd);
283                  return MI_RESULT_FAILED;
284              #else
285                  if (fd < 0 || _os)
286                      return MI_RESULT_FAILED;
287 mike     1.1 
288                  _os = fdopen(fd, "a");
289                  if (!_os)
290                      return MI_RESULT_FAILED;
291              
292                  return MI_RESULT_OK;
293              
294              #endif
295              }
296              
297              MI_Result Log_OpenStdErr()
298              {
299                  _os = stderr;
300                  return MI_RESULT_OK;
301              }
302              
303 krisbash 1.3 MI_Boolean Log_IsRoutedToStdErr()
304              {
305                  return (_os == stderr);
306              }
307              
308 mike     1.1 void Log_Close()
309              {
310                  if (_os && _os != stderr)
311                  {
312                      fclose(_os);
313                      _os = NULL;
314                  }
315              }
316              
317              void Log_SetLevel(
318                  Log_Level level)
319              {
320                  _level = level;
321              }
322              
323              Log_Level Log_GetLevel()
324              {
325                  return _level;
326              }
327              
328 krisbash 1.3 int Log_SetLevelFromString(_In_z_ const char* level)
329 mike     1.1 {
330                  size_t i;
331              
332                  for (i = 0; i < sizeof(_levelStrings) / sizeof(_levelStrings[0]); i++)
333                  {
334 krisbash 1.3         char buf[12];
335                      size_t size;
336                      const char* str = Uint32ToStr(buf, (MI_Uint32)i, &size);
337 mike     1.1 
338                      if (Strcasecmp(level, _levelStrings[i]) == 0 || 
339 krisbash 1.3             (str && Strcasecmp(level, str) == 0))
340 mike     1.1         {
341                          _level = (Log_Level)i;
342                          return 0;
343                      }
344                  }
345              
346                  return -1;
347              }
348              
349 krisbash 1.3 int Log_SetLevelFromPalCharString(_In_z_ const PAL_Char* level)
350              {
351                  if(level && (Tcslen(level) < MAX_LOG_LEVEL_STRING_LENGTH))
352                  {
353                      char buf[MAX_LOG_LEVEL_STRING_LENGTH];
354              #if defined(CONFIG_ENABLE_WCHAR)
355                      StrWcslcpy(buf, level, MAX_LOG_LEVEL_STRING_LENGTH);
356              #else
357                      Strlcpy(buf, level, MAX_LOG_LEVEL_STRING_LENGTH);
358              #endif
359                      if(Log_SetLevelFromString(buf) != 0)
360                      {
361                          return -1;
362                      }
363              
364                      return 0;
365                  }
366              
367                  return -1;
368              }
369              
370 mike     1.1 const char* Log_GetLevelString(Log_Level level)
371              {
372                  return _levelStrings[(int)level];
373              }
374              
375              int Log_Put(
376                  Log_Level level,
377                  const char* file,
378                  MI_Uint32 line,
379 krisbash 1.3     const ZChar* format,
380 mike     1.1     ...)
381              {
382                  va_list ap;
383                  memset(&ap, 0, sizeof(ap));
384              
385                  if (!_os || level > _level)
386                      return 0;
387              
388 krisbash 1.3 #ifdef LOGC_USES_LOCK
389                  Lock_Acquire(&_logLock);
390              #endif
391              
392 mike     1.1     _PutHeader(_os, file, line, level);
393 krisbash 1.3 
394 mike     1.1     va_start(ap, format);
395 krisbash 1.3 
396                  Vftprintf(_os, format, ap);
397              
398                  va_end(ap);
399                  Ftprintf(_os, ZT("\n"));
400              
401              #ifdef LOGC_USES_LOCK
402                  Lock_Release(&_logLock);
403 mike     1.1 #endif
404              
405                  return 1;
406              }
407              
408              int Log_VPut(
409                  Log_Level level,
410                  const char* file,
411                  MI_Uint32 line,
412 krisbash 1.3     const ZChar* format,
413 mike     1.1     va_list ap)
414              {
415                  if (!_os || level > _level)
416                      return 0;
417              
418 krisbash 1.3     file = scs(file);
419              
420              #ifdef LOGC_USES_LOCK
421                  Lock_Acquire(&_logLock);
422              #endif
423              
424 mike     1.1     _PutHeader(_os, file, line, level);
425 krisbash 1.3 
426                  Vftprintf(_os, format, ap);
427              
428                  Ftprintf(_os, ZT("\n"));
429                  fflush(_os);
430              
431              #ifdef LOGC_USES_LOCK
432                  Lock_Release(&_logLock);
433 mike     1.1 #endif
434              
435                  return 1;
436              }
437              
438 krisbash 1.3 #if defined(CONFIG_ENABLE_DEBUG)
439              
440 mike     1.1 int __Log_Put1(
441                  Log_Level level,
442                  const char* file,
443                  MI_Uint32 line)
444              {
445                  if (!_os || level > _level)
446                      return 0;
447              
448 krisbash 1.3 #ifdef LOGC_USES_LOCK
449                  Lock_Acquire(&_logLock);
450              #endif
451 mike     1.1     _PutHeader(_os, file, line, level);
452 krisbash 1.3 #ifdef LOGC_USES_LOCK
453                  Lock_Release(&_logLock);
454              #endif
455 mike     1.1 
456                  return 1;
457              }
458              
459 krisbash 1.3 #endif /* defined(CONFIG_ENABLE_DEBUG) */
460              
461 mike     1.1 void __Log_Put2(
462 krisbash 1.3     const ZChar* format,
463 mike     1.1     ...)
464              {
465                  va_list ap;
466                  memset(&ap, 0, sizeof(ap));
467              
468 krisbash 1.3     if (!_os)
469 mike     1.1         return;
470              
471 krisbash 1.3 #ifdef LOGC_USES_LOCK
472                  Lock_Acquire(&_logLock);
473              #endif
474 mike     1.1     va_start(ap, format);
475 krisbash 1.3 
476                  Vftprintf(_os, format, ap);
477              
478                  Ftprintf(_os, ZT("\n"));
479                  fflush(_os);
480              #ifdef LOGC_USES_LOCK
481                  Lock_Release(&_logLock);
482 mike     1.1 #endif
483              }
484              
485 krisbash 1.3 void __Logf(const ZChar* format, ...)
486              {
487                  va_list ap;
488                  va_start(ap, format);
489                  Log_VPut(OMI_FATAL, NULL, 0, format, ap);
490                  va_end(ap);
491              }
492              
493              void __Loge(const ZChar* format, ...)
494              {
495                  va_list ap;
496                  va_start(ap, format);
497                  Log_VPut(OMI_ERROR, NULL, 0, format, ap);
498                  va_end(ap);
499              }
500              
501              void __Logw(const ZChar* format, ...)
502              {
503                  va_list ap;
504                  va_start(ap, format);
505                  Log_VPut(OMI_WARNING, NULL, 0, format, ap);
506 krisbash 1.3     va_end(ap);
507              }
508              
509              void __Logi(const ZChar* format, ...)
510 mike     1.1 {
511                  va_list ap;
512 krisbash 1.3     va_start(ap, format);
513                  Log_VPut(OMI_INFO, NULL, 0, format, ap);
514                  va_end(ap);
515              }
516 mike     1.1 
517 krisbash 1.3 void __Logd(const ZChar* format, ...)
518              {
519                  va_list ap;
520                  va_start(ap, format);
521                  Log_VPut(OMI_DEBUG, NULL, 0, format, ap);
522                  va_end(ap);
523              }
524 mike     1.1 
525 krisbash 1.3 void __Logv(const ZChar* format, ...)
526              {
527                  va_list ap;
528 mike     1.1     va_start(ap, format);
529 krisbash 1.3     Log_VPut(OMI_VERBOSE, NULL, 0, format, ap);
530                  va_end(ap);
531 mike     1.1 }
532 krisbash 1.3 

ViewCVS 0.9.2