Subversion Repositories planix.SVN

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

#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;
        }
        ndbsetmalloctag(first, getcallerpc(&db));
        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(&db));
        return t;
}

void
_ndbcacheflush(Ndb *db)
{
        Ndbcache *c;

        while(db->cache != nil){
                c = db->cache;
                db->cache = c->next;
                ndbcachefree(c);
        }
        db->ncache = 0;
}