1 /***********************************************************************/
2 /* Open Visualization Data Explorer */
3 /* (C) Copyright IBM Corp. 1989,1999 */
4 /* ALL RIGHTS RESERVED */
5 /* This code licensed under the */
6 /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */
7 /***********************************************************************/
8
9 #include <dxconfig.h>
10
11
12 #include <time.h>
13 #include <dx/dx.h>
14 #include "config.h"
15 #include "cache.h"
16 #include "crc.h"
17 #include "d.h"
18 #include "graph.h"
19 #include "log.h"
20 #include "swap.h"
21 #include "utils.h"
22 #include "context.h"
23 #include "distp.h"
24 #include "exobject.h"
25
26 EXDictionary _dxd_exCacheDict = (EXDictionary) NULL;
27 static gvar *EmptyGvar;
28 void _dxf_ExFlushPathTags();
29
30 static char *
int32tohex(char * buf,int32 l)31 int32tohex (char *buf, int32 l)
32 {
33 static char *htab = "0123456789abcdef";
34
35 buf[8] = '\0';
36 buf[7] = htab[l & 0xf]; l >>= 4;
37 buf[6] = htab[l & 0xf]; l >>= 4;
38 buf[5] = htab[l & 0xf]; l >>= 4;
39 buf[4] = htab[l & 0xf]; l >>= 4;
40 buf[3] = htab[l & 0xf]; l >>= 4;
41 buf[2] = htab[l & 0xf]; l >>= 4;
42 buf[1] = htab[l & 0xf]; l >>= 4;
43 buf[0] = htab[l & 0xf];
44
45 return (buf + 8);
46 }
47
48
_dxf_ExGenCacheTag(char * function,int key,int n,EXCRC * in)49 EXCRC _dxf_ExGenCacheTag(char *function, int key, int n, EXCRC *in)
50 {
51 EXCRC result;
52
53 /* Build a cache string representing the key */
54 result = _dxf_ExCRCString(EX_INITIAL_CRC, function);
55 result = _dxf_ExCRCInt (result, key);
56 result = _dxf_ExCRCIntV (result, (int32 *)in, n);
57
58 return (EXTAG(result));
59 }
60
61 /* this is what the libdx init code calls, but it is too early for
62 * the exec to init the cache at this point, so it is just a dummy
63 * routine. later in the exec init process, when the exo object pool
64 * is set up, then ExCacheInit can be called.
65 */
_dxf_initcache(void)66 Error _dxf_initcache (void)
67 {
68 return OK;
69 }
70
_dxf_ExCacheInit(void)71 Error _dxf_ExCacheInit (void)
72 {
73 _dxd_exCacheDict = _dxf_ExDictionaryCreateSorted(2048, FALSE, TRUE);
74 EmptyGvar = _dxf_ExCreateGvar(GV_UNRESOLVED);
75 /* Never want this gvar to get deleted so add an extra reference */
76 ExReference(EmptyGvar);
77 return (_dxd_exCacheDict == NULL? ERROR: OK);
78 }
79
80
81 /*
82 * Insert an entry into the cache using a reference to an executive-style
83 * object.
84 */
85
_dxf_ExCacheInsert(gvar * obj)86 int _dxf_ExCacheInsert (gvar *obj)
87 {
88 char stringKey[8+3];
89 int ret;
90
91 if ((obj->reccrc & 0x80000000) == 0)
92 _dxf_ExDie("Bad executive cache tag 0x%08x", obj->reccrc);
93
94 stringKey[0] = 'X';
95 int32tohex(stringKey+1, obj->reccrc);
96
97 ExDebug("2", "DXAdd %s to cache at %f", stringKey, obj->object.lastref);
98
99 obj->obj = DXSetObjectTag(obj->obj, obj->reccrc);
100
101 ExTimestamp((EXO_Object)obj);
102
103 ret = _dxf_ExDictionaryInsert (_dxd_exCacheDict, stringKey, (EXObj)obj);
104 if(ret > 0) {
105 /* since we are pointing to shared memory for the data we can
106 * send a size of 0.
107 */
108 _dxf_ExDistributeMsg(DM_INSERTCACHE, (Pointer)&(obj->reccrc), 0,
109 TOPEERS);
110 }
111 return(ret);
112 }
113
_dxf_ExCacheInsertRemoteTag(int fd,int swap)114 int _dxf_ExCacheInsertRemoteTag (int fd, int swap)
115 {
116 EXCRC ct;
117 gvar *cachedGvar;
118 char stringKey[8+3];
119
120 if(_dxf_ExReceiveBuffer(fd, &ct, 1, TYPE_INT, swap) < 0)
121 DXUIMessage("ERROR", "bad remote cache tag");
122
123 if ((ct & 0x80000000) == 0)
124 _dxf_ExDie("Bad executive cache tag 0x%08x", ct);
125
126 stringKey[0] = 'X';
127 int32tohex(stringKey+1, ct);
128
129 /* DPSEND outputs may be already cached */
130 if((cachedGvar = (gvar *)
131 _dxf_ExDictionarySearch(_dxd_exCacheDict, stringKey)) != NULL) {
132 ExDelete(cachedGvar);
133 return(OK);
134 }
135 else {
136 ExDebug("2", "DXAdd RemoteTag %s to cache", stringKey);
137 return(_dxf_ExDictionaryInsert(_dxd_exCacheDict, stringKey,
138 (EXObj)EmptyGvar));
139 }
140 }
141
142 /*
143 * Delete an entry from the cache.
144 */
145
_dxf_ExCacheDelete(EXCRC key)146 Error _dxf_ExCacheDelete (EXCRC key)
147 {
148 char stringKey[8+3];
149 int ret;
150
151 if ((key & 0x80000000) == 0)
152 _dxf_ExDie("Bad executive cache tag 0x%08x", key);
153
154 stringKey[0] = 'X';
155 int32tohex(stringKey+1, key);
156
157 DXDebug ("1","removing cache entry '%s' in _dxf_ExCacheDelete", stringKey);
158 ret = _dxf_ExDictionaryDelete (_dxd_exCacheDict, stringKey);
159 if(ret > 0) {
160 _dxf_ExDistributeMsg(DM_EVICTCACHE, (Pointer)&key,
161 sizeof(EXCRC), TOPEERS);
162 }
163 return(ret);
164
165 }
166
_dxf_ExCacheDeleteRemoteTag(int fd,int swap)167 int _dxf_ExCacheDeleteRemoteTag (int fd, int swap)
168 {
169 EXCRC ct;
170 char stringKey[8+3];
171
172 if(_dxf_ExReceiveBuffer(fd, &ct, 1, TYPE_INT, swap) < 0) {
173 DXUIMessage("ERROR", "bad remote cache tag");
174 return(ERROR);
175 }
176
177 if ((ct & 0x80000000) == 0)
178 _dxf_ExDie("Bad executive cache tag 0x%08x", ct);
179
180 stringKey[0] = 'X';
181 int32tohex(stringKey+1, ct);
182
183 DXDebug ("1","removing cache entry '%s' in _dxf_ExCacheDeleteRemoteTag", stringKey);
184 return(_dxf_ExDictionaryDelete(_dxd_exCacheDict, stringKey));
185 }
186
_dxf_ExCacheListDeleteRemoteTag(int fd,int swap)187 int _dxf_ExCacheListDeleteRemoteTag(int fd, int swap)
188 {
189 CacheTagList pkg;
190 char stringKey[8+3];
191 int i;
192
193 if(_dxf_ExReceiveBuffer(fd, &(pkg.numtags), 1, TYPE_INT, swap) < 0) {
194 DXUIMessage("ERROR", "bad remote cache tag list");
195 return(ERROR);
196 }
197
198 if(_dxf_ExReceiveBuffer(fd, pkg.ct, pkg.numtags, TYPE_INT, swap) < 0) {
199 DXUIMessage("ERROR", "bad remote cache tag");
200 return(ERROR);
201 }
202
203 stringKey[0] = 'X';
204 for(i = 0; i < pkg.numtags; i++) {
205 int32tohex(stringKey+1, pkg.ct[i]);
206 DXDebug ("1","removing cache entry '%s' in _dxf_ExCacheListDeleteRemoteTag", stringKey);
207 if(_dxf_ExDictionaryDelete(_dxd_exCacheDict, stringKey) != OK)
208 DXWarning("Cache Tag %s not deleted", stringKey);
209 }
210 return(OK);
211 }
212
213 /*
214 * Locate an entry in the cache.
215 */
_dxf_ExCacheSearch(EXCRC key)216 gvar *_dxf_ExCacheSearch (EXCRC key)
217 {
218 char stringKey[8+3];
219 gvar *entry;
220
221 if ((key & 0x80000000) == 0)
222 _dxf_ExDie("Bad executive cache tag 0x%08x", key);
223
224 stringKey[0] = 'X';
225 int32tohex(stringKey+1, key);
226
227
228 entry = ((gvar*)_dxf_ExDictionarySearch (_dxd_exCacheDict, stringKey));
229 if (entry)
230 ExTimestamp((EXO_Object)entry);
231
232 return entry;
233 }
234
235 /*
236 * Module interface to allow inserting arbitrary data into the cache.
237 * The module provides a deletion routine which is called when the
238 * entry is removed from the cache. A cost of CACHE_PERMANENT will
239 * insure that the entry is not removed from the cache until the
240 * application exits
241 */
242
DXCacheInsert(char * id,Pointer data,Error (* pdelete)(Pointer),double cost)243 Error DXCacheInsert (char *id, Pointer data, Error (*pdelete)(Pointer), double cost)
244 {
245 Object o;
246
247 o = (Object)DXNewPrivate(data, pdelete);
248 return (DXSetCacheEntry(o, cost, id, 0, 0));
249 }
250
251
252 /*
253 * Module interface to allow deleting specific entries from the cache
254 */
255
DXCacheDelete(char * id)256 Error DXCacheDelete (char *id)
257 {
258 return (DXSetCacheEntry(NULL, 0.0, id, 0, 0));
259 }
260
261 /*
262 * Module interface to look up entries in the cache. The pointer returned
263 * is the pointer supplied to DXCacheInsert when the entry was inserted.
264 */
265 Error
DXCacheSearch(char * id,Pointer * data)266 DXCacheSearch(char *id, Pointer *data)
267 {
268 Object o;
269
270 *data = NULL;
271
272 o = DXGetCacheEntry(id, 0, 0);
273 if (o)
274 *data = DXGetPrivateData((Private)o);
275 DXDelete (o);
276
277 return(OK);
278 }
279
280
281 /*
282 * Module interface to insert a libdx-style object into the cache. This
283 * routine takes care of referencing the object before inserting it into
284 * the cache. The libdx DXDelete routine is called when the entry is removed
285 * from the cache.
286 */
287 Error
DXCacheInsertObject(char * id,Object o,double cost)288 DXCacheInsertObject(char *id, Object o, double cost)
289 {
290 Object p;
291
292 p = (Object)DXNewPrivate((Pointer)o, NULL);
293 return (DXSetCacheEntry(p, cost, id, 0, 0));
294 }
295
296 /*
297 * This routine is responsible for flushing all non-permanent entries from
298 * the executive cache. It walks the dictionary structure and throws
299 * away anything that is not marked permanent.
300 */
301
302 Error
_dxf_ExCacheFlush(int all)303 _dxf_ExCacheFlush (int all)
304 {
305 EXObj obj;
306 EXObj curr;
307 gvar *gv;
308 char *key;
309
310 if (! *_dxd_exTerminating)
311 DXDebug ("1", "flushing cache");
312
313 if(!_dxd_exRemoteSlave)
314 _dxf_ExDistributeMsg(DM_FLUSHCACHE, (Pointer)&all, sizeof(int),
315 TOSLAVES);
316
317 _dxf_ExReclaimDisable ();
318
319 _dxf_ExDictionaryBeginIterate (_dxd_exCacheDict);
320 while ((obj = _dxf_ExDictionaryIterate (_dxd_exCacheDict, &key)) != NULL)
321 {
322 curr = NULL;
323
324 switch (EXO_GetClass (obj))
325 {
326 case EXO_CLASS_GVAR:
327 gv = (gvar *) obj;
328
329 /* The variable is not currently in use */
330 if (all || gv->cost < CACHE_PERMANENT)
331 curr = obj;
332 break;
333
334 default:
335 break;
336 }
337
338 if (curr)
339 {
340 DXDebug ("1", "removing cache entry '%s'", key);
341 _dxf_ExDictionaryDeleteNoLock (_dxd_exCacheDict, key);
342 }
343 }
344
345 _dxf_ExDictionaryEndIterate (_dxd_exCacheDict);
346 _dxf_ExFlushPathTags();
347 _dxf_ExReclaimEnable ();
348
349 return(OK);
350 }
351
DXSetCacheEntryV(Object out,double cost,char * function,int key,int n,Object * in)352 Error DXSetCacheEntryV(Object out, double cost, char *function,
353 int key, int n, Object *in)
354 {
355 char tag[8+3];
356 gvar *entry;
357 int i;
358 EXCRC inTags[100];
359 EXCRC outTag;
360
361
362 if (_dxd_exCacheDict == NULL)
363 return (OK);
364
365 /*---------------------------------------------------------------*/
366 /* See if user has turned caching off and respect his/her wishes */
367 /* unless the cost is CACHE_PERMANENT */
368 /*---------------------------------------------------------------*/
369 ExDebug("*1","In DXSetCacheEntryV with cost = %g and cache attr = %d",
370 cost,_dxd_exCurrentFunc ? _dxd_exCurrentFunc->excache: 1);
371
372 if (cost < CACHE_PERMANENT)
373 if (_dxd_exCurrentFunc && !_dxd_exCurrentFunc->excache) {
374 DXWarning("#4860",function);
375 return OK; /* not an error to not cache .... */
376 }
377
378 for (i = 0; i < n && i < 100; ++i)
379 inTags[i] = DXGetObjectTag(in[i]);
380 outTag = _dxf_ExGenCacheTag(function, key, n, inTags);
381
382 tag[0] = 'U';
383 int32tohex(tag+1, outTag);
384
385 if (out == NULL) {
386 _dxf_ExDictionaryDelete(_dxd_exCacheDict, tag);
387 return (OK);
388 }
389 else
390 {
391 entry = _dxf_ExCreateGvar(GV_CACHE);
392 if (entry == NULL)
393 return (ERROR);
394
395 _dxf_ExDefineGvar(entry, out);
396 entry->cost = cost;
397 /* entry->reccrc = outTag; */
398 entry->procId = exJID;
399 ExTimestamp(entry);
400 /* DXSetObjectTag(out, outTag); */
401 return (_dxf_ExDictionaryInsert (_dxd_exCacheDict, tag, (EXObj)entry));
402 }
403 }
404
DXSetCacheEntry(Object out,double cost,char * function,int key,int n,...)405 Error DXSetCacheEntry(Object out, double cost, char *function,
406 int key, int n, ...)
407 {
408 Object in[100];
409 int i;
410 va_list arg;
411
412 va_start(arg,n);
413 for (i = 0; i < n && i < 100; ++i)
414 in[i] = va_arg(arg, Object);
415 va_end(arg);
416
417 return (DXSetCacheEntryV(out, cost, function, key, n, in));
418 }
419
DXGetCacheEntryV(char * function,int key,int n,Object * in)420 Object DXGetCacheEntryV(char *function, int key, int n, Object *in)
421 {
422 char tag[8+3];
423 gvar *entry;
424 int i;
425 EXCRC inTags[100];
426 EXCRC outTag;
427 Object out = NULL;
428
429 if (_dxd_exCacheDict == NULL)
430 return (NULL);
431
432 for (i = 0; i < n && i < 100; ++i)
433 inTags[i] = DXGetObjectTag(in[i]);
434 outTag = _dxf_ExGenCacheTag(function, key, n, inTags);
435
436 tag[0] = 'U';
437 int32tohex(tag+1, outTag);
438
439 entry = (gvar *)_dxf_ExDictionarySearch (_dxd_exCacheDict, tag);
440 if (entry) {
441 ExTimestamp(entry);
442 out = DXReference (entry->obj); /* Deleted by user */
443 ExDelete(entry);
444 }
445
446 return (out);
447 }
448
DXGetCacheEntry(char * function,int key,int n,...)449 Object DXGetCacheEntry(char *function, int key, int n, ...)
450 {
451 Object in[100];
452 int i;
453 va_list arg;
454
455 va_start(arg,n);
456 for (i = 0; i < n && i < 100; ++i)
457 in[i] = va_arg(arg, Object);
458 va_end(arg);
459
460 return (DXGetCacheEntryV(function, key, n, in));
461 }
462