aboutsummaryrefslogtreecommitdiff
path: root/src/libndb/ndbcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libndb/ndbcache.c')
-rw-r--r--src/libndb/ndbcache.c144
1 files changed, 144 insertions, 0 deletions
diff --git a/src/libndb/ndbcache.c b/src/libndb/ndbcache.c
new file mode 100644
index 00000000..701d63eb
--- /dev/null
+++ b/src/libndb/ndbcache.c
@@ -0,0 +1,144 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <ndb.h>
+
+struct Ndbcache
+{
+ Ndbcache *next;
+ char *attr;
+ char *val;
+ Ndbs s;
+ Ndbtuple *t;
+};
+
+enum
+{
+ Maxcached= 128,
+};
+
+static void
+ndbcachefree(Ndbcache *c)
+{
+ free(c->val);
+ free(c->attr);
+ if(c->t)
+ ndbfree(c->t);
+ free(c);
+}
+
+static Ndbtuple*
+ndbcopy(Ndb *db, Ndbtuple *from_t, Ndbs *from_s, Ndbs *to_s)
+{
+ Ndbtuple *first, *to_t, *last, *line;
+ int newline;
+
+ *to_s = *from_s;
+ to_s->t = nil;
+ to_s->db = db;
+
+ newline = 1;
+ last = nil;
+ first = nil;
+ line = nil;
+ for(; from_t != nil; from_t = from_t->entry){
+ to_t = ndbnew(from_t->attr, from_t->val);
+
+ /* have s point to matching tuple */
+ if(from_s->t == from_t)
+ to_s->t = to_t;
+
+ if(newline)
+ line = to_t;
+ else
+ last->line = to_t;
+
+ if(last != nil)
+ last->entry = to_t;
+ else {
+ first = to_t;
+ line = to_t;
+ }
+ to_t->entry = nil;
+ to_t->line = line;
+ last = to_t;
+ newline = from_t->line != from_t->entry;
+ }
+ return first;
+}
+
+/*
+ * if found, move to front
+ */
+int
+_ndbcachesearch(Ndb *db, Ndbs *s, char *attr, char *val, Ndbtuple **t)
+{
+ Ndbcache *c, **l;
+
+ *t = nil;
+ c = nil;
+ for(l = &db->cache; *l != nil; l = &(*l)->next){
+ c = *l;
+ if(strcmp(c->attr, attr) == 0 && strcmp(c->val, val) == 0)
+ break;
+ }
+ if(*l == nil)
+ return -1;
+
+ /* move to front */
+ *l = c->next;
+ c->next = db->cache;
+ db->cache = c;
+
+ *t = ndbcopy(db, c->t, &c->s, s);
+ return 0;
+}
+
+Ndbtuple*
+_ndbcacheadd(Ndb *db, Ndbs *s, char *attr, char *val, Ndbtuple *t)
+{
+ Ndbcache *c, **l;
+
+ c = mallocz(sizeof *c, 1);
+ if(c == nil)
+ return nil;
+ c->attr = strdup(attr);
+ if(c->attr == nil)
+ goto err;
+ c->val = strdup(val);
+ if(c->val == nil)
+ goto err;
+ c->t = ndbcopy(db, t, s, &c->s);
+ if(c->t == nil && t != nil)
+ goto err;
+
+ /* add to front */
+ c->next = db->cache;
+ db->cache = c;
+
+ /* trim list */
+ if(db->ncache < Maxcached){
+ db->ncache++;
+ return t;
+ }
+ for(l = &db->cache; (*l)->next; l = &(*l)->next)
+ ;
+ c = *l;
+ *l = nil;
+err:
+ ndbcachefree(c);
+ return t;
+}
+
+void
+_ndbcacheflush(Ndb *db)
+{
+ Ndbcache *c;
+
+ while(db->cache != nil){
+ c = db->cache;
+ db->cache = c->next;
+ ndbcachefree(c);
+ }
+ db->ncache = 0;
+}