diff --git a/core/cache.c b/core/cache.c index 5e876176..8b113ac8 100644 --- a/core/cache.c +++ b/core/cache.c @@ -1397,6 +1397,74 @@ char *uwsgi_cache_magic_get(char *key, uint16_t keylen, uint64_t *vallen, char * return NULL; } +int uwsgi_cache_magic_exists(char *key, uint16_t keylen, char *cache) { + struct uwsgi_cache_magic_context ucmc; + struct uwsgi_cache *uc = NULL; + char *cache_server = NULL; + char *cache_name = NULL; + uint16_t cache_name_len = 0; + if (cache) { + char *at = strchr(cache, '@'); + if (!at) { + uc = uwsgi_cache_by_name(cache); + } + else { + cache_server = at + 1; + cache_name = cache; + cache_name_len = at - cache; + } + } + // use default (local) cache + else { + uc = uwsgi.caches; + } + + // we have a local cache !!! + if (uc) { + uwsgi_rlock(uc->lock); + if (!uwsgi_cache_exists2(uc, key, keylen)) { + uwsgi_rwunlock(uc->lock); + return 0; + } + uwsgi_rwunlock(uc->lock); + return 1; + } + + // we have a remote one + if (cache_server) { + int fd = uwsgi_connect(cache_server, 0, 1); + if (fd < 0) return 0; + + int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]); + if (ret <= 0) { + close(fd); + return 0; + } + + struct uwsgi_buffer *ub = uwsgi_cache_prepare_magic_exists(cache_name, cache_name_len, key, keylen); + if (!ub) { + close(fd); + return 0; + } + + if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &ucmc)) { + close(fd); + uwsgi_buffer_destroy(ub); + return 0; + } + + if (uwsgi_strncmp(ucmc.status, ucmc.status_len, "ok", 2)) { + close(fd); + uwsgi_buffer_destroy(ub); + return 0; + } + + return 1; + } + + return 0; +} + int uwsgi_cache_magic_set(char *key, uint16_t keylen, char *value, uint64_t vallen, uint64_t expires, uint64_t flags, char *cache) { struct uwsgi_cache_magic_context ucmc; @@ -1472,28 +1540,72 @@ int uwsgi_cache_magic_set(char *key, uint16_t keylen, char *value, uint64_t vall } -int uwsgi_cache_magic_del(char *key, uint16_t keylen, char *cachename) { - struct uwsgi_cache *uc = NULL; +int uwsgi_cache_magic_del(char *key, uint16_t keylen, char *cache) { + + struct uwsgi_cache_magic_context ucmc; + struct uwsgi_cache *uc = NULL; char *cache_server = NULL; - if (cachename) { - char *at = strchr(cachename, '@'); + char *cache_name = NULL; + uint16_t cache_name_len = 0; + if (cache) { + char *at = strchr(cache, '@'); if (!at) { - uc = uwsgi_cache_by_name(cachename); + uc = uwsgi_cache_by_name(cache); } else { + cache_server = at + 1; + cache_name = cache; + cache_name_len = at - cache; } } - // use default (local) cache - if (uc) { - uwsgi_wlock(uc->lock); - int ret = uwsgi_cache_del2(uc, key, keylen, 0, 0); - uwsgi_rwunlock(uc->lock); - return ret; + // use default (local) cache + else { + uc = uwsgi.caches; } - // we have a remote one - if (cache_server) { - } + // we have a local cache !!! + if (uc) { + uwsgi_wlock(uc->lock); + if (uwsgi_cache_del2(uc, key, keylen, 0, 0)) { + uwsgi_rwunlock(uc->lock); + return -1; + } + uwsgi_rwunlock(uc->lock); + return 0; + } + + // we have a remote one + if (cache_server) { + int fd = uwsgi_connect(cache_server, 0, 1); + if (fd < 0) return -1; + + int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]); + if (ret <= 0) { + close(fd); + return -1; + } + + struct uwsgi_buffer *ub = uwsgi_cache_prepare_magic_del(cache_name, cache_name_len, key, keylen); + if (!ub) { + close(fd); + return -1; + } + + if (cache_magic_send_and_manage(fd, ub, NULL, 0, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &ucmc)) { + close(fd); + uwsgi_buffer_destroy(ub); + return -1; + } + + if (uwsgi_strncmp(ucmc.status, ucmc.status_len, "ok", 2)) { + close(fd); + uwsgi_buffer_destroy(ub); + return -1; + } + + return 0; + } + + return -1 ; - return -1; } diff --git a/plugins/cache/cache.c b/plugins/cache/cache.c index 28d3feb0..4f1253a8 100644 --- a/plugins/cache/cache.c +++ b/plugins/cache/cache.c @@ -97,6 +97,44 @@ static void manage_magic_context(struct wsgi_request *wsgi_req, struct uwsgi_cac return; } + // cache exists + if (!uwsgi_strncmp(ucmc->cmd, ucmc->cmd_len, "exists", 6)) { + uwsgi_rlock(uc->lock); + if (!uwsgi_cache_exists2(uc, ucmc->key, ucmc->key_len)) { + uwsgi_rwunlock(uc->lock); + return; + } + // we are still locked !!! + ub = uwsgi_buffer_new(uwsgi.page_size); + ub->pos = 4; + if (uwsgi_buffer_append_keyval(ub, "status", 6, "ok", 2)) goto error; + if (uwsgi_buffer_set_uh(ub, 111, 17)) goto error; + // unlock !!! + uwsgi_rwunlock(uc->lock); + uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos); + uwsgi_buffer_destroy(ub); + return; + } + + // cache del + if (!uwsgi_strncmp(ucmc->cmd, ucmc->cmd_len, "del", 3)) { + uwsgi_wlock(uc->lock); + if (uwsgi_cache_del2(uc, ucmc->key, ucmc->key_len, 0, 0)) { + uwsgi_rwunlock(uc->lock); + return; + } + // we are still locked !!! + ub = uwsgi_buffer_new(uwsgi.page_size); + ub->pos = 4; + if (uwsgi_buffer_append_keyval(ub, "status", 6, "ok", 2)) goto error; + if (uwsgi_buffer_set_uh(ub, 111, 17)) goto error; + // unlock !!! + uwsgi_rwunlock(uc->lock); + uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos); + uwsgi_buffer_destroy(ub); + return; + } + // cache set if (!uwsgi_strncmp(ucmc->cmd, ucmc->cmd_len, "set", 3) || !uwsgi_strncmp(ucmc->cmd, ucmc->cmd_len, "update", 6)) { if (ucmc->size == 0 || ucmc->size > uc->max_item_size) return; diff --git a/plugins/python/uwsgi_pymodule.c b/plugins/python/uwsgi_pymodule.c index ca3d6ef8..ac1d6f8b 100644 --- a/plugins/python/uwsgi_pymodule.c +++ b/plugins/python/uwsgi_pymodule.c @@ -2544,33 +2544,24 @@ PyObject *py_uwsgi_cache_clear(PyObject * self, PyObject * args) { PyObject *py_uwsgi_cache_del(PyObject * self, PyObject * args) { char *key; - Py_ssize_t keylen = 0; - char *remote = NULL; + Py_ssize_t keylen = 0; + char *cache = NULL; - if (!PyArg_ParseTuple(args, "s#|s:cache_del", &key, &keylen, &remote)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "s#|s:cache_del", &key, &keylen, &cache)) { + return NULL; + } - if (remote && strlen(remote) > 0) { - UWSGI_RELEASE_GIL - //uwsgi_simple_send_string(remote, 111, 2, key, keylen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]); - UWSGI_GET_GIL - } - else if (uwsgi.caches) { - UWSGI_RELEASE_GIL - uwsgi_wlock(uwsgi.caches->lock); - if (uwsgi_cache_del(key, keylen, 0, 0)) { - uwsgi_rwunlock(uwsgi.caches->lock); - UWSGI_GET_GIL - Py_INCREF(Py_None); - return Py_None; - } - uwsgi_rwunlock(uwsgi.caches->lock); - UWSGI_GET_GIL - } + UWSGI_RELEASE_GIL + if (!uwsgi_cache_magic_del(key, keylen, cache)) { + UWSGI_GET_GIL + Py_INCREF(Py_True); + return Py_True; + } + UWSGI_GET_GIL + + Py_INCREF(Py_None); + return Py_None; - Py_INCREF(Py_True); - return Py_True; } @@ -2633,9 +2624,24 @@ PyObject *py_uwsgi_cache_update(PyObject * self, PyObject * args) { PyObject *py_uwsgi_cache_exists(PyObject * self, PyObject * args) { - Py_INCREF(Py_True); - return Py_True; + char *key; + Py_ssize_t keylen = 0; + char *cache = NULL; + if (!PyArg_ParseTuple(args, "s#|s:cache_get", &key, &keylen, &cache)) { + return NULL; + } + + UWSGI_RELEASE_GIL + if (uwsgi_cache_magic_exists(key, keylen, cache)) { + UWSGI_GET_GIL + Py_INCREF(Py_True); + return Py_True; + } + UWSGI_GET_GIL + + Py_INCREF(Py_None); + return Py_None; } PyObject *py_uwsgi_queue_push(PyObject * self, PyObject * args) {