stew

a monorepo of some sort
git clone git://git.nsmpr.xyz/stew.git
Log | Files | Refs

srv.c (3819B)


      1 /*
      2 	primitive key-value database
      3 */
      4 
      5 #include <u.h>
      6 #include <libc.h>
      7 #include <regexp.h>
      8 #include <fcall.h>
      9 #include <thread.h>
     10 #include <9p.h>
     11 
     12 #include "keyval.h"
     13 
     14 typedef struct Keyval Faux;
     15 typedef struct Key Key;
     16 struct Key {
     17 	Keyval;
     18 	Key *next;
     19 };
     20 
     21 enum {
     22 	FauxSize = BufSize,
     23 };
     24 
     25 void usage(void);
     26 
     27 void ctl_open(Req *r);
     28 void ctl_read(Req *r);
     29 void ctl_write(Req *r);
     30 void ctl_destroyfid(Fid *fid);
     31 
     32 void * allocfaux(void);
     33 void freefaux(void *v);
     34 
     35 int fd, pd[2];
     36 Key *keyp;
     37 char *serv = "keyval";
     38 char *mnt = "/mnt/keyval";
     39 
     40 Srv fs = {
     41 	.open = ctl_open,
     42 	.read = ctl_read,
     43 	.write = ctl_write,
     44 	.destroyfid = ctl_destroyfid,
     45 };
     46 
     47 void
     48 main(int argc, char **argv)
     49 {
     50 	ARGBEGIN{
     51 	case 'D':
     52 		chatty9p++;
     53 		break;
     54 	case 's':
     55 		serv = EARGF(usage());
     56 		break;
     57 	case 'm':
     58 		mnt = EARGF(usage());
     59 		break;
     60 	default:
     61 		usage();
     62 	}ARGEND
     63 
     64 	if (argc != 0) usage();
     65 
     66 	fs.tree = alloctree("keyval", "keyval", 0555, nil);
     67 	createfile(fs.tree->root, "ctl", "keyval", DMAPPEND|0666, nil);
     68 
     69 	postmountsrv(&fs, serv, mnt, MREPL);
     70 }
     71 
     72 void
     73 usage(void)
     74 {
     75 	fprint(2, "usage: %s [-s name] [-m path]\n", argv0);
     76 	exits("usage");
     77 }
     78 
     79 Key *
     80 findkey(Key *kp, char *key)
     81 {
     82 	for (; kp != nil; kp = kp->next) {
     83 		if (strncmp(key, kp->key, KeySize) == 0) return kp;
     84 	}
     85 	return nil;
     86 }
     87 
     88 Key *
     89 setkey(Key **root, Keyval *kv)
     90 {
     91 	Key *k = findkey(*root, kv->key);
     92 	if (k == nil) {
     93 		k = mallocz(sizeof(Key), 1);
     94 		strncpy(k->key, kv->key, KeySize);
     95 		k->next = *root;
     96 		*root = k;
     97 	}
     98 	if (k == nil) return nil;
     99 	memcpy(k, kv, kv->count);
    100 	return k;
    101 }
    102 
    103 void
    104 keyreg(Key *kp, Keyval *rv, Keyval *kv)
    105 {
    106 	int i;
    107 	KVHeader *kh = (KVHeader *) kv;
    108 	char *key = mallocz(KeySize + 1, 1);
    109 	char *buf = mallocz(rv->count - MetaSize + 1, 1);
    110 	memcpy(buf, rv->data, rv->count - MetaSize);
    111 	Reprog *reg = regcomp(buf);
    112 	free(buf);
    113 
    114 	for(i = 0; kp != nil; kp = kp->next) {
    115 		memcpy(key, kp->key, KeySize);
    116 		if (regexec(reg, key, nil, 0) == 1) {
    117 			if (i >= BufSize / MetaSize) break;
    118 			if (kp->count < MetaSize) continue;
    119 			memcpy(kh + i, kp, MetaSize);
    120 			i++;
    121 		}
    122 	}
    123 	kv->count = i * MetaSize;
    124 
    125 	free(reg);
    126 	free(key);
    127 }
    128 
    129 /*********
    130 int
    131 valreg(Key *kp, Keyval *rv, Keyval *kv)
    132 {
    133 	Reprog *reg;
    134 	char *buf = mallocz(rv->count - MetaSize + 1, 1);
    135 	memcpy(buf, rv->data, rv->count - MetaSize);
    136 	reg = regcomp(buf);
    137 	free(buf);
    138 
    139 	int n;
    140 	char *bp = kv->data;
    141 	for(n = 0; kp != nil; kp = kp->next) {
    142 		if (regexec(reg, kp->data, nil, 0) == 1) {
    143 			n++;
    144 			bp += snprint(bp, BufSize - (bp - buf), "%s ", kp->key);
    145 		}
    146 	}
    147 	bp[-1] = '\0';
    148 	free(reg);
    149 	return n;
    150 }
    151 **********/
    152 
    153 void ctl_read(Req *r)
    154 {
    155 	if (r->fid->aux == nil) {
    156 		sysfatal("read: aux is nil");
    157 	}
    158 	int count;
    159 	Faux *faux = r->fid->aux;
    160 	count = (r->ifcall.count > faux->count) ? faux->count : r->ifcall.count;
    161 	memcpy(r->ofcall.data, faux, count);
    162 	r->ofcall.count = r->ifcall.count;
    163 	respond(r, nil);
    164 }
    165 
    166 void ctl_write(Req *r)
    167 {
    168 	if (r->fid->aux == nil) {
    169 		sysfatal("write: aux is nil");
    170 	}
    171 	Faux *faux = r->fid->aux;
    172 	memset(faux, 0, FauxSize);
    173 	if (r->ifcall.count < 6) goto badwrite;
    174 	Keyval *kv = (Keyval *)(r->ifcall.data);
    175 	kv->count = r->ifcall.count;
    176 	r->ofcall.count = r->ifcall.count;
    177 	switch(kv->op){
    178 	case KVNop:
    179 		break;
    180 	case KVSet:
    181 		if (r->ifcall.count < MetaSize) goto badwrite;
    182 		setkey(&keyp, kv);
    183 		break;
    184 	case KVGet:
    185 		kv = findkey(keyp, kv->key);
    186 		if (kv != nil) {
    187 			memcpy(faux, kv, kv->count);
    188 		}
    189 		break;
    190 	case KVKeyreg:
    191 		if (r->ifcall.count < MetaSize) goto badwrite;
    192 		keyreg(keyp, kv, faux);
    193 		break;
    194 	case KVValreg:
    195 		break;
    196 	default:
    197 		goto badwrite;
    198 	}
    199 
    200 	respond(r, nil);
    201 	return;
    202 
    203 	badwrite:
    204 	respond(r, "bad write");
    205 }
    206 
    207 void ctl_open(Req *r)
    208 {
    209 	r->fid->aux = allocfaux();
    210 	respond(r, nil);
    211 }
    212 
    213 void ctl_destroyfid(Fid *fid)
    214 {
    215 	freefaux(fid->aux);
    216 }
    217 
    218 void *
    219 allocfaux(void)
    220 {
    221 	void *v = mallocz(FauxSize, 1);
    222 	return v;
    223 }
    224 
    225 void
    226 freefaux(void *v)
    227 {
    228 	free(v);
    229 }