Compare commits

...

2 Commits

Author SHA1 Message Date
3673b10942 修改readme 2026-01-29 12:20:17 +08:00
ee596a654d 修复日志处理,优化磁盘io,优化退出流程 2026-01-29 12:10:36 +08:00
11 changed files with 184 additions and 52 deletions

View File

@ -1,6 +1,6 @@
# OneBot Chatbot Framework
该项目是一个基于OneBot标准的聊天机器人后端框架采用高度可扩展的插件架构设计支持消息的模块化处理和插件热加载。
该项目是一个基于OneBot标准的聊天机器人后端框架采用高度可扩展的插件架构设计支持消息的模块化处理和插件热加载。如果你有任何意见或建议,可以通过 jianfeee@outlook.com 联系我。
## 项目特点

View File

@ -1,13 +1,14 @@
#ifndef SEVERCONFG
#define SEVERCONFG
#define MAX_LOG 256
#define MAX_LOG 64
#define MAX_LOG_LENGTH 4096
#define TEM_MAX_BUF 256
#define TEM_HISTORY_BUF 210
#define TEM_PROMPT "chatbot$$ "
#define NET_MAX_POOL 10
#define NET_MAX_POOL 1
#define NET_MAX_MESSAGE_BUF 1024
#define HTTP_BLOCK_SIZE 512
#define MAX_HTTP_LENGTH 20

View File

@ -139,7 +139,7 @@ int match_cmd(const Cmd* cmd_dic,char *cmd_buf)
}
int exce(const int command,ctx *all_ctx)
int exec(const int command,ctx *all_ctx)
{
switch (command)
@ -202,7 +202,7 @@ int interpret(int mod, ctx *all_ctx,Cmd *cmd_dic)
if(cmd_buf[len-1] == '\n')
cmd_buf[len-1] = '\0';
//执行命令
exce(match_cmd(cmd_dic, cmd_buf),all_ctx);
exec(match_cmd(cmd_dic, cmd_buf),all_ctx);
//释放所有堆内存
free(cmd_buf);

View File

@ -34,8 +34,9 @@ int main()
int port = (int)toml_int_in(server,"list_port").u.i;
//加载配置文件,读取端口
log_manager *logsmanager=(log_manager*)malloc(sizeof(log_manager));
//创建日志管理器与定时清理线层
init_loger(logsmanager);
pthread_create(&logsmanager->pid,NULL,logsmanager->clear_log,logsmanager);
Ctl *teml = init_tem(logsmanager);
teml->config = server;
//初始化终端对象
@ -45,8 +46,8 @@ int main()
netm *networkmanager = (netm*)malloc(sizeof(netm));
init_networkmanager(networkmanager,fifo,logsmanager,port);
//初始化网络管理器对象
pthread_t network_id;
pthread_create(&network_id,NULL,networkmanager->run_network,(void*)networkmanager);
pthread_create(&networkmanager->pid,NULL,networkmanager->run_network,(void*)networkmanager);
//启动网络监听与线程池,并加载插件
alres *resource = (alres*)malloc(sizeof(alres));
resource->loger = logsmanager;
@ -57,8 +58,13 @@ int main()
teml->run(teml,fifo);
//启动终端
pthread_join(network_id,NULL);
log_manager_stop(logsmanager);
pthread_join(logsmanager->pid,NULL);
logsmanager->pid = -1;
//等待网络管理器进程结束
pthread_join(networkmanager->pid,NULL);
close(fifo[1]);
return 1;
}

View File

