1 /***************************************************************************
2     begin       : Wed May 08 2013
3     copyright   : (C) 2013 by Martin Preuss
4     email       : martin@libchipcard.de
5 
6  ***************************************************************************
7  *                                                                         *
8  *   This library is free software; you can redistribute it and/or         *
9  *   modify it under the terms of the GNU Lesser General Public            *
10  *   License as published by the Free Software Foundation; either          *
11  *   version 2.1 of the License, or (at your option) any later version.    *
12  *                                                                         *
13  *   This library is distributed in the hope that it will be useful,       *
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
16  *   Lesser General Public License for more details.                       *
17  *                                                                         *
18  *   You should have received a copy of the GNU Lesser General Public      *
19  *   License along with this library; if not, write to the Free Software   *
20  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
21  *   MA  02111-1307  USA                                                   *
22  *                                                                         *
23  ***************************************************************************/
24 
25 #ifdef HAVE_CONFIG_H
26 # include <config.h>
27 #endif
28 
29 #define DISABLE_DEBUGLOG
30 
31 #include "multicache_p.h"
32 
33 #include <gwenhywfar/debug.h>
34 
35 
36 
37 GWEN_LIST_FUNCTIONS(GWEN_MULTICACHE_ENTRY, GWEN_MultiCache_Entry);
38 GWEN_IDMAP_FUNCTIONS(GWEN_MULTICACHE_ENTRY, GWEN_MultiCache_Entry);
39 GWEN_LIST_FUNCTIONS(GWEN_MULTICACHE_TYPE, GWEN_MultiCache_Type);
40 
41 
42 
43 
GWEN_MultiCache_Entry_new(GWEN_MULTICACHE_TYPE * ct,uint32_t id,void * p,uint32_t i)44 GWEN_MULTICACHE_ENTRY *GWEN_MultiCache_Entry_new(GWEN_MULTICACHE_TYPE *ct, uint32_t id, void *p, uint32_t i)
45 {
46   GWEN_MULTICACHE_ENTRY *e;
47 
48   GWEN_NEW_OBJECT(GWEN_MULTICACHE_ENTRY, e);
49   GWEN_LIST_INIT(GWEN_MULTICACHE_ENTRY, e);
50 
51   e->cacheType=ct;
52   e->id=id;
53   e->dataPtr=p;
54   e->dataSize=i;
55 
56   return e;
57 }
58 
59 
60 
GWEN_MultiCache_Entry_free(GWEN_MULTICACHE_ENTRY * e)61 void GWEN_MultiCache_Entry_free(GWEN_MULTICACHE_ENTRY *e)
62 {
63   if (e) {
64     GWEN_LIST_FINI(GWEN_MULTICACHE_ENTRY, e);
65     GWEN_FREE_OBJECT(e);
66   }
67 }
68 
69 
70 
GWEN_MultiCache_Entry_GetId(const GWEN_MULTICACHE_ENTRY * e)71 uint32_t GWEN_MultiCache_Entry_GetId(const GWEN_MULTICACHE_ENTRY *e)
72 {
73   assert(e);
74   return e->id;
75 }
76 
77 
78 
GWEN_MultiCache_Entry_GetDataSize(const GWEN_MULTICACHE_ENTRY * e)79 uint32_t GWEN_MultiCache_Entry_GetDataSize(const GWEN_MULTICACHE_ENTRY *e)
80 {
81   assert(e);
82   return e->dataSize;
83 }
84 
85 
86 
GWEN_MultiCache_Entry_GetDataPtr(const GWEN_MULTICACHE_ENTRY * e)87 void *GWEN_MultiCache_Entry_GetDataPtr(const GWEN_MULTICACHE_ENTRY *e)
88 {
89   assert(e);
90   return e->dataPtr;
91 }
92 
93 
94 
GWEN_MultiCache_Entry_GetCacheType(const GWEN_MULTICACHE_ENTRY * e)95 GWEN_MULTICACHE_TYPE *GWEN_MultiCache_Entry_GetCacheType(const GWEN_MULTICACHE_ENTRY *e)
96 {
97   assert(e);
98   return e->cacheType;
99 }
100 
101 
102 
GWEN_MultiCache_Entry_GetParam1(const GWEN_MULTICACHE_ENTRY * e)103 uint32_t GWEN_MultiCache_Entry_GetParam1(const GWEN_MULTICACHE_ENTRY *e)
104 {
105   assert(e);
106   return e->param1;
107 }
108 
109 
110 
GWEN_MultiCache_Entry_SetParam1(GWEN_MULTICACHE_ENTRY * e,uint32_t i)111 void GWEN_MultiCache_Entry_SetParam1(GWEN_MULTICACHE_ENTRY *e, uint32_t i)
112 {
113   assert(e);
114   e->param1=i;
115 }
116 
117 
118 
GWEN_MultiCache_Entry_GetParam2(const GWEN_MULTICACHE_ENTRY * e)119 uint32_t GWEN_MultiCache_Entry_GetParam2(const GWEN_MULTICACHE_ENTRY *e)
120 {
121   assert(e);
122   return e->param2;
123 }
124 
125 
126 
GWEN_MultiCache_Entry_SetParam2(GWEN_MULTICACHE_ENTRY * e,uint32_t i)127 void GWEN_MultiCache_Entry_SetParam2(GWEN_MULTICACHE_ENTRY *e, uint32_t i)
128 {
129   assert(e);
130   e->param2=i;
131 }
132 
133 
134 
GWEN_MultiCache_Entry_GetParam3(const GWEN_MULTICACHE_ENTRY * e)135 uint32_t GWEN_MultiCache_Entry_GetParam3(const GWEN_MULTICACHE_ENTRY *e)
136 {
137   assert(e);
138   return e->param3;
139 }
140 
141 
142 
GWEN_MultiCache_Entry_SetParam3(GWEN_MULTICACHE_ENTRY * e,uint32_t i)143 void GWEN_MultiCache_Entry_SetParam3(GWEN_MULTICACHE_ENTRY *e, uint32_t i)
144 {
145   assert(e);
146   e->param3=i;
147 }
148 
149 
150 
GWEN_MultiCache_Entry_GetParam4(const GWEN_MULTICACHE_ENTRY * e)151 uint32_t GWEN_MultiCache_Entry_GetParam4(const GWEN_MULTICACHE_ENTRY *e)
152 {
153   assert(e);
154   return e->param4;
155 }
156 
157 
158 
GWEN_MultiCache_Entry_SetParam4(GWEN_MULTICACHE_ENTRY * e,uint32_t i)159 void GWEN_MultiCache_Entry_SetParam4(GWEN_MULTICACHE_ENTRY *e, uint32_t i)
160 {
161   assert(e);
162   e->param4=i;
163 }
164 
165 
166 
GWEN_MultiCache_Entry_GetParam5(const GWEN_MULTICACHE_ENTRY * e)167 double GWEN_MultiCache_Entry_GetParam5(const GWEN_MULTICACHE_ENTRY *e)
168 {
169   assert(e);
170   return e->param5;
171 }
172 
173 
174 
GWEN_MultiCache_Entry_SetParam5(GWEN_MULTICACHE_ENTRY * e,double d)175 void GWEN_MultiCache_Entry_SetParam5(GWEN_MULTICACHE_ENTRY *e, double d)
176 {
177   assert(e);
178   e->param5=d;
179 }
180 
181 
182 
183 
184 
185 
186 
187 
188 
GWEN_MultiCache_Type_new(GWEN_MULTICACHE * mc)189 GWEN_MULTICACHE_TYPE *GWEN_MultiCache_Type_new(GWEN_MULTICACHE *mc)
190 {
191   GWEN_MULTICACHE_TYPE *ct;
192 
193   GWEN_NEW_OBJECT(GWEN_MULTICACHE_TYPE, ct);
194   GWEN_LIST_INIT(GWEN_MULTICACHE_TYPE, ct);
195   ct->_refCount=1;
196   ct->multiCache=mc;
197   ct->entryMap=GWEN_MultiCache_Entry_IdMap_new(GWEN_IdMapAlgo_Hex4);
198 
199   return ct;
200 }
201 
202 
203 
GWEN_MultiCache_Type_free(GWEN_MULTICACHE_TYPE * ct)204 void GWEN_MultiCache_Type_free(GWEN_MULTICACHE_TYPE *ct)
205 {
206   if (ct) {
207     assert(ct->_refCount);
208     if (ct->_refCount==1) {
209       GWEN_MultiCache_ReleaseEntriesForType(ct->multiCache, ct);
210       GWEN_MultiCache_Entry_IdMap_free(ct->entryMap);
211       GWEN_LIST_FINI(GWEN_MULTICACHE_TYPE, ct);
212       ct->_refCount=0;
213       GWEN_FREE_OBJECT(ct);
214     }
215     else
216       ct->_refCount--;
217   }
218 }
219 
220 
221 
GWEN_MultiCache_Type_GetData(const GWEN_MULTICACHE_TYPE * ct,uint32_t id)222 void *GWEN_MultiCache_Type_GetData(const GWEN_MULTICACHE_TYPE *ct, uint32_t id)
223 {
224   GWEN_MULTICACHE_ENTRY *e;
225 
226   assert(ct);
227   assert(ct->_refCount);
228 
229   e=(GWEN_MULTICACHE_ENTRY *)GWEN_MultiCache_Entry_IdMap_Find(ct->entryMap, id);
230   if (e) {
231     void *p;
232 
233     GWEN_MultiCache_UsingEntry(ct->multiCache, e);
234     p=GWEN_MultiCache_Entry_GetDataPtr(e);
235     GWEN_MultiCache_Type_AttachData(ct, p);
236     GWEN_MultiCache_IncCacheHits(ct->multiCache);
237     return p;
238   }
239   GWEN_MultiCache_IncCacheMisses(ct->multiCache);
240   return NULL;
241 }
242 
243 
244 
GWEN_MultiCache_Type_GetDataWithParams(const GWEN_MULTICACHE_TYPE * ct,uint32_t id,uint32_t param1,uint32_t param2,uint32_t param3,uint32_t param4)245 void *GWEN_MultiCache_Type_GetDataWithParams(const GWEN_MULTICACHE_TYPE *ct, uint32_t id,
246                                              uint32_t param1, uint32_t param2, uint32_t param3, uint32_t param4)
247 {
248 
249   GWEN_MULTICACHE_ENTRY *e;
250 
251   assert(ct);
252   assert(ct->_refCount);
253 
254   e=(GWEN_MULTICACHE_ENTRY *)GWEN_MultiCache_Entry_IdMap_Find(ct->entryMap, id);
255   if (e) {
256     if ((GWEN_MultiCache_Entry_GetParam1(e)==param1) &&
257         (GWEN_MultiCache_Entry_GetParam2(e)==param2) &&
258         (GWEN_MultiCache_Entry_GetParam3(e)==param3) &&
259         (GWEN_MultiCache_Entry_GetParam4(e)==param4)) {
260       void *p;
261 
262       GWEN_MultiCache_UsingEntry(ct->multiCache, e);
263       p=GWEN_MultiCache_Entry_GetDataPtr(e);
264       GWEN_MultiCache_Type_AttachData(ct, p);
265       GWEN_MultiCache_IncCacheHits(ct->multiCache);
266       return p;
267     }
268   }
269   GWEN_MultiCache_IncCacheMisses(ct->multiCache);
270   return NULL;
271 }
272 
273 
274 
GWEN_MultiCache_Type_GetDataWithParams5(const GWEN_MULTICACHE_TYPE * ct,uint32_t id,uint32_t param1,uint32_t param2,uint32_t param3,uint32_t param4,double param5)275 void *GWEN_MultiCache_Type_GetDataWithParams5(const GWEN_MULTICACHE_TYPE *ct, uint32_t id,
276                                               uint32_t param1, uint32_t param2, uint32_t param3, uint32_t param4,
277                                               double param5)
278 {
279 
280   GWEN_MULTICACHE_ENTRY *e;
281 
282   assert(ct);
283   assert(ct->_refCount);
284 
285   e=(GWEN_MULTICACHE_ENTRY *)GWEN_MultiCache_Entry_IdMap_Find(ct->entryMap, id);
286   if (e) {
287     if ((GWEN_MultiCache_Entry_GetParam1(e)==param1) &&
288         (GWEN_MultiCache_Entry_GetParam2(e)==param2) &&
289         (GWEN_MultiCache_Entry_GetParam3(e)==param3) &&
290         (GWEN_MultiCache_Entry_GetParam4(e)==param4) &&
291         (GWEN_MultiCache_Entry_GetParam5(e)==param5)) {
292       void *p;
293 
294       GWEN_MultiCache_UsingEntry(ct->multiCache, e);
295       p=GWEN_MultiCache_Entry_GetDataPtr(e);
296       GWEN_MultiCache_Type_AttachData(ct, p);
297       GWEN_MultiCache_IncCacheHits(ct->multiCache);
298       return p;
299     }
300   }
301   GWEN_MultiCache_IncCacheMisses(ct->multiCache);
302   return NULL;
303 }
304 
305 
306 
GWEN_MultiCache_Type_SetData(GWEN_MULTICACHE_TYPE * ct,uint32_t id,void * ptr,uint32_t size)307 void GWEN_MultiCache_Type_SetData(GWEN_MULTICACHE_TYPE *ct, uint32_t id, void *ptr, uint32_t size)
308 {
309   GWEN_MULTICACHE_ENTRY *e;
310 
311   assert(ct);
312   assert(ct->_refCount);
313 
314   GWEN_MultiCache_Type_PurgeData(ct, id);
315   e=GWEN_MultiCache_Entry_new(ct, id, ptr, size);
316   GWEN_MultiCache_AddEntry(ct->multiCache, e);
317   GWEN_MultiCache_Entry_IdMap_Insert(ct->entryMap, id, (void *) e);
318 }
319 
320 
321 
GWEN_MultiCache_Type_SetDataWithParams(GWEN_MULTICACHE_TYPE * ct,uint32_t id,void * ptr,uint32_t size,uint32_t param1,uint32_t param2,uint32_t param3,uint32_t param4)322 void GWEN_MultiCache_Type_SetDataWithParams(GWEN_MULTICACHE_TYPE *ct, uint32_t id, void *ptr, uint32_t size,
323                                             uint32_t param1, uint32_t param2, uint32_t param3, uint32_t param4)
324 {
325   GWEN_MULTICACHE_ENTRY *e;
326 
327   assert(ct);
328   assert(ct->_refCount);
329 
330   GWEN_MultiCache_Type_PurgeData(ct, id);
331 
332   e=GWEN_MultiCache_Entry_new(ct, id, ptr, size);
333   GWEN_MultiCache_AddEntry(ct->multiCache, e);
334   GWEN_MultiCache_Entry_SetParam1(e, param1);
335   GWEN_MultiCache_Entry_SetParam2(e, param2);
336   GWEN_MultiCache_Entry_SetParam3(e, param3);
337   GWEN_MultiCache_Entry_SetParam4(e, param4);
338   GWEN_MultiCache_Entry_IdMap_Insert(ct->entryMap, id, (void *) e);
339 }
340 
341 
342 
GWEN_MultiCache_Type_SetDataWithParams5(GWEN_MULTICACHE_TYPE * ct,uint32_t id,void * ptr,uint32_t size,uint32_t param1,uint32_t param2,uint32_t param3,uint32_t param4,double param5)343 void GWEN_MultiCache_Type_SetDataWithParams5(GWEN_MULTICACHE_TYPE *ct, uint32_t id, void *ptr, uint32_t size,
344                                              uint32_t param1, uint32_t param2, uint32_t param3, uint32_t param4,
345                                              double param5)
346 {
347   GWEN_MULTICACHE_ENTRY *e;
348 
349   assert(ct);
350   assert(ct->_refCount);
351 
352   GWEN_MultiCache_Type_PurgeData(ct, id);
353 
354   e=GWEN_MultiCache_Entry_new(ct, id, ptr, size);
355   GWEN_MultiCache_AddEntry(ct->multiCache, e);
356   GWEN_MultiCache_Entry_SetParam1(e, param1);
357   GWEN_MultiCache_Entry_SetParam2(e, param2);
358   GWEN_MultiCache_Entry_SetParam3(e, param3);
359   GWEN_MultiCache_Entry_SetParam4(e, param4);
360   GWEN_MultiCache_Entry_SetParam5(e, param5);
361   GWEN_MultiCache_Entry_IdMap_Insert(ct->entryMap, id, (void *) e);
362 }
363 
364 
365 
GWEN_MultiCache_Type_PurgeData(GWEN_MULTICACHE_TYPE * ct,uint32_t id)366 void GWEN_MultiCache_Type_PurgeData(GWEN_MULTICACHE_TYPE *ct, uint32_t id)
367 {
368   GWEN_MULTICACHE_ENTRY *e;
369 
370   assert(ct);
371   assert(ct->_refCount);
372 
373   e=(GWEN_MULTICACHE_ENTRY *)GWEN_MultiCache_Entry_IdMap_Find(ct->entryMap, id);
374   if (e)
375     GWEN_MultiCache_ReleaseEntry(ct->multiCache, e);
376 }
377 
378 
379 
GWEN_MultiCache_Type_PurgeAll(GWEN_MULTICACHE_TYPE * ct)380 void GWEN_MultiCache_Type_PurgeAll(GWEN_MULTICACHE_TYPE *ct)
381 {
382   assert(ct);
383   assert(ct->_refCount);
384 
385   GWEN_MultiCache_ReleaseEntriesForType(ct->multiCache, ct);
386 }
387 
388 
389 
GWEN_MultiCache_Type_SetAttachFn(GWEN_MULTICACHE_TYPE * ct,GWEN_MULTICACHE_TYPE_ATTACH_FN fn)390 void GWEN_MultiCache_Type_SetAttachFn(GWEN_MULTICACHE_TYPE *ct, GWEN_MULTICACHE_TYPE_ATTACH_FN fn)
391 {
392   assert(ct);
393   assert(ct->_refCount);
394 
395   ct->attachFn=fn;
396 }
397 
398 
399 
GWEN_MultiCache_Type_SetFreeFn(GWEN_MULTICACHE_TYPE * ct,GWEN_MULTICACHE_TYPE_FREE_FN fn)400 void GWEN_MultiCache_Type_SetFreeFn(GWEN_MULTICACHE_TYPE *ct, GWEN_MULTICACHE_TYPE_FREE_FN fn)
401 {
402   assert(ct);
403   assert(ct->_refCount);
404 
405   ct->freeFn=fn;
406 }
407 
408 
409 
GWEN_MultiCache_Type_SetAttachObjectFn(GWEN_MULTICACHE_TYPE * ct,GWEN_MULTICACHE_TYPE_ATTACH_OBJECT_FN fn)410 void GWEN_MultiCache_Type_SetAttachObjectFn(GWEN_MULTICACHE_TYPE *ct, GWEN_MULTICACHE_TYPE_ATTACH_OBJECT_FN fn)
411 {
412   assert(ct);
413   assert(ct->_refCount);
414 
415   ct->attachObjectFn=fn;
416 }
417 
418 
419 
GWEN_MultiCache_Type_SetFreeObjectFn(GWEN_MULTICACHE_TYPE * ct,GWEN_MULTICACHE_TYPE_FREE_OBJECT_FN fn)420 void GWEN_MultiCache_Type_SetFreeObjectFn(GWEN_MULTICACHE_TYPE *ct, GWEN_MULTICACHE_TYPE_FREE_OBJECT_FN fn)
421 {
422   assert(ct);
423   assert(ct->_refCount);
424 
425   ct->freeObjectFn=fn;
426 }
427 
428 
429 
GWEN_MultiCache_Type_AttachData(const GWEN_MULTICACHE_TYPE * ct,void * p)430 int GWEN_MultiCache_Type_AttachData(const GWEN_MULTICACHE_TYPE *ct, void *p)
431 {
432   assert(ct);
433   assert(ct->_refCount);
434 
435   /* try attachObjectFn first, because that has THIS object as first argument */
436   if (ct->attachObjectFn)
437     return ct->attachObjectFn(ct, p);
438 
439   if (ct->attachFn)
440     return ct->attachFn(p);
441 
442   return GWEN_ERROR_NOT_IMPLEMENTED;
443 }
444 
445 
446 
GWEN_MultiCache_Type_FreeData(const GWEN_MULTICACHE_TYPE * ct,void * p)447 int GWEN_MultiCache_Type_FreeData(const GWEN_MULTICACHE_TYPE *ct, void *p)
448 {
449   assert(ct);
450   assert(ct->_refCount);
451 
452   /* try freeObjectFn first, because that has THIS object as first argument */
453   if (ct->freeObjectFn)
454     return ct->freeObjectFn(ct, p);
455 
456   if (ct->freeFn)
457     return ct->freeFn(p);
458 
459   return GWEN_ERROR_NOT_IMPLEMENTED;
460 }
461 
462 
GWEN_MultiCache_Type_ReleaseEntry(GWEN_MULTICACHE_TYPE * ct,GWEN_MULTICACHE_ENTRY * e)463 void GWEN_MultiCache_Type_ReleaseEntry(GWEN_MULTICACHE_TYPE *ct, GWEN_MULTICACHE_ENTRY *e)
464 {
465   assert(ct);
466   assert(ct->_refCount);
467 
468   assert(e);
469 
470   GWEN_MultiCache_Entry_IdMap_Remove(ct->entryMap, GWEN_MultiCache_Entry_GetId(e));
471 }
472 
473 
474 
GWEN_MultiCache_Type_GetIdsInCache(const GWEN_MULTICACHE_TYPE * ct)475 GWEN_IDLIST64 *GWEN_MultiCache_Type_GetIdsInCache(const GWEN_MULTICACHE_TYPE *ct)
476 {
477   GWEN_IDLIST64 *idList;
478   GWEN_MULTICACHE_ENTRY *ce;
479 
480   assert(ct);
481   assert(ct->_refCount);
482 
483   idList=GWEN_IdList64_new();
484 
485   ce=GWEN_MultiCache_Entry_List_First(ct->multiCache->entryList);
486   while (ce) {
487     GWEN_MULTICACHE_ENTRY *ceNext;
488 
489     ceNext=GWEN_MultiCache_Entry_List_Next(ce);
490     if (GWEN_MultiCache_Entry_GetCacheType(ce)==ct) {
491       GWEN_IdList64_AddId(idList, ce->id);
492     }
493     ce=ceNext;
494   }
495 
496   if (GWEN_IdList64_GetEntryCount(idList)<1) {
497     GWEN_IdList64_free(idList);
498     return NULL;
499   }
500 
501   return idList;
502 }
503 
504 
505 
506 
507 
508 
509 
GWEN_MultiCache_new(uint64_t maxSize)510 GWEN_MULTICACHE *GWEN_MultiCache_new(uint64_t maxSize)
511 {
512   GWEN_MULTICACHE *mc;
513 
514   GWEN_NEW_OBJECT(GWEN_MULTICACHE, mc);
515   mc->_refCount=1;
516   mc->maxSize=maxSize;
517   mc->typeList=GWEN_MultiCache_Type_List_new();
518   mc->entryList=GWEN_MultiCache_Entry_List_new();
519 
520   return mc;
521 }
522 
523 
524 
GWEN_MultiCache_free(GWEN_MULTICACHE * mc)525 void GWEN_MultiCache_free(GWEN_MULTICACHE *mc)
526 {
527   if (mc) {
528     assert(mc->_refCount);
529 
530     if (mc->_refCount==1) {
531       GWEN_MULTICACHE_ENTRY *ce;
532 
533       ce=GWEN_MultiCache_Entry_List_First(mc->entryList);
534       while (ce) {
535         GWEN_MultiCache_ReleaseEntry(mc, ce);
536         ce=GWEN_MultiCache_Entry_List_First(mc->entryList);
537       }
538 
539       GWEN_MultiCache_Entry_List_free(mc->entryList);
540       GWEN_MultiCache_Type_List_free(mc->typeList);
541 
542       DBG_NOTICE(GWEN_LOGDOMAIN,
543                  "MultiCache usage: "
544                  "%" PRIu64 " hits, "
545                  "%" PRIu64 " misses, "
546                  "%" PRIu64 " drops, "
547                  "%" PRIu64 " mb max memory used from "
548                  "%" PRIu64 " mb "
549                  "(%d %%)",
550                  (uint64_t) mc->cacheHits,
551                  (uint64_t) mc->cacheMisses,
552                  (uint64_t) mc->cacheDrops,
553                  (uint64_t)((mc->maxSizeUsed)/(1024*1024)),
554                  (uint64_t)((mc->maxSize)/(1024*1024)),
555                  (int)((mc->maxSizeUsed)*100.0/mc->maxSize));
556 
557       mc->_refCount=0;
558       GWEN_FREE_OBJECT(mc);
559     }
560     else
561       mc->_refCount--;
562   }
563 }
564 
565 
566 
GWEN_MultiCache_GetUsageString(const GWEN_MULTICACHE * mc,char * ptrBuffer,int lenBuffer)567 int GWEN_MultiCache_GetUsageString(const GWEN_MULTICACHE *mc, char *ptrBuffer, int lenBuffer)
568 {
569   size_t len;
570   uint64_t totalCacheOps;
571   int hitPercentage=0;
572 
573   totalCacheOps=mc->cacheHits+mc->cacheMisses;
574   if (totalCacheOps)
575     hitPercentage=((mc->cacheHits)*100)/totalCacheOps;
576 
577   len=snprintf(ptrBuffer, lenBuffer,
578                "MultiCache usage: "
579                "%" PRIu64 " hits (%d %%), "
580                "%" PRIu64 " misses, "
581                "%" PRIu64 " drops, "
582                "%" PRIu64 " mb max memory used from "
583                "%" PRIu64 " mb "
584                "(%d %%)",
585                (uint64_t) mc->cacheHits,
586                hitPercentage,
587                (uint64_t) mc->cacheMisses,
588                (uint64_t) mc->cacheDrops,
589                (uint64_t)((mc->maxSizeUsed)/(1024*1024)),
590                (uint64_t)((mc->maxSize)/(1024*1024)),
591                (int)((mc->maxSizeUsed)*100.0/mc->maxSize));
592   if (len>=(size_t)lenBuffer) {
593     DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small (%" PRIu64 " < %" PRIu64,
594               (uint64_t) lenBuffer, (uint64_t) len);
595     return GWEN_ERROR_BUFFER_OVERFLOW;
596   }
597   ptrBuffer[len]=0;
598   return 0;
599 }
600 
601 
602 
GWEN_MultiCache_GetMaxSizeUsed(const GWEN_MULTICACHE * mc)603 uint64_t GWEN_MultiCache_GetMaxSizeUsed(const GWEN_MULTICACHE *mc)
604 {
605   assert(mc);
606   assert(mc->_refCount);
607   return mc->maxSizeUsed;
608 }
609 
610 
611 
GWEN_MultiCache_AddEntry(GWEN_MULTICACHE * mc,GWEN_MULTICACHE_ENTRY * e)612 int GWEN_MultiCache_AddEntry(GWEN_MULTICACHE *mc, GWEN_MULTICACHE_ENTRY *e)
613 {
614   uint32_t esize;
615 
616   assert(mc);
617   assert(mc->_refCount);
618   assert(e);
619 
620   esize=GWEN_MultiCache_Entry_GetDataSize(e);
621   if ((mc->currentSize+esize)>mc->maxSize) {
622     int64_t nsize;
623 
624     /* make room */
625     nsize=(mc->currentSize+esize)-mc->maxSize;
626     while (nsize>0) {
627       GWEN_MULTICACHE_ENTRY *ce;
628 
629       ce=GWEN_MultiCache_Entry_List_First(mc->entryList);
630       if (ce) {
631         nsize-=GWEN_MultiCache_Entry_GetDataSize(ce);
632         GWEN_MultiCache_ReleaseEntry(mc, ce);
633         mc->cacheDrops++;
634       }
635       else {
636         DBG_ERROR(GWEN_LOGDOMAIN, "No entry left to release, cache size limit too low");
637         return GWEN_ERROR_MEMORY_FULL;
638       }
639     }
640   }
641 
642   mc->currentSize+=esize;
643   if (mc->currentSize>mc->maxSizeUsed)
644     mc->maxSizeUsed=mc->currentSize;
645   GWEN_MultiCache_Type_AttachData(GWEN_MultiCache_Entry_GetCacheType(e), GWEN_MultiCache_Entry_GetDataPtr(e));
646   GWEN_MultiCache_Entry_List_Add(e, mc->entryList);
647   return 0;
648 }
649 
650 
651 
GWEN_MultiCache_ReleaseEntry(GWEN_MULTICACHE * mc,GWEN_MULTICACHE_ENTRY * e)652 void GWEN_MultiCache_ReleaseEntry(GWEN_MULTICACHE *mc, GWEN_MULTICACHE_ENTRY *e)
653 {
654   uint32_t esize;
655 
656   assert(mc);
657   assert(mc->_refCount);
658   assert(e);
659   assert(e->cacheType);
660 
661   /* remove from list first */
662   GWEN_MultiCache_Entry_List_Del(e);
663 
664   /* release from type's idmap */
665   GWEN_MultiCache_Type_ReleaseEntry(GWEN_MultiCache_Entry_GetCacheType(e), e);
666 
667   /* release */
668   esize=GWEN_MultiCache_Entry_GetDataSize(e);
669   GWEN_MultiCache_Type_FreeData(e->cacheType, GWEN_MultiCache_Entry_GetDataPtr(e));
670   GWEN_MultiCache_Entry_free(e);
671   mc->currentSize-=esize;
672 }
673 
674 
675 
GWEN_MultiCache_ReleaseEntriesForType(GWEN_MULTICACHE * mc,GWEN_MULTICACHE_TYPE * ct)676 void GWEN_MultiCache_ReleaseEntriesForType(GWEN_MULTICACHE *mc, GWEN_MULTICACHE_TYPE *ct)
677 {
678   GWEN_MULTICACHE_ENTRY *ce;
679 
680   assert(mc);
681   assert(mc->_refCount);
682   assert(ct);
683 
684 
685   ce=GWEN_MultiCache_Entry_List_First(mc->entryList);
686   while (ce) {
687     GWEN_MULTICACHE_ENTRY *ceNext;
688 
689     ceNext=GWEN_MultiCache_Entry_List_Next(ce);
690     if (GWEN_MultiCache_Entry_GetCacheType(ce)==ct)
691       GWEN_MultiCache_ReleaseEntry(mc, ce);
692     ce=ceNext;
693   }
694 }
695 
696 
697 
GWEN_MultiCache_UsingEntry(GWEN_MULTICACHE * mc,GWEN_MULTICACHE_ENTRY * e)698 void GWEN_MultiCache_UsingEntry(GWEN_MULTICACHE *mc, GWEN_MULTICACHE_ENTRY *e)
699 {
700   assert(mc);
701   assert(mc->_refCount);
702 
703   /* move cache entry to the end of the list */
704   GWEN_MultiCache_Entry_List_Del(e);
705   GWEN_MultiCache_Entry_List_Add(e, mc->entryList);
706 }
707 
708 
709 
GWEN_MultiCache_IncCacheHits(GWEN_MULTICACHE * mc)710 void GWEN_MultiCache_IncCacheHits(GWEN_MULTICACHE *mc)
711 {
712   assert(mc);
713   assert(mc->_refCount);
714   mc->cacheHits++;
715 }
716 
717 
718 
GWEN_MultiCache_IncCacheMisses(GWEN_MULTICACHE * mc)719 void GWEN_MultiCache_IncCacheMisses(GWEN_MULTICACHE *mc)
720 {
721   assert(mc);
722   assert(mc->_refCount);
723   mc->cacheMisses++;
724 }
725 
726 
727 
728 
729