diff --git a/core/cache.c b/core/cache.c index 91936a47..544715a9 100644 --- a/core/cache.c +++ b/core/cache.c @@ -194,9 +194,15 @@ static void uwsgi_cache_load_files(struct uwsgi_cache *uc) { if (!uwsgi_cache_set2(uc, key, key_len, value, len, 0, 0)) { uwsgi_log("[cache] stored \"%.*s\" in \"%s\"\n", key_len, key, uc->name); } + else { + uwsgi_log("[cache-error] unable to store \"%.*s\" in \"%s\"\n", key_len, key, uc->name); + } uwsgi_rwunlock(uc->lock); free(value); } + else { + uwsgi_log("[cache-error] unable to read file \"%.*s\"\n", key_len, key); + } next: usl = usl->next; } @@ -1089,7 +1095,6 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) { // defaults uc->blocks = uc->max_items; uc->blocksize = UMAX16; - uc->max_item_size = uc->blocksize; uc->keysize = 2048; uc->hashsize = UMAX16; uc->hash = uwsgi_hash_algo_get("djb33x"); @@ -1097,6 +1102,9 @@ struct uwsgi_cache *uwsgi_cache_create(char *arg) { // customize if (c_blocksize) uc->blocksize = uwsgi_n64(c_blocksize); if (!uc->blocksize) { uwsgi_log("invalid cache blocksize for \"%s\"\n", uc->name); exit(1); } + // set the true max size of an item + uc->max_item_size = uc->blocksize; + if (c_blocks) uc->blocks = uwsgi_n64(c_blocks); if (!uc->blocks) { uwsgi_log("invalid cache blocks for \"%s\"\n", uc->name); exit(1); } if (c_hash) uc->hash = uwsgi_hash_algo_get(c_hash); diff --git a/core/offload.c b/core/offload.c index 45acebb0..9550b943 100644 --- a/core/offload.c +++ b/core/offload.c @@ -58,6 +58,23 @@ static int uwsgi_offload_enqueue(struct wsgi_request *wsgi_req, struct uwsgi_off return 0; } +/* + + memory offload engine: + buf -> pointer to the memory to transfer (memory is freed at the end) + len -> amount of data to transfer + +*/ + +int u_offload_memory_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) { + + if (!uor->buf || !uor->len) { + return -1; + } + return 0; +} + + /* transfer offload engine: @@ -240,6 +257,39 @@ struct uwsgi_thread *uwsgi_offload_thread_start() { return uwsgi_thread_new(uwsgi_offload_loop); } +/* + + offload memory transfer + + uor->len -> the size of the memory chunk + uor->buf -> the memory to transfer + uor->written -> written bytes + + status: none + +*/ + +static int u_offload_memory_do(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor, int fd) { + if (fd == -1) { + if (event_queue_add_fd_write(ut->queue, uor->s)) return -1; + return 0; + } + ssize_t rlen = write(uor->s, uor->buf + uor->written, uor->len - uor->written); + if (rlen > 0) { + uor->written += rlen; + if (uor->written >= uor->len) { + return -1; + } + return 0; + } + else if (rlen < 0) { + uwsgi_offload_retry + uwsgi_error("u_offload_memory_do()"); + } + return -1; +} + + /* the offload task starts after having acquired the file fd @@ -490,6 +540,7 @@ struct uwsgi_offload_engine *uwsgi_offload_register_engine(char *name, int (*pre void uwsgi_offload_engines_register_all() { uwsgi.offload_engine_sendfile = uwsgi_offload_register_engine("sendfile", u_offload_sendfile_prepare, u_offload_sendfile_do); uwsgi.offload_engine_transfer = uwsgi_offload_register_engine("transfer", u_offload_transfer_prepare, u_offload_transfer_do); + uwsgi.offload_engine_memory = uwsgi_offload_register_engine("memory", u_offload_memory_prepare, u_offload_memory_do); } int uwsgi_offload_request_sendfile_do(struct wsgi_request *wsgi_req, int fd, size_t len) { @@ -507,3 +558,11 @@ int uwsgi_offload_request_net_do(struct wsgi_request *wsgi_req, char *socketname uor.ubuf = ubuf; return uwsgi_offload_run(wsgi_req, &uor, NULL); } + +int uwsgi_offload_request_memory_do(struct wsgi_request *wsgi_req, char *buf, size_t len) { + struct uwsgi_offload_request uor; + uwsgi_offload_setup(uwsgi.offload_engine_memory, &uor, wsgi_req, 1); + uor.buf = buf; + uor.len = len; + return uwsgi_offload_run(wsgi_req, &uor, NULL); +} diff --git a/plugins/router_cache/router_cache.c b/plugins/router_cache/router_cache.c index d8d072cd..8962279f 100644 --- a/plugins/router_cache/router_cache.c +++ b/plugins/router_cache/router_cache.c @@ -56,6 +56,7 @@ struct uwsgi_router_cache_conf { char *status_str; int status; + char *no_offload; }; // this is allocated for each transformation @@ -189,6 +190,14 @@ static int uwsgi_routing_func_cache(struct wsgi_request *wsgi_req, struct uwsgi_ if (uwsgi_response_add_expires(wsgi_req, expires)) goto error; } if (uwsgi_response_add_content_length(wsgi_req, valsize)) goto error; + if (wsgi_req->socket->can_offload && !ur->custom && !urcc->no_offload) { + if (!uwsgi_offload_request_memory_do(wsgi_req, value, valsize)) { + wsgi_req->via = UWSGI_VIA_OFFLOAD; + wsgi_req->status = 202; + return UWSGI_ROUTE_BREAK; + } + } + uwsgi_response_write_body_do(wsgi_req, value, valsize); free(value); if (ur->custom) @@ -369,6 +378,7 @@ static int uwsgi_router_cache(struct uwsgi_route *ur, char *args) { "content_encoding", &urcc->content_encoding, "mime", &urcc->mime, "name", &urcc->name, + "no_offload", &urcc->no_offload, NULL)) { uwsgi_log("invalid route syntax: %s\n", args); exit(1); diff --git a/uwsgi.h b/uwsgi.h index bc49442e..18ccde0a 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -1944,6 +1944,7 @@ struct uwsgi_server { struct uwsgi_offload_engine *offload_engines; struct uwsgi_offload_engine *offload_engine_sendfile; struct uwsgi_offload_engine *offload_engine_transfer; + struct uwsgi_offload_engine *offload_engine_memory; int offload_threads; int offload_threads_events; struct uwsgi_thread **offload_thread; @@ -3768,6 +3769,7 @@ void uwsgi_offload_engines_register_all(void); struct uwsgi_thread *uwsgi_offload_thread_start(void); int uwsgi_offload_request_sendfile_do(struct wsgi_request *, int, size_t); int uwsgi_offload_request_net_do(struct wsgi_request *, char *, struct uwsgi_buffer *); +int uwsgi_offload_request_memory_do(struct wsgi_request *, char *, size_t); void uwsgi_subscription_set_algo(char *);