4 * Copyright (C) 1989, 1990 by the Massachusetts Institute of Technology
5 * For copying and distribution information, please see the file
10 static char *rcsid_cache_dc = "$Header$";
13 #include <mit-copyright.h>
15 #include "mr_server.h"
16 EXEC SQL INCLUDE sqlca;
18 extern char *whoami, *strsave();
19 extern int ingres_errno, mr_errcode;
22 /*** NOTE **************************************************************
24 * This code depends on each type starting with a unique letter. If
25 * any new types are added to the system that begin with the same
26 * letter as one of the existing types:
33 * then we will have to rework the code that only looks at the first
34 * letter of the types.
36 ***********************************************************************
39 /* Cache parameters: */
40 #define CACHESIZE 101 /* number of cache slots */
41 #define NAMESZ 257 /* max size of a name */
52 static struct item cachehead;
55 /* statistics counters */
56 int cachehits = 0, cachemisses = 0;
59 /* Name hash function. */
61 int hashname(name, type)
65 register int val = *type;
68 val = val<<5 - val + *name++ - '`';
73 /* Initialize the cache, flushing any old data, and report the statistics
74 * if the cache was previously in use.
79 register struct item *i;
81 if (cachehits + cachemisses != 0)
82 com_err(whoami, 0, "Flushing cache; %d hits, %d misses, %d%% hit rate",
83 cachehits, cachemisses,
84 (100 * cachehits) / (cachehits + cachemisses));
86 cachehead.next = cachehead.prev = &cachehead;
87 cachehits = cachemisses = cachesize = 0;
88 for (i = cachehead.next; i != &cachehead; i = i->next) {
89 if (i->prev != &cachehead)
92 if (cachehead.prev != &cachehead)
94 cachehead.next = cachehead.prev = &cachehead;
98 /* Do a name to ID translation. id will be updated with the answer if
99 * it is available, and as a side effect the cache is updated.
102 int name_to_id(name, type, id)
107 register struct item *i;
108 EXEC SQL BEGIN DECLARE SECTION;
111 EXEC SQL END DECLARE SECTION;
114 h = hashname(name, type);
115 for (i = cachehead.next; i != &cachehead; i = i->next) {
117 strcmp(name, i->name) ||
118 strcasecmp(type, i->type))
122 i->next->prev = i->prev;
123 i->prev->next = i->next;
124 i->next = cachehead.next;
125 i->prev = &cachehead;
126 cachehead.next->prev = i;
137 EXEC SQL SELECT users_id INTO :j FROM users WHERE login=:iname;
141 EXEC SQL SELECT list_id INTO :j FROM list WHERE name=:iname;
146 EXEC SQL SELECT mach_id INTO :j FROM machine WHERE name=:iname;
150 EXEC SQL SELECT clu_id INTO :j FROM cluster WHERE name=:iname;
154 EXEC SQL SELECT filsys_id INTO :j FROM filesys WHERE label=:iname;
158 EXEC SQL SELECT string_id INTO :j FROM strings WHERE string=:iname;
163 if (sqlca.sqlcode == 100)
165 if (sqlca.sqlerrd[2] > 1)
166 return(MR_NOT_UNIQUE);
167 if (sqlca.sqlcode != 0)
168 return(MR_INGRES_ERR);
170 if (name[0] == '#' && !strcasecmp(type, "USER"))
172 if (cachesize < CACHESIZE) {
173 i = (struct item *) malloc(sizeof(struct item));
177 cachehead.prev = i->prev;
178 i->prev->next = &cachehead;
180 strcpy(i->name, name);
181 strcpy(i->type, type);
184 i->next = cachehead.next;
185 i->prev = &cachehead;
186 cachehead.next->prev = i;
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.
197 int id_to_name(id, type, name)
202 register struct item *i;
203 EXEC SQL BEGIN DECLARE SECTION;
206 EXEC SQL END DECLARE SECTION;
209 for (i = cachehead.next; i != &cachehead; i = i->next) {
210 if (i->id != id || strcasecmp(type, i->type)) continue;
212 *name = strsave(i->name);
214 i->next->prev = i->prev;
215 i->prev->next = i->next;
216 i->next = cachehead.next;
217 i->prev = &cachehead;
218 cachehead.next->prev = i;
229 EXEC SQL SELECT login INTO :iname FROM users WHERE users_id=:j;
233 EXEC SQL SELECT name INTO :iname FROM list WHERE list_id=:j;
237 EXEC SQL SELECT name INTO :iname FROM machine WHERE mach_id=:j;
241 EXEC SQL SELECT name INTO :iname FROM cluster WHERE clu_id=:j;
245 EXEC SQL SELECT label INTO :iname FROM filesys WHERE filsys_id=:j;
249 EXEC SQL SELECT string INTO :iname FROM strings WHERE string_id=:j;
254 if (sqlca.sqlcode == 100) {
256 sprintf(iname, "#%d", j);
257 *name = strsave(iname);
260 if (sqlca.sqlerrd[2] > 1)
262 if (sqlca.sqlcode != 0)
263 return(MR_INGRES_ERR);
265 *name = strsave(strtrim(iname));
266 if (**name == '#' && !strcasecmp(type, "USER"))
268 if (cachesize < CACHESIZE) {
269 i = (struct item *) malloc(sizeof(struct item));
273 cachehead.prev = i->prev;
274 i->prev->next = &cachehead;
276 strcpy(i->name, *name);
277 strcpy(i->type, type);
278 i->nhash = hashname(*name, type);
280 i->next = cachehead.next;
281 i->prev = &cachehead;
282 cachehead.next->prev = i;
288 /* Explicitly add something to the cache without doing a lookup in the
292 cache_entry(name, type, id)
297 register struct item *i;
299 for (i = cachehead.next; i != &cachehead; i = i->next)
300 if (i->id == id && !strcmp(i->type, type))
302 if (cachesize < CACHESIZE) {
303 i = (struct item *) malloc(sizeof(struct item));
307 cachehead.prev = i->prev;
308 i->prev->next = &cachehead;
310 strcpy(i->name, name);
311 strcpy(i->type, type);
312 i->nhash = hashname(name, type);
314 i->next = cachehead.next;
315 i->prev = &cachehead;
316 cachehead.next->prev = i;
322 /* Flush something that may or may not already be in the cache. */
324 flush_name(name, type)
329 register struct item *i;
331 h = hashname(name, type);
333 for (i = cachehead.next; i != &cachehead; i = i->next) {
334 if (!strcmp(name, i->name) && !strcasecmp(type, i->type)) {
336 i->next->prev = i->prev;
337 i->prev->next = i->next;