#define _POSIX_C_SOURCE 200112L #include "log.h" #include #include #include #include #include #include #include #include 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)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_bufmtx); 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->countlog==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; }