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

File: [OMI] / omi / base / log.c (download)
Revision: 1.1, Wed May 30 21:47:49 2012 UTC (12 years ago) by mike
Branch: MAIN
Initial revision

/*
**==============================================================================
**
** Open Management Infrastructure (OMI)
**
** Copyright (c) Microsoft Corporation
** 
** Licensed under the Apache License, Version 2.0 (the "License"); you may not 
** use this file except in compliance with the License. You may obtain a copy 
** of the License at 
**
**     http://www.apache.org/licenses/LICENSE-2.0 
**
** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
** MERCHANTABLITY OR NON-INFRINGEMENT. 
**
** See the Apache 2 License for the specific language governing permissions 
** and limitations under the License.
**
**==============================================================================
*/

#include "log.h"

#if defined(CONFIG_OS_WINDOWS)
# include <windows.h>
# include <time.h>
#else
# include <unistd.h>
# include <sys/time.h>
# include <sys/types.h>
# include <time.h>
#endif

#include "strings.h"
#include "io.h"

/*
**==============================================================================
**
** Local definitions:
**
**==============================================================================
*/

static FILE* _os;

static const char* _levelStrings[] =
{
    "FATAL",
    "ERROR",
    "WARNING",
    "INFO",
    "DEBUG",
};

static Log_Level _level = LOG_WARNING;
static Log_Level _currentLevel = LOG_WARNING;

static int _GetCurrentTimeInUsec(MI_Uint64* usec)
{
#if defined(CONFIG_OS_WINDOWS)
    FILETIME ft;
    ULARGE_INTEGER tmp;

    GetSystemTimeAsFileTime(&ft);
    tmp.u.LowPart = ft.dwLowDateTime;
    tmp.u.HighPart = ft.dwHighDateTime;
    tmp.QuadPart -= 0X19DB1DED53E8000;
    *usec = tmp.QuadPart / (UINT64)10;

    return 0;
#else
    struct timeval tv;
    struct timezone tz;
    memset(&tv, 0, sizeof(tv));
    memset(&tz, 0, sizeof(tz));

    if (gettimeofday(&tv, &tz) != 0)
        return -1;

    *usec = (MI_Uint64)tv.tv_sec * (MI_Uint64)1000000 + (MI_Uint64)tv.tv_usec;
    return 0;
#endif
}

#define TIMESTAMP_SIZE 128

static int _GetTimeStamp(char buf[TIMESTAMP_SIZE])
{
    MI_Uint64 usec;

    if (_GetCurrentTimeInUsec(&usec) != 0)
    {
        buf[0] = '\0';
        return -1;
    }

#if defined(CONFIG_OS_WINDOWS)
    {
        time_t t = usec / 1000000;
        struct tm tm;
        localtime_s(&tm, &t);
        sprintf_s(
            buf,
            TIMESTAMP_SIZE,
            "%02u/%02u/%02u %02u:%02u:%02u",
            tm.tm_year + 1900,
            tm.tm_mon + 1,
            tm.tm_mday,
            tm.tm_hour,
            tm.tm_min,
            tm.tm_sec);
    }
#else
    {
        time_t t = usec / 1000000;
        struct tm tm;
        localtime_r(&t, &tm);
        sprintf(
            buf,
            "%02u/%02u/%02u %02u:%02u:%02u",
            tm.tm_year + 1900,
            tm.tm_mon + 1,
            tm.tm_mday,
            tm.tm_hour,
            tm.tm_min,
            tm.tm_sec);
    }
#endif

    return 0;
}

#if (MI_CHAR_TYPE == 2)
static char* _StrdupWcharToASCII7(const MI_Char* str)
{
    char* p;
    
    /* Allocate room for string */
    p = (char*)malloc(Wcslen(str) + 1);

    if (!p)
        return NULL;

    /* Copy string while failing on non-ASCII characters */
    while (*str)
    {
        if ((MI_Uint32)*str >= 128)
        {
            free(p);
            return NULL;
        }
        *p++ = (char)*str++;
    }

    return p;
}
#endif

static void _PutHeader(
    FILE* os, 
    const char* file, 
    unsigned int line, 
    Log_Level level)
{
    char buf[TIMESTAMP_SIZE];

    _GetTimeStamp(buf);
    fprintf(os, "%s: ", buf);
    fprintf(os, "%s: ", _levelStrings[(int)level]);
    fprintf(os, "%s(%u): ", file, line);
}

/*
**==============================================================================
**
** Public definitions:
**
**==============================================================================
*/

