📄 rvloglistener.c
字号:
/***********************************************************************
Filename : rvloglistener.c
Description: rvloglistener file - message log listener
************************************************************************
Copyright (c) 2001 RADVISION Inc. and RADVISION Ltd.
************************************************************************
NOTICE:
This document contains information that is confidential and proprietary
to RADVISION Inc. and RADVISION Ltd.. No part of this document may be
reproduced in any form whatsoever without written prior approval by
RADVISION Inc. or RADVISION Ltd..
RADVISION Inc. and RADVISION Ltd. reserve the right to revise this
publication and make changes without obligation to notify any person of
such revisions or changes.
***********************************************************************/
#include "rvmemory.h"
#include "rvthread.h"
#include "rvclock.h"
#include "rvtm.h"
#include "rvstdio.h"
#include "rvloglistener.h"
#if (RV_LOGLISTENER_TYPE != RV_LOGLISTENER_NONE)
/* Make sure we have the internal listeners set */
/* Lets make error codes a little easier to type */
#define RvLogListenerErrorCode(_e) RvErrorCode(RV_ERROR_LIBCODE_CCORE, RV_CCORE_MODULE_LOGLISTENER, (_e))
/* Types of listeners */
#define RV_LOGLISTENER_TYPE_TERMINAL 1
#define RV_LOGLISTENER_TYPE_LOGFILE 2
#define RV_LOGLISTENER_TYPE_DEBUG 3
/* Information about which listeners are allocated */
static RvBool rvListenerUsed[3];
#if ((RV_LOGLISTENER_TYPE == RV_LOGLISTENER_WIN32) || \
(RV_LOGLISTENER_TYPE == RV_LOGLISTENER_FILE_AND_TERMINAL))
typedef struct
{
#if (RV_LOGLISTENER_TYPE == RV_LOGLISTENER_WIN32)
HANDLE openedFile; /* Handle of the currently opened file */
#else
FILE* openedFile; /* Handle of the currently opened file */
#endif
RvChar baseFilename[256]; /* Base name of files */
RvUint32 numFiles; /* Number of files in cycle */
RvUint32 curFileNum; /* Current file number being used */
RvUint32 maxFileSize; /* Maximum size of file in cycle */
RvUint32 curSize; /* Current size of file */
RvBool flushLines; /* If RV_TRUE, then on each message, the logfile is flushed */
RvBool openError; /* Indication of errors - on error, we stop logging to the log files */
} LogFileListener;
static LogFileListener rvLogFileListener;
#endif /* ((RV_LOGLISTENER_TYPE == RV_LOGLISTENER_WIN32) || \
(RV_LOGLISTENER_TYPE == RV_LOGLISTENER_FILE_AND_TERMINAL)) */
/********************************************************************************************
*
* Internal functions
*
********************************************************************************************/
/********************************************************************************************
* logFormatMessage
*
* purpose : Format a log record into a printable string
* input : logRecord - Information related with the logged message
* output : size - Size of formatter message in characters
* Can be passed as NULL
* return : Pointer to string holding the formatted text
********************************************************************************************/
static RvChar* logFormatMessage(
IN RvLogRecord* logRecord,
OUT RvUint32* size)
{
RvChar* buf;
RvChar* threadName = NULL;
RvThread* threadInfo;
RvTime t;
RvTm tm;
const RvChar* mtypeStr;
RvUint32 len;
/* Find the message type string */
switch (RvLogRecordGetMessageType(logRecord))
{
case RV_LOGLEVEL_EXCEP: mtypeStr = "EXCEP"; break;
case RV_LOGLEVEL_ERROR: mtypeStr = "ERROR"; break;
case RV_LOGLEVEL_WARNING: mtypeStr = "WARN "; break;
case RV_LOGLEVEL_INFO : mtypeStr = "INFO "; break;
case RV_LOGLEVEL_DEBUG: mtypeStr = "DEBUG"; break;
case RV_LOGLEVEL_ENTER: mtypeStr = "ENTER"; break;
case RV_LOGLEVEL_LEAVE: mtypeStr = "LEAVE"; break;
default:
return (char*)"Error in message type!";
}
/* Move back in the text - there's free space there for our formatting */
buf = (RvChar *)RvLogRecordGetText(logRecord) - 38;
/* Find out the thread's name */
threadInfo = RvLogRecordGetThread(logRecord);
if (threadInfo != NULL)
threadName = RvThreadGetName(threadInfo);
if (threadName == NULL)
threadName = (RvChar *)"Unknown";
/* Get the time of the log */
RvClockGet(&t);
RvTmConstructLocal(&tm, &t);
/* Format the additional information into the reserved space in the beginning of the buffer */
/* 8+1+2+1+2+1+2+1+10+2+5+3 = */
RvSprintf(buf, "%8.8s %2.2u:%2.2u:%2.2u %-10.10s: %s -",
threadName,
RvTmGetHour(&tm), RvTmGetMin(&tm), RvTmGetSec(&tm),
RvLogSourceGetName(RvLogRecordGetSource(logRecord)),
mtypeStr);
/* We're done with time information */
RvTimeDestruct(&t);
RvTmDestruct(&tm);
/* This one is for the addition of the actual string after the fomatted header */
buf[37] = ' ';
/* Add a newline in the end and calculate the size of message */
len = strlen(buf);
buf[len] = '\0';
if (size != NULL)
*size = len;
/* Return the formatted buffer */
return buf;
}
/********************************************************************************************
* logPrintTerminal
*
* purpose : Callback that is executed whenever a message has to be logged to the terminal
* input : logRecord - Information related with the logged message
* userData - stdout or stderr (FILE*)
* output : None
* return : None
********************************************************************************************/
static void RVCALLCONV logPrintTerminal(
IN RvLogRecord* logRecord,
IN void* userData)
{
FILE* f = (FILE *)userData;
/* We use %s so we don't get formatting characters by mistake into the message - this might
cause us to crash */
fprintf(f, "%s\n", logFormatMessage(logRecord, NULL));
}
#if ((RV_LOGLISTENER_TYPE == RV_LOGLISTENER_WIN32) || \
(RV_LOGLISTENER_TYPE == RV_LOGLISTENER_FILE_AND_TERMINAL))
/********************************************************************************************
* logPrintLogfile
*
* purpose : Callback that is executed whenever a message has to be logged to the logfile
* input : logRecord - Information related with the logged message
* userData - LogFileListener struct
* output : None
* return : None
********************************************************************************************/
static void RVCALLCONV logPrintLogfile(
IN RvLogRecord* logRecord,
IN void* userData)
{
LogFileListener* logInfo = (LogFileListener *)userData;
RvChar* logMessage;
RvUint32 logMessageSize;
/* Make sure we didn't encounter any errors while trying to open a logfile */
if (logInfo->openError) return;
/* See if we have to switch to another file */
if ((logInfo->openedFile == NULL) ||
((logInfo->numFiles > 1) && (logInfo->curSize > logInfo->maxFileSize)))
{
/* We need to open the next file... */
RvChar fname[300];
RvChar* fnamePtr;
/* Close the currently opened one */
if (logInfo->openedFile != NULL)
{
#if (RV_LOGLISTENER_TYPE == RV_LOGLISTENER_WIN32)
CloseHandle(logInfo->openedFile);
#else
fclose(logInfo->openedFile);
#endif
logInfo->openedFile = NULL;
logInfo->curSize = 0;
}
/* Determine the filename */
if (logInfo->numFiles > 1)
{
logInfo->curFileNum = (logInfo->curFileNum + 1) % logInfo->numFiles;
RvSprintf(fname, "%s%d", logInfo->baseFilename, logInfo->curFileNum);
fnamePtr = fname;
}
else
fnamePtr = logInfo->baseFilename;
/* Open the next logfile */
#if (RV_LOGLISTENER_TYPE == RV_LOGLISTENER_WIN32)
logInfo->openedFile = CreateFile((LPCTSTR)fnamePtr, GENERIC_WRITE,
FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
logInfo->openError = (logInfo->openedFile == INVALID_HANDLE_VALUE);
#else
logInfo->openedFile = fopen(fnamePtr, "wb");
logInfo->openError = (logInfo->openedFile == NULL);
#endif
/* If we're having any error opening files we shouldn't continue here */
if (logInfo->openError)
return;
}
if ((logInfo->numFiles == 1) && (logInfo->maxFileSize != 0) &&
(logInfo->curSize > logInfo->maxFileSize))
{
/* move to the beginning of the file */
#if (RV_LOGLISTENER_TYPE == RV_LOGLISTENER_WIN32)
SetFilePointer(logInfo->openedFile, 0, NULL, FILE_BEGIN);
#else
fseek(logInfo->openedFile, 0, SEEK_SET);
#endif
logInfo->curSize = 0;
}
/* At long last - put the message in the logfile */
logMessage = logFormatMessage(logRecord, &logMessageSize);
logMessage[logMessageSize] = '\n';
#if (RV_LOGLISTENER_TYPE == RV_LOGLISTENER_WIN32)
{
DWORD bytesWritten;
WriteFile(logInfo->openedFile, logMessage, logMessageSize, &bytesWritten, NULL);
WriteFile(logInfo->openedFile, "\r\n", 2, &bytesWritten, NULL);
}
#else
fwrite(logMessage, logMessageSize+1, 1, logInfo->openedFile);
#endif
logMessage[logMessageSize] = '\0';
/* See if we have to flush the logfile after adding the message */
if (logInfo->flushLines)
#if (RV_LOGLISTENER_TYPE == RV_LOGLISTENER_WIN32)
FlushFileBuffers(logInfo->openedFile);
#else
fflush(logInfo->openedFile);
#endif
/* Make sure we are aware of the logfile's size */
logInfo->curSize += logMessageSize;
}
#endif /* ((RV_LOGLISTENER_TYPE == RV_LOGLISTENER_WIN32) || \
(RV_LOGLISTENER_TYPE == RV_LOGLISTENER_FILE_AND_TERMINAL)) */
#if (RV_LOGLISTENER_TYPE == RV_LOGLISTENER_WIN32)
#if 0
/********************************************************************************************
* logPrintWindow
*
* purpose : Callback that is executed whenever a message has to be logged to a window
* input : logRecord - Information related with the logged message
* userData - WindowListener struct
* output : None
* return : None
********************************************************************************************/
static void RVCALLCONV logPrintWindow(
IN RvLogRecord* logRecord,
IN void* userData)
{
WindowListener* winInfo = (WindowListener *)userData;
RvChar* logMessage;
RvUint32 logMessageSize;
RvStatus ret;
logMessage = logFormatMessage(logRecord, &logMessageSize);
ret = RvLockGet(&winInfo->lock);
assert(ret == RV_OK);
/* Make sure we have enough space in pending messages buffer */
while (logMessageSize > (winInfo->bufferSize - winInfo->curUsedBufSize))
{
RvLockRelease(&winInfo->lock); /* Must release this lock before calling SendMessage! */
SendMessage(winInfo->hWnd, LOGWND_PENDING, 0, 0);
ret = RvLockGet(&winInfo->lock);
assert(ret == RV_OK);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -