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 }