stew

a monorepo of some sort
Log | Files | Refs

commit 0745c973b5032194c33ef481a302eb1bcff8c11d
parent 90ec56c54528056b5caa8b4ee98f11751063d94e
Author: Renev Pavel <an2qzavok@gmail.com>
Date:   Mon,  6 Feb 2023 20:19:17 +0000

srv/wdb: srv - some kind of keyval store

Diffstat:
Msrc/wdb/mkfile | 5++---
Asrc/wdb/srv.c | 129+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 131 insertions(+), 3 deletions(-)

diff --git a/src/wdb/mkfile b/src/wdb/mkfile @@ -1,5 +1,5 @@ </$objtype/mkfile -TARG=search +TARG=search srv HFILES=wdb.h util.h OFILES=util.$O -</sys/src/cmd/mkmany -\ No newline at end of file +</sys/src/cmd/mkmany diff --git a/src/wdb/srv.c b/src/wdb/srv.c @@ -0,0 +1,129 @@ +#include <u.h> +#include <libc.h> + +enum { + BufSize = 8192, + KeySize = 256, +}; + +typedef struct Key Key; +typedef struct Val Val; + +struct Val { + long n; + char *p; +}; + +struct Key { + char key[KeySize]; + Val val; + Key *next; +}; + +int fd, pd[2]; +Key *keyp; + +void srv(void); +int eval(char *buf, int n); + +void +main(int, char **) +{ + pipe(pd); + fd = create("/srv/wdb", OWRITE, 0666); + fprint(fd, "%d", pd[0]); + close(fd); + close(pd[0]); + close(0); + close(1); + switch(rfork(RFFDG|RFPROC|RFNAMEG|RFNOTEG|RFREND)) { // TODO: double check flags + case -1: + fprint(2, "%r\n"); + exits("fork"); + break; + case 0: + srv(); + break; + } +} + +void +srv(void) +{ + int n; + char buf[BufSize]; + for (;;) { + memset(buf, 0, BufSize); + n = read(pd[1], buf, BufSize); + n = eval(buf, n); + if (write(pd[1], buf, n) < n) break; + } + fprint(2, "%r\n"); +} + +Key * +findkey(Key *root, char *key) +{ + Key *kp; + for (kp = root; kp != nil; kp = kp->next) { + if (strncmp(key, kp->key, KeySize) == 0) return kp; + } + return nil; +} + +int +setkey(Key **root, char *key, char *p, int n) +{ + Key *k = findkey(*root, key); + if (k == nil) { + k = mallocz(sizeof(Key), 1); + strncpy(k->key, key, KeySize); + k->next = *root; + *root = k; + } else if (k->val.p != nil) { + free(k->val.p); + } + if (k == nil) return -1; + k->val.n = n; + k->val.p = mallocz(n, 1); + if (k->val.p == nil) return -1; + memcpy(k->val.p, p, n); + return 0; +} + +Val * +getkey(Key *root, char *key) +{ + Key *k = findkey(root, key); + if (k == nil) return nil; + return &(k->val); +} + +int +eval(char *buf, int n) +{ + char *args[3], *act, *key, *data; + for (; n > 0; buf++, n--) if (strchr(" \t\n", buf[0]) == nil) break; + if (n <= 0) return 0; + if (buf[0] == '\n') return 0; + if (getfields(buf, args, 3, 1, " \t\n") < 2) return sprint(buf, "error malformed message"); + act = args[0], key = args[1], data = args[2]; + if (strlen(act) >= 8) return sprint(buf, "error bad command"); + if (strlen(key) >= KeySize) return sprint(buf, "error bad key"); + if (strncmp(act, "store", 8) == 0) { + if (setkey(&keyp, key, data, data - buf + n) != 0) { + return sprint(buf, "error store failed"); + } else { + return sprint(buf, "ok %s", key); + } + } + if (strncmp(act, "fetch", 8) == 0) { + Val *v = getkey(keyp, key); + if (v == nil) { + return sprint(buf, "nil %s", key); + } else { + return sprint(buf, "ok %s %s", key, v->p); + } + } + return sprint(buf, "error unknown command"); +}