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:
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");
+}