mirror of
https://github.com/fumiama/simple-dict.git
synced 2026-06-23 20:50:27 +08:00
优化代码结构
This commit is contained in:
24
dict.c
24
dict.c
@@ -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
189
server.c
@@ -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", ×);
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user