#include "tc_system.h" /** * CSI(Control Sequence Introducer/Initiator) sign * more information on https://en.wikipedia.org/wiki/ANSI_escape_code */ #define CSI_START "\033[" #define CSI_END "\033[0m" /* output log front color */ #define F_BLACK "30;" #define F_RED "31;" #define F_GREEN "32;" #define F_YELLOW "33;" #define F_BLUE "34;" #define F_MAGENTA "35;" #define F_CYAN "36;" #define F_WHITE "37;" /* output log background color */ #define B_NULL #define B_BLACK "40;" #define B_RED "41;" #define B_GREEN "42;" #define B_YELLOW "43;" #define B_BLUE "44;" #define B_MAGENTA "45;" #define B_CYAN "46;" #define B_WHITE "47;" /* output log fonts style */ #define S_BOLD "1m" #define S_UNDERLINE "4m" #define S_BLINK "5m" #define S_NORMAL "22m" /* output log default color definition: [front color] + [background color] + [show style] */ /* color output info */ static const char *console_color_info[] = { [CLOG_LVL_ASSERT] = (F_MAGENTA B_NULL S_NORMAL), [CLOG_LVL_ERROR] = (F_RED B_NULL S_NORMAL), [CLOG_LVL_WARN] = (F_YELLOW B_NULL S_NORMAL), [CLOG_LVL_INFO] = (F_CYAN B_NULL S_NORMAL), [CLOG_LVL_DEBUG] = (F_GREEN B_NULL S_NORMAL), [CLOG_LVL_VERBOSE] = (F_BLUE B_NULL S_NORMAL), }; typedef struct clog { char buff[CLOG_BUFF_SIZE]; int idx_r; int idx_w; int bytes; sem_t sempare; pthread_mutex_t mutex; pthread_t threadID; char *log_pathname; char *log_filename; FILE *fp; int log_filesize; // bytes current file int max_filesize; // bytes pre file int max_filenumb; // files from running time_t utc; struct tm ltm; int quit; char** flist; time_t *flutc; int fnumb; //---------------- int xhlog_fd; struct sockaddr_in peer_addr; socklen_t peer_addrlen; // struct sockaddr_in self_addr; // socklen_t self_addrlen; }clog_t; static clog_t clogger; void clog_bind_serverip(const char* serverip, short port) { clog_t *dev = (clog_t*)&clogger; dev->xhlog_fd = socket(AF_INET, SOCK_DGRAM, 0); dev->peer_addr.sin_family = AF_INET; dev->peer_addr.sin_addr.s_addr = inet_addr(serverip); dev->peer_addr.sin_port = htons(port); dev->peer_addrlen = sizeof(dev->peer_addr); printf("clog.sendto(%s.%d).\n", serverip, port); } int clog_sendto_serverip(uint8_t *loginfo) { clog_t *dev = (clog_t*)&clogger; if (dev->xhlog_fd > 0) { char logline[CLOG_LINE_SIZE]={0}; int length = sprintf(logline, "HW | %s", loginfo); int ret = sendto(dev->xhlog_fd, logline, length, 0, (struct sockaddr*)&dev->peer_addr, dev->peer_addrlen); if (ret < 0) { printf("clog_sendto_serverip.errno=%d, ret=%d, log:%s\n", errno, ret, logline); } return ret; } return -1; } void show_flist(clog_t* dev) { int i; printf("\nflist.fnumb:%d\n", dev->fnumb); for (i=0; ifnumb; i++) { printf("flist:%d, utc:%ld, log_filename:%s\n", i, dev->flutc[i], dev->flist[i]); } printf("\n"); } static void clog_flast(clog_t* dev, time_t lutc, char* log_filename) { if (dev) { int i; if (dev->fnumb < dev->max_filenumb) { for (i = dev->fnumb; i > 0; i--) { if (lutc == dev->flutc[i - 1]){ //在缓存队列中已经存在这个文件,不行再次保存这个文件 return; }else if (lutc < dev->flutc[i - 1]) { dev->flutc[i] = dev->flutc[i-1]; strcpy(dev->flist[i], dev->flist[i-1]); }else{ break; } } dev->flutc[i] = lutc; strcpy(dev->flist[i], log_filename); dev->fnumb++; } else { if (lutc < dev->flutc[0]) return;//不需加入缓存队列 time_t tutc = lutc; char lfilename[256]; char tfilename[512]; char *pfilename = lfilename; strcpy(lfilename, log_filename); for (i = dev->fnumb - 1; i >= 0; i--) { if (lutc > dev->flutc[i]) { tutc = dev->flutc[i]; dev->flutc[i] = lutc; lutc = tutc; strcpy(tfilename, dev->flist[i]); strcpy(dev->flist[i], lfilename); strcpy(lfilename, tfilename); }else{ break; } if (lutc == dev->flutc[i]) return; } snprintf(tfilename, 511, "%s/%s", dev->log_pathname, pfilename); remove(tfilename); } // show_flist(dev); } } static void clog_fload(clog_t* dev) { if (dev) { DIR *dir = NULL; int len = strlen(dev->log_filename); dir = opendir(dev->log_pathname); if (dir) { struct tm ltm; struct dirent *dirent = NULL; while ((dirent = readdir(dir))) { if (strncmp(dirent->d_name, dev->log_filename, len)==0) { // memset(<m, 9, sizeof(ltm)); char* ftime = &dirent->d_name[len+1]; sscanf(ftime, "%4d%2d%2d_%2d%2d%2d.log", <m.tm_year, <m.tm_mon, <m.tm_mday, <m.tm_hour, <m.tm_min, <m.tm_sec); ltm.tm_year -= 1900; ltm.tm_mon -= 1; ltm.tm_isdst = -1; dev->utc = mktime(<m); clog_flast(dev, dev->utc, dirent->d_name); } } closedir(dir); } } } static void clog_fopen(clog_t* dev) { int len; char logfilename[256]; if (dev) { if (dev->fp) fclose(dev->fp); len = sprintf(logfilename, "%s_%04d%02d%02d_%02d%02d%02d.log", dev->log_filename, dev->ltm.tm_year+1900, dev->ltm.tm_mon+1, dev->ltm.tm_mday, dev->ltm.tm_hour, dev->ltm.tm_min, dev->ltm.tm_sec); clog_flast(dev, mktime(&dev->ltm), logfilename); len = sprintf(logfilename, "%s/%s_%04d%02d%02d_%02d%02d%02d.log", dev->log_pathname, dev->log_filename, dev->ltm.tm_year+1900, dev->ltm.tm_mon+1, dev->ltm.tm_mday, dev->ltm.tm_hour, dev->ltm.tm_min, dev->ltm.tm_sec); // printf("logfilename:%s\n", logfilename); dev->fp = fopen(logfilename, "a+"); dev->log_filesize = 0; } } int clog_print(int level, const char *tag, const char* FUNCNAME, const char* FILENAME, int LINENO, const char *format, ...) { int len = 0; char logline[CLOG_LINE_SIZE]={0}; char strltime[32]; clog_t *dev = (clog_t*)&clogger; if (dev) { if (level<0) level = 0; if (level>6) level = 6; // if (tag == NULL) tag = "NON"; len += sprintf(&logline[len], "%s", CSI_START); len += sprintf(&logline[len], "%s", console_color_info[level]); { struct tm ltm; time_t utc = time(NULL); localtime_r(&utc, <m); len += strftime(&logline[len], 32, "%F %T", <m); len += snprintf(&logline[len], 16, " PID:%6d", getpid()); len += snprintf(&logline[len], 16, " TID:%6ld", syscall(SYS_gettid)); } if (tag) { len += snprintf(&logline[len], 6, " %s ", tag); } len += snprintf(&logline[len], 64, " %-33s %17s:%3d | ", FUNCNAME, basename((char*)FILENAME), LINENO); { va_list args; va_start(args, format); len += vsnprintf(&logline[len], CLOG_LINE_SIZE - len, format, args); va_end(args); } len += sprintf(&logline[len], "%s\n", CSI_END); clog_sendto_serverip(logline); pthread_mutex_lock(&dev->mutex); if ((dev->idx_w + len) <= CLOG_BUFF_SIZE) { memcpy(&dev->buff[dev->idx_w], logline, len); dev->idx_w += len; }else{ int seg1 = CLOG_BUFF_SIZE - dev->idx_w; int seg2 = len - seg1; memcpy(&dev->buff[dev->idx_w], logline, seg1); memcpy(&dev->buff[0], &logline[seg1], seg2); dev->idx_w = seg2; } if ((dev->bytes + len) <= CLOG_BUFF_SIZE) { dev->bytes += len; }else{ dev->idx_r = dev->idx_w; dev->bytes = CLOG_BUFF_SIZE; } pthread_mutex_unlock(&dev->mutex); sem_post(&dev->sempare); return len; } return 0; } void* clog_loop(void* args) { int len; static char logline[CLOG_BUFF_SIZE]; clog_t* dev = (clog_t*)args; while(dev->quit == 0) { sem_wait(&dev->sempare); len = 0; pthread_mutex_lock(&dev->mutex); if (dev->bytes > 0) { if (dev->idx_w > dev->idx_r) { len = dev->idx_w - dev->idx_r; memcpy(logline, &dev->buff[dev->idx_r], len); }else{ len = CLOG_BUFF_SIZE - dev->idx_r; memcpy(&logline[0], &dev->buff[dev->idx_r], len); memcpy(&logline[len], &dev->buff[0], dev->idx_w); len += dev->idx_w; } dev->bytes -= len; dev->idx_r = dev->idx_w; } pthread_mutex_unlock(&dev->mutex); if (len > 0) { printf("%.*s", len, logline); struct tm ltm; time_t utc = time(NULL); localtime_r(&utc, <m); if (ltm.tm_yday != dev->ltm.tm_yday) { dev->ltm = ltm; clog_fopen(dev); } // printf(".size:%d, len:%d, all(%d), max(%d)\n", dev->log_filesize, len, (dev->log_filesize + len), dev->max_filesize); // if ((dev->log_filesize + len) >= dev->max_filesize) // { // dev->ltm = ltm; // clog_fopen(dev); // } // if ((dev->log_filesize + len) <= dev->max_filesize) { if (dev->fp) { dev->log_filesize += len; fwrite(logline, len, 1, dev->fp); fflush(dev->fp); } } } } return NULL; } void clog_init(const char* log_filename, int max_filesize, int max_filenumb) { clog_t *dev = (clog_t*)&clogger; if (dev) { char* tmp0 = strdup(log_filename); char* tmp1 = strdup(log_filename); memset(dev, 0, sizeof(clog_t)); dev->log_pathname = strdup(dirname((char*)tmp0)); dev->log_filename = strdup(basename((char*)tmp1)); dev->max_filesize = max_filesize; dev->max_filenumb = max_filenumb; dev->fnumb = 0; dev->bytes = 0; free(tmp0); free(tmp1); { int flen = strlen(dev->log_filename) + 32; dev->flutc = (time_t*)malloc(sizeof(time_t) * dev->max_filenumb); if (dev->flutc == NULL) { printf("malloc(%p) failed.\n",dev->flutc); } dev->flist = (char**)malloc(sizeof(char*) * dev->max_filenumb); if (dev->flist) { int i; for (i = 0; imax_filenumb; i++) { dev->flist[i] = malloc(sizeof(char)*flen); if (dev->flist[i] == NULL) { printf("malloc(%d, %p) failed.\n", i, dev->flist[i]); } } }else{ printf("malloc(%p) failed.\n",dev->flist); } } clog_fload(dev); time(&dev->utc); localtime_r(&dev->utc, &dev->ltm); clog_fopen(dev); dev->quit = 0; pthread_mutex_init(&dev->mutex, NULL); sem_init(&dev->sempare, 0, 0); { pthread_attr_t thread_attr; struct sched_param thread_sched_param; pthread_attr_init(&thread_attr); //pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); pthread_attr_setstacksize(&thread_attr, 1024); pthread_attr_setschedpolicy(&thread_attr, SCHED_RR); thread_sched_param.sched_priority = sched_get_priority_max(SCHED_RR) - 1; pthread_attr_setschedparam(&thread_attr, &thread_sched_param); pthread_create(&dev->threadID, &thread_attr, clog_loop, dev); pthread_attr_destroy(&thread_attr); } } } void clog_exit(void) { clog_t *dev = (clog_t*)&clogger; if (dev) { dev->quit = 1; pthread_join(dev->threadID, NULL); if (dev->fp) { fflush(dev->fp); fclose(dev->fp); dev->fp = NULL; } pthread_mutex_destroy(&dev->mutex); sem_destroy(&dev->sempare); if (dev->log_filename) { free(dev->log_filename); dev->log_filename = NULL; } if (dev->log_pathname) { free(dev->log_pathname); dev->log_pathname = NULL; } if (dev->flist) { int i; for (i = 0; imax_filenumb; i++) { if (dev->flist[i]) { free(dev->flist[i]); dev->flist[i] = NULL; } } free(dev->flist); dev->flist = NULL; } if (dev->flutc) { free(dev->flutc); dev->flutc = NULL; } } }