]>
Commit | Line | Data |
---|---|---|
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 | |
13 | static 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 | ||
21 | extern char *whoami, *strsave(); | |
d548a4e7 | 22 | extern 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 | ||
46 | struct 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 | 55 | static struct item cachehead; |
56 | static int cachesize; | |
dc37f07c | 57 | |
dc37f07c | 58 | /* statistics counters */ |
59 | int cachehits = 0, cachemisses = 0; | |
60 | ||
dc37f07c | 61 | |
62 | /* Name hash function. */ | |
63 | ||
64 | int hashname(name, type) | |
65 | register char *name; | |
66 | char *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 | ||
80 | flush_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 | ||
105 | int name_to_id(name, type, id) | |
106 | char *name; | |
107 | char *type; | |
108 | int *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 | ||
197 | int id_to_name(id, type, name) | |
198 | int id; | |
199 | char *type; | |
200 | char **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 | ||
290 | cache_entry(name, type, id) | |
291 | char *name; | |
292 | char *type; | |
293 | int 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 | ||
322 | flush_name(name, type) | |
323 | char *name; | |
324 | char *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 | } |