6 * Copyright (C) 1989 by the Massachusetts Institute of Technology
7 * For copying and distribution information, please see the file
13 static char *rcsid_qsupport_qc = "$Header$";
16 #include <mit-copyright.h>
18 #include "mr_server.h"
21 extern char *whoami, *strsave();
22 extern int ingres_errno, mr_errcode;
25 /*** NOTE **************************************************************
27 * This code depends on each type starting with a unique letter. If
28 * any new types are added to the system that begin with the same
29 * letter as one of the existing types:
36 * then we will have to rework the code that only looks at the first
37 * letter of the types.
39 ***********************************************************************
42 /* Cache parameters: */
43 #define CACHESIZE 101 /* number of cache slots */
44 #define NAMESZ 257 /* max size of a name */
55 static struct item cachehead;
58 /* statistics counters */
59 int cachehits = 0, cachemisses = 0;
62 /* Name hash function. */
64 int hashname(name, type)
68 register int val = *type;
71 val = val<<5 - val + *name++ - '`';
76 /* Initialize the cache, flushing any old data, and report the statistics
77 * if the cache was previously in use.
82 register struct item *i;
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));
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)
95 if (cachehead.prev != &cachehead)
97 cachehead.next = cachehead.prev = &cachehead;
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.
105 int name_to_id(name, type, id)
110 register struct item *i;
115 h = hashname(name, type);
116 for (i = cachehead.next; i != &cachehead; i = i->next) {
118 strcmp(name, i->name) ||
119 strcasecmp(type, i->type))
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;
138 ## repeat retrieve (j = users.users_id) where users.#login=@iname
142 ## repeat retrieve (j = list.list_id) where list.#name=@iname
146 ## repeat retrieve (j = machine.mach_id) where machine.#name=uppercase(@iname)
150 ## repeat retrieve (j = cluster.clu_id) where cluster.#name=@iname
154 ## repeat retrieve (j = filesys.filsys_id) where filesys.#label=@iname
158 ## repeat retrieve (j = strings.string_id) where strings.#string=@iname
163 ## inquire_equel(rowcount = "rowcount")
164 if (ingres_errno) return(mr_errcode);
168 return(MR_NOT_UNIQUE);
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 ## char iname[NAMESZ];
207 for (i = cachehead.next; i != &cachehead; i = i->next) {
208 if (i->id != id || strcasecmp(type, i->type)) continue;
210 *name = strsave(i->name);
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;
227 ## repeat retrieve (iname = users.login) where users.users_id=@j
231 ## repeat retrieve (iname = list.name) where list.list_id=@j
235 ## repeat retrieve (iname = machine.name) where machine.mach_id=@j
239 ## repeat retrieve (iname = cluster.name) where cluster.clu_id=@j
243 ## repeat retrieve (iname = filesys.label) where filesys.filsys_id=@j
247 ## repeat retrieve (iname = strings.string) where strings.string_id=@j
252 ## inquire_equel(rowcount = "rowcount")
253 if (ingres_errno) return(mr_errcode);
256 sprintf(iname, "#%d", j);
257 *name = strsave(iname);
263 *name = strsave(strtrim(iname));
264 if (**name == '#' && !strcasecmp(type, "USER"))
266 if (cachesize < CACHESIZE) {
267 i = (struct item *) malloc(sizeof(struct item));
271 cachehead.prev = i->prev;
272 i->prev->next = &cachehead;
274 strcpy(i->name, *name);
275 strcpy(i->type, type);
276 i->nhash = hashname(*name, type);
278 i->next = cachehead.next;
279 i->prev = &cachehead;
280 cachehead.next->prev = i;
286 /* Explicitly add something to the cache without doing a lookup in the
290 cache_entry(name, type, id)
295 register struct item *i;
297 for (i = cachehead.next; i != &cachehead; i = i->next)
298 if (i->id == id && !strcmp(i->type, type))
300 if (cachesize < CACHESIZE) {
301 i = (struct item *) malloc(sizeof(struct item));
305 cachehead.prev = i->prev;
306 i->prev->next = &cachehead;
308 strcpy(i->name, name);
309 strcpy(i->type, type);
310 i->nhash = hashname(name, type);
312 i->next = cachehead.next;
313 i->prev = &cachehead;
314 cachehead.next->prev = i;
320 /* Flush something that may or may not already be in the cache. */
322 flush_name(name, type)
327 register struct item *i;
329 h = hashname(name, type);
331 for (i = cachehead.next; i != &cachehead; i = i->next) {
332 if (!strcmp(name, i->name) && !strcasecmp(type, i->type)) {
334 i->next->prev = i->prev;
335 i->prev->next = i->next;