Files
uwsgi/plugins/cache/cache.c
T
2013-02-07 16:15:26 +01:00

149 lines
5.4 KiB
C

#include <uwsgi.h>
/*
Plugin for remote access to the uWSGI cache
For request generating a response containing cache data, we need to make
a copy to avoid holding the lock too much in case of blocking/slow writes
uwsgi_cache_safe_get2() will do the job
the modifier2 is the command to run. Some command is extremely raw, and generally it is mean
for internal uWSGI usage.
*/
extern struct uwsgi_server uwsgi;
static void cache_command(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
struct wsgi_request *wsgi_req = (struct wsgi_request *) data;
uint64_t tmp_vallen = 0;
if (vallen > 0) {
if (!uwsgi_strncmp(key, keylen, "key", 3)) {
val = uwsgi_cache_get(val, vallen, &tmp_vallen);
if (val && tmp_vallen > 0) {
#ifdef UWSGI_DEBUG
uwsgi_log("cache value size: %llu\n", tmp_vallen);
#endif
uwsgi_response_write_body_do(wsgi_req, val, tmp_vallen);
}
}
else if (!uwsgi_strncmp(key, keylen, "get", 3)) {
val = uwsgi_cache_get(val, vallen, &tmp_vallen);
if (val && vallen > 0) {
uwsgi_response_write_body_do(wsgi_req, val, tmp_vallen);
}
else {
uwsgi_404(wsgi_req);
}
}
}
}
int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
uint64_t vallen = 0;
char *value;
char *argv[3];
uint16_t argvs[3];
uint8_t argc = 0;
switch(wsgi_req->uh->modifier2) {
case 0:
// get
if (wsgi_req->uh->pktsize > 0) {
value = uwsgi_cache_get(wsgi_req->buffer, wsgi_req->uh->pktsize, &vallen);
if (value && vallen > 0) {
wsgi_req->uh->pktsize = vallen;
if (uwsgi_response_write_body_do(wsgi_req, (char *)&wsgi_req->uh, 4)) return -1;
uwsgi_response_write_body_do(wsgi_req, value, vallen);
}
}
break;
case 1:
// set
if (wsgi_req->uh->pktsize > 0) {
argc = 3;
if (!uwsgi_parse_array(wsgi_req->buffer, wsgi_req->uh->pktsize, argv, argvs, &argc)) {
if (argc > 1) {
uwsgi_cache_set(argv[0], argvs[0], argv[1], argvs[1], 0, 0);
}
}
}
break;
case 2:
// del
if (wsgi_req->uh->pktsize > 0) {
uwsgi_cache_del(wsgi_req->buffer, wsgi_req->uh->pktsize, 0, 0);
}
break;
case 3:
case 4:
// dict
if (wsgi_req->uh->pktsize > 0) {
uwsgi_hooked_parse(wsgi_req->buffer, wsgi_req->uh->pktsize, cache_command, (void *) wsgi_req);
}
break;
case 5:
// get (uwsgi + stream)
if (wsgi_req->uh->pktsize > 0) {
value = uwsgi_cache_get(wsgi_req->buffer, wsgi_req->uh->pktsize, &vallen);
if (value && vallen > 0) {
wsgi_req->uh->pktsize = 0;
wsgi_req->uh->modifier2 = 1;
if (uwsgi_response_write_body_do(wsgi_req, (char *)&wsgi_req->uh, 4)) return -1;
uwsgi_response_write_body_do(wsgi_req, value, vallen);
}
else {
wsgi_req->uh->pktsize = 0;
wsgi_req->uh->modifier2 = 0;
if (uwsgi_response_write_body_do(wsgi_req, (char *)&wsgi_req->uh, 4)) return -1;
}
}
break;
case 6:
// dump
wsgi_req->uh->modifier2 = 7;
struct uwsgi_buffer *cache_dump = uwsgi_buffer_new(4096);
if (uwsgi_buffer_append_keynum(cache_dump, "items", 5, uwsgi.cache_max_items)) {
uwsgi_buffer_destroy(cache_dump);
break;
}
if (uwsgi_buffer_append_keynum(cache_dump, "blocksize", 9, uwsgi.cache_blocksize)) {
uwsgi_buffer_destroy(cache_dump);
break;
}
wsgi_req->uh->pktsize = cache_dump->pos;
if (uwsgi_response_write_body_do(wsgi_req, (char *)&wsgi_req->uh, 4)) {
uwsgi_buffer_destroy(cache_dump);
return -1;
}
uwsgi_response_write_body_do(wsgi_req, cache_dump->buf, cache_dump->pos);
uwsgi_buffer_destroy(cache_dump);
uwsgi_wlock(uwsgi.caches->lock);
int ret = uwsgi_write_nb(wsgi_req->fd, (char *)uwsgi.caches->items, uwsgi.caches->filesize, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (!ret) {
wsgi_req->response_size += uwsgi.caches->filesize;
}
uwsgi_rwunlock(uwsgi.caches->lock);
break;
}
return 0;
}
struct uwsgi_plugin cache_plugin = {
.name = "cache",
.modifier1 = 111,
.request = uwsgi_cache_request,
};