]> andersk Git - moira.git/blame - server/cache.qc
Used /bin/sh format instead of /bin/csh format, by accident.
[moira.git] / server / cache.qc
CommitLineData
dc37f07c 1/*
2 * $Source$
3 * $Author$
4 * $Header$
5 *
6 * Copyright (C) 1989 by the Massachusetts Institute of Technology
7 * For copying and distribution information, please see the file
8 * <mit-copyright.h>.
9 *
10 */
11
12#ifndef lint
13static char *rcsid_qsupport_qc = "$Header$";
14#endif lint
15
16#include <mit-copyright.h>
17#include "query.h"
d548a4e7 18#include "mr_server.h"
dc37f07c 19
20
21extern char *whoami, *strsave();
d548a4e7 22extern int ingres_errno, mr_errcode;
dc37f07c 23
24
25/*** NOTE **************************************************************
26 *
0119a9d6 27 * This code depends on each type starting with a unique letter. If
dc37f07c 28 * any new types are added to the system that begin with the same
29 * letter as one of the existing types:
30 * User
31 * List
32 * String
33 * Machine
34 * Cluster
35 * Filesystem
36 * then we will have to rework the code that only looks at the first
37 * letter of the types.
38 *
39 ***********************************************************************
40 */
41
42/* Cache parameters: */
43#define CACHESIZE 101 /* number of cache slots */
44#define NAMESZ 257 /* max size of a name */
45
46struct item {
47 char name[NAMESZ];
48 char type[9];
0119a9d6 49 int nhash;
dc37f07c 50 int id;
0119a9d6 51 struct item *next;
52 struct item *prev;
dc37f07c 53};
54
0119a9d6 55static struct item cachehead;
56static int cachesize;
dc37f07c 57
dc37f07c 58/* statistics counters */
59int cachehits = 0, cachemisses = 0;
60
dc37f07c 61
62/* Name hash function. */
63
64int hashname(name, type)
65register char *name;
66char *type;
67{
68 register int val = *type;
69
70 while (*name)
71 val = val<<5 - val + *name++ - '`';
0119a9d6 72 return(val);
dc37f07c 73}
74
75
76/* Initialize the cache, flushing any old data, and report the statistics
77 * if the cache was previously in use.
78 */
79
80flush_cache()
81{
0119a9d6 82 register struct item *i;
dc37f07c 83
84 if (cachehits + cachemisses != 0)
85 com_err(whoami, 0, "Flushing cache; %d hits, %d misses, %d%% hit rate",
86 cachehits, cachemisses,
87 (100 * cachehits) / (cachehits + cachemisses));
0119a9d6 88 else
89 cachehead.next = cachehead.prev = &cachehead;
90 cachehits = cachemisses = cachesize = 0;
91 for (i = cachehead.next; i != &cachehead; i = i->next) {
92 if (i->prev != &cachehead)
93 free(i->prev);
dc37f07c 94 }
0119a9d6 95 if (cachehead.prev != &cachehead)
96 free(cachehead.prev);
97 cachehead.next = cachehead.prev = &cachehead;
dc37f07c 98}
99
100
101/* Do a name to ID translation. id will be updated with the answer if
102 * it is available, and as a side effect the cache is updated.
103 */
104
105int name_to_id(name, type, id)
106char *name;
107char *type;
108int *id;
109##{
0119a9d6 110 register struct item *i;
dc37f07c 111## char *iname;
112## int j, rowcount;
0119a9d6 113 int h, ctr;
114
115 h = hashname(name, type);
116 for (i = cachehead.next; i != &cachehead; i = i->next) {
117 if (i->nhash != h ||
118 strcmp(name, i->name) ||
119 strcasecmp(type, i->type))
120 continue;
dc37f07c 121 *id = i->id;
dc37f07c 122 cachehits++;
0119a9d6 123 i->next->prev = i->prev;
124 i->prev->next = i->next;
125 i->next = cachehead.next;
126 i->prev = &cachehead;
127 cachehead.next->prev = i;
128 cachehead.next = i;
d548a4e7 129 return(MR_SUCCESS);
dc37f07c 130 }
131
132 cachemisses++;
133 iname = name;
134
135 switch (*type) {
136 case 'U':
137 case 'u':
138## repeat retrieve (j = users.users_id) where users.#login=@iname
139 break;
140 case 'L':
141 case 'l':
142## repeat retrieve (j = list.list_id) where list.#name=@iname
143 break;
144 case 'M':
145 case 'm':
146## repeat retrieve (j = machine.mach_id) where machine.#name=uppercase(@iname)
147 break;
148 case 'C':
149 case 'c':
150## repeat retrieve (j = cluster.clu_id) where cluster.#name=@iname
151 break;
152 case 'F':
153 case 'f':
154## repeat retrieve (j = filesys.filsys_id) where filesys.#label=@iname
155 break;
156 case 'S':
157 case 's':
158## repeat retrieve (j = strings.string_id) where strings.#string=@iname
159 break;
160 default:
d548a4e7 161 return(MR_INTERNAL);
dc37f07c 162 }
163## inquire_equel(rowcount = "rowcount")
d548a4e7 164 if (ingres_errno) return(mr_errcode);
dc37f07c 165 if (rowcount == 0)
d548a4e7 166 return(MR_NO_MATCH);
dc37f07c 167 if (rowcount > 1)
d548a4e7 168 return(MR_NOT_UNIQUE);
dc37f07c 169 *id = j;
170 if (name[0] == '#' && !strcasecmp(type, "USER"))
d548a4e7 171 return(MR_SUCCESS);
0119a9d6 172 if (cachesize < CACHESIZE) {
173 i = (struct item *) malloc(sizeof(struct item));
174 cachesize++;
175 } else {
176 i = cachehead.prev;
177 cachehead.prev = i->prev;
178 i->prev->next = &cachehead;
dc37f07c 179 }
0119a9d6 180 strcpy(i->name, name);
181 strcpy(i->type, type);
182 i->nhash = h;
183 i->id = j;
184 i->next = cachehead.next;
185 i->prev = &cachehead;
186 cachehead.next->prev = i;
187 cachehead.next = i;
d548a4e7 188 return(MR_SUCCESS);
dc37f07c 189##}
190
191
192/* Perform an ID to name mapping. name should be a pointer to a pointer to
193 * malloc'ed data. The buffer it refers to will be freed, and a new buffer
194 * allocated with the answer.
195 */
196
197int id_to_name(id, type, name)
198int id;
199char *type;
200char **name;
201##{
0119a9d6 202 register struct item *i;
dc37f07c 203## char iname[NAMESZ];
204## int j, rowcount;
0119a9d6 205 int ctr;
dc37f07c 206
0119a9d6 207 for (i = cachehead.next; i != &cachehead; i = i->next) {
208 if (i->id != id || strcasecmp(type, i->type)) continue;
dc37f07c 209 free(*name);
210 *name = strsave(i->name);
dc37f07c 211 cachehits++;
0119a9d6 212 i->next->prev = i->prev;
213 i->prev->next = i->next;
214 i->next = cachehead.next;
215 i->prev = &cachehead;
216 cachehead.next->prev = i;
217 cachehead.next = i;
d548a4e7 218 return(MR_SUCCESS);
dc37f07c 219 }
220
221 cachemisses++;
222 j = id;
223
224 switch (*type) {
225 case 'U':
226 case 'u':
227## repeat retrieve (iname = users.login) where users.users_id=@j
228 break;
229 case 'L':
230 case 'l':
231## repeat retrieve (iname = list.name) where list.list_id=@j
232 break;
233 case 'M':
234 case 'm':
235## repeat retrieve (iname = machine.name) where machine.mach_id=@j
236 break;
237 case 'C':
238 case 'c':
239## repeat retrieve (iname = cluster.name) where cluster.clu_id=@j
240 break;
241 case 'F':
242 case 'f':
243## repeat retrieve (iname = filesys.label) where filesys.filsys_id=@j
244 break;
245 case 'S':
246 case 's':
247## repeat retrieve (iname = strings.string) where strings.string_id=@j
248 break;
249 default:
d548a4e7 250 return(MR_INTERNAL);
dc37f07c 251 }
252## inquire_equel(rowcount = "rowcount")
d548a4e7 253 if (ingres_errno) return(mr_errcode);
dc37f07c 254 if (rowcount == 0) {
255 free(*name);
256 sprintf(iname, "#%d", j);
257 *name = strsave(iname);
d548a4e7 258 return(MR_NO_MATCH);
dc37f07c 259 }
260 if (rowcount != 1)
d548a4e7 261 return(MR_INTERNAL);
dc37f07c 262 free(*name);
263 *name = strsave(strtrim(iname));
264 if (**name == '#' && !strcasecmp(type, "USER"))
d548a4e7 265 return(MR_SUCCESS);
0119a9d6 266 if (cachesize < CACHESIZE) {
267 i = (struct item *) malloc(sizeof(struct item));
268 cachesize++;
269 } else {
270 i = cachehead.prev;
271 cachehead.prev = i->prev;
272 i->prev->next = &cachehead;
dc37f07c 273 }
0119a9d6 274 strcpy(i->name, *name);
275 strcpy(i->type, type);
276 i->nhash = hashname(*name, type);
277 i->id = id;
278 i->next = cachehead.next;
279 i->prev = &cachehead;
280 cachehead.next->prev = i;
281 cachehead.next = i;
d548a4e7 282 return(MR_SUCCESS);
dc37f07c 283##}
284
285
286/* Explicitly add something to the cache without doing a lookup in the
287 * database.
288 */
289
290cache_entry(name, type, id)
291char *name;
292char *type;
293int id;
294{
0119a9d6 295 register struct item *i;
dc37f07c 296
0119a9d6 297 for (i = cachehead.next; i != &cachehead; i = i->next)
298 if (i->id == id && !strcmp(i->type, type))
d548a4e7 299 return(MR_SUCCESS);
0119a9d6 300 if (cachesize < CACHESIZE) {
301 i = (struct item *) malloc(sizeof(struct item));
302 cachesize++;
303 } else {
304 i = cachehead.prev;
305 cachehead.prev = i->prev;
306 i->prev->next = &cachehead;
307 }
308 strcpy(i->name, name);
309 strcpy(i->type, type);
310 i->nhash = hashname(name, type);
311 i->id = id;
312 i->next = cachehead.next;
313 i->prev = &cachehead;
314 cachehead.next->prev = i;
315 cachehead.next = i;
d548a4e7 316 return(MR_SUCCESS);
dc37f07c 317}
318
319
320/* Flush something that may or may not already be in the cache. */
321
322flush_name(name, type)
323char *name;
324char *type;
325{
0119a9d6 326 int h;
327 register struct item *i;
328
329 h = hashname(name, type);
330
331 for (i = cachehead.next; i != &cachehead; i = i->next) {
332 if (!strcmp(name, i->name) && !strcasecmp(type, i->type)) {
333 cachesize--;
334 i->next->prev = i->prev;
335 i->prev->next = i->next;
336 free(i);
d548a4e7 337 return(MR_SUCCESS);
0119a9d6 338 }
dc37f07c 339 }
340}
This page took 0.357894 seconds and 5 git commands to generate.