MI_Result Log_Open(
    const MI_Char* path)
{
    if (!path || _os)
        return MI_RESULT_FAILED;

#if defined(CONFIG_OS_WINDOWS)
# if (MI_CHAR_TYPE == 1)
    {
        if (fopen_s(&_os, path, "a") != 0)
            return MI_RESULT_FAILED;

        return MI_RESULT_OK;
    }
# else
    {
        if (_wfopen_s(&_os, path, L"a") != 0)
            return MI_RESULT_FAILED;

        return MI_RESULT_OK;
    }
# endif
#else
# if (MI_CHAR_TYPE == 1)
    {
        _os = fopen(path, "a");
        if (!_os)
            return MI_RESULT_FAILED;

        return MI_RESULT_OK;
    }
# else
    {
        char* path7 = _StrdupWcharToASCII7(path);

        if (!path7)
            return MI_RESULT_FAILED;
        
        _os = fopen(path7, _os, "a");

        if (!_os)
        {
            free(path7);
            return MI_RESULT_FAILED;
        }

        free(path7);
        return MI_RESULT_OK;
    }
# endif
#endif
}

MI_Result Log_OpenFD(
    int fd)
{
#if defined(CONFIG_OS_WINDOWS)
    MI_UNUSED(fd);
    return MI_RESULT_FAILED;
#else
    if (fd < 0 || _os)
        return MI_RESULT_FAILED;

    _os = fdopen(fd, "a");
    if (!_os)
        return MI_RESULT_FAILED;

    return MI_RESULT_OK;

#endif
}

MI_Result Log_OpenStdErr()
{
    _os = stderr;
    return MI_RESULT_OK;
}

void Log_Close()
{
    if (_os && _os != stderr)
    {
        fclose(_os);
        _os = NULL;
    }
}

void Log_SetLevel(
    Log_Level level)
{
    _level = level;
}

Log_Level Log_GetLevel()
{
    return _level;
}

int Log_SetLevelFromString(const char* level)
{
    size_t i;

    for (i = 0; i < sizeof(_levelStrings) / sizeof(_levelStrings[0]); i++)
    {
        char buf[32];

        Snprintf(buf, sizeof(buf), "%u", (int)i);

        if (Strcasecmp(level, _levelStrings[i]) == 0 || 
            Strcasecmp(level, buf) == 0)
        {
            _level = (Log_Level)i;
            return 0;
        }
    }

    return -1;
}

const char* Log_GetLevelString(Log_Level level)
{
    return _levelStrings[(int)level];
}

int Log_Put(
    Log_Level level,
    const char* file,
    MI_Uint32 line,
    const MI_Char* format,
    ...)
{
    va_list ap;
    memset(&ap, 0, sizeof(ap));

    if (!_os || level > _level)
        return 0;

    _PutHeader(_os, file, line, level);
    va_start(ap, format);
#if (MI_CHAR_TYPE == 1)
    vfprintf(_os, format, ap);
#else
    vfwprintf(_os, format, ap);
#endif
    va_end(ap);
    fputc('\n', _os);

    return 1;
}

int Log_VPut(
    Log_Level level,
    const char* file,
    MI_Uint32 line,
    const MI_Char* format,
    va_list ap)
{
    if (!_os || level > _level)
        return 0;

    _PutHeader(_os, file, line, level);
#if (MI_CHAR_TYPE == 1)
    vfprintf(_os, format, ap);
#else
    vfwprintf(_os, format, ap);
#endif
    fputc('\n', _os);

    return 1;
}

int __Log_Put1(
    Log_Level level,
    const char* file,
    MI_Uint32 line)
{
    if (!_os || level > _level)
        return 0;

    _currentLevel = level;
    _PutHeader(_os, file, line, level);

    return 1;
}

void __Log_Put2(
    const MI_Char* format,
    ...)
{
    va_list ap;
    memset(&ap, 0, sizeof(ap));

    if (!_os || _currentLevel > _level)
        return;

    va_start(ap, format);
#if (MI_CHAR_TYPE == 1)
    vfprintf(_os, format, ap);
#else
    vfwprintf(_os, format, ap);
#endif
    fputc('\n', _os);
    fflush(_os);
}

void __Log_Put2_char(
    const char* format,
    ...)
{
    va_list ap;
    memset(&ap, 0, sizeof(ap));

    if (!_os || _currentLevel > _level)
        return;

    va_start(ap, format);
    vfprintf(_os, format, ap);
    fputc('\n', _os);
    fflush(_os);
}

ViewCVS 0.9.2