From 35f47371ed2e57b143e413c8dd372a30ce23a3c0 Mon Sep 17 00:00:00 2001 From: Unbit Date: Mon, 18 Mar 2013 13:22:10 +0100 Subject: [PATCH] first part of uwsgi_legion_scrolls() function api --- core/legion.c | 53 +++++++++++++++++++++++++++++++++ plugins/python/uwsgi_pymodule.c | 32 ++++++++++++++++++++ uwsgi.h | 7 +++++ 3 files changed, 92 insertions(+) diff --git a/core/legion.c b/core/legion.c index f5ffb50f..bc1a150a 100644 --- a/core/legion.c +++ b/core/legion.c @@ -81,6 +81,37 @@ void uwsgi_parse_legion(char *key, uint16_t keylen, char *value, uint16_t vallen } } +// this function is called when a node is added or removed (heavy locking is needed) +static void legion_rebuild_scrolls(struct uwsgi_legion *ul) { + uint64_t max_size = ul->scrolls_max_size; + + // first, try to add myself + if (ul->scroll_len + (uint64_t) 2 > max_size) { + uwsgi_log("[DANGER] you have configured a too much tiny buffer for the scrolls list !!! tune it with --legion-scroll-list-max-size\n"); + ul->scroll_len = 0; + return; + } + + char *ptr = ul->scrolls; + *ptr ++= (uint8_t) (ul->scroll_len & 0xff); + *ptr ++= (uint8_t) ((ul->scroll_len >> 8) &0xff); + memcpy(ptr, ul->scroll, ul->scroll_len); ptr += ul->scroll_len; + ul->scrolls_len = 2 + ul->scroll_len; + // ok start adding nodes; + struct uwsgi_legion_node *uln = ul->nodes_head; + while(uln) { + if (ul->scrolls_len + 2 + uln->scroll_len > max_size) { + uwsgi_log("[DANGER] you have configured a too much tiny buffer for the scrolls list !!! tune it with --legion-scroll-list-max-size\n"); + return; + } + *ptr ++= (uint8_t) (uln->scroll_len & 0xff); + *ptr ++= (uint8_t) ((uln->scroll_len >> 8) &0xff); + memcpy(ptr, uln->scroll, uln->scroll_len); ptr += uln->scroll_len; + ul->scrolls_len += 2 + uln->scroll_len; + uln = uln->next; + } +} + // critical section (remember to lock when you use it) struct uwsgi_legion_node *uwsgi_legion_add_node(struct uwsgi_legion *ul, uint16_t valor, char *name, uint16_t name_len, char *uuid) { @@ -104,6 +135,8 @@ struct uwsgi_legion_node *uwsgi_legion_add_node(struct uwsgi_legion *ul, uint16_ ul->nodes_head = node; } + legion_rebuild_scrolls(ul); + return node; @@ -141,6 +174,8 @@ void uwsgi_legion_remove_node(struct uwsgi_legion *ul, struct uwsgi_legion_node } free(node); + + legion_rebuild_scrolls(ul); } struct uwsgi_legion_node *uwsgi_legion_get_node(struct uwsgi_legion *ul, uint64_t valor, char *name, uint16_t name_len, char *uuid) { @@ -937,8 +972,14 @@ void uwsgi_opt_legion(char *opt, char *value, void *foobar) { uwsgi.legion_scroll_max_size = 4096; } + if (!uwsgi.legion_scroll_list_max_size) { + uwsgi.legion_scroll_list_max_size = 32768; + } + ul->lord_scroll_size = uwsgi.legion_scroll_max_size; ul->lord_scroll = uwsgi_calloc_shared(ul->lord_scroll_size); + ul->scrolls_max_size = uwsgi.legion_scroll_list_max_size; + ul->scrolls = uwsgi_calloc_shared(ul->scrolls_max_size); uwsgi_legion_add(ul); } @@ -1020,3 +1061,15 @@ char *uwsgi_legion_lord_scroll(char *name, uint16_t *rlen) { uwsgi_rwunlock(legion->lock); return buf; } + +char *uwsgi_legion_scrolls(char *name, uint64_t *rlen) { + char *buf = NULL; + struct uwsgi_legion *legion = uwsgi_legion_get_by_name(name); + if (!legion) return NULL; + uwsgi_rlock(legion->lock); + buf = uwsgi_malloc(legion->scrolls_len); + memcpy(buf, legion->scrolls, legion->scrolls_len); + *rlen = legion->scrolls_len; + uwsgi_rwunlock(legion->lock); + return buf; +} diff --git a/plugins/python/uwsgi_pymodule.c b/plugins/python/uwsgi_pymodule.c index d9b6c49e..d1e61394 100644 --- a/plugins/python/uwsgi_pymodule.c +++ b/plugins/python/uwsgi_pymodule.c @@ -474,6 +474,37 @@ PyObject *py_uwsgi_lord_scroll(PyObject * self, PyObject * args) { return ret; } +static void scrolls_items(uint16_t pos, char *key, uint16_t keylen, void *data) { + PyObject *list = (PyObject *) data; + PyObject *zero = PyString_FromStringAndSize(key, keylen); + PyList_Append(list, zero); + Py_DECREF(zero); +} + +PyObject *py_uwsgi_scrolls(PyObject * self, PyObject * args) { + char *legion_name = NULL; + + if (!PyArg_ParseTuple(args, "s:scrolls", &legion_name)) { + return NULL; + } + + uint64_t rlen = 0; + char *buf = uwsgi_legion_scrolls(legion_name, &rlen); + if (!buf) goto end; + PyObject *list = PyList_New(0); + if (uwsgi_hooked_parse_array(buf, rlen, scrolls_items, list)) { + goto error; + } + free(buf); + return list; +error: + free(buf); +end: + Py_INCREF(Py_None); + return Py_None; +} + + #endif PyObject *py_uwsgi_register_signal(PyObject * self, PyObject * args) { @@ -2434,6 +2465,7 @@ static PyMethodDef uwsgi_advanced_methods[] = { #ifdef UWSGI_SSL {"i_am_the_lord", py_uwsgi_i_am_the_lord, METH_VARARGS, ""}, {"lord_scroll", py_uwsgi_lord_scroll, METH_VARARGS, ""}, + {"scrolls", py_uwsgi_scrolls, 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 3f085ba2..c58490e6 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -624,6 +624,10 @@ union uwsgi_sockaddr_ptr { EVP_CIPHER_CTX *encrypt_ctx; EVP_CIPHER_CTX *decrypt_ctx; + char *scrolls; + uint64_t scrolls_len; + uint64_t scrolls_max_size; + // found nodes dynamic lists struct uwsgi_legion_node *nodes_head; struct uwsgi_legion_node *nodes_tail; @@ -2239,6 +2243,7 @@ struct uwsgi_server { int legion_tolerance; int legion_skew_tolerance; uint16_t legion_scroll_max_size; + uint64_t legion_scroll_list_max_size; #endif #ifdef __linux__ @@ -3921,6 +3926,8 @@ int uwsgi_cache_magic_exists(char *, uint16_t, char *); int uwsgi_cache_magic_clear(char *); void uwsgi_cache_magic_context_hook(char *, uint16_t, char *, uint16_t, void *); +char *uwsgi_legion_scrolls(char *, uint64_t *); + #ifdef UWSGI_ZLIB #include int uwsgi_deflate_init(z_stream *, char *, size_t);