#define _POSIX_C_SOURCE 200112L #include "log.h" #include #include #include #include #include #include #include #include int write_into_block(char *writein,char *org,int *length,int maxlength,char *logname) { if(writein == NULL||org == NULL||length == NULL||logname == NULL) return -1; if(*length+strlen(org)log[MAX_LOG_LENGTH-1] = '\0'; sem_wait(&self->log_sem);//加锁 if(self->log == NULL){ self->log = log; self->rear = log; self->count++; sem_post(&self->log_sem); return self->count; } if(self->count == 1) self->log->next = log; self->count++; log->next = NULL; self->rear->next = log; self->rear = log; sem_post(&self->log_sem); return self->count; } logs *out_log(log_manager *self) { if(self == NULL) return NULL; sem_wait(&self->log_sem); logs *buf = self->log; if(buf==NULL) { sem_post(&self->log_sem); return NULL; } if(self->log->next ==NULL) self->log = self->rear = NULL; else self->log = self->log->next; 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;//摘取log链 sem_post(&self->log_sem); //释放信号量 char *logbuf; void *logbufbk; char failback[MAX_LOG_LENGTH]; logbuf = (char*)malloc(1); logbuf[0] = '\0'; size_t buf_length = 0,buf_lengthbk = 0; int fd; while(loc->next !=NULL) { tobeclean = loc; loc = loc->next; if(logbuf != failback){ logbufbk = logbuf; logbuf = (char*)realloc(logbuf,strlen(logbuf)+strlen(tobeclean->log)+1);//为日志分配新的内存 } if(logbuf == NULL){ fd = open("log.txt",O_CREAT | O_WRONLY | O_APPEND, 0644); if(fd != -1) { write(fd,logbufbk,buf_length); close(fd); } free(logbufbk); logbuf = failback;//降级策略,堆空间不足时,使用预分配栈空间 buf_length = 0; } if(logbuf != failback){ buf_lengthbk = buf_length; buf_length = strlen(logbuf)+strlen(tobeclean->log); strcpy(logbuf+buf_lengthbk,tobeclean->log); } else { write_into_block(logbuf,tobeclean->log,&buf_length,MAX_LOG_LENGTH,"log.txt"); } free(tobeclean); } if(logbuf != failback){ logbufbk = logbuf; logbuf = (char*)realloc(logbuf,strlen(logbuf)+strlen(loc->log)+2); if(logbuf == NULL) { free(logbufbk); logbuf = failback; strcpy(logbuf,loc->log); buf_length = strlen(loc->log); } else{ buf_lengthbk = buf_length; buf_length = strlen(logbuf)+strlen(loc->log); strcpy(logbuf+buf_lengthbk,loc->log); } } else{ write_into_block(logbuf,loc->log,&buf_length,MAX_LOG_LENGTH,"log.txt"); } logbuf[buf_length] = '\0'; free(loc); fd = open("log.txt",O_CREAT | O_WRONLY | O_APPEND, 0644); if(fd == -1){ perror("file:"); if(logbuf != failback) free(logbuf); return -1; } int error_buf = write(fd,logbuf,strlen(logbuf)); if(error_buf==-1){ close(fd); if(logbuf != failback) free(logbuf); return -1; } else if(error_bufmtx); if(self->stop == 1){ pthread_mutex_unlock(&self->mtx); return ; } self->stop = 1; /* 置退出标志 */ printf("SYS:stopping loger\n"); logs *log = malloc(sizeof(logs)); strcpy(log->log,"SYS:stopping loger\n"); self->in_log(log,self); log = malloc(sizeof(logs)); strcpy(log->log,"SYS:done\n"); printf("SYS:done\n"); self->in_log(log,self); 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) { 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->out_log = out_log; self->clear_log = clear_log; self->log = NULL; self->stop = 0; self->cleanup = cleanup; self->count = 0; return 0; }