mirror of
https://github.com/radareorg/sdb.git
synced 2026-11-08 17:44:10 -10:00
227 lines
5.6 KiB
C
227 lines
5.6 KiB
C
/* mcsdb - LGPLv3 - Copyright 2011-2022 - pancake */
|
|
|
|
#include "mcsdb.h"
|
|
#include <ctype.h>
|
|
#include <sys/resource.h>
|
|
|
|
static inline void strtolower(char *s) {
|
|
int i = 0;
|
|
for (i = 0; s[i]; i++) {
|
|
s[i] = tolower (s[i]);
|
|
}
|
|
}
|
|
|
|
static void handle_get(McSdb *ms, int fd, char *key, int smode) {
|
|
ut64 exptime = 0LL;
|
|
ut32 cas;
|
|
int n = 0;
|
|
char *s, *k, *K = key;
|
|
if (!key) {
|
|
net_printf (fd, "ERROR\r\n");
|
|
return;
|
|
}
|
|
do {
|
|
k = strchr (K, ' ');
|
|
if (k) *k = 0;
|
|
s = mcsdb_get (ms, K, &exptime, &cas);
|
|
if (s) {
|
|
if (smode) {
|
|
net_printf (fd, "VALUE %s %llu %d %d\r\n",
|
|
K, exptime, (int)strlen (s), cas);
|
|
} else {
|
|
net_printf (fd, "VALUE %s %llu %d\r\n",
|
|
K, exptime, (int)strlen (s));
|
|
}
|
|
net_printf (fd, "%s\r\n", s);
|
|
free (s);
|
|
n++;
|
|
}
|
|
if (k) K = k + 1;
|
|
} while (k);
|
|
net_printf (fd, "END\r\n"); // no elements found
|
|
}
|
|
|
|
int protocol_handle(McSdb *ms, McSdbClient *c, char *buf) {
|
|
struct rusage ru;
|
|
int fd, ret, reply, stored = 1;
|
|
char *b, *p, *q, *cmd = buf, *key = NULL;
|
|
int flags = 0, bytes = 0;
|
|
ut64 n = 0;
|
|
ut32 cmdhash = 0;
|
|
|
|
if (!c || !*buf) { // never happenz
|
|
//net_printf (fd, "ERROR\r\n");
|
|
return 0;
|
|
}
|
|
fd = c->fd;
|
|
//printf ("----> mode=%d buf=(%s)\n", c->mode, buf);
|
|
if (c->mode == 1) {
|
|
b = buf;
|
|
b[c->len-1] = 0;
|
|
switch (c->cmdhash) {
|
|
case MCSDB_CMD_SET: mcsdb_set (ms, c->key, b, c->exptime, 0); break;
|
|
case MCSDB_CMD_APPEND: mcsdb_append (ms, c->key, c->exptime, b); break;
|
|
case MCSDB_CMD_ADD: stored = mcsdb_add (ms, c->key, c->exptime, b); break;
|
|
case MCSDB_CMD_PREPEND: mcsdb_prepend (ms, c->key, c->exptime, b); break;
|
|
case MCSDB_CMD_REPLACE: stored = mcsdb_replace (ms, c->key, c->exptime, b); break;
|
|
default: break;
|
|
}
|
|
net_printf (fd, stored? "STORED\r\n": "NOT_STORED\r\n");
|
|
c->mode = 0;
|
|
c->idx = c->next;
|
|
c->cmdhash = 0;
|
|
return 1;
|
|
}
|
|
p = strchr (buf, ' ');
|
|
if (p) {
|
|
*p = 0;
|
|
key = p + 1;
|
|
if ((p=strchr (key, ' ')))
|
|
*p = 0;
|
|
strncpy (c->key, key, sizeof (c->key)-1); // XXX overflow
|
|
if (p) {
|
|
*p = ' ';
|
|
p++;
|
|
}
|
|
}
|
|
strtolower (cmd);
|
|
|
|
cmdhash = sdb_hash (cmd);
|
|
switch (cmdhash) {
|
|
case MCSDB_CMD_FLUSH_ALL:
|
|
mcsdb_flush (ms);
|
|
net_printf (fd, "OK\r\n");
|
|
break;
|
|
case MCSDB_CMD_VERBOSITY:
|
|
// not yet implemented
|
|
net_printf (fd, "OK\r\n");
|
|
break;
|
|
case MCSDB_CMD_QUIT:
|
|
return -1;
|
|
case MCSDB_CMD_GET:
|
|
if (key) // ignore error
|
|
handle_get (ms, fd, key, 0);
|
|
break;
|
|
case MCSDB_CMD_GETS:
|
|
handle_get (ms, fd, key, 1);
|
|
break;
|
|
case MCSDB_CMD_TOUCH: /* key exptime [noreply] */
|
|
if (!key || !p) {
|
|
net_printf (fd, "ERROR\r\n");
|
|
return 0;
|
|
}
|
|
sscanf (p, "%llu", &n);
|
|
net_printf (fd, mcsdb_touch (ms, key, n)?
|
|
"TOUCHED\r\n": "NOT_TOUCHED\r\n");
|
|
break;
|
|
case MCSDB_CMD_INCR:
|
|
case MCSDB_CMD_DECR:
|
|
if (!key || !p) {
|
|
net_printf (fd, "ERROR\r\n");
|
|
return 0;
|
|
}
|
|
n = strtoull (p, &q, 10);
|
|
if (q) {
|
|
p--;
|
|
*p=0;
|
|
if (cmdhash == MCSDB_CMD_INCR) {
|
|
p = mcsdb_incr (ms, key, n);
|
|
} else {
|
|
p = mcsdb_decr (ms, key, n);
|
|
}
|
|
if (p) {
|
|
net_printf (fd, "%s\r\n", p);
|
|
free (p);
|
|
} else net_printf (fd, "NOT_FOUND\r\n");
|
|
} else net_printf (fd, "ERROR\r\n");
|
|
break;
|
|
case MCSDB_CMD_STATS:
|
|
net_printf (fd, "STAT pid %d\r\n", getpid ());
|
|
net_printf (fd, "STAT version "MCSDB_VERSION"\r\n");
|
|
net_printf (fd, "STAT pointer_size %u\r\n", (int)sizeof (void*)*8);
|
|
net_printf (fd, "STAT time %llu\r\n", sdb_now ());
|
|
net_printf (fd, "STAT uptime %llu\r\n", sdb_now ()-ms->time);
|
|
#ifndef __wasi__
|
|
getrusage (0, &ru);
|
|
net_printf (fd, "STAT rusage_user %u.%u\r\n",
|
|
(ut32)ru.ru_utime.tv_sec, (ut32)ru.ru_utime.tv_usec);
|
|
net_printf (fd, "STAT rusage_system %u.%u\r\n",
|
|
(ut32)ru.ru_stime.tv_sec, (ut32)ru.ru_stime.tv_usec);
|
|
#endif
|
|
net_printf (fd, "STAT curr_connections %u\r\n", ms->nfds-1);
|
|
net_printf (fd, "STAT total_connections %u\r\n", ms->tfds);
|
|
net_printf (fd, "STAT cmd_get %llu\r\n", ms->gets);
|
|
net_printf (fd, "STAT cmd_set %llu\r\n", ms->sets);
|
|
net_printf (fd, "STAT get_hits %llu\r\n", ms->hits);
|
|
net_printf (fd, "STAT get_misses %llu\r\n", ms->misses);
|
|
net_printf (fd, "STAT evictions %llu\r\n", ms->evictions);
|
|
net_printf (fd, "STAT bytes_read %llu\r\n", ms->bread);
|
|
net_printf (fd, "STAT bytes_written %llu\r\n", ms->bwrite);
|
|
// ?? net_printf (fd, "STAT limit_maxbytes 0\r\n");
|
|
net_printf (fd, "STAT threads 1\r\n");
|
|
net_printf (fd, "END\r\n");
|
|
break;
|
|
case MCSDB_CMD_VERSION:
|
|
net_printf (fd, "VERSION 0.1\r\n");
|
|
break;
|
|
case MCSDB_CMD_DELETE:
|
|
if (!key) return 0;
|
|
p = strchr (key, ' ');
|
|
if (p) {
|
|
*p = 0;
|
|
if (!memcmp (p+1, "noreply", 7)) {
|
|
reply = 0;
|
|
} else {
|
|
reply = 1;
|
|
}
|
|
} else {
|
|
reply = 1;
|
|
}
|
|
c->exptime = 0LL;
|
|
sscanf (key, "%llu", &c->exptime);
|
|
ret = mcsdb_remove (ms, key, c->exptime);
|
|
if (reply) {
|
|
if (ret) {
|
|
net_printf (fd, "DELETED\r\n");
|
|
} else {
|
|
net_printf (fd, "NOT_FOUND\r\n");
|
|
}
|
|
}
|
|
break;
|
|
case MCSDB_CMD_ADD:
|
|
case MCSDB_CMD_SET:
|
|
case MCSDB_CMD_APPEND:
|
|
case MCSDB_CMD_PREPEND:
|
|
case MCSDB_CMD_REPLACE:
|
|
if (!key || !p) {// || !((p=strchr (key, ' ')))) {
|
|
net_printf (fd, "ERROR\r\n");
|
|
return 0;
|
|
}
|
|
ret = sscanf (p, "%d %llu %d", &flags, &c->exptime, &bytes);
|
|
if (ret != 3) {
|
|
net_printf (fd, "ERROR parsing (%s)\r\n", p+1);
|
|
return 0;
|
|
}
|
|
if (bytes<1) {
|
|
net_printf (fd, "CLIENT_ERROR invalid length\r\n");
|
|
net_printf (fd, "ERROR\r\n");
|
|
return 0;
|
|
}
|
|
c->mode = 1; // read N bytes
|
|
//c->next = 0;
|
|
c->idx = c->next;
|
|
c->len = bytes+1;
|
|
c->cmdhash = cmdhash;
|
|
// continue on mode 1
|
|
return 1;
|
|
case MCSDB_CMD_CAS:
|
|
// check and set
|
|
// cas <key> <flags> <exptime> <bytes> <cas unqiue> [noreply]\r\n
|
|
printf ("NOT YET IMPLEMENTED\n");
|
|
return 0;
|
|
default:
|
|
net_printf (fd, "ERROR\r\n");
|
|
}
|
|
return 0;
|
|
}
|