Files
chat_rebot-connect-with-one…/c/tools/log/log.c

248 lines
6.5 KiB
C
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#define _POSIX_C_SOURCE 200112L
#include "log.h"
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
logs* getbody(void **log_p)
{
return (logs*)*log_p;
}
int write_into_block(char *writein,char *org,size_t* length,size_t maxlength,char *logname)
{
if(writein == NULL||org == NULL||length == NULL||logname == NULL)
return -1;
if(*length+strlen(org)<maxlength-1)
{
strcpy(&writein[*length],org);
*length +=strlen(org);//栈内存充足
}
else
{
int n = *length + strlen(org) - maxlength+1;
strncpy(&writein[*length],org,strlen(org)-n);//栈内存不足
writein[maxlength-1] = '\0';
int fd = open(logname,O_CREAT | O_WRONLY | O_APPEND, 0644);
if(fd != -1)
{
int eno = write(fd,writein,strlen(writein));
if(eno <strlen(writein))
perror("log");
close(fd);
}
else if(fd == -1)
perror("log:");//仅警告
strncpy(writein,&org[0],n);//剩余部分拷贝
*length = n;
}
return 0;
}
int in_log(log_manager *self,const char *logbody,const char *info)
{
if(self == NULL)
return -1;
void **log_p = self->mempool->GetBlock(self->mempool,LOGMOD);
if(log_p == NULL)
{
perror("Mem_runout");
return -1;
}
logs *log = getbody(log_p);
snprintf(log->info,INFO_LENGTH,"%s",info);
snprintf(log->log,MAX_LOG_LENGTH,"%s",logbody);
log->log[MAX_LOG_LENGTH-1] = '\0';
log->next = NULL;
sem_wait(&self->log_sem);//加锁
if(self->log == NULL){
self->log = log_p;
self->rear = getbody(log_p);
atomic_fetch_add(&self->count,1);
sem_post(&self->log_sem);
return self->count;
}
if(self->count == 1){
logs *p = getbody(self->log);
p->next = log_p;
}
self->count++;
log->next = NULL;
self->rear->next = log_p;
self->rear = log;
sem_post(&self->log_sem);
return self->count;
}
int sleep_with_signal(log_manager *self)
{
struct timespec ts;
int rc;
/* 计算绝对超时:当前 + 1000 s */
if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0)
return -1; /* 罕见失败 */
ts.tv_sec += LOG_SLEEP_LENGTH;
/* 纳秒部分无需处理1000 s 整不会溢出 */
pthread_mutex_lock(&self->mtx); /* 进入临界区 */
while (1) {
rc = pthread_cond_timedwait(&self->cond, &self->mtx, &ts);
if (rc == ETIMEDOUT) { /* 1000 s 到点 */
pthread_mutex_unlock(&self->mtx);
return 1; /* 正常超时 */
}
if (rc != 0) { /* 其他错误 */
pthread_mutex_unlock(&self->mtx);
return -1;
}
/* 被 signal / broadcast 提前唤醒,检查 stop */
if (self->stop == 1) {/* 主线程要求退出 */
pthread_mutex_unlock(&self->mtx);
return 0; /* 告诉调用者:该结束了 */
}
}
}
int cleanup(log_manager *self)
{
if(self->log ==NULL)
return 1;
logs *tobeclean,*loc;
void **tobeclean_p;
sem_wait(&self->log_sem);//获取信号量
void **loc_p = self->log;
self->log = NULL;
atomic_store(&self->count,0);//摘取log链
sem_post(&self->log_sem);
//释放信号量
loc = getbody(loc_p);
char logbuf[MAX_LOG_LENGTH];
size_t buf_length = 0;
int fd;
while(loc->next !=NULL)
{
tobeclean_p = loc_p;
tobeclean = getbody(tobeclean_p);
loc_p = loc->next;
loc = getbody(loc_p);
int eno = write_into_block(logbuf,tobeclean->info,&buf_length,MAX_LOG_LENGTH,"log.txt");
if(eno == -1)
perror("log");
eno = write_into_block(logbuf,":",&buf_length,MAX_LOG_LENGTH,"log.txt");
eno = write_into_block(logbuf,tobeclean->log,&buf_length,MAX_LOG_LENGTH,"log.txt");
if(eno == -1)
perror("log");//非业务逻辑只警告
self->mempool->FreeBlock(self->mempool,tobeclean_p);
}
write_into_block(logbuf,loc->info,&buf_length,MAX_LOG_LENGTH,"log.txt");
write_into_block(logbuf,":",&buf_length,MAX_LOG_LENGTH,"log.txt");
write_into_block(logbuf,loc->log,&buf_length,MAX_LOG_LENGTH,"log.txt");
free(loc);
fd = open("log.txt",O_CREAT | O_WRONLY | O_APPEND, 0644);
if(fd == -1){
perror("log:");
}
int error_buf = write(fd,logbuf,strlen(logbuf));
if(error_buf==-1){
return -1;
}
else if(error_buf<strlen(logbuf)){
perror("file");
write(fd,"unknown error case log write cut down\n",38);
}
close(fd);
return 0;
}
void log_manager_stop(log_manager *self)
{
pthread_mutex_lock(&self->mtx);
if(self->stop == 1){
pthread_mutex_unlock(&self->mtx);
return ;
}
self->stop = 1;
/* 置退出标志 */
printf("SYS:stopping loger\n");
self->in_log(self,"stopping loger\n","SYS:");
printf("SYS:done\n");
self->in_log(self,"done","SYS:");
pthread_mutex_unlock(&self->mtx);
pthread_cond_broadcast(&self->cond); /* 唤醒所有等待线程 */
}
//定期清理函数
void *clear_log(void *self_p)
{
log_manager *self = (log_manager*)self_p;
for(;;)
{
sleep_with_signal(self);
sem_wait(&self->log_sem);
if((self->count<MAX_LOG||self->log==NULL)&&self->stop !=1){
sem_post(&self->log_sem);
continue;
}
sem_post(&self->log_sem);
cleanup(self);
if(self->stop == 1){
return NULL;
}
}
}
int init_loger(log_manager *self,mem_ctl *mempool)
{
if(self == NULL)
{
perror("NULL\n");
return -1;
}
if(sem_init(&self->log_sem, 0,1)==-1)
return -1;
if(pthread_mutex_init(&self->mtx,NULL)==-1)
{
if(sem_destroy(&self->log_sem)==-1)
{
perror("log:");
}
return -1;
}
if(pthread_cond_init(&self->cond,NULL)==-1)
{
if(sem_destroy(&self->log_sem)==-1)
{
perror("log:");
}
if(pthread_mutex_destroy(&self->mtx)==-1)
{
perror("log:");
}
return -1;
}
self->in_log = in_log;
self->clear_log = clear_log;
self->log = NULL;
self->stop = 0;
self->cleanup = cleanup;
atomic_init(&self->count,0);
self->mempool = mempool;
return 0;
}