1
0
mirror of https://github.com/fumiama/simple-dict.git synced 2026-06-23 20:50:27 +08:00

优化代码结构

This commit is contained in:
源文雨
2022-04-17 19:42:46 +08:00
parent 622bbdc0a4
commit 1855c82551
2 changed files with 118 additions and 95 deletions

24
dict.c
View File

@@ -25,29 +25,29 @@ int fill_md5(pthread_rwlock_t* mu) {
if(!size) { if(!size) {
memset(dict_md5, 0, 16); memset(dict_md5, 0, 16);
puts("Dict is empty, use all zero md5"); puts("Dict is empty, use all zero md5");
return 1; return 0;
} }
uint8_t* dict_buff = (uint8_t*)malloc(size); uint8_t* dict_buff = (uint8_t*)malloc(size);
if(dict_buff) { if(dict_buff) {
if(pthread_rwlock_tryrdlock(mu)) { if(pthread_rwlock_tryrdlock(mu)) {
puts("Readlock busy"); perror("Readlock busy: ");
return 0; return 1;
} }
rewind(fp_read); rewind(fp_read);
if(fread(dict_buff, size, 1, fp_read) == 1) { if(fread(dict_buff, size, 1, fp_read) == 1) {
pthread_rwlock_unlock(mu); pthread_rwlock_unlock(mu);
md5(dict_buff, size, dict_md5); md5(dict_buff, size, dict_md5);
free(dict_buff); free(dict_buff);
return 1; return 0;
} else { } else {
pthread_rwlock_unlock(mu); pthread_rwlock_unlock(mu);
free(dict_buff); free(dict_buff);
puts("Read dict error"); perror("Read dict error: ");
return 0; return 2;
} }
} else { } else {
puts("Allocate memory error"); perror("Allocate memory error: ");
return 0; return 3;
} }
} }
@@ -57,14 +57,14 @@ int init_dict(char* file_path, pthread_rwlock_t* mu) {
if(fp) { if(fp) {
int err = pthread_rwlock_init(mu, NULL); int err = pthread_rwlock_init(mu, NULL);
if(err) { if(err) {
puts("Init lock error"); perror("Init lock error: ");
return 0; return 1;
} }
filepath = file_path; filepath = file_path;
return fill_md5(mu); return fill_md5(mu);
} }
puts("Open dict error"); perror("Open dict error: ");
return 0; return 2;
} }
FILE* open_dict(uint8_t lock_type, uint32_t index, pthread_rwlock_t* mu) { FILE* open_dict(uint8_t lock_type, uint32_t index, pthread_rwlock_t* mu) {

189
server.c
View File

@@ -55,20 +55,19 @@ static pthread_rwlock_t mu;
#define DICTPOOLSZ (((uint32_t)-1)>>((sizeof(uint32_t)*8-DICTPOOLBIT))) #define DICTPOOLSZ (((uint32_t)-1)>>((sizeof(uint32_t)*8-DICTPOOLBIT)))
static DICT* dict_pool[DICTPOOLSZ+1]; static DICT* dict_pool[DICTPOOLSZ+1];
#define showUsage(program) printf("Usage: %s [-d] listen_port try_times dict_file config_file\n\t-d: As daemon\n", program)
static void accept_client(); static void accept_client();
static void accept_timer(void *p); static void accept_timer(void *p);
static int bind_server(uint16_t port, int try_times); static uint16_t bind_server(uint16_t port);
static int close_and_send(THREADTIMER* timer, enum SERVERACK cmd, char *data, size_t numbytes); static int close_and_send(THREADTIMER* timer, enum SERVERACK cmd, char *data, size_t numbytes);
static enum SERVERACK del(FILE *fp, char* key, int len, char ret[4]); static enum SERVERACK del(FILE *fp, char* key, int len, char ret[4]);
static void handle_accept(void *accept_fd_p); static void handle_accept(void *accept_fd_p);
static void handle_int(int signo);
static void handle_pipe(int signo); static void handle_pipe(int signo);
static void handle_quit(int signo); static void handle_quit(int signo);
static void init_dict_pool(FILE *fp); static void init_dict_pool(FILE *fp);
static void kill_thread(THREADTIMER* timer); static void kill_thread(THREADTIMER* timer);
static uint32_t last_nonnull(char* p, uint32_t max_size); static uint32_t last_nonnull(char* p, uint32_t max_size);
static int listen_socket(int try_times); static int listen_socket();
static int send_all(THREADTIMER *timer); static int send_all(THREADTIMER *timer);
static int send_data(int accept_fd, int index, enum SERVERACK cmd, char *data, size_t length); static int send_data(int accept_fd, int index, enum SERVERACK cmd, char *data, size_t length);
static int s1_get(THREADTIMER *timer); static int s1_get(THREADTIMER *timer);
@@ -77,9 +76,7 @@ static int s3_set_data(THREADTIMER *timer);
static int s4_del(THREADTIMER *timer); static int s4_del(THREADTIMER *timer);
static int s5_md5(THREADTIMER *timer); static int s5_md5(THREADTIMER *timer);
static int bind_server(uint16_t port, int try_times) { static uint16_t bind_server(uint16_t port) {
int fail_count = 0;
int result = -1;
#ifdef LISTEN_ON_IPV6 #ifdef LISTEN_ON_IPV6
server_addr.sin6_family = AF_INET6; server_addr.sin6_family = AF_INET6;
server_addr.sin6_port = htons(port); server_addr.sin6_port = htons(port);
@@ -92,27 +89,32 @@ static int bind_server(uint16_t port, int try_times) {
bzero(&(server_addr.sin_zero), 8); bzero(&(server_addr.sin_zero), 8);
fd = socket(AF_INET, SOCK_STREAM, 0); fd = socket(AF_INET, SOCK_STREAM, 0);
#endif #endif
while(!~(result = bind(fd, (struct sockaddr *)&server_addr, struct_len)) && fail_count++ < try_times) sleep(1); if(!~bind(fd, (struct sockaddr *)&server_addr, struct_len)) {
if(!~result && fail_count >= try_times) { perror("Bind server failure: ");
puts("Bind server failure!");
return 0; return 0;
} else{
puts("Bind server success!");
return 1;
} }
#ifdef LISTEN_ON_IPV6
port = ntohs(server_addr.sin6_port);
struct in6_addr in = server_addr.sin6_addr;
char str[INET6_ADDRSTRLEN]; // 46
inet_ntop(AF_INET6, &in, str, sizeof(str));
#else
port = ntohs(server_addr.sin_port);
struct in_addr in = server_addr.sin_addr;
char str[INET_ADDRSTRLEN]; // 16
inet_ntop(AF_INET, &in, str, sizeof(str));
#endif
printf("Bind server successfully on %s:%u\n", str, port);
return port;
} }
static int listen_socket(int try_times) { static int listen_socket() {
int fail_count = 0; if(!~listen(fd, THREADCNT)) {
int result = -1; perror("Listen failed: ");
while(!~(result = listen(fd, 10)) && fail_count++ < try_times) sleep(1);
if(!~result && fail_count >= try_times) {
puts("Listen failed!");
return 0; return 0;
} else{
puts("Listening...");
return 1;
} }
puts("Listening...");
return 1;
} }
static uint32_t last_nonnull(char* p, uint32_t max_size) { static uint32_t last_nonnull(char* p, uint32_t max_size) {
@@ -428,6 +430,11 @@ static void kill_thread(THREADTIMER* timer) {
puts("Finish killing"); puts("Finish killing");
} }
static void handle_int(int signo) {
puts("Keyboard interrupted");
exit(0);
}
static void handle_pipe(int signo) { static void handle_pipe(int signo) {
fprintf(stderr, "Pipe error: %d\n", signo); fprintf(stderr, "Pipe error: %d\n", signo);
pthread_exit(NULL); pthread_exit(NULL);
@@ -549,22 +556,25 @@ static void handle_accept(void *p) {
puts("Thread exited normally"); puts("Thread exited normally");
} }
static pid_t pid;
static void accept_client() { static void accept_client() {
pid = fork(); pid_t pid = fork();
while (pid > 0) { //主进程监控子进程状态,如果子进程异常终止则重启之 while (pid > 0) { //主进程监控子进程状态,如果子进程异常终止则重启之
wait(NULL); wait(NULL);
puts("Server subprocess exited. Restart..."); puts("Server subprocess exited. Restart...");
pid = fork(); pid = fork();
} }
while(pid < 0) {
perror("Error when forking a subprocess: ");
sleep(1);
}
signal(SIGINT, handle_int);
signal(SIGQUIT, handle_quit); signal(SIGQUIT, handle_quit);
signal(SIGPIPE, handle_pipe); signal(SIGPIPE, handle_pipe);
pthread_attr_init(&attr); pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
init_crypto(); init_crypto();
init_dict_pool(get_dict_fp_rd()); init_dict_pool(get_dict_fp_rd());
if(pid < 0) perror("Error when forking a subprocess: "); while(1) {
else while(1) {
puts("Ready for accept, waitting..."); puts("Ready for accept, waitting...");
int p = 0; int p = 0;
while(p < THREADCNT && accept_threads[p] && !pthread_kill(accept_threads[p], 0)) p++; while(p < THREADCNT && accept_threads[p] && !pthread_kill(accept_threads[p], 0)) p++;
@@ -616,64 +626,77 @@ static int close_and_send(THREADTIMER* timer, enum SERVERACK cmd, char *data, si
} }
#define argequ(i, arg) (*(uint16_t*)argv[i] == *(uint16_t*)(arg)) #define argequ(i, arg) (*(uint16_t*)argv[i] == *(uint16_t*)(arg))
#define showUsage(program) \
printf("Usage:\n%s [-d] listen_port dict_file [config_file | -]\n\t-d: As daemon\n\t- : Read config from env SDS_PWD & SDS_SPS\n", program)
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
if(argc != 5 && argc != 6) showUsage(argv[0]); if(argc != 4 && argc != 5) {
else { showUsage(argv[0]);
int port = 0; return 0;
int as_daemon = argequ(1, "-d");
sscanf(argv[as_daemon?2:1], "%d", &port);
if(port > 0 && port < 65536) {
int times = 0;
sscanf(argv[as_daemon?3:2], "%d", &times);
if(times > 0) {
if(!as_daemon || (as_daemon && (daemon(1, 1) >= 0))) {
FILE *fp = NULL;
fp = fopen(argv[as_daemon?4:3], "rb+");
if(!fp) fp = fopen(argv[as_daemon?4:3], "wb+");
if(fp) {
fclose(fp);
if(init_dict(argv[as_daemon?4:3], &mu)) {
fp = NULL;
if(argv[as_daemon?5:4][0] == '-') { // use env
fp = (FILE*)1;
puts("Read config from env");
char* pwd = getenv("SDS_PWD");
if(pwd) {
char* sps = getenv("SDS_SPS");
if(sps) {
strncpy(cfg.pwd, pwd, 64);
strncpy(cfg.sps, sps, 64);
cfg.pwd[63] = 0;
cfg.sps[63] = 0;
fp = (FILE*)-1;
} else puts("Env SDS_SPS is null");
} else puts("Env SDS_PWD is null");
}
if(!fp) fp = fopen(argv[as_daemon?5:4], "rb");
if(fp && ((int)fp-1)) {
if(~((int)fp)) {
SIMPLE_PB* spb = get_pb(fp);
cfg = *(CONFIG*)spb->target;
fclose(fp);
free(spb);
}
items_len = align_struct(sizeof(DICT), 2, d.key, d.data);
if(items_len) {
if(bind_server(port, times)) if(listen_socket(times)) accept_client();
} else fputs("Align struct error", stderr);
} else {
fprintf(stderr, "Error opening config file: %s : ", argv[as_daemon?5:4]);
perror("");
}
}
} else {
fprintf(stderr, "Error opening dict file: %s : ", argv[as_daemon?4:3]);
perror("");
}
} else perror("Start daemon error: ");
} else fprintf(stderr, "Error times: %d\n", times);
} else fprintf(stderr, "Error port: %d\n", port);
} }
int port = 0;
int as_daemon = argequ(1, "-d");
sscanf(argv[as_daemon?2:1], "%d", &port);
if(port < 0 || port >= 65536) {
fprintf(stderr, "Error port: %d\n", port);
return 1;
}
if(as_daemon && daemon(1, 1)<0) {
perror("Start daemon error: ");
return 2;
}
FILE *fp = NULL;
fp = fopen(argv[as_daemon?3:2], "rb+");
if(!fp) fp = fopen(argv[as_daemon?3:2], "wb+");
if(!fp) {
fprintf(stderr, "Error opening dict file: %s : ", argv[as_daemon?3:2]);
perror("");
return 3;
}
fclose(fp);
if(init_dict(argv[as_daemon?3:2], &mu))
return 4;
fp = NULL;
if(argv[as_daemon?4:3][0] == '-') { // use env
fp = (FILE*)1;
puts("Read config from env");
char* pwd = getenv("SDS_PWD");
if(pwd) {
char* sps = getenv("SDS_SPS");
if(sps) {
strncpy(cfg.pwd, pwd, 64);
strncpy(cfg.sps, sps, 64);
cfg.pwd[63] = 0;
cfg.sps[63] = 0;
fp = (FILE*)-1;
} else {
fputs("Env SDS_SPS is null", stderr);
return 5;
}
} else {
fputs("Env SDS_PWD is null", stderr);
return 6;
}
}
if(!fp) fp = fopen(argv[as_daemon?4:3], "rb");
if(fp == NULL) {
fprintf(stderr, "Error opening config file: %s : ", argv[as_daemon?4:3]);
perror("");
return 7;
}
if(~((int)fp)) {
SIMPLE_PB* spb = get_pb(fp);
cfg = *(CONFIG*)spb->target;
fclose(fp);
free(spb);
}
items_len = align_struct(sizeof(DICT), 2, d.key, d.data);
if(!items_len) {
fputs("Align struct error", stderr);
return 8;
}
if(!bind_server((uint16_t)port)) return 9;
if(!listen_socket()) return 10;
accept_client();
close(fd); close(fd);
exit(EXIT_FAILURE); return 11;
} }