Parlib and other user libs are built with -fPIC
[akaros.git] / user / ndblib / ndbcache.c
1 /* 
2  * This file is part of the UCB release of Plan 9. It is subject to the license
3  * terms in the LICENSE file found in the top-level directory of this
4  * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
5  * part of the UCB release of Plan 9, including this file, may be copied,
6  * modified, propagated, or distributed except according to the terms contained
7  * in the LICENSE file.
8  */
9 #include <stdlib.h>
10
11 #include <stdio.h>
12 #include <parlib.h>
13 #include <unistd.h>
14 #include <signal.h>
15 #include <fcntl.h>
16 #include <iplib.h>
17 #include <ndb.h>
18
19 enum
20 {
21         Maxcached=      128,
22 };
23
24 static void
25 ndbcachefree(struct ndbcache *c)
26 {
27         free(c->val);
28         free(c->attr);
29         if(c->t)
30                 ndbfree(c->t);
31         free(c);
32 }
33
34 static struct ndbtuple*
35 ndbcopy(struct ndb *db, struct ndbtuple *from_t, struct ndbs *from_s,
36         struct ndbs *to_s)
37 {
38         struct ndbtuple *first, *to_t, *last, *line;
39         int newline;
40
41         *to_s = *from_s;
42         to_s->t = NULL;
43         to_s->db = db;
44
45         newline = 1;
46         last = NULL;
47         first = NULL;
48         line = NULL;
49         for(; from_t != NULL; from_t = from_t->entry){
50                 to_t = ndbnew(from_t->attr, from_t->val);
51
52                 /* have s point to matching tuple */
53                 if(from_s->t == from_t)
54                         to_s->t = to_t;
55
56                 if(newline)
57                         line = to_t;
58                 else
59                         last->line = to_t;
60
61                 if(last != NULL)
62                         last->entry = to_t;
63                 else {
64                         first = to_t;
65                         line = to_t;
66                 }
67                 to_t->entry = NULL;
68                 to_t->line = line;
69                 last = to_t;
70                 newline = from_t->line != from_t->entry;
71         }
72         ndbsetmalloctag(first, getcallerpc(&db));
73         return first;
74 }
75
76 /*
77  *  if found, move to front
78  */
79 int
80 _ndbcachesearch(struct ndb *db,
81                 struct ndbs *s, char *attr, char *val, struct ndbtuple **t)
82 {
83         struct ndbcache *c, **l;
84
85         *t = NULL;
86         c = NULL;
87         for(l = &db->cache; *l != NULL; l = &(*l)->next){
88                 c = *l;
89                 if(strcmp(c->attr, attr) == 0 && strcmp(c->val, val) == 0)
90                         break;
91         }
92         if(*l == NULL)
93                 return -1;
94
95         /* move to front */
96         *l = c->next;
97         c->next = db->cache;
98         db->cache = c;
99
100         *t = ndbcopy(db, c->t, &c->s, s);
101         return 0;
102 }
103
104 struct ndbtuple*
105 _ndbcacheadd(struct ndb *db,
106              struct ndbs *s, char *attr, char *val, struct ndbtuple *t)
107 {
108         struct ndbcache *c, **l;
109
110         c = calloc(1, sizeof *c);
111         if(c == NULL)
112                 return NULL;
113         c->attr = strdup(attr);
114         if(c->attr == NULL)
115                 goto err;
116         c->val = strdup(val);
117         if(c->val == NULL)
118                 goto err;
119         c->t = ndbcopy(db, t, s, &c->s);
120         if(c->t == NULL && t != NULL)
121                 goto err;
122
123         /* add to front */
124         c->next = db->cache;
125         db->cache = c;
126
127         /* trim list */
128         if(db->ncache < Maxcached){
129                 db->ncache++;
130                 return t;
131         }
132         for(l = &db->cache; (*l)->next; l = &(*l)->next)
133                 ;
134         c = *l;
135         *l = NULL;
136 err:
137         ndbcachefree(c);
138         ndbsetmalloctag(t, getcallerpc(&db));
139         return t;
140 }
141
142 void
143 _ndbcacheflush(struct ndb *db)
144 {
145         struct ndbcache *c;
146
147         while(db->cache != NULL){
148                 c = db->cache;
149                 db->cache = c->next;
150                 ndbcachefree(c);
151         }
152         db->ncache = 0;
153 }