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