| /* |
| * This file is part of the UCB release of Plan 9. It is subject to the license |
| * terms in the LICENSE file found in the top-level directory of this |
| * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No |
| * part of the UCB release of Plan 9, including this file, may be copied, |
| * modified, propagated, or distributed except according to the terms contained |
| * in the LICENSE file. |
| */ |
| #include <stdlib.h> |
| |
| #include <stdio.h> |
| #include <parlib/parlib.h> |
| #include <unistd.h> |
| #include <signal.h> |
| #include <fcntl.h> |
| #include <iplib/iplib.h> |
| #include <ndblib/ndb.h> |
| |
| enum |
| { |
| Maxcached= 128, |
| }; |
| |
| static void |
| ndbcachefree(struct ndbcache *c) |
| { |
| free(c->val); |
| free(c->attr); |
| if(c->t) |
| ndbfree(c->t); |
| free(c); |
| } |
| |
| static struct ndbtuple* |
| ndbcopy(struct ndb *db, struct ndbtuple *from_t, struct ndbs *from_s, |
| struct ndbs *to_s) |
| { |
| struct ndbtuple *first, *to_t, *last, *line; |
| int newline; |
| |
| *to_s = *from_s; |
| to_s->t = NULL; |
| to_s->db = db; |
| |
| newline = 1; |
| last = NULL; |
| first = NULL; |
| line = NULL; |
| for(; from_t != NULL; 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 != NULL) |
| last->entry = to_t; |
| else { |
| first = to_t; |
| line = to_t; |
| } |
| to_t->entry = NULL; |
| to_t->line = line; |
| last = to_t; |
| newline = from_t->line != from_t->entry; |
| } |
| ndbsetmalloctag(first, getcallerpc(&db)); |
| return first; |
| } |
| |
| /* |
| * if found, move to front |
| */ |
| int |
| _ndbcachesearch(struct ndb *db, |
| struct ndbs *s, char *attr, char *val, struct ndbtuple **t) |
| { |
| struct ndbcache *c, **l; |
| |
| *t = NULL; |
| c = NULL; |
| for(l = &db->cache; *l != NULL; l = &(*l)->next){ |
| c = *l; |
| if(strcmp(c->attr, attr) == 0 && strcmp(c->val, val) == 0) |
| break; |
| } |
| if(*l == NULL) |
| 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; |
| } |
| |
| struct ndbtuple* |
| _ndbcacheadd(struct ndb *db, |
| struct ndbs *s, char *attr, char *val, struct ndbtuple *t) |
| { |
| struct ndbcache *c, **l; |
| |
| c = calloc(1, sizeof *c); |
| if(c == NULL) |
| return NULL; |
| c->attr = strdup(attr); |
| if(c->attr == NULL) |
| goto err; |
| c->val = strdup(val); |
| if(c->val == NULL) |
| goto err; |
| c->t = ndbcopy(db, t, s, &c->s); |
| if(c->t == NULL && t != NULL) |
| 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 = NULL; |
| err: |
| ndbcachefree(c); |
| ndbsetmalloctag(t, getcallerpc(&db)); |
| return t; |
| } |
| |
| void |
| _ndbcacheflush(struct ndb *db) |
| { |
| struct ndbcache *c; |
| |
| while(db->cache != NULL){ |
| c = db->cache; |
| db->cache = c->next; |
| ndbcachefree(c); |
| } |
| db->ncache = 0; |
| } |