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 "sms_server.h"
21 extern char *whoami, *strsave();
22 extern int ingres_errno, sms_errcode;
25 /*** NOTE **************************************************************
27 * This code depends 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 */
53 static struct item cache[CACHESIZE];
54 static struct item *ncache[CACHESIZE];
55 static struct item *icache[CACHESIZE];
57 /* use counter for implementing LRU */
59 /* statistics counters */
60 int cachehits = 0, cachemisses = 0;
62 /* ID hash function */
63 #define hashid(id, type) (((id) + *(type)) % CACHESIZE)
66 /* Name hash function. */
68 int hashname(name, type)
72 register int val = *type;
75 val = val<<5 - val + *name++ - '`';
76 return(val % CACHESIZE);
80 /* Initialize the cache, flushing any old data, and report the statistics
81 * if the cache was previously in use.
88 if (cachehits + cachemisses != 0)
89 com_err(whoami, 0, "Flushing cache; %d hits, %d misses, %d%% hit rate",
90 cachehits, cachemisses,
91 (100 * cachehits) / (cachehits + cachemisses));
92 cachehits = cachemisses = 0;
93 for (i = 0; i < CACHESIZE; i++) {
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 struct item *i, *mini;
115 i = ncache[hashname(name, type)];
116 if (i && !strcmp(name, i->name) && !strcasecmp(type, i->type)) {
129 ## repeat retrieve (j = users.users_id) where users.#login=@iname
133 ## repeat retrieve (j = list.list_id) where list.#name=@iname
137 ## repeat retrieve (j = machine.mach_id) where machine.#name=uppercase(@iname)
141 ## repeat retrieve (j = cluster.clu_id) where cluster.#name=@iname
145 ## repeat retrieve (j = filesys.filsys_id) where filesys.#label=@iname
149 ## repeat retrieve (j = strings.string_id) where strings.#string=@iname
152 return(SMS_INTERNAL);
154 ## inquire_equel(rowcount = "rowcount")
155 if (ingres_errno) return(sms_errcode);
157 return(SMS_NO_MATCH);
159 return(SMS_NOT_UNIQUE);
161 if (name[0] == '#' && !strcasecmp(type, "USER"))
164 for (i = &cache[0]; i < &cache[CACHESIZE]; i++) {
174 strcpy(mini->name, name);
175 strcpy(mini->type, type);
176 ncache[hashname(name, type)] = icache[hashid(j, type)] = mini;
181 /* Perform an ID to name mapping. name should be a pointer to a pointer to
182 * malloc'ed data. The buffer it refers to will be freed, and a new buffer
183 * allocated with the answer.
186 int id_to_name(id, type, name)
191 struct item *i, *mini;
192 ## char iname[NAMESZ];
196 i = icache[hashid(id, type)];
197 if (i && id == i->id && !strcasecmp(type, i->type)) {
199 *name = strsave(i->name);
211 ## repeat retrieve (iname = users.login) where users.users_id=@j
215 ## repeat retrieve (iname = list.name) where list.list_id=@j
219 ## repeat retrieve (iname = machine.name) where machine.mach_id=@j
223 ## repeat retrieve (iname = cluster.name) where cluster.clu_id=@j
227 ## repeat retrieve (iname = filesys.label) where filesys.filsys_id=@j
231 ## repeat retrieve (iname = strings.string) where strings.string_id=@j
234 return(SMS_INTERNAL);
236 ## inquire_equel(rowcount = "rowcount")
237 if (ingres_errno) return(sms_errcode);
240 sprintf(iname, "#%d", j);
241 *name = strsave(iname);
242 return(SMS_NO_MATCH);
245 return(SMS_INTERNAL);
247 *name = strsave(strtrim(iname));
248 if (**name == '#' && !strcasecmp(type, "USER"))
251 for (i = &cache[0]; i < &cache[CACHESIZE]; i++) {
261 strcpy(mini->name, *name);
262 strcpy(mini->type, type);
263 ncache[hashname(name, type)] = icache[hashid(id, type)] = mini;
268 /* Explicitly add something to the cache without doing a lookup in the
272 cache_entry(name, type, id)
278 struct item *i, *mini;
280 i = icache[hashid(id, type)];
282 !strcasecmp(i->type, type) &&
283 !strcmp(i->name, name))
289 for (i = &cache[0]; i < &cache[CACHESIZE]; i++) {
299 strcpy(mini->name, name);
300 strcpy(mini->type, type);
301 ncache[hashname(name, type)] = icache[hashid(id, type)] = mini;
305 /* Flush something that may or may not already be in the cache. */
307 flush_name(name, type)
313 i = ncache[hashname(name, type)];
314 if (i && !strcmp(name, i->name) && !strcasecmp(type, i->type)) {
315 ncache[hashname(name, type)] = NULL;
316 icache[hashid(i->id, type)] = NULL;