From ace79b1179758180f335340d80145d8f51a5271d Mon Sep 17 00:00:00 2001 From: Unbit Date: Sat, 30 Nov 2013 10:41:56 +0000 Subject: [PATCH] various websockets and sharedarea optimizations --- core/sharedarea.c | 58 ++++++++++++++++++++++++--------- core/utils.c | 3 ++ core/websockets.c | 20 +++++++----- core/writer.c | 3 ++ plugins/psgi/uwsgi_plmodule.c | 9 ++++- plugins/python/uwsgi_pymodule.c | 8 +++++ uwsgi.h | 6 ++++ 7 files changed, 83 insertions(+), 24 deletions(-) diff --git a/core/sharedarea.c b/core/sharedarea.c index aca579e4..0a14a680 100644 --- a/core/sharedarea.c +++ b/core/sharedarea.c @@ -210,7 +210,30 @@ int uwsgi_sharedarea_wait(int id, int freq, int timeout) { return -2; } -struct uwsgi_sharedarea *uwsgi_sharedarea_init(int id, int pages) { +int uwsgi_sharedarea_new_id() { + int id = uwsgi.sharedareas_cnt; + uwsgi.sharedareas_cnt++; + if (!uwsgi.sharedareas) { + uwsgi.sharedareas = uwsgi_malloc(sizeof(struct uwsgi_sharedarea *)); + } + else { + struct uwsgi_sharedarea **usa = realloc(uwsgi.sharedareas, ((sizeof(struct uwsgi_sharedarea *)) * uwsgi.sharedareas_cnt)); + if (!usa) { + uwsgi_error("uwsgi_sharedarea_init()/realloc()"); + exit(1); + } + uwsgi.sharedareas = usa; + } + return id; +} + +static struct uwsgi_sharedarea *announce_sa(struct uwsgi_sharedarea *sa) { + uwsgi_log("sharedarea %d created at %p (%d pages, area at %p)\n", sa->id, sa, sa->pages, sa->area); + return sa; +} + +struct uwsgi_sharedarea *uwsgi_sharedarea_init(int pages) { + int id = uwsgi_sharedarea_new_id(); uwsgi.sharedareas[id] = uwsgi_calloc_shared(uwsgi.page_size * (pages + 1)); uwsgi.sharedareas[id]->area = ((char *) uwsgi.sharedareas[id]) + uwsgi.page_size; uwsgi.sharedareas[id]->id = id; @@ -220,10 +243,25 @@ struct uwsgi_sharedarea *uwsgi_sharedarea_init(int id, int pages) { char *id_str = uwsgi_num2str(id); uwsgi.sharedareas[id]->lock = uwsgi_rwlock_init(uwsgi_concat2("sharedarea", id_str)); free(id_str); - return uwsgi.sharedareas[id]; + return announce_sa(uwsgi.sharedareas[id]); } -struct uwsgi_sharedarea *uwsgi_sharedarea_init_keyval(int id, char *arg) { +struct uwsgi_sharedarea *uwsgi_sharedarea_init_ptr(char *area, uint64_t len) { + int id = uwsgi_sharedarea_new_id(); + uwsgi.sharedareas[id] = uwsgi_calloc_shared(sizeof(struct uwsgi_sharedarea)); + uwsgi.sharedareas[id]->area = area; + uwsgi.sharedareas[id]->id = id; + uwsgi.sharedareas[id]->fd = -1; + uwsgi.sharedareas[id]->pages = len / uwsgi.page_size; + if (len % uwsgi.page_size != 0) uwsgi.sharedareas[id]->pages++; + uwsgi.sharedareas[id]->max_pos = len-1; + char *id_str = uwsgi_num2str(id); + uwsgi.sharedareas[id]->lock = uwsgi_rwlock_init(uwsgi_concat2("sharedarea", id_str)); + free(id_str); + return announce_sa(uwsgi.sharedareas[id]); +} + +struct uwsgi_sharedarea *uwsgi_sharedarea_init_keyval(char *arg) { char *s_pages = NULL; char *s_file = NULL; char *s_fd = NULL; @@ -244,23 +282,13 @@ struct uwsgi_sharedarea *uwsgi_sharedarea_init_keyval(int id, char *arg) { void uwsgi_sharedareas_init() { struct uwsgi_string_list *usl = NULL; - uwsgi_foreach(usl, uwsgi.sharedareas_list) { - uwsgi.sharedareas_cnt++; - } - uwsgi.sharedareas = uwsgi_calloc(sizeof(struct uwsgi_sharedarea *) * uwsgi.sharedareas_cnt); - int id = 0; uwsgi_foreach(usl, uwsgi.sharedareas_list) { char *is_keyval = strchr(usl->value, '='); - struct uwsgi_sharedarea *sa = NULL; if (!is_keyval) { - sa = uwsgi_sharedarea_init(id, atoi(usl->value)); + uwsgi_sharedarea_init(atoi(usl->value)); } else { - sa = uwsgi_sharedarea_init_keyval(id, usl->value); + uwsgi_sharedarea_init_keyval(usl->value); } - if (sa) { - uwsgi_log("sharedaread % initialized at %p\n", id, sa); - } - id++; } } diff --git a/core/utils.c b/core/utils.c index ea94ebf8..6b5eb9b6 100644 --- a/core/utils.c +++ b/core/utils.c @@ -1138,6 +1138,9 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) { if (wsgi_req->websocket_buf) { uwsgi_buffer_destroy(wsgi_req->websocket_buf); } + if (wsgi_req->websocket_send_buf) { + uwsgi_buffer_destroy(wsgi_req->websocket_send_buf); + } // reset request diff --git a/core/websockets.c b/core/websockets.c index 8bc7b15f..f4f629ec 100644 --- a/core/websockets.c +++ b/core/websockets.c @@ -10,8 +10,16 @@ extern struct uwsgi_server uwsgi; -static struct uwsgi_buffer *uwsgi_websocket_message(char *msg, size_t len, uint8_t opcode) { - struct uwsgi_buffer *ub = uwsgi_buffer_new(10 + len); +static struct uwsgi_buffer *uwsgi_websocket_message(struct wsgi_request *wsgi_req, char *msg, size_t len, uint8_t opcode) { + struct uwsgi_buffer *ub = wsgi_req->websocket_send_buf; + if (!ub) { + wsgi_req->websocket_send_buf = uwsgi_buffer_new(10 + len); + ub = wsgi_req->websocket_send_buf; + } + else { + // reset the buffer + ub->pos = 0; + } if (uwsgi_buffer_u8(ub, opcode)) goto error; if (len < 126) { if (uwsgi_buffer_u8(ub, len)) goto error; @@ -29,7 +37,6 @@ static struct uwsgi_buffer *uwsgi_websocket_message(char *msg, size_t len, uint8 return ub; error: - uwsgi_buffer_destroy(ub); return NULL; } @@ -67,13 +74,10 @@ static int uwsgi_websockets_check_pingpong(struct wsgi_request *wsgi_req) { } static int uwsgi_websocket_send_do(struct wsgi_request *wsgi_req, char *msg, size_t len, uint8_t opcode) { - struct uwsgi_buffer *ub = uwsgi_websocket_message(msg, len, opcode); + struct uwsgi_buffer *ub = uwsgi_websocket_message(wsgi_req, msg, len, opcode); if (!ub) return -1; - ssize_t ret = uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos); - uwsgi_buffer_destroy(ub); - return ret; - + return uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos); } int uwsgi_websocket_send(struct wsgi_request *wsgi_req, char *msg, size_t len) { diff --git a/core/writer.c b/core/writer.c index e7ee2475..603f57a3 100644 --- a/core/writer.c +++ b/core/writer.c @@ -221,6 +221,7 @@ int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) { if (ret == UWSGI_OK) { break; } + if (!uwsgi_is_again()) continue; ret = uwsgi_wait_write_req(wsgi_req); if (ret < 0) { wsgi_req->write_errors++; return -1;} if (ret == 0) { @@ -301,6 +302,7 @@ sendbody: if (ret == UWSGI_OK) { break; } + if (!uwsgi_is_again()) continue; ret = uwsgi_wait_write_req(wsgi_req); if (ret < 0) { wsgi_req->write_errors++; return -1;} if (ret == 0) { @@ -465,6 +467,7 @@ int uwsgi_simple_write(struct wsgi_request *wsgi_req, char *buf, size_t len) { if (ret == UWSGI_OK) { break; } + if (!uwsgi_is_again()) continue; ret = uwsgi_wait_write_req(wsgi_req); if (ret < 0) { wsgi_req->write_errors++; return -1;} if (ret == 0) { diff --git a/plugins/psgi/uwsgi_plmodule.c b/plugins/psgi/uwsgi_plmodule.c index cb5721b7..aaebe3ab 100644 --- a/plugins/psgi/uwsgi_plmodule.c +++ b/plugins/psgi/uwsgi_plmodule.c @@ -720,6 +720,14 @@ XS(XS_sharedarea_read) { if (items > 2) { len = SvIV(ST(2)); } + else { + struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos); + if (!sa) { + croak("unable to read from sharedarea %d", id); + XSRETURN_UNDEF; + } + len = sa->max_pos+1; + } char *buf = uwsgi_malloc(len); if (uwsgi_sharedarea_read(id, pos, buf, len)) { @@ -874,4 +882,3 @@ void init_perl_embedded_module() { psgi_xs(sharedarea_write); psgi_xs(sharedarea_wait); } - diff --git a/plugins/python/uwsgi_pymodule.c b/plugins/python/uwsgi_pymodule.c index 8fd735a6..862e10e3 100644 --- a/plugins/python/uwsgi_pymodule.c +++ b/plugins/python/uwsgi_pymodule.c @@ -1584,6 +1584,14 @@ PyObject *py_uwsgi_sharedarea_read(PyObject * self, PyObject * args) { return NULL; } + if (!len) { + struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos); + if (!sa) { + return PyErr_Format(PyExc_ValueError, "error calling uwsgi_sharedarea_read()"); + } + len = sa->max_pos+1; + } + PyObject *ret = PyString_FromStringAndSize(NULL, len); #ifdef PYTHREE char *storage = PyBytes_AsString(ret); diff --git a/uwsgi.h b/uwsgi.h index a47f713f..bdfcce86 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -1495,6 +1495,7 @@ struct wsgi_request { struct uwsgi_string_list *remove_headers; struct uwsgi_buffer *websocket_buf; + struct uwsgi_buffer *websocket_send_buf; size_t websocket_need; int websocket_phase; uint8_t websocket_opcode; @@ -4563,6 +4564,9 @@ void uwsgi_build_plugin(char *dir); void uwsgi_sharedareas_init(); +struct uwsgi_sharedarea *uwsgi_sharedarea_init(int); +struct uwsgi_sharedarea *uwsgi_sharedarea_init_ptr(char *, uint64_t); + int uwsgi_sharedarea_read(int, uint64_t, char *, uint64_t); int uwsgi_sharedarea_write(int, uint64_t, char *, uint64_t); int uwsgi_sharedarea_read64(int, uint64_t, int64_t *); @@ -4583,6 +4587,8 @@ int uwsgi_sharedarea_dec32(int, uint64_t, int32_t); int uwsgi_sharedarea_dec64(int, uint64_t, int64_t); int uwsgi_sharedarea_wait(int, int, int); +struct uwsgi_sharedarea *uwsgi_sharedarea_get_by_id(int, uint64_t); + void uwsgi_setup(int, char **, char **); int uwsgi_run(void);