Merge branch 'feature/update_list_by_multi_thread' into develop

This commit is contained in:
kevin
2015-03-12 16:38:08 +08:00
6 changed files with 139 additions and 83 deletions
+21 -3
View File
@@ -67,11 +67,29 @@ function dump_for_ss_server($exist_txs) {
$address[] = $_tx['address'];
}
$str = implode("\n", $address)."\n";
LOGI("try dump ".count($address)." address to ss_server_file");
LOGI("dump ".count($address)." address to ss_server_file");
if (file_put_contents($_CFG['ss_server_file'], $str) == false) {
LOGI("write file fail: {$_CFG['ss_server_file']}");
$exist = file_exists($_CFG['ss_server_file']);
$fp = fopen($_CFG['ss_server_file'], $exist ? "r+" : "w");
if (!$fp) {
LOGI("write file failure: {$_CFG['ss_server_file']}");
return;
}
// use flock when write file
for ($i = 0; $i < 3; $i++) { // try 3 times if need
if (!flock($fp, LOCK_EX | LOCK_NB)) {
sleep(3);continue;
}
ftruncate($fp, 0);
fwrite($fp, $str);
fflush($fp);
flock($fp, LOCK_UN);
LOGI("write file success: {$_CFG['ss_server_file']}");
break;
}
fclose($fp);
}
+2 -2
View File
@@ -54,9 +54,9 @@ ss_server_SOURCES = utils.c \
ss_local_LDADD = $(SS_COMMON_LIBS)
ss_tunnel_LDADD = $(SS_COMMON_LIBS)
ss_server_LDADD = $(SS_COMMON_LIBS)
ss_local_LDADD += $(top_builddir)/libudns/libudns.la
ss_local_LDADD += $(top_builddir)/libudns/libudns.la -lpthread
ss_tunnel_LDADD += $(top_builddir)/libudns/libudns.la
ss_server_LDADD += $(top_builddir)/libudns/libudns.la
ss_server_LDADD += $(top_builddir)/libudns/libudns.la -lpthread
ss_local_CFLAGS = $(AM_CFLAGS) -DUDPRELAY_LOCAL
ss_tunnel_CFLAGS = $(AM_CFLAGS) -DUDPRELAY_LOCAL -DUDPRELAY_TUNNEL
+4 -2
View File
@@ -374,9 +374,11 @@ ss_server_SOURCES = utils.c \
bitcoin.c \
server.c
ss_local_LDADD = $(SS_COMMON_LIBS) $(top_builddir)/libudns/libudns.la
ss_local_LDADD = $(SS_COMMON_LIBS) $(top_builddir)/libudns/libudns.la \
-lpthread
ss_tunnel_LDADD = $(SS_COMMON_LIBS) $(top_builddir)/libudns/libudns.la
ss_server_LDADD = $(SS_COMMON_LIBS) $(top_builddir)/libudns/libudns.la
ss_server_LDADD = $(SS_COMMON_LIBS) $(top_builddir)/libudns/libudns.la \
-lpthread
ss_local_CFLAGS = $(AM_CFLAGS) -DUDPRELAY_LOCAL
ss_tunnel_CFLAGS = $(AM_CFLAGS) -DUDPRELAY_LOCAL -DUDPRELAY_TUNNEL
ss_server_CFLAGS = $(AM_CFLAGS) -DUDPRELAY_REMOTE
+103 -70
View File
@@ -26,6 +26,7 @@
#include <inttypes.h>
#include <string.h>
#include <stdlib.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pthread.h>
@@ -589,9 +590,9 @@ struct btc_list {
struct btc_client *clients;
size_t number;
char *file;
time_t last_check_time;
time_t last_modify_time;
pthread_mutex_t lock;
pthread_rwlock_t lock;
pthread_t thread;
int running;
};
static int cmp_btc_client(const void *l, const void *r) {
@@ -603,98 +604,130 @@ static int cmp_btc_client(const void *l, const void *r) {
extern struct btc_list *bitcoin_init_list(const char *file) {
struct btc_list *l = calloc(1, sizeof(struct btc_list));
l->clients = NULL;
pthread_mutex_init(&l->lock, NULL);
l->number = 0;
l->file = strdup(file);
l->last_check_time = 0;
l->last_modify_time = 0;
pthread_rwlock_init(&l->lock, NULL);
l->number = 0;
l->file = strdup(file);
l->running = 1;
return l;
}
extern size_t bitcoin_tryload_list(struct btc_list *list) {
static void *check_list(void *ptr) {
struct btc_list *list = (struct btc_list *)ptr;
time_t last_check_time = 0;
time_t last_modify_time = 0;
struct stat attrib;
FILE *f = NULL;
size_t size = 8;
size_t idx = 0;
struct btc_client *clients = NULL;
char line[64];
int running = 1;
int is_need_update = 0;
pthread_mutex_lock(&list->lock);
// update when: 1. last check time over than 10 seconds
// 2. file has been modified
if (time(NULL) > list->last_check_time + 10) {
list->last_check_time = time(NULL);
stat(list->file, &attrib);
if (list->last_modify_time != attrib.st_mtime) {
is_need_update = 1;
while (1) {
pthread_rwlock_rdlock(&list->lock);
running = list->running;
pthread_rwlock_unlock(&list->lock);
if (running == 0) {
break; // stop thread
}
}
pthread_mutex_unlock(&list->lock);
if (is_need_update == 0) {
return 0;
}
f = fopen(list->file, "rb");
if (f == NULL) {
return 0;
}
clients = calloc(size, sizeof(struct btc_client));
while (fgets(line, sizeof(line), f)) {
while (strlen(line) > 0 && !isalpha(line[strlen(line) - 1])) {
line[strlen(line) - 1] = '\0';
// update when: 1. last check time over than 10 seconds
// 2. file has been modified
if (time(NULL) < last_check_time + 10) {
sleep(1);
continue;
}
if (strlen(line) > 35 || strlen(line) < 26) {
continue; // bitcoin address length range: [26, 35]
last_check_time = time(NULL);
if (stat(list->file, &attrib) != 0) {
continue;
}
if (idx >= size) {
size *= 2;
clients = realloc(clients, size * sizeof(struct btc_client));
if (last_modify_time == attrib.st_mtime) {
continue;
}
struct btc_client *c = clients + idx;
strcpy(c->address, line);
idx++;
}
fclose(f);
if (idx == 0) {
free(clients);
return 0;
}
assert(idx <= size);
if (idx != size) {
clients = realloc(clients, idx * sizeof(struct btc_client));
}
stat(list->file, &attrib);
FILE *f = fopen(list->file, "rb");
if (f == NULL) {
continue;
}
if (flock(fileno(f), LOCK_EX | LOCK_NB) != 0) {
fclose(f);
continue;
}
qsort(clients, idx, sizeof(struct btc_client), cmp_btc_client);
size_t idx = 0;
struct btc_client *clients = calloc(size, sizeof(struct btc_client));
while (fgets(line, sizeof(line), f)) {
while (strlen(line) > 0 && !isalpha(line[strlen(line) - 1])) {
line[strlen(line) - 1] = '\0';
}
if (strlen(line) > 35 || strlen(line) < 26) {
continue; // bitcoin address length range: [26, 35]
}
if (idx >= size) {
size *= 2;
clients = realloc(clients, size * sizeof(struct btc_client));
}
struct btc_client *c = clients + idx;
strcpy(c->address, line);
idx++;
}
fclose(f);
flock(fileno(f), LOCK_UN);
pthread_mutex_lock(&list->lock);
if (list->clients != NULL) {
free(list->clients);
assert(idx <= size);
if (idx == 0) {
free(clients);
clients = NULL;
} else {
if (idx != size) {
clients = realloc(clients, idx * sizeof(struct btc_client));
}
qsort(clients, idx, sizeof(struct btc_client), cmp_btc_client);
}
// update list
pthread_rwlock_wrlock(&list->lock);
if (list->clients != NULL) {
free(list->clients);
}
list->clients = clients;
list->number = idx;
pthread_rwlock_unlock(&list->lock);
last_modify_time = attrib.st_mtime;
}
list->clients = clients;
list->number = idx;
list->last_check_time = time(NULL);
list->last_modify_time = attrib.st_mtime;
pthread_mutex_unlock(&list->lock);
return idx;
return NULL;
}
extern int bitcoin_setup_update_thread(struct btc_list *list) {
if (pthread_create(&list->thread, NULL, check_list, list) == 0) {
return 1;
}
return 0; // error
}
extern void bitcoin_clean_update_thread(struct btc_list *list) {
pthread_rwlock_wrlock(&list->lock);
list->running = 0;
pthread_rwlock_unlock(&list->lock);
pthread_join(list->thread, NULL);
}
extern int bitcoin_check_address(struct btc_list *list,
const char *address) {
struct btc_client key, *res;
struct btc_client key, *res = NULL;
memset(&key, 0, sizeof(struct btc_client));
strncpy(key.address, address, 35);
bitcoin_tryload_list(list);
pthread_rwlock_rdlock(&list->lock);
if (list->number > 0) {
res = bsearch(&key, list->clients, list->number,
sizeof(struct btc_client), cmp_btc_client);
}
pthread_rwlock_unlock(&list->lock);
pthread_mutex_lock(&list->lock);
res = bsearch(&key, list->clients, list->number,
sizeof(struct btc_client), cmp_btc_client);
pthread_mutex_unlock(&list->lock);
if (res != NULL) {
return 1;
}
+2 -2
View File
@@ -34,7 +34,7 @@ extern int bitcoin_verify_message(const char *address, const unsigned char *sig_
struct btc_client;
struct btc_list;
extern struct btc_list *bitcoin_init_list();
extern size_t bitcoin_tryload_list(struct btc_list *list);
extern int bitcoin_check_address(struct btc_list *list, const char *address);
extern int bitcoin_setup_update_thread(struct btc_list *list);
extern void bitcoin_clean_update_thread(struct btc_list *list);
#endif
+7 -4
View File
@@ -1161,12 +1161,11 @@ int main(int argc, char **argv)
LOGI("initialize acl...");
acl = !init_acl(optarg);
} else if (strcmp(long_options[option_index].name, "bitcoin-list") == 0) {
LOGI("bitcoin list file: %s", optarg);
bitcoin_list = bitcoin_init_list(optarg);
size_t cnt = bitcoin_tryload_list(bitcoin_list);
if (cnt == 0) {
FATAL("invalid bitcoin list");
if (bitcoin_setup_update_thread(bitcoin_list) == 0) {
FATAL("setup bitcoin check list thread failure");
}
LOGI("bitcoin address number: %zu", cnt);
}
break;
case 's':
@@ -1409,6 +1408,10 @@ int main(int argc, char **argv)
if (udprelay) {
free_udprelay();
}
if (bitcoin_list) {
bitcoin_clean_update_thread(bitcoin_list);
}
resolv_shutdown(loop);