From e640bd6f9b2cbb6ef5d2f596c2f68d6e3677ed4a Mon Sep 17 00:00:00 2001 From: Unbit Date: Mon, 11 Mar 2013 09:44:50 +0100 Subject: [PATCH] completed legion scroll --- core/legion.c | 67 ++++++++++++++++++++++----------- core/lock.c | 9 +++++ core/master_utils.c | 6 +-- core/uwsgi.c | 2 + plugins/python/uwsgi_pymodule.c | 21 +++++++++++ uwsgi.h | 4 +- 6 files changed, 83 insertions(+), 26 deletions(-) diff --git a/core/legion.c b/core/legion.c index 34514d07..f5ffb50f 100644 --- a/core/legion.c +++ b/core/legion.c @@ -174,9 +174,9 @@ static void legions_check_nodes() { struct uwsgi_legion_node *tmp_node = node; node = node->next; uwsgi_log("[uwsgi-legion] node: %.*s valor: %llu uuid: %.*s left Legion %s\n", tmp_node->name_len, tmp_node->name, tmp_node->valor, 36, tmp_node->uuid, legion->legion); - pthread_mutex_lock(&legion->lock); + uwsgi_wlock(legion->lock); uwsgi_legion_remove_node(legion, tmp_node); - pthread_mutex_unlock(&legion->lock); + uwsgi_rwunlock(legion->lock); continue; } node = node->next; @@ -285,6 +285,15 @@ static void legions_check_nodes_step2() { } usl = usl->next; } + if (ul->scroll_len > 0 && ul->scroll_len <= ul->lord_scroll_size) { + uwsgi_wlock(ul->lock); + ul->lord_scroll_len = ul->scroll_len; + memcpy(ul->lord_scroll, ul->scroll, ul->lord_scroll_len); + uwsgi_rwunlock(ul->lock); + } + else { + ul->lord_scroll_len = 0; + } ul->i_am_the_lord = uwsgi_now(); // trick: reduce the time needed by the old lord to unlord itself uwsgi_legion_announce(ul); @@ -296,7 +305,7 @@ static void legions_check_nodes_step2() { if (ul->lord_scroll_len > 0) { uwsgi_log("*********** The New Lord Scroll ***********\n\n"); uwsgi_log("%.*s\n", ul->lord_scroll_len, ul->lord_scroll); - uwsgi_log("*********** End of the New Lord Scroll ***********\n\n"); + uwsgi_log("\n*********** End of the New Lord Scroll ***********\n\n"); } // no more lord, trigger unlord hooks struct uwsgi_string_list *usl = ul->unlord_hooks; @@ -365,18 +374,11 @@ struct uwsgi_legion_node *uwsgi_legion_get_lord(struct uwsgi_legion *ul) { if (!best_node) return NULL; - if (best_node->scroll_len > 0) { - if (best_node->scroll_len > ul->lord_scroll_size) { - char *tmp_buf = realloc(ul->lord_scroll, best_node->scroll_len); - if (!tmp_buf) { - uwsgi_error("uwsgi_legion_get_lord()/realloc()"); - return NULL; - } - ul->lord_scroll_size = best_node->scroll_len; - ul->lord_scroll = tmp_buf; - } + if (best_node->scroll_len > 0 && best_node->scroll_len <= ul->lord_scroll_size) { + uwsgi_wlock(ul->lock); ul->lord_scroll_len = best_node->scroll_len; memcpy(ul->lord_scroll, best_node->scroll, ul->lord_scroll_len); + uwsgi_rwunlock(ul->lock); } else { ul->lord_scroll_len = 0; @@ -511,15 +513,15 @@ static void *legion_loop(void *foobar) { struct uwsgi_legion_node *node = uwsgi_legion_get_node(ul, legion_msg.valor, legion_msg.name, legion_msg.name_len, legion_msg.uuid); if (!node) { // add the new node - pthread_mutex_lock(&ul->lock); + uwsgi_wlock(ul->lock); node = uwsgi_legion_add_node(ul, legion_msg.valor, legion_msg.name, legion_msg.name_len, legion_msg.uuid); if (!node) continue; - if (node->scroll_len > 0) { - char *scroll = node->scroll; - node->scroll = uwsgi_malloc(node->scroll_len); - memcpy(node->scroll, scroll, node->scroll_len); + if (legion_msg.scroll_len > 0) { + node->scroll = uwsgi_malloc(legion_msg.scroll_len); + node->scroll_len = legion_msg.scroll_len; + memcpy(node->scroll, legion_msg.scroll, node->scroll_len); } - pthread_mutex_unlock(&ul->lock); + uwsgi_rwunlock(ul->lock); uwsgi_log("[uwsgi-legion] node: %.*s valor: %llu uuid: %.*s joined Legion %s\n", node->name_len, node->name, node->valor, 36, node->uuid, ul->legion); } @@ -777,7 +779,8 @@ void uwsgi_opt_legion_scroll(char *opt, char *value, void *foobar) { ul->scroll = space+1; ul->scroll_len = strlen(ul->scroll); - free(legion); + // DO NOT FREE IT !!! + //free(legion); } @@ -930,7 +933,12 @@ void uwsgi_opt_legion(char *opt, char *value, void *foobar) { ul->encrypt_ctx = ctx; ul->decrypt_ctx = ctx2; - pthread_mutex_init(&ul->lock, NULL); + if (!uwsgi.legion_scroll_max_size) { + uwsgi.legion_scroll_max_size = 4096; + } + + ul->lord_scroll_size = uwsgi.legion_scroll_max_size; + ul->lord_scroll = uwsgi_calloc_shared(ul->lord_scroll_size); uwsgi_legion_add(ul); } @@ -992,8 +1000,23 @@ next: int uwsgi_legion_i_am_the_lord(char *name) { struct uwsgi_legion *legion = uwsgi_legion_get_by_name(name); - if (legion && legion->i_am_the_lord) { + if (!legion) return 0; + if (legion->i_am_the_lord) { return 1; } return 0; } + +char *uwsgi_legion_lord_scroll(char *name, uint16_t *rlen) { + char *buf = NULL; + struct uwsgi_legion *legion = uwsgi_legion_get_by_name(name); + if (!legion) return 0; + uwsgi_rlock(legion->lock); + if (legion->lord_scroll_len > 0) { + buf = uwsgi_malloc(legion->lord_scroll_len); + memcpy(buf, legion->lord_scroll, legion->lord_scroll_len); + *rlen = legion->lord_scroll_len; + } + uwsgi_rwunlock(legion->lock); + return buf; +} diff --git a/core/lock.c b/core/lock.c index 6e50a1ce..211a0dee 100644 --- a/core/lock.c +++ b/core/lock.c @@ -641,6 +641,15 @@ ready: } uwsgi.rpc_table_lock = uwsgi_lock_init("rpc"); + +#ifdef UWSGI_SSL + // register locking for legions + struct uwsgi_legion *ul = uwsgi.legions; + while(ul) { + ul->lock = uwsgi_lock_init(uwsgi_concat2("legion_", ul->legion)); + ul = ul->next; + } +#endif uwsgi.locking_setup = 1; } diff --git a/core/master_utils.c b/core/master_utils.c index dbdb4619..59aea4b7 100644 --- a/core/master_utils.c +++ b/core/master_utils.c @@ -1312,7 +1312,7 @@ struct uwsgi_stats *uwsgi_master_generate_stats() { if (uwsgi_stats_list_open(us)) goto end; - pthread_mutex_lock(&legion->lock); + uwsgi_rlock(legion->lock); struct uwsgi_legion_node *node = legion->nodes_head; while (node) { if (uwsgi_stats_object_open(us)) @@ -1342,7 +1342,7 @@ struct uwsgi_stats *uwsgi_master_generate_stats() { goto unlock_legion_mutex; } } - pthread_mutex_unlock(&legion->lock); + uwsgi_rwunlock(legion->lock); if (uwsgi_stats_list_close(us)) goto end; @@ -1371,7 +1371,7 @@ struct uwsgi_stats *uwsgi_master_generate_stats() { #ifdef UWSGI_SSL unlock_legion_mutex: if (legion) - pthread_mutex_unlock(&legion->lock); + uwsgi_rwunlock(legion->lock); #endif end: free(us->base); diff --git a/core/uwsgi.c b/core/uwsgi.c index b77d55aa..08a0f0c7 100644 --- a/core/uwsgi.c +++ b/core/uwsgi.c @@ -373,6 +373,8 @@ static struct uwsgi_option uwsgi_base_options[] = { {"legion-death", required_argument, 0, "action to call on legion death (shutdown of the instance)", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER}, {"legion-quorum", required_argument, 0, "set the quorum of a legion", uwsgi_opt_legion_quorum, NULL, UWSGI_OPT_MASTER}, {"legion-scroll", required_argument, 0, "set the scroll of a legion", uwsgi_opt_legion_scroll, NULL, UWSGI_OPT_MASTER}, + {"legion-scroll", required_argument, 0, "set the scroll of a legion", uwsgi_opt_legion_scroll, NULL, UWSGI_OPT_MASTER}, + {"legion-scroll-max-size", required_argument, 0, "set max size of legion scroll buffer", uwsgi_opt_set_16bit, &uwsgi.legion_scroll_max_size, 0}, {"subscriptions-sign-check", required_argument, 0, "set digest algorithm and certificate directory for secured subscription system", uwsgi_opt_scd, NULL, UWSGI_OPT_MASTER}, {"subscriptions-sign-check-tolerance", required_argument, 0, "set the maximum tolerance (in seconds) of clock skew for secured subscription system", uwsgi_opt_set_int, &uwsgi.subscriptions_sign_check_tolerance, UWSGI_OPT_MASTER}, #endif diff --git a/plugins/python/uwsgi_pymodule.c b/plugins/python/uwsgi_pymodule.c index 7626c436..d9b6c49e 100644 --- a/plugins/python/uwsgi_pymodule.c +++ b/plugins/python/uwsgi_pymodule.c @@ -454,6 +454,26 @@ PyObject *py_uwsgi_i_am_the_lord(PyObject * self, PyObject * args) { Py_INCREF(Py_False); return Py_False; } + +PyObject *py_uwsgi_lord_scroll(PyObject * self, PyObject * args) { + char *legion_name = NULL; + + if (!PyArg_ParseTuple(args, "s:lord_scroll", &legion_name)) { + return NULL; + } + + uint16_t rlen = 0; + char *buf = uwsgi_legion_lord_scroll(legion_name, &rlen); + if (!buf) { + Py_INCREF(Py_None); + return Py_None; + } + + PyObject *ret = PyString_FromStringAndSize(buf, rlen); + free(buf); + return ret; +} + #endif PyObject *py_uwsgi_register_signal(PyObject * self, PyObject * args) { @@ -2413,6 +2433,7 @@ static PyMethodDef uwsgi_advanced_methods[] = { {"logsize", py_uwsgi_logsize, METH_VARARGS, ""}, #ifdef UWSGI_SSL {"i_am_the_lord", py_uwsgi_i_am_the_lord, METH_VARARGS, ""}, + {"lord_scroll", py_uwsgi_lord_scroll, METH_VARARGS, ""}, #endif {"async_sleep", py_uwsgi_async_sleep, METH_VARARGS, ""}, {"async_connect", py_uwsgi_async_connect, METH_VARARGS, ""}, diff --git a/uwsgi.h b/uwsgi.h index ab975935..1843c04a 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -605,7 +605,7 @@ union uwsgi_sockaddr_ptr { time_t last_warning; - pthread_mutex_t lock; + struct uwsgi_lock_item *lock; EVP_CIPHER_CTX *encrypt_ctx; EVP_CIPHER_CTX *decrypt_ctx; @@ -2224,6 +2224,7 @@ struct uwsgi_server { int legion_freq; int legion_tolerance; int legion_skew_tolerance; + uint16_t legion_scroll_max_size; #endif #ifdef __linux__ @@ -3767,6 +3768,7 @@ void uwsgi_uuid(char *); int uwsgi_uuid_cmp(char *, char *); int uwsgi_legion_i_am_the_lord(char *); +char *uwsgi_legion_lord_scroll(char *, uint16_t *); void uwsgi_additional_header_add(struct wsgi_request *, char *, uint16_t); void uwsgi_remove_header(struct wsgi_request *, char *, uint16_t);