@ -243,7 +243,6 @@ int server_run(int port,int fifo_fd,netm *self)
{
/*工作循环-----------------------------*/
int nf = epoll_wait(epfd,events,10,-1);
printf("%d\n",nf);
if (nf == -1) {
perror("epoll_wait");
break;
@ -259,21 +258,43 @@ int server_run(int port,int fifo_fd,netm *self)
sprintf(iss_buf,"s/%d/e",nt_fd);
self->iss_work(self,iss_buf);
}
if(events[i].data.fd == fifo_fd)
{
char command;
while(read(fifo_fd,&command,1)==1)
{
switch(command){
case 'q':
//退出逻辑
quit_server(self);
return 1;
break;
case 'u':
//插件更新逻辑
break;
if(events[i].data.fd == fifo_fd) {
char buffer[256];
ssize_t bytes_read;
// 一次性读取所有可用数据
bytes_read = read(fifo_fd, buffer, sizeof(buffer));
if (bytes_read > 0) {
printf("DEBUG: Read %zd bytes from pipe: ", bytes_read);
for (int j = 0; j < bytes_read; j++) {
printf("%c ", buffer[j]);
}
printf("\n");
// 处理每个命令(按接收顺序)
for (int j = 0; j < bytes_read; j++) {
printf("Processing command[%d]: %c\n", j, buffer[j]);
switch(buffer[j]) {
case 'q':
printf("Quit command found at position %d\n", j);
quit_server(self);
return 1; // 立即退出,不处理后续命令
case 'u':
printf("Update command\n");
// 更新逻辑
break;
default:
printf("Unknown command: %c (ASCII: %d)\n",
buffer[j], buffer[j]);
}
}
} else if (bytes_read == 0) {
printf("Pipe closed by writer\n");
close(fifo_fd);
} else if (errno != EAGAIN && errno != EWOULDBLOCK) {
perror("Error reading from pipe");
}
}
}

View File

@ -29,6 +29,7 @@ typedef struct network_manager//网络管理器
int (*iss_work)(struct network_manager*,char *);
int fifo_fd[2];
pthread_t pid;
log_manager *logmanager;
indiector *err_indictor;
int last_alc;

View File

@ -241,9 +241,7 @@ int teml(Ctl *self,int fifo[2])
char input[TEM_MAX_BUF] = {'\0'};
ctx *command = (ctx*)malloc(sizeof(ctx));
Cmd cmd_dir[10];
init_interpreter(cmd_dir,command,fifo,self->logmanager);//初始化解释器
//创建线程用于定期清理日志
pthread_create(&self->logwathcher,NULL,self->logmanager->clear_log,self->logmanager);
init_interpreter(cmd_dir,command,fifo,self->logmanager);
command->statue = 0;
self->command = command;
do
@ -262,12 +260,6 @@ int teml(Ctl *self,int fifo[2])
const char fexp[256] = {'\0'};
memcpy(&input,&fexp,TEM_MAX_BUF);
}while(command->statue == 0);
log_manager_stop(self->logmanager);
pthread_join(self->logwathcher,NULL);
//关闭log定期清理程序
close(fifo[0]);
close(fifo[1]);
free_history(self);
self->command = NULL;
free(command);

View File

@ -15,7 +15,6 @@ typedef struct Ctl
int (*infifo)(struct Ctl*,const char*);
int index;
char *history[TEM_HISTORY_BUF];
pthread_t logwathcher;
log_manager *logmanager;
ctx *command;//解释器上下文
toml_table_t *config;

View File

@ -11,18 +11,22 @@
int in_log(logs *log,log_manager *self)
{
if(log == NULL||self == NULL)
return -1;
log->log[MAX_LOG_LENGTH-1] = '\0';
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;
return self->count;
}
if(self->count == 1)
self->log->next = log;
self->count++;
buf->next = log;
log->next = NULL;
self->rear->next = log;
self->rear = log;
sem_post(&self->log_sem);
return self->count;
@ -30,15 +34,19 @@ int in_log(logs *log,log_manager *self)
logs *out_log(log_manager *self)
{
if(self == NULL)
return NULL;
sem_wait(&self->log_sem);
logs *buf = self->log;
if(self->log==NULL)
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;
@ -90,28 +98,105 @@ int cleanup(log_manager *self)
sem_post(&self->log_sem);
//释放信号量
int fd = open("log.txt",O_CREAT | O_WRONLY | O_APPEND, 0777);
char *logbuf;
void *logbufbk;
char failback[MAX_LOG_LENGTH];
logbuf = (char*)malloc(1);
logbuf[0] = '\0';
size_t buf_length,buf_lengthbk = 0;
while(loc->next !=NULL)
{
tobeclean = loc;
loc = loc->next;
if(fd == -1)
perror("file:");
write(fd,tobeclean->log,strlen(tobeclean->log));
if(logbuf != failback){
logbufbk = logbuf;
logbuf = (char*)realloc(logbuf,strlen(logbuf)+strlen(tobeclean->log)+1);//为日志分配新的内存
}
if(logbuf == NULL){
free(logbufbk);
logbuf = failback;//降级策略,堆空间不足时,使用预分配栈空间,保留最后一条日志
}
if(logbuf != failback){
buf_lengthbk = buf_length;
buf_length = strlen(logbuf)+strlen(tobeclean->log);
strcpy(logbuf+buf_lengthbk,tobeclean->log);
}
else
{
buf_length = MAX_LOG_LENGTH;
}
free(tobeclean);
}
close(fd);
int fd = open("log.txt",O_CREAT | O_WRONLY | O_APPEND, 0644);
if(fd == -1){
perror("file:");
free(loc);
if(logbuf != failback)
free(logbuf);
return -1;
}
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{
strcpy(logbuf,loc->log);
buf_length = strlen(logbuf);
}
if(logbuf == failback&&buf_length>MAX_LOG_LENGTH)
logbuf[MAX_LOG_LENGTH-1] = '\0';
else{
logbuf[buf_length] = '\0';
}
free(loc);
int error_buf = write(fd,logbuf,strlen(logbuf));
if(error_buf==-1){
close(fd);
if(logbuf != failback)
free(logbuf);
return -1;
}
else if(error_buf<buf_length)
write(fd,"unknown error case log write cut down\n",38);
if(logbuf != failback)
free(logbuf);
close(fd);
return 0;
}
void log_manager_stop(log_manager *self)
{
pthread_mutex_lock(&self->mtx);
self->stop = 1; /* 置退出标志 */
pthread_cond_broadcast(&self->cond); /* 唤醒所有等待线程 */
if(self->stop == 1){
pthread_mutex_unlock(&self->mtx);
return ;
}
self->stop = 1;
/* 置退出标志 */
printf("SYS:stopping loger\n");
pthread_mutex_unlock(&self->mtx);
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); /* 唤醒所有等待线程 */
}
//定期清理函数
@ -122,7 +207,7 @@ void *clear_log(void *self_p)
{
sleep_with_signal(self);
sem_wait(&self->log_sem);
if((self->count<256||self->log==NULL)&&self->stop !=1){
if((self->count<MAX_LOG||self->log==NULL)&&self->stop !=1){
sem_post(&self->log_sem);
continue;
}
@ -141,9 +226,28 @@ int init_loger(log_manager *self)
perror("NULL\n");
return -1;
}
sem_init(&self->log_sem, 0,1);
pthread_mutex_init(&self->mtx,NULL);
pthread_cond_init(&self->cond,NULL);
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;
@ -151,4 +255,5 @@ int init_loger(log_manager *self)
self->stop = 0;
self->cleanup = cleanup;
self->count = 0;
return 0;
}

View File

@ -8,12 +8,13 @@
typedef struct logs
{
char log[4096];
char log[MAX_LOG_LENGTH];
struct logs *next;
}logs;
typedef struct log_manager
{
pthread_t pid;
int (*in_log)(logs *,struct log_manager*);
logs* (*out_log)(struct log_manager*);
void *(*clear_log)(void*);

View File

@ -72,8 +72,14 @@ void quit_all(int status,void *self_p)
free(resouce->tem->command);
}
//释放终端资源
//释放日志管理器
if(resouce->loger->pid != -1){
log_manager_stop(resouce->loger);
pthread_join(resouce->loger->pid,NULL);
}
pthread_mutex_destroy(&resouce->loger->mtx);
resouce->loger->cleanup(resouce->loger);
pthread_cond_destroy(&resouce->loger->cond);
log_manager_stop(resouce->loger);
sem_destroy(&resouce->loger->log_sem);
//销毁信号量