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 
00027 #include "P_Cache.h"
00028 #include "I_Tasks.h"
00029 #if TS_HAS_LIBZ
00030 #include <zlib.h>
00031 #endif
00032 #if TS_HAS_LZMA
00033 #include <lzma.h>
00034 #endif
00035 
00036 #define REQUIRED_COMPRESSION 0.9 // must get to this size or declared incompressible
00037 #define REQUIRED_SHRINK 0.8 // must get to this size or keep orignal buffer (with padding)
00038 #define HISTORY_HYSTERIA 10 // extra temporary history
00039 #define ENTRY_OVERHEAD 256 // per-entry overhead to consider when computing cache value/size
00040 #define LZMA_BASE_MEMLIMIT (64 * 1024 * 1024)
00041 
00042 
00043 #define REQUEUE_HITS(_h) ((_h) ? 1 : 0)
00044 #define CACHE_VALUE_HITS_SIZE(_h, _s) ((float)((_h)+1) / ((_s) + ENTRY_OVERHEAD))
00045 #define CACHE_VALUE(_x) CACHE_VALUE_HITS_SIZE((_x)->hits, (_x)->size)
00046 
00047 struct RamCacheCLFUSEntry {
00048   INK_MD5 key;
00049   uint32_t auxkey1;
00050   uint32_t auxkey2;
00051   uint64_t hits;
00052   uint32_t size; 
00053   uint32_t len;  
00054   uint32_t compressed_len;
00055   union {
00056     struct {
00057       uint32_t compressed:3; 
00058       uint32_t incompressible:1;
00059       uint32_t lru:1;
00060       uint32_t copy:1; 
00061     } flag_bits;
00062     uint32_t flags;
00063   };
00064   LINK(RamCacheCLFUSEntry, lru_link);
00065   LINK(RamCacheCLFUSEntry, hash_link);
00066   Ptr<IOBufferData> data;
00067 };
00068 
00069 struct RamCacheCLFUS : public RamCache {
00070   int64_t max_bytes;
00071   int64_t bytes;
00072   int64_t objects;
00073 
00074   
00075   int get(INK_MD5 *key, Ptr<IOBufferData> *ret_data, uint32_t auxkey1 = 0, uint32_t auxkey2 = 0);
00076   int put(INK_MD5 *key, IOBufferData *data, uint32_t len, bool copy = false, uint32_t auxkey1 = 0, uint32_t auxkey2 = 0);
00077   int fixup(INK_MD5 *key, uint32_t old_auxkey1, uint32_t old_auxkey2, uint32_t new_auxkey1, uint32_t new_auxkey2);
00078 
00079   void init(int64_t max_bytes, Vol *vol);
00080 
00081   
00082   Vol *vol; 
00083   int64_t history;
00084   int ibuckets;
00085   int nbuckets;
00086   DList(RamCacheCLFUSEntry, hash_link) *bucket;
00087   Que(RamCacheCLFUSEntry, lru_link) lru[2];
00088   uint16_t *seen;
00089   int ncompressed;
00090   RamCacheCLFUSEntry *compressed; 
00091   void compress_entries(EThread *thread, int do_at_most = INT_MAX);
00092   void resize_hashtable();
00093   void victimize(RamCacheCLFUSEntry *e);
00094   void move_compressed(RamCacheCLFUSEntry *e);
00095   RamCacheCLFUSEntry *destroy(RamCacheCLFUSEntry *e);
00096   void requeue_victims(RamCacheCLFUS *c, Que(RamCacheCLFUSEntry, lru_link) &victims);
00097   void tick(); 
00098   RamCacheCLFUS(): max_bytes(0), bytes(0), objects(0), vol(0), history(0), ibuckets(0), nbuckets(0), bucket(0),
00099               seen(0), ncompressed(0), compressed(0) { }
00100 };
00101 
00102 class RamCacheCLFUSCompressor : public Continuation {
00103 public:
00104   RamCacheCLFUS *rc;
00105   int mainEvent(int event, Event *e);
00106 
00107   RamCacheCLFUSCompressor(RamCacheCLFUS *arc)
00108     : rc(arc)
00109   { 
00110     SET_HANDLER(&RamCacheCLFUSCompressor::mainEvent); 
00111   }
00112 };
00113 
00114 int
00115 RamCacheCLFUSCompressor::mainEvent(int , Event *e)
00116 {
00117   switch (cache_config_ram_cache_compress) {
00118     default:
00119       Warning("unknown RAM cache compression type: %d", cache_config_ram_cache_compress);
00120     case CACHE_COMPRESSION_NONE: 
00121     case CACHE_COMPRESSION_FASTLZ:
00122       break;
00123     case CACHE_COMPRESSION_LIBZ:
00124 #if ! TS_HAS_LIBZ
00125       Warning("libz not available for RAM cache compression");
00126 #endif
00127       break;
00128     case CACHE_COMPRESSION_LIBLZMA:
00129 #if ! TS_HAS_LZMA
00130       Warning("lzma not available for RAM cache compression");
00131 #endif
00132       break;
00133   }
00134   if (cache_config_ram_cache_compress_percent)
00135     rc->compress_entries(e->ethread);
00136   return EVENT_CONT;
00137 }
00138 
00139 ClassAllocator<RamCacheCLFUSEntry> ramCacheCLFUSEntryAllocator("RamCacheCLFUSEntry");
00140 
00141 static const int bucket_sizes[] = {
00142   127, 251, 509, 1021, 2039, 4093, 8191, 16381, 32749, 65521, 131071, 262139,
00143   524287, 1048573, 2097143, 4194301, 8388593, 16777213, 33554393, 67108859,
00144   134217689, 268435399, 536870909, 1073741789, 2147483647
00145 };
00146 
00147 void
00148 RamCacheCLFUS::resize_hashtable()
00149 {
00150   int anbuckets = bucket_sizes[ibuckets];
00151   DDebug("ram_cache", "resize hashtable %d", anbuckets);
00152   int64_t s = anbuckets * sizeof(DList(RamCacheCLFUSEntry, hash_link));
00153   DList(RamCacheCLFUSEntry, hash_link) *new_bucket = (DList(RamCacheCLFUSEntry, hash_link) *)ats_malloc(s);
00154   memset(new_bucket, 0, s);
00155   if (bucket) {
00156     for (int64_t i = 0; i < nbuckets; i++) {
00157       RamCacheCLFUSEntry *e = 0;
00158       while ((e = bucket[i].pop()))
00159         new_bucket[e->key.slice32(3) % anbuckets].push(e);
00160     }
00161     ats_free(bucket);
00162   }
00163   bucket = new_bucket;
00164   nbuckets = anbuckets;
00165   ats_free(seen);
00166   if (cache_config_ram_cache_use_seen_filter) {
00167     int size = bucket_sizes[ibuckets] * sizeof(uint16_t);
00168     seen = (uint16_t*)ats_malloc(size);
00169     memset(seen, 0, size);
00170   }
00171 }
00172 
00173 void
00174 RamCacheCLFUS::init(int64_t abytes, Vol *avol)
00175 {
00176   ink_assert(avol != 0);
00177   vol = avol;
00178   max_bytes = abytes;
00179   DDebug("ram_cache", "initializing ram_cache %" PRId64 " bytes", abytes);
00180   if (!max_bytes)
00181     return;
00182   resize_hashtable();
00183   eventProcessor.schedule_every(new RamCacheCLFUSCompressor(this), HRTIME_SECOND, ET_TASK);
00184 }
00185 
00186 #ifdef CHECK_ACOUNTING
00187 static void check_accounting(RamCacheCLFUS *c)
00188 {
00189   int64_t x = 0, xsize = 0, h = 0;
00190   RamCacheCLFUSEntry *y = c->lru[0].head;
00191   while (y) { x++; xsize += y->size + ENTRY_OVERHEAD; y = y->lru_link.next; }
00192   y = c->lru[1].head;
00193   while (y) { h++; y = y->lru_link.next; }
00194   ink_assert(x == c->objects);
00195   ink_assert(xsize == c->bytes);
00196   ink_assert(h == c->history);
00197 }
00198 #else
00199 #define check_accounting(_c)
00200 #endif
00201 
00202 int
00203 RamCacheCLFUS::get(INK_MD5 *key, Ptr<IOBufferData> *ret_data, uint32_t auxkey1, uint32_t auxkey2)
00204 {
00205   if (!max_bytes)
00206     return 0;
00207   int64_t i = key->slice32(3) % nbuckets;
00208   RamCacheCLFUSEntry *e = bucket[i].head;
00209   char *b = 0;
00210   while (e) {
00211     if (e->key == *key && e->auxkey1 == auxkey1 && e->auxkey2 == auxkey2) {
00212       move_compressed(e);
00213       lru[e->flag_bits.lru].remove(e);
00214       lru[e->flag_bits.lru].enqueue(e);
00215       if (!e->flag_bits.lru) { 
00216         e->hits++;
00217         if (e->flag_bits.compressed) {
00218           b = (char*)ats_malloc(e->len);
00219           switch (e->flag_bits.compressed) {
00220             default: goto Lfailed;
00221             case CACHE_COMPRESSION_FASTLZ: {
00222               int l = (int)e->len;
00223               if ((l != (int)fastlz_decompress(e->data->data(), e->compressed_len, b, l)))
00224                 goto Lfailed;
00225               break;
00226             }
00227 #if TS_HAS_LIBZ
00228             case CACHE_COMPRESSION_LIBZ: {
00229               uLongf l = e->len;
00230               if (Z_OK != uncompress((Bytef*)b, &l, (Bytef*)e->data->data(), e->compressed_len))
00231                 goto Lfailed;
00232               break;
00233             }
00234 #endif
00235 #if TS_HAS_LZMA
00236             case CACHE_COMPRESSION_LIBLZMA: {
00237               size_t l = (size_t)e->len, ipos = 0, opos = 0;
00238               uint64_t memlimit = e->len * 2 + LZMA_BASE_MEMLIMIT;
00239               if (LZMA_OK != lzma_stream_buffer_decode(
00240                     &memlimit, 0, NULL, (uint8_t*)e->data->data(), &ipos, e->compressed_len, (uint8_t*)b, &opos, l))
00241                 goto Lfailed;
00242               break;
00243             }
00244 #endif
00245           }
00246           IOBufferData *data = new_xmalloc_IOBufferData(b, e->len);
00247           data->_mem_type = DEFAULT_ALLOC;
00248           if (!e->flag_bits.copy) { 
00249             int64_t delta = ((int64_t)e->compressed_len) - (int64_t)e->size;
00250             bytes += delta;
00251             CACHE_SUM_DYN_STAT_THREAD(cache_ram_cache_bytes_stat, delta);
00252             e->size = e->compressed_len;
00253             check_accounting(this);
00254             e->flag_bits.compressed = 0;
00255             e->data = data;
00256           }
00257           (*ret_data) = data;
00258         } else {
00259           IOBufferData *data = e->data;
00260           if (e->flag_bits.copy) {
00261             data = new_IOBufferData(iobuffer_size_to_index(e->len, MAX_BUFFER_SIZE_INDEX), MEMALIGNED);
00262             memcpy(data->data(), e->data->data(), e->len);
00263           }
00264           (*ret_data) = data;
00265         }
00266         CACHE_SUM_DYN_STAT_THREAD(cache_ram_cache_hits_stat, 1);
00267         DDebug("ram_cache", "get %X %d %d size %d HIT", key->slice32(3), auxkey1, auxkey2, e->size);
00268         return 1;
00269       } else {
00270         CACHE_SUM_DYN_STAT_THREAD(cache_ram_cache_misses_stat, 1);
00271         DDebug("ram_cache", "get %X %d %d HISTORY", key->slice32(3), auxkey1, auxkey2);
00272         return 0;
00273       }
00274     }
00275     assert(e != e->hash_link.next);
00276     e = e->hash_link.next;
00277   }
00278   DDebug("ram_cache", "get %X %d %d MISS", key->slice32(3), auxkey1, auxkey2);
00279 Lerror:
00280   CACHE_SUM_DYN_STAT_THREAD(cache_ram_cache_misses_stat, 1);
00281   return 0;
00282 Lfailed:
00283   ats_free(b);
00284   destroy(e);
00285   DDebug("ram_cache", "get %X %d %d Z_ERR", key->slice32(3), auxkey1, auxkey2);
00286   goto Lerror;
00287 }
00288 
00289 void RamCacheCLFUS::tick() {
00290   RamCacheCLFUSEntry *e = lru[1].dequeue();
00291   if (!e)
00292     return;
00293   e->hits <<= 1;
00294   if (e->hits) {
00295     e->hits = REQUEUE_HITS(e->hits);
00296     lru[1].enqueue(e);
00297   } else
00298     goto Lfree;
00299   if (history <= objects + HISTORY_HYSTERIA)
00300     return;
00301   e = lru[1].dequeue();
00302 Lfree:
00303   e->flag_bits.lru = 0;
00304   history--;
00305   uint32_t b = e->key.slice32(3) % nbuckets;
00306   bucket[b].remove(e);
00307   DDebug("ram_cache", "put %X %d %d size %d FREED", e->key.slice32(3), e->auxkey1, e->auxkey2, e->size);
00308   THREAD_FREE(e, ramCacheCLFUSEntryAllocator, this_thread());
00309 }
00310 
00311 void
00312 RamCacheCLFUS::victimize(RamCacheCLFUSEntry *e)
00313 {
00314   objects--;
00315   DDebug("ram_cache", "put %X %d %d size %d VICTIMIZED", e->key.slice32(3), e->auxkey1, e->auxkey2, e->size);
00316   e->data = NULL;
00317   e->flag_bits.lru = 1;
00318   lru[1].enqueue(e);
00319   history++;
00320 }
00321 
00322 void
00323 RamCacheCLFUS::move_compressed(RamCacheCLFUSEntry *e)
00324 {
00325   if (e == compressed) {
00326     if (compressed->lru_link.next)
00327       compressed = compressed->lru_link.next;
00328     else {
00329       ncompressed--;
00330       compressed = compressed->lru_link.prev;
00331     }
00332   }
00333 }
00334 
00335 RamCacheCLFUSEntry *
00336 RamCacheCLFUS::destroy(RamCacheCLFUSEntry *e)
00337 {
00338   RamCacheCLFUSEntry *ret = e->hash_link.next;
00339   move_compressed(e);
00340   lru[e->flag_bits.lru].remove(e);
00341   if (!e->flag_bits.lru) {
00342     objects--;
00343     bytes -= e->size + ENTRY_OVERHEAD;
00344     CACHE_SUM_DYN_STAT_THREAD(cache_ram_cache_bytes_stat, -(int64_t)e->size);
00345     e->data = NULL;
00346   } else
00347     history--;
00348   uint32_t b = e->key.slice32(3) % nbuckets;
00349   bucket[b].remove(e);
00350   DDebug("ram_cache", "put %X %d %d DESTROYED", e->key.slice32(3), e->auxkey1, e->auxkey2);
00351   THREAD_FREE(e, ramCacheCLFUSEntryAllocator, this_thread());
00352   return ret;
00353 }
00354 
00355 void
00356 RamCacheCLFUS::compress_entries(EThread *thread, int do_at_most)
00357 {
00358   if (!cache_config_ram_cache_compress)
00359     return;
00360   ink_assert(vol != 0);
00361   MUTEX_TAKE_LOCK(vol->mutex, thread);
00362   if (!compressed) {
00363     compressed = lru[0].head;
00364     ncompressed = 0;
00365   }
00366   float target = (cache_config_ram_cache_compress_percent / 100.0) * objects;
00367   int n = 0;
00368   char *b = 0, *bb = 0;
00369   while (compressed && target > ncompressed) {
00370     RamCacheCLFUSEntry *e = compressed;
00371     if (e->flag_bits.incompressible || e->flag_bits.compressed)
00372       goto Lcontinue;
00373     n++;
00374     if (do_at_most < n)
00375       break;
00376     {
00377       e->compressed_len = e->size;
00378       uint32_t l = 0;
00379       int ctype = cache_config_ram_cache_compress;
00380       switch (ctype) {
00381         default: goto Lcontinue;
00382         case CACHE_COMPRESSION_FASTLZ: l = (uint32_t)((double)e->len * 1.05 + 66); break;
00383 #if TS_HAS_LIBZ
00384         case CACHE_COMPRESSION_LIBZ: l = (uint32_t)compressBound(e->len); break;
00385 #endif
00386 #if TS_HAS_LZMA
00387         case CACHE_COMPRESSION_LIBLZMA: l = e->len; break;
00388 #endif
00389       }
00390       
00391       Ptr<IOBufferData> edata = e->data;
00392       uint32_t elen = e->len;
00393       INK_MD5 key = e->key;
00394       MUTEX_UNTAKE_LOCK(vol->mutex, thread);
00395       b = (char*)ats_malloc(l);
00396       bool failed = false;
00397       switch (ctype) {
00398         default: goto Lfailed;
00399         case CACHE_COMPRESSION_FASTLZ:
00400           if (e->len < 16) goto Lfailed;
00401           if ((l = fastlz_compress(edata->data(), elen, b)) <= 0)
00402             failed = true;
00403           break;
00404 #if TS_HAS_LIBZ
00405         case CACHE_COMPRESSION_LIBZ: {
00406           uLongf ll = l;
00407           if ((Z_OK != compress((Bytef*)b, &ll, (Bytef*)edata->data(), elen)))
00408             failed = true;
00409           l = (int)ll;
00410           break;
00411         }
00412 #endif
00413 #if TS_HAS_LZMA
00414         case CACHE_COMPRESSION_LIBLZMA: {
00415           size_t pos = 0, ll = l;
00416           if (LZMA_OK != lzma_easy_buffer_encode(LZMA_PRESET_DEFAULT, LZMA_CHECK_NONE, NULL,
00417                                                  (uint8_t*)edata->data(), elen, (uint8_t*)b, &pos, ll))
00418             failed = true;
00419           l = (int)pos;
00420           break;
00421         }
00422 #endif
00423       }
00424       MUTEX_TAKE_LOCK(vol->mutex, thread);
00425       
00426       {
00427         uint32_t i = key.slice32(3) % nbuckets;
00428         RamCacheCLFUSEntry *ee = bucket[i].head;
00429         while (ee) {
00430           if (ee->key == key && ee->data == edata) break;
00431           ee = ee->hash_link.next;
00432         }
00433         if (!ee || ee != e) {
00434           e = compressed;
00435           goto Lcontinue;
00436         }
00437         if (failed)
00438           goto Lfailed;
00439       }
00440       if (l > REQUIRED_COMPRESSION * e->len)
00441         e->flag_bits.incompressible = true;
00442       if (l > REQUIRED_SHRINK * e->size)
00443         goto Lfailed;
00444       if (l < e->len) {
00445         e->flag_bits.compressed = cache_config_ram_cache_compress;
00446         bb = (char*)ats_malloc(l);
00447         memcpy(bb, b, l);
00448         ats_free(b);
00449         e->compressed_len = l;
00450         int64_t delta = ((int64_t)l) - (int64_t)e->size;
00451         bytes += delta;
00452         CACHE_SUM_DYN_STAT_THREAD(cache_ram_cache_bytes_stat, delta);
00453         e->size = l;
00454       } else {
00455         ats_free(b);
00456         e->flag_bits.compressed = 0;
00457         bb = (char*)ats_malloc(e->len);
00458         memcpy(bb, e->data->data(), e->len);
00459         int64_t delta = ((int64_t)e->len) - (int64_t)e->size;
00460         bytes += delta;
00461         CACHE_SUM_DYN_STAT_THREAD(cache_ram_cache_bytes_stat, delta);
00462         e->size = e->len;
00463         l = e->len;
00464       }
00465       e->data = new_xmalloc_IOBufferData(bb, l);
00466       e->data->_mem_type = DEFAULT_ALLOC;
00467       check_accounting(this);
00468     }
00469     goto Lcontinue;
00470   Lfailed:
00471     ats_free(b);
00472     e->flag_bits.incompressible = 1;
00473   Lcontinue:;
00474     DDebug("ram_cache", "compress %X %d %d %d %d %d %d %d",
00475            e->key.slice32(3), e->auxkey1, e->auxkey2,
00476            e->flag_bits.incompressible, e->flag_bits.compressed,
00477            e->len, e->compressed_len, ncompressed);
00478     if (!e->lru_link.next)
00479       break;
00480     compressed = e->lru_link.next;
00481     ncompressed++;
00482   }
00483   MUTEX_UNTAKE_LOCK(vol->mutex, thread);
00484   return;
00485 }
00486 
00487 void
00488 RamCacheCLFUS::requeue_victims(RamCacheCLFUS *c, Que(RamCacheCLFUSEntry, lru_link) &victims)
00489 {
00490   RamCacheCLFUSEntry *victim = 0;
00491   while ((victim = victims.dequeue())) {
00492     c->bytes += victim->size + ENTRY_OVERHEAD;
00493     CACHE_SUM_DYN_STAT_THREAD(cache_ram_cache_bytes_stat, victim->size);
00494     victim->hits = REQUEUE_HITS(victim->hits);
00495     c->lru[0].enqueue(victim);
00496   }
00497 }
00498 
00499 int
00500 RamCacheCLFUS::put(INK_MD5 *key, IOBufferData *data, uint32_t len, bool copy, uint32_t auxkey1, uint32_t auxkey2)
00501 {
00502   if (!max_bytes)
00503     return 0;
00504   uint32_t i = key->slice32(3) % nbuckets;
00505   RamCacheCLFUSEntry *e = bucket[i].head;
00506   uint32_t size = copy ? len : data->block_size();
00507   while (e) {
00508     if (e->key == *key) {
00509       if (e->auxkey1 == auxkey1 && e->auxkey2 == auxkey2)
00510         break;
00511       else {
00512         e = destroy(e); 
00513         continue;
00514       }
00515     }
00516     e = e->hash_link.next;
00517   }
00518   if (e) {
00519     e->hits++;
00520     if (!e->flag_bits.lru) { 
00521       move_compressed(e);
00522       lru[e->flag_bits.lru].remove(e);
00523       lru[e->flag_bits.lru].enqueue(e);
00524       int64_t delta = ((int64_t)size) - (int64_t)e->size;
00525       bytes += delta;
00526       CACHE_SUM_DYN_STAT_THREAD(cache_ram_cache_bytes_stat, delta);
00527       if (!copy) {
00528         e->size = size;
00529         e->data = data;
00530       } else {
00531         char *b = (char*)ats_malloc(len);
00532         memcpy(b, data->data(), len);
00533         e->data = new_xmalloc_IOBufferData(b, len);
00534         e->data->_mem_type = DEFAULT_ALLOC;
00535         e->size = size;
00536       }
00537       check_accounting(this);
00538       e->flag_bits.copy = copy;
00539       e->flag_bits.compressed = 0;
00540       DDebug("ram_cache", "put %X %d %d size %d HIT", key->slice32(3), auxkey1, auxkey2, e->size);
00541       return 1;
00542     } else
00543       lru[1].remove(e);
00544   }
00545   Que(RamCacheCLFUSEntry, lru_link) victims;
00546   RamCacheCLFUSEntry *victim = 0;
00547   if (!lru[1].head) 
00548     if (bytes + size <= max_bytes)
00549       goto Linsert;
00550   if (!e && cache_config_ram_cache_use_seen_filter) {
00551     uint32_t s = key->slice32(3) % bucket_sizes[ibuckets];
00552     uint16_t k = key->slice32(3) >> 16;
00553     uint16_t kk = seen[s];
00554     seen[s] = k;
00555     if (history >= objects && kk != k) {
00556       DDebug("ram_cache", "put %X %d %d size %d UNSEEN", key->slice32(3), auxkey1, auxkey2, size);
00557       return 0;
00558     }
00559   }
00560   while (1) {
00561     victim = lru[0].dequeue();
00562     if (!victim) {
00563       if (bytes + size <= max_bytes)
00564         goto Linsert;
00565       if (e)
00566         lru[1].enqueue(e);
00567       requeue_victims(this, victims);
00568       DDebug("ram_cache", "put %X %d %d NO VICTIM", key->slice32(3), auxkey1, auxkey2);
00569       return 0;
00570     }
00571     bytes -= victim->size + ENTRY_OVERHEAD;
00572     CACHE_SUM_DYN_STAT_THREAD(cache_ram_cache_bytes_stat, -(int64_t)victim->size);
00573     victims.enqueue(victim);
00574     if (victim == compressed)
00575       compressed = 0;
00576     else
00577       ncompressed--;
00578     victim->hits <<= 1;
00579     tick();
00580     if (!e)
00581       goto Lhistory;
00582     else { 
00583       DDebug("ram_cache_compare", "put %f %f", CACHE_VALUE(victim), CACHE_VALUE(e));
00584       if (bytes + victim->size + size > max_bytes && CACHE_VALUE(victim) > CACHE_VALUE(e)) {
00585         requeue_victims(this, victims);
00586         lru[1].enqueue(e);
00587         DDebug("ram_cache", "put %X %d %d size %d INC %" PRId64" HISTORY",
00588                key->slice32(3), auxkey1, auxkey2, e->size, e->hits);
00589         return 0;
00590       }
00591     }
00592     if (bytes + size <= max_bytes)
00593       goto Linsert;
00594   }
00595 Linsert:
00596   while ((victim = victims.dequeue())) {
00597     if (bytes + size + victim->size <= max_bytes) {
00598       bytes += victim->size + ENTRY_OVERHEAD;
00599       CACHE_SUM_DYN_STAT_THREAD(cache_ram_cache_bytes_stat, victim->size);
00600       victim->hits = REQUEUE_HITS(victim->hits);
00601       lru[0].enqueue(victim);
00602     } else
00603       victimize(victim);
00604   }
00605   if (e) {
00606     history--; 
00607   } else {
00608     e = THREAD_ALLOC(ramCacheCLFUSEntryAllocator, this_ethread());
00609     e->key = *key;
00610     e->auxkey1 = auxkey1;
00611     e->auxkey2 = auxkey2;
00612     e->hits = 1;
00613     bucket[i].push(e);
00614     if (objects > nbuckets) {
00615       ++ibuckets;
00616       resize_hashtable();
00617     }
00618   }
00619   check_accounting(this);
00620   e->flags = 0;
00621   if (!copy)
00622     e->data = data;
00623   else {
00624     char *b = (char*)ats_malloc(len);
00625     memcpy(b, data->data(), len);
00626     e->data = new_xmalloc_IOBufferData(b, len);
00627     e->data->_mem_type = DEFAULT_ALLOC;
00628   }
00629   e->flag_bits.copy = copy;
00630   bytes += size + ENTRY_OVERHEAD;
00631   CACHE_SUM_DYN_STAT_THREAD(cache_ram_cache_bytes_stat, size);
00632   e->size = size;
00633   objects++;
00634   lru[0].enqueue(e);
00635   e->len = len;
00636   check_accounting(this);
00637   DDebug("ram_cache", "put %X %d %d size %d INSERTED", key->slice32(3), auxkey1, auxkey2, e->size);
00638   return 1;
00639 Lhistory:
00640   requeue_victims(this, victims);
00641   check_accounting(this);
00642   e = THREAD_ALLOC(ramCacheCLFUSEntryAllocator, this_ethread());
00643   e->key = *key;
00644   e->auxkey1 = auxkey1;
00645   e->auxkey2 = auxkey2;
00646   e->hits = 1;
00647   e->size = data->block_size();
00648   e->flags = 0;
00649   bucket[i].push(e);
00650   e->flag_bits.lru = 1;
00651   lru[1].enqueue(e);
00652   history++;
00653   DDebug("ram_cache", "put %X %d %d HISTORY", key->slice32(3), auxkey1, auxkey2);
00654   return 0;
00655 }
00656 
00657 int
00658 RamCacheCLFUS::fixup(INK_MD5 * key, uint32_t old_auxkey1, uint32_t old_auxkey2, uint32_t new_auxkey1,
00659                      uint32_t new_auxkey2)
00660 {
00661   if (!max_bytes)
00662     return 0;
00663   uint32_t i = key->slice32(3) % nbuckets;
00664   RamCacheCLFUSEntry *e = bucket[i].head;
00665   while (e) {
00666     if (e->key == *key && e->auxkey1 == old_auxkey1 && e->auxkey2 == old_auxkey2) {
00667       e->auxkey1 = new_auxkey1;
00668       e->auxkey2 = new_auxkey2;
00669       return 1;
00670     }
00671     e = e->hash_link.next;
00672   }
00673   return 0;
00674 }
00675 
00676 RamCache *
00677 new_RamCacheCLFUS()
00678 {
00679   RamCacheCLFUS *r = new RamCacheCLFUS;
00680   return r;
00681 }