xref: /plan9/sys/src/libndb/ndbcache.c (revision 1a4050f5b2ddf426a278e3233ccd7b6bcb0639b8)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <ndb.h>
5 
6 struct Ndbcache
7 {
8 	Ndbcache	*next;
9 	char		*attr;
10 	char		*val;
11 	Ndbs		s;
12 	Ndbtuple	*t;
13 };
14 
15 enum
16 {
17 	Maxcached=	128,
18 };
19 
20 static void
ndbcachefree(Ndbcache * c)21 ndbcachefree(Ndbcache *c)
22 {
23 	free(c->val);
24 	free(c->attr);
25 	if(c->t)
26 		ndbfree(c->t);
27 	free(c);
28 }
29 
30 static Ndbtuple*
ndbcopy(Ndb * db,Ndbtuple * from_t,Ndbs * from_s,Ndbs * to_s)31 ndbcopy(Ndb *db, Ndbtuple *from_t, Ndbs *from_s, Ndbs *to_s)
32 {
33 	Ndbtuple *first, *to_t, *last, *line;
34 	int newline;
35 
36 	*to_s = *from_s;
37 	to_s->t = nil;
38 	to_s->db = db;
39 
40 	newline = 1;
41 	last = nil;
42 	first = nil;
43 	line = nil;
44 	for(; from_t != nil; from_t = from_t->entry){
45 		to_t = ndbnew(from_t->attr, from_t->val);
46 
47 		/* have s point to matching tuple */
48 		if(from_s->t == from_t)
49 			to_s->t = to_t;
50 
51 		if(newline)
52 			line = to_t;
53 		else
54 			last->line = to_t;
55 
56 		if(last != nil)
57 			last->entry = to_t;
58 		else {
59 			first = to_t;
60 			line = to_t;
61 		}
62 		to_t->entry = nil;
63 		to_t->line = line;
64 		last = to_t;
65 		newline = from_t->line != from_t->entry;
66 	}
67 	ndbsetmalloctag(first, getcallerpc(&db));
68 	return first;
69 }
70 
71 /*
72  *  if found, move to front
73  */
74 int
_ndbcachesearch(Ndb * db,Ndbs * s,char * attr,char * val,Ndbtuple ** t)75 _ndbcachesearch(Ndb *db, Ndbs *s, char *attr, char *val, Ndbtuple **t)
76 {
77 	Ndbcache *c, **l;
78 
79 	*t = nil;
80 	c = nil;
81 	for(l = &db->cache; *l != nil; l = &(*l)->next){
82 		c = *l;
83 		if(strcmp(c->attr, attr) == 0 && strcmp(c->val, val) == 0)
84 			break;
85 	}
86 	if(*l == nil)
87 		return -1;
88 
89 	/* move to front */
90 	*l = c->next;
91 	c->next = db->cache;
92 	db->cache = c;
93 
94 	*t = ndbcopy(db, c->t, &c->s, s);
95 	return 0;
96 }
97 
98 Ndbtuple*
_ndbcacheadd(Ndb * db,Ndbs * s,char * attr,char * val,Ndbtuple * t)99 _ndbcacheadd(Ndb *db, Ndbs *s, char *attr, char *val, Ndbtuple *t)
100 {
101 	Ndbcache *c, **l;
102 
103 	c = mallocz(sizeof *c, 1);
104 	if(c == nil)
105 		return nil;
106 	c->attr = strdup(attr);
107 	if(c->attr == nil)
108 		goto err;
109 	c->val = strdup(val);
110 	if(c->val == nil)
111 		goto err;
112 	c->t = ndbcopy(db, t, s, &c->s);
113 	if(c->t == nil && t != nil)
114 		goto err;
115 
116 	/* add to front */
117 	c->next = db->cache;
118 	db->cache = c;
119 
120 	/* trim list */
121 	if(db->ncache < Maxcached){
122 		db->ncache++;
123 		return t;
124 	}
125 	for(l = &db->cache; (*l)->next; l = &(*l)->next)
126 		;
127 	c = *l;
128 	*l = nil;
129 err:
130 	ndbcachefree(c);
131 	ndbsetmalloctag(t, getcallerpc(&db));
132 	return t;
133 }
134 
135 void
_ndbcacheflush(Ndb * db)136 _ndbcacheflush(Ndb *db)
137 {
138 	Ndbcache *c;
139 
140 	while(db->cache != nil){
141 		c = db->cache;
142 		db->cache = c->next;
143 		ndbcachefree(c);
144 	}
145 	db->ncache = 0;
146 }
147