]> andersk Git - moira.git/blame - server/cache.dc
increase Argv[] size to match QMAXARGS
[moira.git] / server / cache.dc
CommitLineData
7de02494 1/*
2 * $Header$
3 *
4 * Copyright (C) 1989, 1990 by the Massachusetts Institute of Technology
5 * For copying and distribution information, please see the file
6 * <mit-copyright.h>.
7 */
8
9#ifndef lint
10static char *rcsid_cache_dc = "$Header$";
11#endif lint
12
13#include <mit-copyright.h>
14#include "query.h"
15#include "mr_server.h"
16EXEC SQL INCLUDE sqlca;
17
45bf7573 18EXEC SQL WHENEVER SQLERROR CALL ingerr;
a49e54ea 19
7de02494 20extern char *whoami, *strsave();
21extern int ingres_errno, mr_errcode;
22
23
24/*** NOTE **************************************************************
25 *
26 * This code depends on each type starting with a unique letter. If
27 * any new types are added to the system that begin with the same
28 * letter as one of the existing types:
29 * User
30 * List
31 * String
32 * Machine
33 * Cluster
34 * Filesystem
35 * then we will have to rework the code that only looks at the first
36 * letter of the types.
37 *
38 ***********************************************************************
39 */
40
41/* Cache parameters: */
42#define CACHESIZE 101 /* number of cache slots */
43#define NAMESZ 257 /* max size of a name */
44
45struct item {
46 char name[NAMESZ];
47 char type[9];
48 int nhash;
49 int id;
50 struct item *next;
51 struct item *prev;
a49e54ea 52 struct item *trans; /* keep track of transactions */
7de02494 53};
54
55static struct item cachehead;
56static int cachesize;
57
58/* statistics counters */
59int cachehits = 0, cachemisses = 0;
60
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++ - '`';
72 return(val);
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{
82 register struct item *i;
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));
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);
94 }
95 if (cachehead.prev != &cachehead)
96 free(cachehead.prev);
97 cachehead.next = cachehead.prev = &cachehead;
a49e54ea 98 cachehead.trans = (struct item *)NULL;
7de02494 99}
100
101
102/* Do a name to ID translation. id will be updated with the answer if
103 * it is available, and as a side effect the cache is updated.
104 */
105
106int name_to_id(name, type, id)
107char *name;
108char *type;
109int *id;
110{
a49e54ea 111 register struct item *i, *t;
7de02494 112 EXEC SQL BEGIN DECLARE SECTION;
113 char *iname;
114 int j, rowcount;
115 EXEC SQL END DECLARE SECTION;
116 int h, ctr;
117
118 h = hashname(name, type);
119 for (i = cachehead.next; i != &cachehead; i = i->next) {
120 if (i->nhash != h ||
121 strcmp(name, i->name) ||
122 strcasecmp(type, i->type))
123 continue;
124 *id = i->id;
125 cachehits++;
126 i->next->prev = i->prev;
127 i->prev->next = i->next;
128 i->next = cachehead.next;
129 i->prev = &cachehead;
130 cachehead.next->prev = i;
131 cachehead.next = i;
132 return(MR_SUCCESS);
133 }
134
135 cachemisses++;
136 iname = name;
137
138 switch (*type) {
139 case 'U':
140 case 'u':
06c1c8ff 141 if (index(iname, '@')) {
142 sqlca.sqlcode = 100;
143 break;
144 }
7de02494 145 EXEC SQL SELECT users_id INTO :j FROM users WHERE login=:iname;
146 break;
147 case 'L':
148 case 'l':
149 EXEC SQL SELECT list_id INTO :j FROM list WHERE name=:iname;
150 break;
151 case 'M':
152 case 'm':
99e09b48 153 EXEC SQL SELECT mach_id INTO :j FROM machine WHERE name=UPPERCASE(:iname);
7de02494 154 break;
155 case 'C':
156 case 'c':
157 EXEC SQL SELECT clu_id INTO :j FROM cluster WHERE name=:iname;
158 break;
159 case 'F':
160 case 'f':
161 EXEC SQL SELECT filsys_id INTO :j FROM filesys WHERE label=:iname;
162 break;
163 case 'S':
164 case 's':
165 EXEC SQL SELECT string_id INTO :j FROM strings WHERE string=:iname;
166 break;
167 default:
168 return(MR_INTERNAL);
169 }
170 if (sqlca.sqlcode == 100)
171 return(MR_NO_MATCH);
172 if (sqlca.sqlerrd[2] > 1)
173 return(MR_NOT_UNIQUE);
174 if (sqlca.sqlcode != 0)
175 return(MR_INGRES_ERR);
176 *id = j;
177 if (name[0] == '#' && !strcasecmp(type, "USER"))
178 return(MR_SUCCESS);
179 if (cachesize < CACHESIZE) {
180 i = (struct item *) malloc(sizeof(struct item));
181 cachesize++;
182 } else {
183 i = cachehead.prev;
184 cachehead.prev = i->prev;
185 i->prev->next = &cachehead;
186 }
187 strcpy(i->name, name);
188 strcpy(i->type, type);
189 i->nhash = h;
190 i->id = j;
191 i->next = cachehead.next;
192 i->prev = &cachehead;
193 cachehead.next->prev = i;
194 cachehead.next = i;
a49e54ea 195 /* find the end of the transaction chain & add this item */
196 for (t = &cachehead; t->trans && t != i; t = t->trans);
197 if (t != i) {
198 t->trans = i;
199 i->trans = (struct item *)NULL;
200 }
7de02494 201 return(MR_SUCCESS);
202}
203
204
205/* Perform an ID to name mapping. name should be a pointer to a pointer to
206 * malloc'ed data. The buffer it refers to will be freed, and a new buffer
207 * allocated with the answer.
208 */
209
210int id_to_name(id, type, name)
211int id;
212char *type;
213char **name;
214{
45bf7573 215 register struct item *i, *t;
7de02494 216 EXEC SQL BEGIN DECLARE SECTION;
217 char iname[NAMESZ];
218 int j, rowcount;
219 EXEC SQL END DECLARE SECTION;
220 int ctr;
221
222 for (i = cachehead.next; i != &cachehead; i = i->next) {
223 if (i->id != id || strcasecmp(type, i->type)) continue;
224 free(*name);
225 *name = strsave(i->name);
226 cachehits++;
227 i->next->prev = i->prev;
228 i->prev->next = i->next;
229 i->next = cachehead.next;
230 i->prev = &cachehead;
231 cachehead.next->prev = i;
232 cachehead.next = i;
233 return(MR_SUCCESS);
234 }
235
236 cachemisses++;
237 j = id;
238
239 switch (*type) {
240 case 'U':
241 case 'u':
a112f91e 242 EXEC SQL SELECT CHAR(login) INTO :iname FROM users WHERE users_id=:j;
7de02494 243 break;
244 case 'L':
245 case 'l':
a112f91e 246 EXEC SQL SELECT CHAR(name) INTO :iname FROM list WHERE list_id=:j;
7de02494 247 break;
248 case 'M':
249 case 'm':
a112f91e 250 EXEC SQL SELECT CHAR(name) INTO :iname FROM machine WHERE mach_id=:j;
7de02494 251 break;
252 case 'C':
253 case 'c':
a112f91e 254 EXEC SQL SELECT CHAR(name) INTO :iname FROM cluster WHERE clu_id=:j;
7de02494 255 break;
256 case 'F':
257 case 'f':
a112f91e 258 EXEC SQL SELECT CHAR(label) INTO :iname FROM filesys WHERE filsys_id=:j;
7de02494 259 break;
260 case 'S':
261 case 's':
a112f91e 262 EXEC SQL SELECT CHAR(string) INTO :iname FROM strings WHERE string_id=:j;
7de02494 263 break;
264 default:
265 return(MR_INTERNAL);
266 }
267 if (sqlca.sqlcode == 100) {
268 free(*name);
269 sprintf(iname, "#%d", j);
270 *name = strsave(iname);
271 return(MR_NO_MATCH);
272 }
273 if (sqlca.sqlerrd[2] > 1)
274 return(MR_INTERNAL);
275 if (sqlca.sqlcode != 0)
276 return(MR_INGRES_ERR);
277 free(*name);
278 *name = strsave(strtrim(iname));
279 if (**name == '#' && !strcasecmp(type, "USER"))
280 return(MR_SUCCESS);
281 if (cachesize < CACHESIZE) {
282 i = (struct item *) malloc(sizeof(struct item));
283 cachesize++;
284 } else {
285 i = cachehead.prev;
286 cachehead.prev = i->prev;
287 i->prev->next = &cachehead;
288 }
289 strcpy(i->name, *name);
290 strcpy(i->type, type);
291 i->nhash = hashname(*name, type);
292 i->id = id;
293 i->next = cachehead.next;
294 i->prev = &cachehead;
295 cachehead.next->prev = i;
296 cachehead.next = i;
a49e54ea 297 /* find the end of the transaction chain & add this item */
298 for (t = &cachehead; t->trans && t != i; t = t->trans);
299 if (t != i) {
300 t->trans = i;
301 i->trans = (struct item *)NULL;
302 }
7de02494 303 return(MR_SUCCESS);
304}
305
306
307/* Explicitly add something to the cache without doing a lookup in the
308 * database.
309 */
310
311cache_entry(name, type, id)
312char *name;
313char *type;
314int id;
315{
a49e54ea 316 register struct item *i, *t;
7de02494 317
318 for (i = cachehead.next; i != &cachehead; i = i->next)
a49e54ea 319 if (i->id == id && !strcmp(i->type, type)) {
320 if (strcmp(i->name, name)) {
321 strcpy(i->name, name);
322 i->nhash = hashname(name, type);
323 }
324 return(MR_SUCCESS);
325 }
7de02494 326 if (cachesize < CACHESIZE) {
327 i = (struct item *) malloc(sizeof(struct item));
328 cachesize++;
329 } else {
330 i = cachehead.prev;
331 cachehead.prev = i->prev;
332 i->prev->next = &cachehead;
333 }
334 strcpy(i->name, name);
335 strcpy(i->type, type);
336 i->nhash = hashname(name, type);
337 i->id = id;
338 i->next = cachehead.next;
339 i->prev = &cachehead;
340 cachehead.next->prev = i;
341 cachehead.next = i;
a49e54ea 342 /* find the end of the transaction chain & add this item */
343 for (t = &cachehead; t->trans && t != i; t = t->trans);
344 if (t != i) {
345 t->trans = i;
346 i->trans = (struct item *)NULL;
347 }
7de02494 348 return(MR_SUCCESS);
349}
350
351
352/* Flush something that may or may not already be in the cache. */
353
354flush_name(name, type)
355char *name;
356char *type;
357{
358 int h;
359 register struct item *i;
360
361 h = hashname(name, type);
362
363 for (i = cachehead.next; i != &cachehead; i = i->next) {
364 if (!strcmp(name, i->name) && !strcasecmp(type, i->type)) {
365 cachesize--;
366 i->next->prev = i->prev;
367 i->prev->next = i->next;
368 free(i);
369 return(MR_SUCCESS);
370 }
371 }
372}
a49e54ea 373
374
375/* Called when a transaction is committed to also commit any cache changes.
376 * Just throws away the list of cache changes for this transaction.
377 */
378
379cache_commit()
380{
381 cachehead.trans = (struct item *)NULL;
382}
383
384
385/* Called whan a transaction is aborted to throw away any cache changes
386 * from that transaction.
387 */
388
389cache_abort()
390{
391 register struct item *i, *t;
392
393 for (i = cachehead.trans; i; i = t) {
394 t = i->trans;
395 flush_name(i->name, i->type);
396 }
397 cachehead.trans = (struct item *)NULL;
398}
This page took 0.10355 seconds and 5 git commands to generate.