gwenhywfar  4.8.0beta
multicache.c
Go to the documentation of this file.
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 
44 GWEN_MULTICACHE_ENTRY *GWEN_MultiCache_Entry_new(GWEN_MULTICACHE_TYPE *ct, uint32_t id, void *p, uint32_t i) {
45  GWEN_MULTICACHE_ENTRY *e;
46 
47  GWEN_NEW_OBJECT(GWEN_MULTICACHE_ENTRY, e);
48  GWEN_LIST_INIT(GWEN_MULTICACHE_ENTRY, e);
49 
50  e->cacheType=ct;
51  e->id=id;
52  e->dataPtr=p;
53  e->dataSize=i;
54 
55  return e;
56 }
57 
58 
59 
60 void GWEN_MultiCache_Entry_free(GWEN_MULTICACHE_ENTRY *e) {
61  if (e) {
62  GWEN_LIST_FINI(GWEN_MULTICACHE_ENTRY, e);
64  }
65 }
66 
67 
68 
69 uint32_t GWEN_MultiCache_Entry_GetId(const GWEN_MULTICACHE_ENTRY *e) {
70  assert(e);
71  return e->id;
72 }
73 
74 
75 
76 uint32_t GWEN_MultiCache_Entry_GetDataSize(const GWEN_MULTICACHE_ENTRY *e) {
77  assert(e);
78  return e->dataSize;
79 }
80 
81 
82 
83 void *GWEN_MultiCache_Entry_GetDataPtr(const GWEN_MULTICACHE_ENTRY *e) {
84  assert(e);
85  return e->dataPtr;
86 }
87 
88 
89 
90 GWEN_MULTICACHE_TYPE *GWEN_MultiCache_Entry_GetCacheType(const GWEN_MULTICACHE_ENTRY *e) {
91  assert(e);
92  return e->cacheType;
93 }
94 
95 
96 
97 uint32_t GWEN_MultiCache_Entry_GetParam1(const GWEN_MULTICACHE_ENTRY *e) {
98  assert(e);
99  return e->param1;
100 }
101 
102 
103 
104 void GWEN_MultiCache_Entry_SetParam1(GWEN_MULTICACHE_ENTRY *e, uint32_t i) {
105  assert(e);
106  e->param1=i;
107 }
108 
109 
110 
111 uint32_t GWEN_MultiCache_Entry_GetParam2(const GWEN_MULTICACHE_ENTRY *e) {
112  assert(e);
113  return e->param2;
114 }
115 
116 
117 
118 void GWEN_MultiCache_Entry_SetParam2(GWEN_MULTICACHE_ENTRY *e, uint32_t i) {
119  assert(e);
120  e->param2=i;
121 }
122 
123 
124 
125 uint32_t GWEN_MultiCache_Entry_GetParam3(const GWEN_MULTICACHE_ENTRY *e) {
126  assert(e);
127  return e->param3;
128 }
129 
130 
131 
132 void GWEN_MultiCache_Entry_SetParam3(GWEN_MULTICACHE_ENTRY *e, uint32_t i) {
133  assert(e);
134  e->param3=i;
135 }
136 
137 
138 
139 uint32_t GWEN_MultiCache_Entry_GetParam4(const GWEN_MULTICACHE_ENTRY *e) {
140  assert(e);
141  return e->param4;
142 }
143 
144 
145 
146 void GWEN_MultiCache_Entry_SetParam4(GWEN_MULTICACHE_ENTRY *e, uint32_t i) {
147  assert(e);
148  e->param4=i;
149 }
150 
151 
152 
153 double GWEN_MultiCache_Entry_GetParam5(const GWEN_MULTICACHE_ENTRY *e) {
154  assert(e);
155  return e->param5;
156 }
157 
158 
159 
160 void GWEN_MultiCache_Entry_SetParam5(GWEN_MULTICACHE_ENTRY *e, double d) {
161  assert(e);
162  e->param5=d;
163 }
164 
165 
166 
167 
168 
169 
170 
171 
172 
175 
178  ct->_refCount=1;
179  ct->multiCache=mc;
180  ct->entryMap=GWEN_MultiCache_Entry_IdMap_new(GWEN_IdMapAlgo_Hex4);
181 
182  return ct;
183 }
184 
185 
186 
188  if (ct) {
189  assert(ct->_refCount);
190  if (ct->_refCount==1) {
191  GWEN_MultiCache_ReleaseEntriesForType(ct->multiCache, ct);
192  GWEN_MultiCache_Entry_IdMap_free(ct->entryMap);
194  ct->_refCount=0;
195  GWEN_FREE_OBJECT(ct);
196  }
197  else
198  ct->_refCount--;
199  }
200 }
201 
202 
203 
204 void *GWEN_MultiCache_Type_GetData(const GWEN_MULTICACHE_TYPE *ct, uint32_t id) {
205  GWEN_MULTICACHE_ENTRY *e;
206 
207  assert(ct);
208  assert(ct->_refCount);
209 
210  e=(GWEN_MULTICACHE_ENTRY*)GWEN_MultiCache_Entry_IdMap_Find(ct->entryMap, id);
211  if (e) {
212  void *p;
213 
214  GWEN_MultiCache_UsingEntry(ct->multiCache, e);
217  return p;
218  }
219  return NULL;
220 }
221 
222 
223 
225  uint32_t param1, uint32_t param2, uint32_t param3, uint32_t param4) {
226 
227  GWEN_MULTICACHE_ENTRY *e;
228 
229  assert(ct);
230  assert(ct->_refCount);
231 
232  e=(GWEN_MULTICACHE_ENTRY*)GWEN_MultiCache_Entry_IdMap_Find(ct->entryMap, id);
233  if (e) {
234  if ((GWEN_MultiCache_Entry_GetParam1(e)==param1) &&
235  (GWEN_MultiCache_Entry_GetParam2(e)==param2) &&
236  (GWEN_MultiCache_Entry_GetParam3(e)==param3) &&
237  (GWEN_MultiCache_Entry_GetParam4(e)==param4)) {
238  void *p;
239 
240  GWEN_MultiCache_UsingEntry(ct->multiCache, e);
243  GWEN_MultiCache_IncCacheHits(ct->multiCache);
244  return p;
245  }
246  }
247  GWEN_MultiCache_IncCacheMisses(ct->multiCache);
248  return NULL;
249 }
250 
251 
252 
254  uint32_t param1, uint32_t param2, uint32_t param3, uint32_t param4,
255  double param5) {
256 
257  GWEN_MULTICACHE_ENTRY *e;
258 
259  assert(ct);
260  assert(ct->_refCount);
261 
262  e=(GWEN_MULTICACHE_ENTRY*)GWEN_MultiCache_Entry_IdMap_Find(ct->entryMap, id);
263  if (e) {
264  if ((GWEN_MultiCache_Entry_GetParam1(e)==param1) &&
265  (GWEN_MultiCache_Entry_GetParam2(e)==param2) &&
266  (GWEN_MultiCache_Entry_GetParam3(e)==param3) &&
267  (GWEN_MultiCache_Entry_GetParam4(e)==param4) &&
268  (GWEN_MultiCache_Entry_GetParam5(e)==param5)) {
269  void *p;
270 
271  GWEN_MultiCache_UsingEntry(ct->multiCache, e);
274  GWEN_MultiCache_IncCacheHits(ct->multiCache);
275  return p;
276  }
277  }
278  GWEN_MultiCache_IncCacheMisses(ct->multiCache);
279  return NULL;
280 }
281 
282 
283 
284 void GWEN_MultiCache_Type_SetData(GWEN_MULTICACHE_TYPE *ct, uint32_t id, void *ptr, uint32_t size) {
285  GWEN_MULTICACHE_ENTRY *e;
286 
287  assert(ct);
288  assert(ct->_refCount);
289 
291  e=GWEN_MultiCache_Entry_new(ct, id, ptr, size);
292  GWEN_MultiCache_AddEntry(ct->multiCache, e);
293  GWEN_MultiCache_Entry_IdMap_Insert(ct->entryMap, id, (void*) e);
294 }
295 
296 
297 
298 void GWEN_MultiCache_Type_SetDataWithParams(GWEN_MULTICACHE_TYPE *ct, uint32_t id, void *ptr, uint32_t size,
299  uint32_t param1, uint32_t param2, uint32_t param3, uint32_t param4) {
300  GWEN_MULTICACHE_ENTRY *e;
301 
302  assert(ct);
303  assert(ct->_refCount);
304 
306 
307  e=GWEN_MultiCache_Entry_new(ct, id, ptr, size);
308  GWEN_MultiCache_AddEntry(ct->multiCache, e);
313  GWEN_MultiCache_Entry_IdMap_Insert(ct->entryMap, id, (void*) e);
314 }
315 
316 
317 
318 void GWEN_MultiCache_Type_SetDataWithParams5(GWEN_MULTICACHE_TYPE *ct, uint32_t id, void *ptr, uint32_t size,
319  uint32_t param1, uint32_t param2, uint32_t param3, uint32_t param4,
320  double param5) {
321  GWEN_MULTICACHE_ENTRY *e;
322 
323  assert(ct);
324  assert(ct->_refCount);
325 
327 
328  e=GWEN_MultiCache_Entry_new(ct, id, ptr, size);
329  GWEN_MultiCache_AddEntry(ct->multiCache, e);
335  GWEN_MultiCache_Entry_IdMap_Insert(ct->entryMap, id, (void*) e);
336 }
337 
338 
339 
341  GWEN_MULTICACHE_ENTRY *e;
342 
343  assert(ct);
344  assert(ct->_refCount);
345 
346  e=(GWEN_MULTICACHE_ENTRY*)GWEN_MultiCache_Entry_IdMap_Find(ct->entryMap, id);
347  if (e)
348  GWEN_MultiCache_ReleaseEntry(ct->multiCache, e);
349 }
350 
351 
352 
354  assert(ct);
355  assert(ct->_refCount);
356 
357  GWEN_MultiCache_ReleaseEntriesForType(ct->multiCache, ct);
358 }
359 
360 
361 
363  assert(ct);
364  assert(ct->_refCount);
365 
366  ct->attachFn=fn;
367 }
368 
369 
370 
372  assert(ct);
373  assert(ct->_refCount);
374 
375  ct->freeFn=fn;
376 }
377 
378 
379 
381  assert(ct);
382  assert(ct->_refCount);
383 
384  if (ct->attachFn)
385  return ct->attachFn(p);
386  else
388 }
389 
390 
391 
393  assert(ct);
394  assert(ct->_refCount);
395 
396  if (ct->freeFn)
397  return ct->freeFn(p);
398  else
400 }
401 
402 
403 void GWEN_MultiCache_Type_ReleaseEntry(GWEN_MULTICACHE_TYPE *ct, GWEN_MULTICACHE_ENTRY *e) {
404  assert(ct);
405  assert(ct->_refCount);
406 
407  assert(e);
408 
409  GWEN_MultiCache_Entry_IdMap_Remove(ct->entryMap, GWEN_MultiCache_Entry_GetId(e));
410 }
411 
412 
413 
414 
415 
416 
417 
419  GWEN_MULTICACHE *mc;
420 
422  mc->_refCount=1;
423  mc->maxSize=maxSize;
424  mc->typeList=GWEN_MultiCache_Type_List_new();
425  mc->entryList=GWEN_MultiCache_Entry_List_new();
426 
427  return mc;
428 }
429 
430 
431 
433  if (mc) {
434  assert(mc->_refCount);
435 
436  if (mc->_refCount==1) {
437  GWEN_MULTICACHE_ENTRY *ce;
438 
439  ce=GWEN_MultiCache_Entry_List_First(mc->entryList);
440  while(ce) {
442  ce=GWEN_MultiCache_Entry_List_First(mc->entryList);
443  }
444 
445  GWEN_MultiCache_Entry_List_free(mc->entryList);
446  GWEN_MultiCache_Type_List_free(mc->typeList);
447 
448  DBG_NOTICE(GWEN_LOGDOMAIN, "MultiCache usage: %lld hits, %lld misses, %lld drops, %lld mb max memory used from %lld mb (%d %%)",
449  (unsigned long long int) mc->cacheHits,
450  (unsigned long long int) mc->cacheMisses,
451  (unsigned long long int) mc->cacheDrops,
452  (unsigned long long int) ((mc->maxSizeUsed)/(1024*1024)),
453  (unsigned long long int) ((mc->maxSize)/(1024*1024)),
454  (int)((mc->maxSizeUsed)*100.0/mc->maxSize));
455 
456  mc->_refCount=0;
457  GWEN_FREE_OBJECT(mc);
458  }
459  else
460  mc->_refCount--;
461  }
462 }
463 
464 
465 
467  assert(mc);
468  assert(mc->_refCount);
469  return mc->maxSizeUsed;
470 }
471 
472 
473 
474 int GWEN_MultiCache_AddEntry(GWEN_MULTICACHE *mc, GWEN_MULTICACHE_ENTRY *e) {
475  uint32_t esize;
476 
477  assert(mc);
478  assert(mc->_refCount);
479  assert(e);
480 
482  if ((mc->currentSize+esize)>mc->maxSize) {
483  int64_t nsize;
484 
485  /* make room */
486  nsize=(mc->currentSize+esize)-mc->maxSize;
487  while(nsize>0) {
488  GWEN_MULTICACHE_ENTRY *ce;
489 
490  ce=GWEN_MultiCache_Entry_List_First(mc->entryList);
491  if (ce) {
494  mc->cacheDrops++;
495  }
496  else {
497  DBG_ERROR(GWEN_LOGDOMAIN, "No entry left to release, cache size limit too low");
498  return GWEN_ERROR_MEMORY_FULL;
499  }
500  }
501  }
502 
503  mc->currentSize+=esize;
504  if (mc->currentSize>mc->maxSizeUsed)
505  mc->maxSizeUsed=mc->currentSize;
507  GWEN_MultiCache_Entry_List_Add(e, mc->entryList);
508  return 0;
509 }
510 
511 
512 
513 void GWEN_MultiCache_ReleaseEntry(GWEN_MULTICACHE *mc, GWEN_MULTICACHE_ENTRY *e) {
514  uint32_t esize;
515 
516  assert(mc);
517  assert(mc->_refCount);
518  assert(e);
519  assert(e->cacheType);
520 
521  /* remove from list first */
522  GWEN_MultiCache_Entry_List_Del(e);
523 
524  /* release from type's idmap */
526 
527  /* release */
531  mc->currentSize-=esize;
532 }
533 
534 
535 
537  GWEN_MULTICACHE_ENTRY *ce;
538 
539  assert(mc);
540  assert(mc->_refCount);
541  assert(ct);
542 
543 
544  ce=GWEN_MultiCache_Entry_List_First(mc->entryList);
545  while(ce) {
546  GWEN_MULTICACHE_ENTRY *ceNext;
547 
548  ceNext=GWEN_MultiCache_Entry_List_Next(ce);
551  ce=ceNext;
552  }
553 }
554 
555 
556 
557 void GWEN_MultiCache_UsingEntry(GWEN_MULTICACHE *mc, GWEN_MULTICACHE_ENTRY *e) {
558  assert(mc);
559  assert(mc->_refCount);
560 
561  /* move cache entry to the end of the list */
562  GWEN_MultiCache_Entry_List_Del(e);
563  GWEN_MultiCache_Entry_List_Add(e, mc->entryList);
564 }
565 
566 
567 
569  assert(mc);
570  assert(mc->_refCount);
571  mc->cacheHits++;
572 }
573 
574 
575 
577  assert(mc);
578  assert(mc->_refCount);
579  mc->cacheMisses++;
580 }
581 
582 
583 
584