|
|
/******************************************************************************
|
|
|
* file lib/management/better_log.c
|
|
|
* author YuLiang
|
|
|
* version 1.0.0
|
|
|
* date 14-Sep-2021
|
|
|
* brief This file provides all the log operation functions.
|
|
|
*
|
|
|
******************************************************************************
|
|
|
* Attention
|
|
|
*
|
|
|
* <h2><center>© COPYRIGHT(c) 2021 LandPower</center></h2>
|
|
|
*
|
|
|
* Redistribution and use in source and binary forms, with or without modification,
|
|
|
* are permitted provided that the following conditions are met:
|
|
|
* 1. Redistributions of source code must retain the above copyright notice,
|
|
|
* this list of conditions and the following disclaimer.
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
|
* and/or other materials provided with the distribution.
|
|
|
* 3. Neither the name of LandPower nor the names of its contributors may be used to
|
|
|
* endorse or promote products derived from this software without specific
|
|
|
* prior written permission.
|
|
|
*
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
*
|
|
|
******************************************************************************/
|
|
|
|
|
|
/* Includes ------------------------------------------------------------------*/
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
#include "config.h"
|
|
|
#endif
|
|
|
|
|
|
/* 标准C库头文件. */
|
|
|
#include <stdarg.h>
|
|
|
#include <sys/types.h>
|
|
|
#include <sys/stat.h>
|
|
|
#include <execinfo.h>
|
|
|
|
|
|
/* 用户代码头文件. */
|
|
|
#include <fifo.h>
|
|
|
|
|
|
/* Private define ------------------------------------------------------------*/
|
|
|
|
|
|
#define LOG_LOCK pthread_mutex_lock( &log_sys->log_mutex )
|
|
|
#define LOG_UNLOCK pthread_mutex_unlock( &log_sys->log_mutex )
|
|
|
|
|
|
#define LOG_OUT_LOCK pthread_mutex_lock( &log_sys->log_out_mutex )
|
|
|
#define LOG_OUT_UNLOCK pthread_mutex_unlock( &log_sys->log_out_mutex )
|
|
|
|
|
|
#define LOG_DB_LOCK pthread_mutex_lock(&log_sys->log_db_mutex)
|
|
|
#define LOG_DB_UNLOCK pthread_mutex_unlock(&log_sys->log_db_mutex)
|
|
|
|
|
|
#define LOG_OUT 0
|
|
|
#define LOG_SHOW 1
|
|
|
/* Private macro -------------------------------------------------------------*/
|
|
|
|
|
|
/* Private typedef -----------------------------------------------------------*/
|
|
|
|
|
|
/* Private variables ---------------------------------------------------------*/
|
|
|
_log_fifo_t log_fifo;
|
|
|
log_sys_t *log_sys;
|
|
|
_log_out_t *log_out_struct;
|
|
|
_log_show_t *log_show_struct;
|
|
|
|
|
|
static char *log_str = NULL;
|
|
|
static char *log_out_va_str = NULL;
|
|
|
static char *log_fifo_va_str = NULL;
|
|
|
|
|
|
/* log等级. */
|
|
|
static const log_lvl_t log_priority[] =
|
|
|
{
|
|
|
{LOG_LVL_ERR, "err"},
|
|
|
{LOG_LVL_WARN, "warn"},
|
|
|
{LOG_LVL_NOTIF, "notif"},
|
|
|
{LOG_LVL_INFO, "info"},
|
|
|
{LOG_LVL_DBG, "debug"},
|
|
|
{-1, NULL}
|
|
|
};
|
|
|
|
|
|
/* log模块. */
|
|
|
static const log_module_t log_module_names[] =
|
|
|
{
|
|
|
{LOG_DEFAULT, "DEFAULT"},
|
|
|
{LOG_CLI, "CLI"},
|
|
|
{LOG_MEMORY, "MEMORY"},
|
|
|
{LOG_FIFO, "FIFO"},
|
|
|
{LOG_GPIO, "GPIO"},
|
|
|
{LOG_PD, "PD"},
|
|
|
{LOG_DAU, "DAU"},
|
|
|
{LOG_CSG, "CSG"},
|
|
|
{LOG_STORAGE, "STORAGE"},
|
|
|
{LOG_DEBUG, "DEBUG"},
|
|
|
{-1, NULL}
|
|
|
};
|
|
|
|
|
|
/* Private function prototypes -----------------------------------------------*/
|
|
|
|
|
|
/* Internal functions --------------------------------------------------------*/
|
|
|
|
|
|
/* 文件log输出底层函数. */
|
|
|
static void _log_out_db( LOG_MODULE_E module, LOG_LVL_E priority, const char *va_str )
|
|
|
{
|
|
|
log_sys_t *log = log_sys;
|
|
|
|
|
|
char time_str[TIME_STR_LEN] = {0};
|
|
|
char *zErrMsg = NULL;
|
|
|
static uint64_t logCnt = 0;
|
|
|
time_string( log->timestamp_precision, time_str, sizeof(time_str) );
|
|
|
|
|
|
LOG_DB_LOCK;
|
|
|
|
|
|
memset( log_str, 0, LOG_STR_LEN );
|
|
|
snprintf( log_str, LOG_STR_LEN,
|
|
|
"INSERT INTO better_log (LEVEL,LOG) VALUES (%d, \"%s %s-%s: %s\"); ",
|
|
|
priority, time_str, log_priority[priority].describe, log_module_names[module].describe, va_str ); //id 已设为自增
|
|
|
|
|
|
if (sqlite3_exec( log->db, log_str, 0, 0, &zErrMsg ) != SQLITE_OK)
|
|
|
{
|
|
|
printh("SQL INSERT error: %s\r\n", zErrMsg);
|
|
|
sqlite3_free(zErrMsg);
|
|
|
}
|
|
|
|
|
|
/*定量清除log*/
|
|
|
logCnt++;
|
|
|
if (logCnt >= 100)
|
|
|
{
|
|
|
clock_t begin,end;
|
|
|
begin = clock();
|
|
|
log_clean();
|
|
|
end = clock();
|
|
|
printh("-------------------log_clean RunTimer : %lf----------------\r\n",(double)(end-begin)/CLOCKS_PER_SEC);
|
|
|
printh("-------------------log_clean RunTimer : %lf----------------\r\n",(double)(end-begin)/CLOCKS_PER_SEC);
|
|
|
printh("-------------------log_clean RunTimer : %lf----------------\r\n",(double)(end-begin)/CLOCKS_PER_SEC);
|
|
|
logCnt = 0;
|
|
|
}
|
|
|
|
|
|
LOG_DB_UNLOCK;
|
|
|
}
|
|
|
|
|
|
/* 解日志输出fifo数据封装 */
|
|
|
static void _log_out( _log_out_t *data )
|
|
|
{
|
|
|
_log_out_db( data->module, data->lvl, data->log_out_str );
|
|
|
}
|
|
|
|
|
|
/* 串口日志输出 */
|
|
|
static void _log_out_std( LOG_MODULE_E module, LOG_LVL_E priority, const char *va_str )
|
|
|
{
|
|
|
log_sys_t *log = log_sys;
|
|
|
|
|
|
char time_str[TIME_STR_LEN] = {0};
|
|
|
time_string(log->timestamp_precision, time_str, sizeof(time_str));
|
|
|
|
|
|
printh("%s %s-%s: %s\n", time_str, log_priority[priority].describe, log_module_names[module].describe, va_str);
|
|
|
}
|
|
|
|
|
|
/* 将日志按照格式串口打印 */
|
|
|
static int _log_show_print( void *data, int argc, char **argv, char **azColName )
|
|
|
{
|
|
|
printh("LOG id %s: %s\r\n", argv[0], argv[2]);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
/* log打印底层函数 */
|
|
|
static void _log_show( _log_show_t *data )
|
|
|
{
|
|
|
log_sys_t *log = log_sys;
|
|
|
char *zErrMsg = NULL;
|
|
|
|
|
|
LOG_DB_LOCK;
|
|
|
|
|
|
memset( log_str, 0, LOG_STR_LEN );
|
|
|
switch (data->type)
|
|
|
{
|
|
|
case LOG_SHOW_CNT: //打印指定数量的日志
|
|
|
snprintf( log_str, LOG_STR_LEN, "SELECT * FROM better_log ORDER BY id DESC LIMIT %d;", data->param );
|
|
|
break;
|
|
|
|
|
|
case LOG_SHOW_LVL: //打印指定等级的日志
|
|
|
snprintf( log_str, LOG_STR_LEN, "SELECT * FROM better_log WHERE LEVEL = %d ORDER BY id DESC LIMIT 100;", data->param );
|
|
|
break;
|
|
|
|
|
|
case LOG_SHOW_KEYWORD: //打印含关键词的日志
|
|
|
if (data->param <= 0)
|
|
|
{
|
|
|
snprintf( log_str, LOG_STR_LEN, "SELECT * FROM better_log WHERE LOG GLOB \'*%s*\' ORDER BY id DESC;",
|
|
|
data->log_show_str );
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
snprintf( log_str, LOG_STR_LEN, "SELECT * FROM better_log WHERE LOG GLOB \'*%s*\' ORDER BY id DESC LIMIT %d;",
|
|
|
data->log_show_str, data->param );
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
default: //打印所有日志
|
|
|
snprintf( log_str, LOG_STR_LEN, "SELECT * FROM better_log ORDER BY id DESC;" );
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
if (sqlite3_exec( log->db, log_str, _log_show_print, 0, &zErrMsg ) != SQLITE_OK)
|
|
|
{
|
|
|
printh("SQL show error: %s\r\n", zErrMsg);
|
|
|
sqlite3_free(zErrMsg);
|
|
|
}
|
|
|
|
|
|
LOG_DB_UNLOCK;
|
|
|
}
|
|
|
|
|
|
/* 封装数据并写fifo */
|
|
|
int32_t _log_msg_send(uint32_t type, void *data)
|
|
|
{
|
|
|
_log_msg_t log_msg;
|
|
|
|
|
|
/* 封装消息. */
|
|
|
log_msg.type = type;
|
|
|
log_msg.data = data;
|
|
|
|
|
|
/* 发送消息 */
|
|
|
if( fifo_write( log_fifo.log_fifo_id, (void*)(&log_msg), sizeof(_log_msg_t)) != sizeof(_log_msg_t) )
|
|
|
{
|
|
|
DBG( DBG_M_FIFO, "LOG write ERROR!\r\n" );
|
|
|
return E_ERROR;
|
|
|
}
|
|
|
|
|
|
return E_NONE;
|
|
|
}
|
|
|
|
|
|
/* 经由fifo输出日志 */
|
|
|
void _log_fifo_out( LOG_MODULE_E module, LOG_LVL_E priority, const char *va_str )
|
|
|
{
|
|
|
memset( log_out_struct, 0, sizeof(_log_out_t) );
|
|
|
_log_out_t *log_data = log_out_struct;
|
|
|
log_data->module = module;
|
|
|
log_data->lvl = priority;
|
|
|
memcpy( log_data->log_out_str, va_str, LOG_STR_LEN );
|
|
|
|
|
|
_log_msg_send( LOG_OUT, log_data );
|
|
|
}
|
|
|
|
|
|
/* Interface functions -------------------------------------------------------*/
|
|
|
/* log打印输出函数. */
|
|
|
#define BLOG_FUNC(FUNCNAME,PRIORITY) \
|
|
|
void FUNCNAME(LOG_MODULE_E module, const char *format, ...) \
|
|
|
{ \
|
|
|
log_sys_t *log = log_sys; \
|
|
|
if (NULL == log) return; \
|
|
|
LOG_LOCK; \
|
|
|
memset( log_fifo_va_str, 0, LOG_STR_LEN ); \
|
|
|
va_list args; \
|
|
|
va_start(args, format); \
|
|
|
vsnprintf(log_fifo_va_str, LOG_STR_LEN, format, args); \
|
|
|
va_end(args); \
|
|
|
if ((1 << PRIORITY) & log->enable_lvl[LOG_MODE_STDOUT]) \
|
|
|
_log_out_std(module, PRIORITY, log_fifo_va_str); \
|
|
|
if (((1 << PRIORITY) & log->enable_lvl[LOG_MODE_FILE]) && log->db){ \
|
|
|
if (log_fifo.log_fifo_id) \
|
|
|
_log_out_db(module, PRIORITY, log_fifo_va_str); \
|
|
|
else \
|
|
|
_log_fifo_out(module, PRIORITY, log_fifo_va_str);} \
|
|
|
LOG_UNLOCK; \
|
|
|
}
|
|
|
|
|
|
BLOG_FUNC(log_err, LOG_LVL_ERR)
|
|
|
BLOG_FUNC(log_warn, LOG_LVL_WARN)
|
|
|
BLOG_FUNC(log_info, LOG_LVL_INFO)
|
|
|
BLOG_FUNC(log_notice, LOG_LVL_NOTIF)
|
|
|
BLOG_FUNC(log_debug, LOG_LVL_DBG)
|
|
|
#undef BLOG_FUNC
|
|
|
|
|
|
/* description: log输出.
|
|
|
param: module -- 指定模块
|
|
|
priority -- 指定优先级
|
|
|
return: */
|
|
|
void log_out(LOG_MODULE_E module, LOG_LVL_E priority, const char *format, ...)
|
|
|
{
|
|
|
log_sys_t *log = log_sys;
|
|
|
if (NULL == log) return;
|
|
|
|
|
|
LOG_OUT_LOCK;
|
|
|
|
|
|
memset( log_out_va_str, 0, LOG_STR_LEN );
|
|
|
va_list args;
|
|
|
va_start(args, format);
|
|
|
vsnprintf(log_out_va_str, LOG_STR_LEN, format, args);
|
|
|
va_end (args);
|
|
|
|
|
|
/* 串口log. */
|
|
|
if ((1 << priority) & log->enable_lvl[LOG_MODE_STDOUT])
|
|
|
_log_out_std(module, priority, log_out_va_str);
|
|
|
|
|
|
/* 判断是否是文件输出 */
|
|
|
if (((1 << priority) & log->enable_lvl[LOG_MODE_FILE]) && log->db)
|
|
|
_log_out_db(module, priority, log_out_va_str);
|
|
|
|
|
|
LOG_OUT_UNLOCK;
|
|
|
}
|
|
|
|
|
|
/* 打印日志函数 */
|
|
|
void log_show( int32_t show_cnt, LOG_LVL_E priority, const char *key_word )
|
|
|
{
|
|
|
memset( log_show_struct, 0, sizeof(_log_show_t) );
|
|
|
_log_show_t *log_data = log_show_struct;
|
|
|
|
|
|
if (priority != LOG_LVL_MAX) // 按等级打印日志
|
|
|
{
|
|
|
log_data->type = LOG_SHOW_LVL;
|
|
|
log_data->param = priority;
|
|
|
}
|
|
|
else if (key_word != NULL) // 高级打印功能
|
|
|
{
|
|
|
log_data->type = LOG_SHOW_KEYWORD;
|
|
|
log_data->param = show_cnt;
|
|
|
memcpy( log_data->log_show_str, key_word, LOG_STR_LEN );
|
|
|
}
|
|
|
else if (show_cnt > 0) // 按数量打印日志
|
|
|
{
|
|
|
log_data->type = LOG_SHOW_CNT;
|
|
|
log_data->param = show_cnt;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
log_data->type = LOG_SHOW_MAX;
|
|
|
}
|
|
|
|
|
|
_log_msg_send( LOG_SHOW, log_data );
|
|
|
}
|
|
|
|
|
|
/* description: log系统初始化.
|
|
|
param:
|
|
|
return: (0)完成,(-1)失败 */
|
|
|
int32_t log_open()
|
|
|
{
|
|
|
log_sys_t *log = NULL;
|
|
|
int32_t i = 0;
|
|
|
int32_t rv = 0;
|
|
|
char *sql = NULL;
|
|
|
char *zErrMsg = NULL;
|
|
|
|
|
|
/* 申请内存. */
|
|
|
log_str = XMALLOC(MTYPE_LOG, LOG_STR_LEN);
|
|
|
log_out_va_str = XMALLOC(MTYPE_LOG, LOG_STR_LEN);
|
|
|
log_fifo_va_str = XMALLOC(MTYPE_LOG, LOG_STR_LEN);
|
|
|
|
|
|
log_out_struct = XMALLOC(MTYPE_LOG, sizeof(_log_out_t));
|
|
|
log_show_struct = XMALLOC(MTYPE_LOG, sizeof(_log_show_t));
|
|
|
log_sys = XMALLOC(MTYPE_LOG, sizeof(log_sys_t));
|
|
|
|
|
|
if (NULL == log_sys)
|
|
|
{
|
|
|
return E_MEM;
|
|
|
}
|
|
|
|
|
|
log = log_sys;
|
|
|
|
|
|
pthread_mutex_init(&log->log_mutex, NULL);
|
|
|
pthread_mutex_init(&log->log_out_mutex, NULL);
|
|
|
pthread_mutex_init(&log->log_db_mutex, NULL);
|
|
|
|
|
|
/* 打开 log 数据库. */
|
|
|
log->filename = XSTRDUP(MTYPE_LOG, LOG_FILE);
|
|
|
rv = sqlite3_open(log->filename, &log->db);
|
|
|
if (rv)
|
|
|
{
|
|
|
log->db = NULL;
|
|
|
printf("Can't open database: %s\r\n", sqlite3_errmsg(log->db));
|
|
|
return E_SYS_CALL;
|
|
|
}
|
|
|
|
|
|
/* 创建表. */
|
|
|
sql = "CREATE TABLE IF NOT EXISTS better_log(" \
|
|
|
"ID INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," \
|
|
|
"LEVEL INT8 NOT NULL," \
|
|
|
"LOG TEXT);";
|
|
|
if (sqlite3_exec(log->db, sql, 0, 0, &zErrMsg) != SQLITE_OK)
|
|
|
{
|
|
|
printf("SQL create error: %s\r\n", zErrMsg);
|
|
|
sqlite3_free(zErrMsg);
|
|
|
}
|
|
|
|
|
|
/* 设置默认log级别输出方式 */
|
|
|
for (i = 0; i < LOG_MODE_MAX; i++)
|
|
|
{
|
|
|
log->enable_lvl[i] = 0;
|
|
|
}
|
|
|
log->enable_lvl[LOG_MODE_FILE] = (1 << LOG_LVL_ERR) | (1 << LOG_LVL_WARN) | (1 << LOG_LVL_NOTIF);
|
|
|
log->enable_lvl[LOG_MODE_STDOUT] = (1 << LOG_LVL_ERR) | (1 << LOG_LVL_WARN) | (1 << LOG_LVL_NOTIF);
|
|
|
log->enable_lvl[LOG_MODE_MONITOR] = (1 << LOG_LVL_ERR) | (1 << LOG_LVL_WARN) | (1 << LOG_LVL_NOTIF);
|
|
|
log->default_lvl = 0;
|
|
|
|
|
|
return E_NONE;
|
|
|
}
|
|
|
|
|
|
/* description: 配置对应等级的log的输出方式.
|
|
|
param: mode -- 输出方式
|
|
|
log_level -- 输出等级
|
|
|
return: */
|
|
|
void log_set_level(LOG_MODE_E mode, LOG_LVL_E log_level)
|
|
|
{
|
|
|
log_sys->enable_lvl[mode] |= (1 << log_level);
|
|
|
}
|
|
|
|
|
|
/* description: 取消对应等级的log的输出方式.
|
|
|
param: mode -- 输出方式
|
|
|
log_level -- 输出等级
|
|
|
return: */
|
|
|
void log_unset_level(LOG_MODE_E mode, LOG_LVL_E log_level)
|
|
|
{
|
|
|
log_sys->enable_lvl[mode] &= ~(1 << log_level);
|
|
|
}
|
|
|
|
|
|
/* description: 根据传入的字符串返回相应的log优先级.
|
|
|
param: lvl_name -- 输出等级的字符串
|
|
|
return: (LOG_LVL_E)输出等级 */
|
|
|
int32_t log_level_get_by_name(const char *lvl_name)
|
|
|
{
|
|
|
int32_t level = LOG_LVL_MAX;
|
|
|
|
|
|
for (level = 0 ; log_priority[level].describe != NULL ; level++)
|
|
|
if (!strncmp(lvl_name, log_priority[level].describe, 2))
|
|
|
return log_priority[level].lvl;
|
|
|
|
|
|
return LOG_LVL_MAX;
|
|
|
}
|
|
|
|
|
|
/* 打印堆栈使用情况: */
|
|
|
/* description: 根据传入的字符串返回相应的log优先级.
|
|
|
param: priority -- log优先级
|
|
|
return: */
|
|
|
void log_backtrace(int32_t priority)
|
|
|
{
|
|
|
void *array[BACKTRACE_SIZE] = {NULL};
|
|
|
int32_t size = 0;
|
|
|
int32_t i = 0;
|
|
|
char **strings = NULL;
|
|
|
|
|
|
size = backtrace(array, BACKTRACE_SIZE);
|
|
|
if ((size <= 0) || ((size_t)size > BACKTRACE_SIZE))
|
|
|
{
|
|
|
log_err(LOG_DEFAULT, "Cannot get backtrace, returned invalid # of frames %d "
|
|
|
"(valid range is between 1 and %d)", size, BACKTRACE_SIZE);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
log_out(LOG_DEFAULT, priority, "Backtrace for %d stack frames:", size);
|
|
|
strings = backtrace_symbols(array, size);
|
|
|
if (!strings)
|
|
|
{
|
|
|
log_out(LOG_DEFAULT, priority, "Cannot get backtrace symbols (out of memory?)");
|
|
|
for (i = 0; i < size; i++)
|
|
|
log_out(LOG_DEFAULT, priority, "[bt %d] %p", i, array[i]);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
for (i = 0; i < size; i++)
|
|
|
log_out(LOG_DEFAULT, priority, "[bt %d] %s",i,strings[i]);
|
|
|
free(strings);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* 删除多余的 log 保留 5000 条. */
|
|
|
void log_clean(void)
|
|
|
{
|
|
|
log_sys_t *log = log_sys;
|
|
|
char *zErrMsg = NULL;
|
|
|
const char *sql = "delete from better_log where id<(select Max(id) from better_log)-5000;";
|
|
|
|
|
|
if (sqlite3_exec(log->db, sql, 0, 0, &zErrMsg) != SQLITE_OK)
|
|
|
{
|
|
|
printh("SQL delete error: %s\r\n", zErrMsg);
|
|
|
sqlite3_free(zErrMsg);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* 读取log fifo数据循环线程 */
|
|
|
void *_log_handle( void *arg )
|
|
|
{
|
|
|
_log_msg_t *recv_msg = NULL;
|
|
|
|
|
|
while(1)
|
|
|
{
|
|
|
if (fifo_read( log_fifo.log_fifo_id, (void **)&recv_msg ) != 0)
|
|
|
{
|
|
|
DBG( DBG_M_FIFO, "ERROR at fifo %d read!\r\n", log_fifo.log_fifo_id );
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
if (recv_msg->type == LOG_OUT) //输出日志,写数据库
|
|
|
{
|
|
|
_log_out( (_log_out_t*) recv_msg->data );
|
|
|
}
|
|
|
else if (recv_msg->type == LOG_SHOW) //打印日志,读数据库
|
|
|
{
|
|
|
_log_show( (_log_show_t*) recv_msg->data );
|
|
|
}
|
|
|
|
|
|
fifo_push( log_fifo.log_fifo_id );
|
|
|
}
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
/* log线程初始化函数 */
|
|
|
int32_t _log_init_common( void )
|
|
|
{
|
|
|
struct sched_param param;
|
|
|
pthread_attr_t attr;
|
|
|
pthread_t pid;
|
|
|
int rv = 0;
|
|
|
|
|
|
/* 初始化log fifo */
|
|
|
log_fifo.log_fifo_id = fifo_create( LOG_DB_FIFO, 32 );
|
|
|
if (log_fifo.log_fifo_id < 0)
|
|
|
{
|
|
|
log_out( LOG_DEFAULT, LOG_LVL_ERR, "Open fifo " LOG_DB_FIFO " error." );
|
|
|
return E_ERROR;
|
|
|
}
|
|
|
pthread_mutex_init( &log_fifo.mutex, NULL );
|
|
|
|
|
|
/* 配置线程RR调度,优先级50 */
|
|
|
pthread_attr_init( &attr );
|
|
|
param.sched_priority = 25;
|
|
|
pthread_attr_setschedpolicy( &attr, SCHED_RR );
|
|
|
pthread_attr_setschedparam( &attr, ¶m );
|
|
|
pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED );
|
|
|
rv = pthread_create( &pid, &attr, _log_handle, NULL );
|
|
|
if (rv != 0)
|
|
|
{
|
|
|
log_out( LOG_DEFAULT, LOG_LVL_ERR, "PD can't create log db pthread %d.", rv );
|
|
|
return E_SYS_CALL;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
thread_m_add( "LOG_DB_THREAD", pid );
|
|
|
}
|
|
|
pthread_attr_destroy( &attr );
|
|
|
|
|
|
return E_NONE;
|
|
|
}
|
|
|
|
|
|
int32_t log_handle_init( void )
|
|
|
{
|
|
|
LD_E_RETURN( DBG_M_DBG, _log_init_common() );
|
|
|
return E_NONE;
|
|
|
}
|
|
|
/************************ (C) COPYRIGHT LandPower ***** END OF FILE ****************/
|