Commit 2653a04f authored by wujing's avatar wujing

add log-mem function to collect log

parent 8f4a842c
...@@ -45,7 +45,19 @@ ...@@ -45,7 +45,19 @@
#include "common/config/config_userapi.h" #include "common/config/config_userapi.h"
// main log variables // main log variables
log_mem_cnt_t log_mem_d[2];
int log_mem_flag=0;
int log_mem_multi=1;
volatile int log_mem_side=0;
pthread_mutex_t log_mem_lock;
pthread_cond_t log_mem_notify;
pthread_t log_mem_thread;
int log_mem_file_cnt=0;
volatile int log_mem_write_flag=0;
volatile int log_mem_write_side=0;
char __log_mem_filename[1024]={0};
char * log_mem_filename = &__log_mem_filename[0];
char logmem_filename[1024] = {0};
mapping log_level_names[] = { mapping log_level_names[] = {
...@@ -456,15 +468,23 @@ void logRecord_mt(const char *file, const char *func, int line, int comp, int le ...@@ -456,15 +468,23 @@ void logRecord_mt(const char *file, const char *func, int line, int comp, int le
char log_buffer[MAX_LOG_TOTAL]; char log_buffer[MAX_LOG_TOTAL];
va_list args; va_list args;
va_start(args, format); va_start(args, format);
if (log_mem_flag == 1) {
log_output_memory(file,func,line,comp,level, format,args);
} else {
log_header(log_buffer,MAX_LOG_TOTAL,comp, level,format); log_header(log_buffer,MAX_LOG_TOTAL,comp, level,format);
g_log->log_component[comp].vprint(g_log->log_component[comp].stream,log_buffer, args); g_log->log_component[comp].vprint(g_log->log_component[comp].stream,log_buffer, args);
}
va_end(args); va_end(args);
} }
void vlogRecord_mt(const char *file, const char *func, int line, int comp, int level, const char *format, va_list args ) { void vlogRecord_mt(const char *file, const char *func, int line, int comp, int level, const char *format, va_list args ) {
char log_buffer[MAX_LOG_TOTAL]; char log_buffer[MAX_LOG_TOTAL];
if (log_mem_flag == 1) {
log_output_memory(file,func,line,comp,level, format,args);
} else {
log_header(log_buffer,MAX_LOG_TOTAL,comp, level,format); log_header(log_buffer,MAX_LOG_TOTAL,comp, level,format);
g_log->log_component[comp].vprint(g_log->log_component[comp].stream,log_buffer, args); g_log->log_component[comp].vprint(g_log->log_component[comp].stream,log_buffer, args);
}
} }
void log_dump(int component, void *buffer, int buffsize,int datatype, const char *format, ... ) { void log_dump(int component, void *buffer, int buffsize,int datatype, const char *format, ... ) {
...@@ -646,6 +666,265 @@ void logClean (void) { ...@@ -646,6 +666,265 @@ void logClean (void) {
} }
} }
extern int oai_exit;
void flush_mem_to_file(void)
{
int fp;
char f_name[1024];
struct timespec slp_tm;
slp_tm.tv_sec = 0;
slp_tm.tv_nsec = 10000;
pthread_setname_np( pthread_self(), "flush_mem_to_file");
while (!oai_exit) {
pthread_mutex_lock(&log_mem_lock);
log_mem_write_flag=0;
pthread_cond_wait(&log_mem_notify, &log_mem_lock);
log_mem_write_flag=1;
pthread_mutex_unlock(&log_mem_lock);
// write!
if(log_mem_d[log_mem_write_side].enable_flag==0){
if(log_mem_file_cnt>5){
log_mem_file_cnt=5;
printf("log over write!!!\n");
}
snprintf(f_name,1024, "%s_%d.log",log_mem_filename,log_mem_file_cnt);
fp=open(f_name, O_WRONLY | O_CREAT, 0666);
int ret = write(fp, log_mem_d[log_mem_write_side].buf_p, log_mem_d[log_mem_write_side].buf_index);
if ( ret < 0) {
fprintf(stderr,"{LOG} %s %d Couldn't write in %s \n",__FILE__,__LINE__,f_name);
exit(EXIT_FAILURE);
}
close(fp);
log_mem_file_cnt++;
log_mem_d[log_mem_write_side].buf_index=0;
log_mem_d[log_mem_write_side].enable_flag=1;
}else{
printf("If you'd like to write log, you should set enable flag to 0!!!\n");
nanosleep(&slp_tm,NULL);
}
}
}
char logmem_log_level[NUM_LOG_LEVEL]={'E','W','I','D','T'};
void log_output_memory(const char *file, const char *func, int line, int comp, int level, const char* format,va_list args)
{
//logRecord_mt(file,func,line, pthread_self(), comp, level, format, ##args)
int len = 0;
log_component_t *c;
char *log_start;
char *log_end;
/* The main difference with the version above is the use of this local log_buffer.
* The other difference is the return value of snprintf which was not used
* correctly. It was not a big problem because in practice MAX_LOG_TOTAL is
* big enough so that the buffer is never full.
*/
char log_buffer[MAX_LOG_TOTAL];
/* for no gcc warnings */
(void)log_start;
(void)log_end;
c = &g_log->log_component[comp];
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LOG_RECORD, VCD_FUNCTION_IN);
// make sure that for log trace the extra info is only printed once, reset when the level changes
if (level == OAILOG_TRACE) {
log_start = log_buffer;
len = vsnprintf(log_buffer, MAX_LOG_TOTAL, format, args);
if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
log_end = log_buffer + len;
} else {
if ( (g_log->flag & 0x001) || (c->flag & 0x001) ) {
len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "%s",
log_level_highlight_start[level]);
if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
}
log_start = log_buffer + len;
// if ( (g_log->flag & 0x004) || (c->flag & 0x004) ) {
len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "[%s]",
g_log->log_component[comp].name);
if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
// }
if ( (level >= OAILOG_ERR) && (level <= OAILOG_TRACE) ) {
len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "[%c]",
logmem_log_level[level]);
if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
}
if ( (g_log->flag & FLAG_THREAD) || (c->flag & FLAG_THREAD) ) {
# define THREAD_NAME_LEN 128
char threadname[THREAD_NAME_LEN];
if (pthread_getname_np(pthread_self(), threadname, THREAD_NAME_LEN) != 0)
{
perror("pthread_getname_np : ");
} else {
len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "[%s]", threadname);
if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
}
# undef THREAD_NAME_LEN
}
if ( (g_log->flag & FLAG_FUNCT) || (c->flag & FLAG_FUNCT) ) {
len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "[%s] ",
func);
if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
}
if ( (g_log->flag & FLAG_FILE_LINE) || (c->flag & FLAG_FILE_LINE) ) {
len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "[%s:%d]",
file, line);
if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
}
/* len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "[%08lx]", thread_id);
if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
struct timeval gettime;
gettimeofday(&gettime,NULL);
len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "[%ld.%06ld]", gettime.tv_sec, gettime.tv_usec);
if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
*/
if ( (g_log->flag & FLAG_NOCOLOR) || (c->flag & FLAG_NOCOLOR) ) {
len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "%s",
log_level_highlight_end[level]);
if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
}
len += vsnprintf(&log_buffer[len], MAX_LOG_TOTAL - len, format, args);
if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
log_end = log_buffer + len;
}
//va_end(args);
// OAI printf compatibility
if(log_mem_flag==1){
if(log_mem_d[log_mem_side].enable_flag==1){
int temp_index;
temp_index=log_mem_d[log_mem_side].buf_index;
if(temp_index+len+1 < LOG_MEM_SIZE){
log_mem_d[log_mem_side].buf_index+=len;
memcpy(&log_mem_d[log_mem_side].buf_p[temp_index],log_buffer,len);
}else{
log_mem_d[log_mem_side].enable_flag=0;
if(log_mem_d[1-log_mem_side].enable_flag==1){
temp_index=log_mem_d[1-log_mem_side].buf_index;
if(temp_index+len+1 < LOG_MEM_SIZE){
log_mem_d[1-log_mem_side].buf_index+=len;
log_mem_side=1-log_mem_side;
memcpy(&log_mem_d[log_mem_side].buf_p[temp_index],log_buffer,len);
/* write down !*/
if (pthread_mutex_lock(&log_mem_lock) != 0) {
return;
}
if(log_mem_write_flag==0){
log_mem_write_side=1-log_mem_side;
if(pthread_cond_signal(&log_mem_notify) != 0) {
}
}
if(pthread_mutex_unlock(&log_mem_lock) != 0) {
return;
}
}else{
log_mem_d[1-log_mem_side].enable_flag=0;
}
}
}
}
}else{
fwrite(log_buffer, len, 1, stdout);
}
}
int logInit_log_mem (void)
{
if(log_mem_flag==1){
if(log_mem_multi==1){
printf("log-mem multi!!!\n");
log_mem_d[0].buf_p = malloc(LOG_MEM_SIZE);
log_mem_d[0].buf_index=0;
log_mem_d[0].enable_flag=1;
log_mem_d[1].buf_p = malloc(LOG_MEM_SIZE);
log_mem_d[1].buf_index=0;
log_mem_d[1].enable_flag=1;
log_mem_side=0;
if ((pthread_mutex_init (&log_mem_lock, NULL) != 0)
|| (pthread_cond_init (&log_mem_notify, NULL) != 0)) {
log_mem_d[1].enable_flag=0;
return -1;
}
pthread_create(&log_mem_thread, NULL, (void *(*)(void *))flush_mem_to_file, (void*)NULL);
}else{
printf("log-mem single!!!\n");
log_mem_d[0].buf_p = malloc(LOG_MEM_SIZE);
log_mem_d[0].buf_index=0;
log_mem_d[0].enable_flag=1;
log_mem_d[1].enable_flag=0;
log_mem_side=0;
}
}else{
log_mem_d[0].buf_p=NULL;
log_mem_d[1].buf_p=NULL;
log_mem_d[0].enable_flag=0;
log_mem_d[1].enable_flag=0;
}
printf("log init done\n");
return 0;
}
void close_log_mem(void){
int fp;
char f_name[1024];
if(log_mem_flag==1){
log_mem_d[0].enable_flag=0;
log_mem_d[1].enable_flag=0;
usleep(10); // wait for log writing
while(log_mem_write_flag==1){
usleep(100);
}
if(log_mem_multi==1){
snprintf(f_name,1024, "%s_%d.log",log_mem_filename,log_mem_file_cnt);
fp=open(f_name, O_WRONLY | O_CREAT, 0666);
int ret = write(fp, log_mem_d[0].buf_p, log_mem_d[0].buf_index);
if ( ret < 0) {
fprintf(stderr,"{LOG} %s %d Couldn't write in %s \n",__FILE__,__LINE__,f_name);
exit(EXIT_FAILURE);
}
close(fp);
free(log_mem_d[0].buf_p);
snprintf(f_name,1024, "%s_%d.log",log_mem_filename,log_mem_file_cnt);
fp=open(f_name, O_WRONLY | O_CREAT, 0666);
ret = write(fp, log_mem_d[1].buf_p, log_mem_d[1].buf_index);
if ( ret < 0) {
fprintf(stderr,"{LOG} %s %d Couldn't write in %s \n",__FILE__,__LINE__,f_name);
exit(EXIT_FAILURE);
}
close(fp);
free(log_mem_d[1].buf_p);
}else{
fp=open(log_mem_filename, O_WRONLY | O_CREAT, 0666);
int ret = write(fp, log_mem_d[0].buf_p, log_mem_d[0].buf_index);
if ( ret < 0) {
fprintf(stderr,"{LOG} %s %d Couldn't write in %s \n",__FILE__,__LINE__,log_mem_filename);
exit(EXIT_FAILURE);
}
close(fp);
free(log_mem_d[0].buf_p);
}
}
}
#ifdef LOG_TEST #ifdef LOG_TEST
......
...@@ -118,6 +118,8 @@ extern "C" { ...@@ -118,6 +118,8 @@ extern "C" {
#define FLAG_NOCOLOR 0x0001 /*!< \brief use colors in log messages, depending on level */ #define FLAG_NOCOLOR 0x0001 /*!< \brief use colors in log messages, depending on level */
#define FLAG_THREAD 0x0008 /*!< \brief display thread name in log messages */ #define FLAG_THREAD 0x0008 /*!< \brief display thread name in log messages */
#define FLAG_LEVEL 0x0010 /*!< \brief display log level in log messages */ #define FLAG_LEVEL 0x0010 /*!< \brief display log level in log messages */
#define FLAG_FUNCT 0x0020
#define FLAG_FILE_LINE 0x0040
#define FLAG_TIME 0x0100 #define FLAG_TIME 0x0100
#define FLAG_INITIALIZED 0x8000 #define FLAG_INITIALIZED 0x8000
...@@ -307,6 +309,19 @@ int is_newline( char *str, int size); ...@@ -307,6 +309,19 @@ int is_newline( char *str, int size);
int register_log_component(char *name, char *fext, int compidx); int register_log_component(char *name, char *fext, int compidx);
#define LOG_MEM_SIZE 100*1024*1024
#define LOG_MEM_FILE "./logmem.log"
void flush_mem_to_file(void);
void log_output_memory(const char *file, const char *func, int line, int comp, int level, const char* format,va_list args);
int logInit_log_mem(void);
void close_log_mem(void);
typedef struct {
char* buf_p;
int buf_index;
int enable_flag;
} log_mem_cnt_t;
/* @}*/ /* @}*/
/*!\fn int32_t write_file_matlab(const char *fname, const char *vname, void *data, int length, int dec, char format); /*!\fn int32_t write_file_matlab(const char *fname, const char *vname, void *data, int length, int dec, char format);
......
...@@ -27,4 +27,6 @@ extern log_t *g_log; ...@@ -27,4 +27,6 @@ extern log_t *g_log;
extern mapping log_level_names[]; extern mapping log_level_names[];
extern mapping log_options[]; extern mapping log_options[];
extern mapping log_maskmap[]; extern mapping log_maskmap[];
extern int log_mem_flag;
extern char * log_mem_filename;
extern char logmem_filename[1024];
...@@ -60,6 +60,7 @@ void get_common_options(void) { ...@@ -60,6 +60,7 @@ void get_common_options(void) {
uint32_t nonbiot; uint32_t nonbiot;
uint32_t rfsim; uint32_t rfsim;
uint32_t basicsim; uint32_t basicsim;
char *logmem_filename = NULL;
paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC ; paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC ;
paramdef_t cmdline_logparams[] =CMDLINE_LOGPARAMS_DESC ; paramdef_t cmdline_logparams[] =CMDLINE_LOGPARAMS_DESC ;
checkedparam_t cmdline_log_CheckParams[] = CMDLINE_LOGPARAMS_CHECK_DESC; checkedparam_t cmdline_log_CheckParams[] = CMDLINE_LOGPARAMS_CHECK_DESC;
...@@ -80,6 +81,13 @@ void get_common_options(void) { ...@@ -80,6 +81,13 @@ void get_common_options(void) {
load_module_shlib("telnetsrv",NULL,0,NULL); load_module_shlib("telnetsrv",NULL,0,NULL);
} }
if (logmem_filename != NULL && strlen(logmem_filename) > 0) {
log_mem_filename = &logmem_filename[0];
log_mem_flag = 1;
printf("Enabling OPT for log save at memory %s\n",log_mem_filename);
logInit_log_mem();
}
if (noS1) { if (noS1) {
set_softmodem_optmask(SOFTMODEM_NOS1_BIT); set_softmodem_optmask(SOFTMODEM_NOS1_BIT);
} }
......
...@@ -279,7 +279,7 @@ void exit_function(const char *file, const char *function, const int line, const ...@@ -279,7 +279,7 @@ void exit_function(const char *file, const char *function, const int line, const
if (s != NULL) { if (s != NULL) {
printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, s); printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, s);
} }
close_log_mem();
oai_exit = 1; oai_exit = 1;
if (RC.ru == NULL) if (RC.ru == NULL)
......
...@@ -222,6 +222,7 @@ ...@@ -222,6 +222,7 @@
{"g" , CONFIG_HLP_LOGL, 0, uptr:&glog_level, defintval:0, TYPE_UINT, 0}, \ {"g" , CONFIG_HLP_LOGL, 0, uptr:&glog_level, defintval:0, TYPE_UINT, 0}, \
{"telnetsrv", CONFIG_HLP_TELN, PARAMFLAG_BOOL, uptr:&start_telnetsrv, defintval:0, TYPE_UINT, 0}, \ {"telnetsrv", CONFIG_HLP_TELN, PARAMFLAG_BOOL, uptr:&start_telnetsrv, defintval:0, TYPE_UINT, 0}, \
{"msc", CONFIG_HLP_MSC, PARAMFLAG_BOOL, uptr:&START_MSC, defintval:0, TYPE_UINT, 0}, \ {"msc", CONFIG_HLP_MSC, PARAMFLAG_BOOL, uptr:&START_MSC, defintval:0, TYPE_UINT, 0}, \
{"log-mem", NULL, 0, strptr:(char **)&logmem_filename, defstrval:NULL, TYPE_STRING, 0}, \
} }
#define CMDLINE_ONLINELOG_IDX 0 #define CMDLINE_ONLINELOG_IDX 0
#define CMDLINE_GLOGLEVEL_IDX 1 #define CMDLINE_GLOGLEVEL_IDX 1
...@@ -233,6 +234,7 @@ ...@@ -233,6 +234,7 @@
{ .s2= { config_check_intrange, {0,4}}}, \ { .s2= { config_check_intrange, {0,4}}}, \
{ .s5= {NULL }} , \ { .s5= {NULL }} , \
{ .s5= {NULL }} , \ { .s5= {NULL }} , \
{ .s5= {NULL }} , \
} }
/***************************************************************************************************************************************/ /***************************************************************************************************************************************/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment