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