xref: /plan9-contrib/sys/src/libndb/ndbcache.c (revision d46c239f8612929b7dbade67d0d071633df3a15d)
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
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*
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 = malloc(sizeof *to_t);
46 		if(to_t == nil){
47 			ndbfree(first);
48 			return nil;
49 		}
50 		*to_t = *from_t;
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 != nil)
62 			last->entry = to_t;
63 		else {
64 			first = to_t;
65 			line = to_t;
66 		}
67 		to_t->entry = nil;
68 		to_t->line = line;
69 		last = to_t;
70 		newline = from_t->line != from_t->entry;
71 	}
72 	return first;
73 }
74 
75 /*
76  *  if found, move to front
77  */
78 int
79 _ndbcachesearch(Ndb *db, Ndbs *s, char *attr, char *val, Ndbtuple **t)
80 {
81 	Ndbcache *c, **l;
82 
83 	*t = nil;
84 	c = nil;
85 	for(l = &db->cache; *l != nil; l = &(*l)->next){
86 		c = *l;
87 		if(strcmp(c->attr, attr) == 0 && strcmp(c->val, val) == 0)
88 			break;
89 	}
90 	if(*l == nil)
91 		return -1;
92 
93 	/* move to front */
94 	*l = c->next;
95 	c->next = db->cache;
96 	db->cache = c;
97 
98 	*t = ndbcopy(db, c->t, &c->s, s);
99 	return 0;
100 }
101 
102 Ndbtuple*
103 _ndbcacheadd(Ndb *db, Ndbs *s, char *attr, char *val, Ndbtuple *t)
104 {
105 	Ndbcache *c, **l;
106 
107 	c = mallocz(sizeof *c, 1);
108 	if(c == nil)
109 		return nil;
110 	c->attr = strdup(attr);
111 	if(c->attr == nil)
112 		goto err;
113 	c->val = strdup(val);
114 	if(c->val == nil)
115 		goto err;
116 	c->t = ndbcopy(db, t, s, &c->s);
117 	if(c->t == nil && t != nil)
118 		goto err;
119 
120 	/* add to front */
121 	c->next = db->cache;
122 	db->cache = c;
123 
124 	/* trim list */
125 	if(db->ncache < Maxcached){
126 		db->ncache++;
127 		return t;
128 	}
129 	for(l = &db->cache; (*l)->next; l = &(*l)->next)
130 		;
131 	c = *l;
132 	*l = nil;
133 err:
134 	ndbcachefree(c);
135 	return t;
136 }
137 
138 void
139 _ndbcacheflush(Ndb *db)
140 {
141 	Ndbcache *c;
142 
143 	while(db->cache != nil){
144 		c = db->cache;
145 		db->cache = c->next;
146 		ndbcachefree(c);
147 	}
148 	db->ncache = 0;
149 }
150