145 lines
3.4 KiB
C
145 lines
3.4 KiB
C
#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>
|
||
|
||
int in_log(logs *log,log_manager *self)
|
||
{
|
||
sem_wait(&self->log_sem);//加锁
|
||
logs *buf = self->rear;
|
||
if(self->log == NULL){
|
||
self->log = log;
|
||
self->rear = log;
|
||
self->count++;
|
||
sem_post(&self->log_sem);
|
||
return 0;
|
||
}
|
||
self->count++;
|
||
buf->next = log;
|
||
log->next = NULL;
|
||
self->rear = log;
|
||
sem_post(&self->log_sem);
|
||
return self->count;
|
||
}
|
||
|
||
logs *out_log(log_manager *self)
|
||
{
|
||
sem_wait(&self->log_sem);
|
||
logs *buf = self->log;
|
||
if(self->log==NULL)
|
||
{
|
||
sem_post(&self->log_sem);
|
||
return NULL;
|
||
}
|
||
if(self->log->next ==NULL)
|
||
self->log = self->rear = NULL;
|
||
self->count--;
|
||
sem_post(&self->log_sem);
|
||
buf->next =NULL;
|
||
return buf;
|
||
}
|
||
|
||
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 += 1000;
|
||
/* 纳秒部分无需处理,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;
|
||
sem_wait(&self->log_sem);
|
||
loc = self->log;
|
||
self->log = NULL;
|
||
self->count = 0;
|
||
sem_post(&self->log_sem);
|
||
while(loc->next !=NULL)
|
||
{
|
||
tobeclean = loc;
|
||
loc = loc->next;
|
||
free(tobeclean);
|
||
}
|
||
free(loc);
|
||
}
|
||
|
||
void log_manager_stop(log_manager *self)
|
||
{
|
||
pthread_mutex_lock(&self->mtx);
|
||
self->stop = 1; /* 置退出标志 */
|
||
pthread_cond_broadcast(&self->cond); /* 唤醒所有等待线程 */
|
||
printf("SYS:stopping loger\n");
|
||
pthread_mutex_unlock(&self->mtx);
|
||
printf("SYS:done\n");
|
||
}
|
||
|
||
//定期清理函数
|
||
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<256||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)
|
||
{
|
||
if(self == NULL)
|
||
{
|
||
perror("NULL\n");
|
||
return -1;
|
||
}
|
||
sem_init(&self->log_sem, 0,1);
|
||
pthread_mutex_init(&self->mtx,NULL);
|
||
pthread_cond_init(&self->cond,NULL);
|
||
self->in_log = in_log;
|
||
self->out_log = out_log;
|
||
self->clear_log = clear_log;
|
||
self->log = NULL;
|
||
self->stop = 0;
|
||
self->cleanup = cleanup;
|
||
self->count = 0;
|
||
} |