diff --git a/core/cache.c b/core/cache.c index bf97450b..ca8101f7 100644 --- a/core/cache.c +++ b/core/cache.c @@ -126,9 +126,18 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) { uc->data = ((char *)uc->items) + ((sizeof(struct uwsgi_cache_item)+uc->keysize) * uc->max_items); - uc->lock = uwsgi_rwlock_init("cache"); + if (uc->name) { + char *lock_name = uwsgi_concat2("cache_", uc->name); + uc->lock = uwsgi_rwlock_init(lock_name); + free(lock_name); + } + else { + uc->lock = uwsgi_rwlock_init("cache"); + } - uwsgi_log("*** Cache subsystem initialized: %lluMB (key: %llu bytes, keys: %llu bytes, data: %llu bytes) preallocated ***\n", (unsigned long long) uc->filesize / (1024 * 1024), + uwsgi_log("*** Cache \"%s\" initialized: %lluMB (key: %llu bytes, keys: %llu bytes, data: %llu bytes) preallocated ***\n", + uc->name ? uc->name : "default", + (unsigned long long) uc->filesize / (1024 * 1024), (unsigned long long) sizeof(struct uwsgi_cache_item)+uc->keysize, (unsigned long long) ((sizeof(struct uwsgi_cache_item)+uc->keysize) * uc->max_items), (unsigned long long) (uc->blocksize * uc->max_items)); @@ -862,19 +871,68 @@ void uwsgi_cache_create(char *arg) { char *c_blocks = NULL; char *c_hash = NULL; char *c_hashsize = NULL; + char *c_keysize = NULL; char *c_store = NULL; if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=', "name", &c_name, "max_items", &c_max_items, + "maxitems", &c_max_items, "blocksize", &c_blocksize, "blocks", &c_blocks, "hash", &c_hash, "hashsize", &c_hashsize, + "hash_size", &c_hashsize, + "keysize", &c_keysize, + "key_size", &c_keysize, "store", &c_store, - NULL)) { - return; - } + NULL)) { + uwsgi_log("unable to parse cache definition\n"); + exit(1); + } + if (!c_name) { + uwsgi_log("you have to specify a cache name\n"); + exit(1); + } + if (!c_max_items) { + uwsgi_log("you have to specify the maximum number of cache items\n"); + exit(1); + } + + uc->name = c_name; + uc->max_items = uwsgi_n64(c_max_items); + if (!uc->max_items) { + uwsgi_log("you have to specify the maximum number of cache items\n"); + exit(1); + } + + // defaults + uc->blocks = uc->max_items; + uc->blocksize = UMAX16; + uc->keysize = 2048; + uc->hashsize = UMAX16; + uc->hash = uwsgi_hash_algo_get("djb33x"); + + // 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); } + 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); + if (!uc->hash) { uwsgi_log("invalid cache hash for \"%s\"\n", uc->name); exit(1); } + if (c_hashsize) uc->hashsize = uwsgi_n64(c_hashsize); + if (!uc->hashsize) { uwsgi_log("invalid cache hashsize for \"%s\"\n", uc->name); exit(1); } + if (c_keysize) uc->keysize = uwsgi_n64(c_keysize); + if (!uc->keysize) { uwsgi_log("invalid cache keysize for \"%s\"\n", uc->name); exit(1); } + + + if (uc->blocks < uc->max_items) { + uwsgi_log("invalid number of cache blocks for \"%s\", must be higher than max_items (%llu)\n", uc->name, uc->max_items); + exit(1); + } + + uc->store = c_store; + } uwsgi_cache_init(uc); diff --git a/core/uwsgi.c b/core/uwsgi.c index b6453d24..9966e901 100644 --- a/core/uwsgi.c +++ b/core/uwsgi.c @@ -191,6 +191,8 @@ static struct uwsgi_option uwsgi_base_options[] = { {"load-file-in-cache", required_argument, 0, "load a static file in the cache", uwsgi_opt_add_string_list, &uwsgi.load_file_in_cache, 0}, + {"cache2", required_argument, 0, "create a new generation shared cache (keyval syntax)", uwsgi_opt_add_string_list, &uwsgi.cache2, 0}, + {"queue", required_argument, 0, "enable shared queue", uwsgi_opt_set_int, &uwsgi.queue_size, 0}, {"queue-blocksize", required_argument, 0, "set queue blocksize", uwsgi_opt_set_int, &uwsgi.queue_store_sync, 0}, @@ -2296,6 +2298,11 @@ int uwsgi_start(void *v_argv) { } // setup new generation caches + struct uwsgi_string_list *usl = uwsgi.cache2; + while(usl) { + uwsgi_cache_create(usl->value); + usl = usl->next; + } // create the cache server if (uwsgi.master_process && uwsgi.cache_server) { diff --git a/uwsgi.h b/uwsgi.h index da91ce7f..7d9e11da 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -39,6 +39,8 @@ extern "C" { #define uwsgi_check_scheme(file) (!uwsgi_startswith(file, "emperor://", 10) || !uwsgi_startswith(file, "http://", 7) || !uwsgi_startswith(file, "data://", 7) || !uwsgi_startswith(file, "sym://", 6) || !uwsgi_startswith(file, "fd://", 5) || !uwsgi_startswith(file, "exec://", 7) || !uwsgi_startswith(file, "section://", 10)) +#define uwsgi_n64(x) strtoul(x, NULL, 10) + #define ushared uwsgi.shared #define UWSGI_OPT_IMMEDIATE (1 << 0) @@ -1709,6 +1711,7 @@ struct uwsgi_server { uint64_t cache_blocksize; char *cache_store; int cache_store_sync; + struct uwsgi_string_list *cache2; struct uwsgi_dyn_dict *static_expires_type; struct uwsgi_dyn_dict *static_expires_type_mtime;