00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifdef HAVE_CONFIG_H
00027 # include <config.h>
00028 #endif
00029
00030 #include "memcache_p.h"
00031 #include <gwenhywfar/misc.h>
00032 #include <gwenhywfar/debug.h>
00033
00034
00035
00036 GWEN_IDMAP_FUNCTIONS(GWEN_MEMCACHE_ENTRY, GWEN_MemCacheEntry)
00037
00038
00039
00040 GWEN_MEMCACHE_ENTRY *GWEN_MemCacheEntry_new(GWEN_MEMCACHE *memCache,
00041 uint32_t id,
00042 void *dataPtr,
00043 size_t dataLen) {
00044 GWEN_MEMCACHE_ENTRY *me;
00045
00046 GWEN_NEW_OBJECT(GWEN_MEMCACHE_ENTRY, me);
00047
00048 me->memCache=memCache;
00049 me->id=id;
00050 me->dataPtr=dataPtr;
00051 me->dataLen=dataLen;
00052 me->isValid=1;
00053
00054
00055 me->memCache->currentCacheEntries++;
00056 me->memCache->currentCacheMemory+=me->dataLen;
00057
00058 return me;
00059 }
00060
00061
00062
00063 void GWEN_MemCacheEntry_free(GWEN_MEMCACHE_ENTRY *me) {
00064 if (me) {
00065 assert(me->useCounter==0);
00066 assert(me->memCache);
00067
00068
00069 me->memCache->currentCacheEntries--;
00070 me->memCache->currentCacheMemory-=me->dataLen;
00071
00072 if (me->dataPtr && me->dataLen)
00073 free(me->dataPtr);
00074
00075 GWEN_FREE_OBJECT(me);
00076 }
00077 }
00078
00079
00080
00081 int GWEN_MemCacheEntry_GetUseCounter(const GWEN_MEMCACHE_ENTRY *me) {
00082 assert(me);
00083 return me->useCounter;
00084 }
00085
00086
00087
00088 time_t GWEN_MemCacheEntry_GetUnusedSince(GWEN_MEMCACHE_ENTRY *me) {
00089 assert(me);
00090 return me->unusedSince;
00091 }
00092
00093
00094
00095 uint32_t GWEN_MemCacheEntry_GetId(GWEN_MEMCACHE_ENTRY *me) {
00096 assert(me);
00097 return me->id;
00098 }
00099
00100
00101
00102 void *GWEN_MemCacheEntry_GetDataPtr(GWEN_MEMCACHE_ENTRY *me) {
00103 assert(me);
00104 return me->dataPtr;
00105 }
00106
00107
00108
00109 size_t GWEN_MemCacheEntry_GetDataLen(GWEN_MEMCACHE_ENTRY *me) {
00110 assert(me);
00111 return me->dataLen;
00112 }
00113
00114
00115
00116 void GWEN_MemCacheEntry_BeginUse(GWEN_MEMCACHE_ENTRY *me) {
00117 int rv;
00118
00119 assert(me);
00120 rv=GWEN_MemCache_Lock(me->memCache);
00121 if (rv) {
00122 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00123 assert(0);
00124 }
00125 me->useCounter++;
00126 GWEN_MemCache_Unlock(me->memCache);
00127 }
00128
00129
00130
00131 void GWEN_MemCacheEntry_EndUse(GWEN_MEMCACHE_ENTRY *me) {
00132 int rv;
00133
00134 assert(me);
00135 rv=GWEN_MemCache_Lock(me->memCache);
00136 if (rv) {
00137 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00138 assert(0);
00139 }
00140 if (me->useCounter>0) {
00141 me->useCounter--;
00142 if (me->useCounter==0) {
00143 if (!(me->isValid)) {
00144 GWEN_MemCacheEntry_free(me);
00145 }
00146 else
00147 me->unusedSince=time(0);
00148 }
00149 }
00150 else {
00151 DBG_ERROR(GWEN_LOGDOMAIN, "Use counter < 1, aborting");
00152 GWEN_MemCache_Unlock(me->memCache);
00153 assert(me->useCounter>0);
00154 }
00155 GWEN_MemCache_Unlock(me->memCache);
00156 }
00157
00158
00159
00160
00161
00162
00163
00164 GWEN_MEMCACHE *GWEN_MemCache_new(size_t maxCacheMemory,
00165 uint32_t maxCacheEntries) {
00166 GWEN_MEMCACHE *mc;
00167
00168 GWEN_NEW_OBJECT(GWEN_MEMCACHE, mc);
00169 mc->mutex=GWEN_Mutex_new();
00170 mc->idMap=GWEN_MemCacheEntry_IdMap_new(GWEN_IdMapAlgo_Hex4);
00171 mc->maxCacheMemory=maxCacheMemory;
00172 mc->maxCacheEntries=maxCacheEntries;
00173
00174 return mc;
00175 }
00176
00177
00178
00179 void GWEN_MemCache_free(GWEN_MEMCACHE *mc) {
00180 if (mc) {
00181 GWEN_MemCacheEntry_IdMap_free(mc->idMap);
00182 GWEN_Mutex_free(mc->mutex);
00183 GWEN_FREE_OBJECT(mc);
00184 }
00185 }
00186
00187
00188
00189 GWEN_MEMCACHE_ENTRY *GWEN_MemCache_FindEntry(GWEN_MEMCACHE *mc,
00190 uint32_t id) {
00191 GWEN_MEMCACHE_ENTRY *me;
00192
00193 assert(mc);
00194 GWEN_MemCache_Lock(mc);
00195 me=GWEN_MemCacheEntry_IdMap_Find(mc->idMap, id);
00196 if (me) {
00197
00198 me->useCounter++;
00199 }
00200 GWEN_MemCache_Unlock(mc);
00201
00202 return me;
00203 }
00204
00205
00206
00207 void GWEN_MemCache_PurgeEntry(GWEN_MEMCACHE *mc,
00208 uint32_t id) {
00209 GWEN_MEMCACHE_ENTRY *me;
00210
00211 assert(mc);
00212 GWEN_MemCache_Lock(mc);
00213 me=GWEN_MemCacheEntry_IdMap_Find(mc->idMap, id);
00214 if (me) {
00215 me->isValid=0;
00216 GWEN_MemCacheEntry_IdMap_Remove(mc->idMap, id);
00217 if (me->useCounter==0)
00218 GWEN_MemCacheEntry_free(me);
00219 }
00220 GWEN_MemCache_Unlock(mc);
00221 }
00222
00223
00224
00225 int GWEN_MemCache__MakeRoom(GWEN_MEMCACHE *mc,
00226 size_t neededSize) {
00227 assert(mc);
00228
00229
00230 while(neededSize) {
00231 GWEN_MEMCACHE_ENTRY *oldestEntry;
00232 GWEN_IDMAP_RESULT res;
00233 uint32_t currentId;
00234
00235
00236 oldestEntry=NULL;
00237 res=GWEN_MemCacheEntry_IdMap_GetFirst(mc->idMap, ¤tId);
00238 while(res==GWEN_IdMapResult_Ok) {
00239 GWEN_MEMCACHE_ENTRY *me;
00240
00241 me=GWEN_MemCacheEntry_IdMap_Find(mc->idMap, currentId);
00242 if (me) {
00243 if (me->isValid && me->useCounter==0) {
00244 if (oldestEntry==NULL)
00245 oldestEntry=me;
00246 else {
00247 if (me->unusedSince<oldestEntry->unusedSince)
00248 oldestEntry=me;
00249 }
00250 }
00251 }
00252 res=GWEN_MemCacheEntry_IdMap_GetNext(mc->idMap, ¤tId);
00253 }
00254
00255 if (oldestEntry==NULL)
00256
00257 break;
00258
00259
00260 if (neededSize<oldestEntry->dataLen)
00261 neededSize=0;
00262 else
00263 neededSize-=oldestEntry->dataLen;
00264
00265
00266 GWEN_MemCacheEntry_IdMap_Remove(mc->idMap, oldestEntry->id);
00267 GWEN_MemCacheEntry_free(oldestEntry);
00268 }
00269
00270 return (neededSize==0)?0:GWEN_ERROR_MEMORY_FULL;
00271 }
00272
00273
00274
00275 GWEN_MEMCACHE_ENTRY *GWEN_MemCache_CreateEntry(GWEN_MEMCACHE *mc,
00276 uint32_t id,
00277 void *dataPtr,
00278 size_t dataLen) {
00279 GWEN_MEMCACHE_ENTRY *me;
00280
00281 assert(mc);
00282 GWEN_MemCache_Lock(mc);
00283
00284
00285 me=GWEN_MemCacheEntry_IdMap_Find(mc->idMap, id);
00286 if (me) {
00287 me->isValid=0;
00288 GWEN_MemCacheEntry_IdMap_Remove(mc->idMap, id);
00289 if (me->useCounter==0)
00290 GWEN_MemCacheEntry_free(me);
00291 }
00292
00293
00294 if (mc->currentCacheEntries>=mc->maxCacheEntries) {
00295 int rv;
00296
00297
00298 rv=GWEN_MemCache__MakeRoom(mc, 1);
00299 if (rv) {
00300 DBG_WARN(GWEN_LOGDOMAIN, "Too many entries in use");
00301 GWEN_MemCache_Unlock(mc);
00302 return NULL;
00303 }
00304 }
00305
00306
00307 if ((mc->currentCacheMemory+dataLen)>=mc->maxCacheMemory) {
00308 size_t diff;
00309 int rv;
00310
00311 diff=(mc->currentCacheMemory+dataLen)-mc->maxCacheMemory;
00312
00313 rv=GWEN_MemCache__MakeRoom(mc, diff);
00314 if (rv) {
00315 DBG_WARN(GWEN_LOGDOMAIN, "Too much memory in use");
00316 GWEN_MemCache_Unlock(mc);
00317 return NULL;
00318 }
00319 }
00320
00321
00322 me=GWEN_MemCacheEntry_new(mc, id, dataPtr, dataLen);
00323 assert(me);
00324 me->useCounter++;
00325 GWEN_MemCacheEntry_IdMap_Insert(mc->idMap, id, me);
00326
00327 GWEN_MemCache_Unlock(mc);
00328
00329 return me;
00330 }
00331
00332
00333
00334 void GWEN_MemCache_PurgeEntries(GWEN_MEMCACHE *mc,
00335 uint32_t id, uint32_t mask) {
00336 GWEN_IDMAP_RESULT res;
00337 uint32_t currentId;
00338
00339 assert(mc);
00340 GWEN_MemCache_Lock(mc);
00341
00342 res=GWEN_MemCacheEntry_IdMap_GetFirst(mc->idMap, ¤tId);
00343 while(res==GWEN_IdMapResult_Ok) {
00344 uint32_t nextId;
00345
00346 nextId=currentId;
00347 res=GWEN_MemCacheEntry_IdMap_GetNext(mc->idMap, &nextId);
00348 if ((currentId & mask)==id) {
00349 GWEN_MEMCACHE_ENTRY *me;
00350
00351 me=GWEN_MemCacheEntry_IdMap_Find(mc->idMap, currentId);
00352 if (me) {
00353 me->isValid=0;
00354 GWEN_MemCacheEntry_IdMap_Remove(mc->idMap, currentId);
00355 if (me->useCounter==0)
00356 GWEN_MemCacheEntry_free(me);
00357 }
00358
00359 }
00360 currentId=nextId;
00361 }
00362
00363 GWEN_MemCache_Unlock(mc);
00364 }
00365
00366
00367
00368 void GWEN_MemCache_Purge(GWEN_MEMCACHE *mc) {
00369 assert(mc);
00370 GWEN_MemCache_PurgeEntries(mc, 0, 0);
00371 }
00372
00373
00374
00375 int GWEN_MemCache_Lock(GWEN_MEMCACHE *mc) {
00376 assert(mc);
00377 return GWEN_Mutex_Lock(mc->mutex);
00378 }
00379
00380
00381
00382 int GWEN_MemCache_Unlock(GWEN_MEMCACHE *mc) {
00383 assert(mc);
00384 return GWEN_Mutex_Unlock(mc->mutex);
00385 }
00386
00387
00388
00389
00390
00391
00392
00393