2016-11-25 17:18:40 +01:00
|
|
|
/*
|
|
|
|
* 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 <u.h>
|
2017-04-19 23:33:14 +02:00
|
|
|
#include <lib9.h>
|
2016-11-25 17:18:40 +01:00
|
|
|
#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;
|
|
|
|
}
|
|
|
|
ndbsetmalloctag(first, getcallerpc());
|
|
|
|
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);
|
|
|
|
ndbsetmalloctag(t, getcallerpc());
|
|
|
|
return t;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
_ndbcacheflush(Ndb *db)
|
|
|
|
{
|
|
|
|
Ndbcache *c;
|
|
|
|
|
|
|
|
while(db->cache != nil){
|
|
|
|
c = db->cache;
|
|
|
|
db->cache = c->next;
|
|
|
|
ndbcachefree(c);
|
|
|
|
}
|
|
|
|
db->ncache = 0;
|
|
|
|
}
|