看看AMPS中的日志模块,有两种写日志的方法,一是直接使用封装好的API函数写,另一种是通过应用层注册的日志回调函数,利用事件管理机制来写。
AMPS_Log.h
#ifndef __HEADER_AMPS_LOG_H__
#define __HEADER_AMPS_LOG_H__
#include <stdio.h>
#include "AMPS_SystemAPI.h"
#include "AMPS_Core.h"
#include "AMPS_Components.h"
#ifdef __cplusplus
extern "C" {
#endif
#define AMPS_LOG_MAX_SIZE_OF_WRITE_BUFFER (1024)
typedef struct _AMPSLogContext t_AMPSLogContext;
struct _AMPSLogContext
{
void* pvAMPSContext;
void* pvAMPSNetworkMsg;
};
void* Log_Init(void* r_pvAMPSContext, char* r_pchFileName);
void Log_Cleanup(void* r_pvAMPSLogContext);
//AMPS_API int AMPS_Log(void* r_pvAMPSContext, const char* r_puchMessage , ...);
int Log_HandleFileWriteEvent(t_AMPSContext* r_poAMPSContext, t_AMPSSNMEvent* r_poAMPSSNMEvent, t_AMPSNetworkMsg* r_poAMPSNetworkMsg);
#ifdef __cplusplus
}
#endif
#endif /*#ifndef __HEADER_AMPS_LOG_H__*/
AMPS_Log.c
#include "AMPS_Defines.h"
#include "AMPS_LinkList.h"
#include "AMPS_SystemAPI.h"
#include "AMPS_Core.h"
#include "AMPS_MemMgt.h"
#include "AMPS_Log.h"
/*****************************************************************
函数名称: Log_Init
功能描述: 日志模块初始化
入参::
void* r_pvAMPSContext APMS应用上下文
char* r_pchFileName 日志文件名
出参:
返回值:
void* 日志句柄
*****************************************************************/
void* Log_Init(void* r_pvAMPSContext, char* r_pchFileName)
{
t_AMPSLogContext* poAMPSLogContext = NULL;
t_AMPSSNMEvent oAMPSEpollEvent;
t_AMPSNetworkMsg* poAMPSNetworkMsg = NULL;
TRACE( LOG_TRACE_ID(r_pvAMPSContext), AMPS_TRACE_LEVEL_INFO, "Entering.\n");
poAMPSLogContext = (t_AMPSLogContext*)AMPS_InternalMalloc(sizeof(t_AMPSLogContext));
if(NULL == poAMPSLogContext)
{
TRACE( LOG_TRACE_ID(r_pvAMPSContext), AMPS_TRACE_LEVEL_ERROR, "AMPS_InternalMalloc failed.\n");
return NULL;
}
/*以追加模式打开(如没有,则创建)日志文件*/
poAMPSLogContext->pvAMPSNetworkMsg = SAPI_FileOpenInterface(r_pvAMPSContext, (const char*)r_pchFileName, AMPS_TRUE, AMPS_FILE_MODE_APPEND_WRITE_CREATE);
if(NULL == poAMPSLogContext->pvAMPSNetworkMsg)
{
TRACE( LOG_TRACE_ID(r_pvAMPSContext), AMPS_TRACE_LEVEL_ERROR, "SAPI_FileOpenForWriting failed.\n");
return NULL;
}
poAMPSNetworkMsg = (t_AMPSNetworkMsg*)poAMPSLogContext->pvAMPSNetworkMsg;
/*注册日志写事件*/
AMPS_SetSNMWriteEvtHandlerInNetMsg(r_pvAMPSContext, poAMPSNetworkMsg, Log_HandleFileWriteEvent);
/*注册I/O事件通知*/
SAPI_SetDataInSNMEvent(r_pvAMPSContext, &oAMPSEpollEvent, poAMPSNetworkMsg);
SAPI_ResetSNMEvent(r_pvAMPSContext, &oAMPSEpollEvent);
SAPI_SetWriteSNMEvent(r_pvAMPSContext, &oAMPSEpollEvent);
/*if (AMPS_SUCCESS != SAPI_InsertSNMEvent(r_pvAMPSContext, poAMPSNetworkMsg->nHandle, &oAMPSEpollEvent))
{
TRACE( LOG_TRACE_ID(r_pvAMPSContext), AMPS_TRACE_LEVEL_ERROR, "SAPI_InsertSNMEvent failed \n");
return NULL;
}*/
poAMPSLogContext->pvAMPSContext = r_pvAMPSContext;
TRACE( LOG_TRACE_ID(r_pvAMPSContext), AMPS_TRACE_LEVEL_INFO, "Leaving %p.\n", poAMPSLogContext);
return poAMPSLogContext;
}
/*****************************************************************
函数名称: Log_Cleanup
功能描述: 日志模块销毁
入参::
void* r_pvAMPSContext APMS应用上下文
出参:
返回值:
NA
*****************************************************************/
void Log_Cleanup(void* r_pvAMPSLogContext)
{
t_AMPSLogContext* poAMPSLogContext = r_pvAMPSLogContext;
void* pvAMPSContext = poAMPSLogContext->pvAMPSContext;
TRACE( LOG_TRACE_ID(pvAMPSContext), AMPS_TRACE_LEVEL_INFO, "Entering %p.\n", poAMPSLogContext);
/*关闭文件*/
SAPI_FileCloseInterface(pvAMPSContext, poAMPSLogContext->pvAMPSNetworkMsg);
AMPS_InternalFree(r_pvAMPSLogContext);
TRACE( LOG_TRACE_ID(pvAMPSContext), AMPS_TRACE_LEVEL_INFO, "Leaving.\n");
}
/*****************************************************************
函数名称: AMPS_Log
功能描述: 日志打点函数
入参::
void* r_pvAMPSContext APMS应用上下文
const char* r_puchMessage 日志内容
... 变长参数
出参:
返回值:
int
*****************************************************************/
int AMPS_Log(void* r_pvAMPSContext, const char* r_puchMessage , ...)
{
t_AMPSLogContext* poAMPSLogContext = AMPS_GetLogCtxt(r_pvAMPSContext);
t_AMPSNetworkMsg* poAMPSNetworkMsg = poAMPSLogContext->pvAMPSNetworkMsg;
t_AMPSParameterList oAMPSParameterList;
void* pvMessageToSend = NULL;
int nSizeOfMessage = 0;
int nLengthOfQueue = 0;
int nReturnValue = AMPS_ERROR_FAILURE;
int nBytesWritten = 0;
TRACE( LOG_TRACE_ID(r_pvAMPSContext), AMPS_TRACE_LEVEL_INFO, "Entering.\n");
AMPS_INIT_PARAM_LIST(oAMPSParameterList, r_puchMessage);
pvMessageToSend = AMPS_InternalMalloc(AMPS_LOG_MAX_SIZE_OF_WRITE_BUFFER);
if (NULL == pvMessageToSend)
{
TRACE( LOG_TRACE_ID(r_pvAMPSContext), AMPS_TRACE_LEVEL_ERROR, "AMPS_InternalMalloc failed for pvMessageToSend.\n");
return AMPS_ERROR_FAILURE;
}
/*组装日志信息*/
nSizeOfMessage = SAPI_WriteToString(r_pvAMPSContext, pvMessageToSend, &oAMPSParameterList, r_puchMessage);
if (0 >= nSizeOfMessage)
{
TRACE( LOG_TRACE_ID(r_pvAMPSContext), AMPS_TRACE_LEVEL_ERROR, "SAPI_WriteToString failed.\n");
AMPS_InternalFree(pvMessageToSend);
return AMPS_ERROR_FAILURE;
}
/*获取消息队列长度*/
nLengthOfQueue = Queue_GetListBasedQueueLength(r_pvAMPSContext, &poAMPSNetworkMsg->oAMPSListBasedQueue);
if(0 < nLengthOfQueue)
{
if(AMPS_SUCCESS != AMPS_EnQueueDataToNetMsgQ(r_pvAMPSContext, poAMPSNetworkMsg, &poAMPSNetworkMsg->oAMPSListBasedQueue, pvMessageToSend, nSizeOfMessage, 0, NULL))
{
TRACE( AMPS_TRACE_ID(r_pvAMPSContext), AMPS_TRACE_LEVEL_ERROR, "AMPS_EnQueueDataToNetMsgQ failed.\n");
return AMPS_ERROR_FAILURE;
}
return AMPS_SUCCESS;
}
/*写日志*/
nReturnValue = SAPI_FileWrite(r_pvAMPSContext, poAMPSNetworkMsg, pvMessageToSend, nSizeOfMessage, &nBytesWritten);
if(AMPS_ERROR_IO_PENDING == nReturnValue)
{
TRACE( LOG_TRACE_ID(r_pvAMPSContext), AMPS_TRACE_LEVEL_WARNING, "File is marked non-blocking and the write operation would block. \n");
}
else
if(AMPS_SUCCESS == nReturnValue)
{
TRACE( LOG_TRACE_ID(r_pvAMPSContext), AMPS_TRACE_LEVEL_DEBUG, "SAPI_FileWrite is successfull. \n");
AMPS_InternalFree(pvMessageToSend);
}
else
if(AMPS_ERROR_FAILURE == nReturnValue)
{
TRACE( LOG_TRACE_ID(r_pvAMPSContext), AMPS_TRACE_LEVEL_ERROR, "SAPI_FileWrite failed.\n");
AMPS_InternalFree(pvMessageToSend);
AMPS_CLEANUP_PARAM_LIST(oAMPSParameterList);
return AMPS_ERROR_FAILURE;
}
AMPS_CLEANUP_PARAM_LIST(oAMPSParameterList);
TRACE( LOG_TRACE_ID(r_pvAMPSContext), AMPS_TRACE_LEVEL_INFO, "Leaving\n");
return AMPS_SUCCESS;
}
/*****************************************************************
函数名称: Log_HandleFileWriteEvent
功能描述: 日志事件回调函数
入参::
void* r_pvAMPSContext APMS应用上下文
t_AMPSSNMEvent* r_poAMPSSNMEvent 事件上下文
t_AMPSNetworkMsg* r_poAMPSNetworkMsg
出参:
返回值:
int
*****************************************************************/
int Log_HandleFileWriteEvent(t_AMPSContext* r_poAMPSContext, t_AMPSSNMEvent* r_poAMPSSNMEvent, t_AMPSNetworkMsg* r_poAMPSNetworkMsg)
{
int nLengthOfQueue = 0;
void* pvMessageToSend = NULL;
int nSizeOfMessage = 0;
int nMessageOffSet = 0;
int nReturnValue = AMPS_ERROR_FAILURE;
int nBytesWritten = 0;
TRACE( LOG_TRACE_ID(r_poAMPSContext), AMPS_TRACE_LEVEL_DEBUG, "Event is EPOLLOUT.\n");
/*获取事件队列长度*/
nLengthOfQueue = Queue_GetListBasedQueueLength(r_poAMPSContext, &r_poAMPSNetworkMsg->oAMPSListBasedQueue);
for ( ; nLengthOfQueue > 0; nLengthOfQueue--)
{
/*从事件队列中取出消息及相关信息*/
if(AMPS_SUCCESS != AMPS_DeQueueDataFromNetMsgQ(r_poAMPSContext, r_poAMPSNetworkMsg, &r_poAMPSNetworkMsg->oAMPSListBasedQueue, &pvMessageToSend, &nSizeOfMessage, &nMessageOffSet, NULL))
{
TRACE( LOG_TRACE_ID(r_poAMPSContext), AMPS_TRACE_LEVEL_ERROR, "AMPS_DeQueueDataFromNetMsgQ failed\n");
continue;
}
if((NULL == pvMessageToSend) || (0 >= nSizeOfMessage))
{
TRACE( LOG_TRACE_ID(r_poAMPSContext), AMPS_TRACE_LEVEL_ERROR, "NULL Pointers\n");
continue;
}
/*写日志*/
nReturnValue = SAPI_FileWrite(r_poAMPSContext, r_poAMPSNetworkMsg, pvMessageToSend, nSizeOfMessage, &nBytesWritten);
if(AMPS_ERROR_IO_PENDING == nReturnValue)
{
TRACE( LOG_TRACE_ID(r_poAMPSContext), AMPS_TRACE_LEVEL_WARNING, "File is marked non-blocking and write operation would block \n");
return AMPS_SUCCESS;
}
else
if(AMPS_SUCCESS == nReturnValue)
{
TRACE( LOG_TRACE_ID(r_poAMPSContext), AMPS_TRACE_LEVEL_DEBUG, "SAPI_FileWrite is successfull. \n");
AMPS_InternalFree(pvMessageToSend);
}
else
if(AMPS_ERROR_FAILURE == nReturnValue)
{
TRACE( LOG_TRACE_ID(r_poAMPSContext), AMPS_TRACE_LEVEL_ERROR, "SAPI_FileWrite failed.\n");
AMPS_InternalFree(pvMessageToSend);
return AMPS_SUCCESS;
}
}
/*写完后,销毁注册的I/O事件*/
if (AMPS_SUCCESS != SAPI_DeleteSNMEvent(r_poAMPSContext, r_poAMPSNetworkMsg, r_poAMPSSNMEvent))
{
TRACE( LOG_TRACE_ID(r_poAMPSContext), AMPS_TRACE_LEVEL_ERROR, "SAPI_DeleteSNMEvent is failed \n");
}
return AMPS_SUCCESS;
}