00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 #include <stdlib.h>
00010 #include <unistd.h>
00011 
00012 
00013 #include "global.h"
00014 #include "cache.h"
00015 
00016 
00049 inline int cch__entry_set(struct cache_entry_t **cache, 
00050         cache_value_t id, const char *data, int len,
00051         int copy_old_data,
00052         char **copy)
00053 {
00054     int status;
00055     struct cache_entry_t *ce;
00056     int alloc_len;
00057 
00058     if (len == -1) len=strlen(data);
00059 
00060     status=0;
00061     ce=*cache;
00062     alloc_len=len+sizeof(struct cache_entry_t);
00063     if (!ce || 
00064             alloc_len > ce->len || 
00065             (ce->len - len) > 1024)
00066     {
00067         
00068         alloc_len = (alloc_len + 96-1) & ~64;
00069 
00070         if (copy_old_data)
00071             STOPIF( hlp__realloc( &ce, alloc_len), NULL);
00072         else
00073         {
00074             
00075 
00076             free(*cache);
00077             STOPIF( hlp__alloc( &ce, alloc_len), NULL);
00078         }
00079 
00080         ce->len = alloc_len-sizeof(struct cache_entry_t)-1;
00081         *cache=ce;
00082     }
00083 
00084     ce->id = id;
00085     if (data) memcpy(ce->data, data, len);
00086 
00087     
00088     ce->data[len]=0;
00089 
00090     if (copy) *copy=ce->data;
00091 
00092 ex:
00093     return status;
00094 }
00095 
00096 
00099 inline int cch__find(struct cache_t *cache, cache_value_t id, 
00100         int *index, char **data, int *len)
00101 {
00102     int i;
00103 
00104     for(i=0; i<cache->used; i++)
00105         if (cache->entries[i]->id == id)
00106         {
00107             if (data) *data= cache->entries[i]->data;
00108             if (len) *len= cache->entries[i]->len;
00109             if (index) *index=i;
00110 
00111             return 0;
00112         }
00113 
00114     return ENOENT;
00115 }
00116 
00117 
00123 int cch__add(struct cache_t *cache, 
00124         cache_value_t id, const char *data, int len,
00125         char **copy)
00126 {
00127     int i;
00128 
00129     if ( cache->used >= cache->max) 
00130     {
00131         i=cache->lru+1;
00132         if (i >= cache->max) i=0;
00133     }
00134     else
00135         i= cache->used++;
00136 
00137     cache->lru=i;
00138 
00139     
00140     return cch__entry_set(cache->entries + i, id, data, len, 0, copy);
00141 }
00142 
00143 
00148 int cch__set_by_id(struct cache_t *cache, 
00149         cache_value_t id, const char *data, int len,
00150         int copy_old_data,
00151         char **copy)
00152 {
00153     int i;
00154 
00155     
00156     if (cch__find(cache, id, &i, NULL, NULL) == ENOENT)
00157     {
00158         return cch__add(cache, id, data, len, copy);
00159     }
00160 
00161         
00162     cch__set_active(cache, i);
00163 
00164     
00165     return cch__entry_set(cache->entries + i, 
00166             id, data, len, 
00167             copy_old_data, copy);
00168 }
00169 
00170 
00173 void cch__set_active(struct cache_t *cache, int i)
00174 {
00175     struct cache_entry_t *tmp, **entries;
00176 
00177 
00178     entries=cache->entries;
00179     
00180     if (i < cache->lru)
00181     {
00182         
00183 
00184 
00185         tmp=entries[i];
00186         memmove(entries+i, 
00187                 entries+i+1, 
00188                 (cache->lru-i) * sizeof(entries[0]));
00189         entries[cache->lru]=tmp;
00190     }
00191     else if (i > cache->lru)
00192     {
00193         
00194 
00195 
00196         cache->lru++;
00197         BUG_ON(cache->lru >= cache->max);
00198 
00199         
00200         tmp=entries[i];
00201         memmove(entries+cache->lru+1, 
00202                 entries+cache->lru, 
00203                 (i-cache->lru) * sizeof(entries[0]));
00204         entries[cache->lru]=tmp;
00205     }
00206 }
00207 
00212 inline cache_value_t cch___string_to_cv(const char *stg)
00213 {
00214   union {
00215       cache_value_t cv;
00216         struct {
00217             unsigned int c0:5;
00218             unsigned int c1:5;
00219             unsigned int c2:5;
00220             unsigned int c3:5;
00221             unsigned int c4:5;
00222             unsigned int c5:5;
00223             unsigned int ignore_me:2;
00224         };
00225     } __attribute__((packed)) result;
00226 
00227     result.cv=0;
00228     if (*stg) 
00229     { result.c0 = *(stg++) - 0x20;
00230         if (*stg) 
00231         { result.c1 = *(stg++) - 0x20;
00232             if (*stg) 
00233             { result.c2 = *(stg++) - 0x20;
00234                 if (*stg) 
00235                 { result.c3 = *(stg++) - 0x20;
00236                     if (*stg) 
00237                     { result.c4 = *(stg++) - 0x20;
00238                         if (*stg) 
00239                         { result.c5 = *(stg++) - 0x20;
00240                         } } } } } }
00241 
00242     return result.cv;
00243 }
00244 
00245 
00248 int cch__hash_find(struct cache_t *cache, const char *key, cache_value_t *data)
00249 {
00250     int status;
00251     cache_value_t id;
00252     int i;
00253 
00254     id=cch___string_to_cv(key);
00255 
00256     DEBUGP("looking for %lX = %s", id, key);
00257     if (cch__find(cache, id, &i, NULL, NULL) == 0 && 
00258             strcmp(key, cache->entries[i]->data) == 0)
00259     {
00260         *data = cache->entries[i]->hash_data;
00261         DEBUGP("found %s=%ld", key, *data);
00262         status=0;
00263     }
00264     else
00265         status=ENOENT;
00266 
00267     return status;
00268 }
00269 
00270 
00273 int cch__hash_add(struct cache_t *cache, const char *key, cache_value_t value)
00274 {
00275     int status;
00276     cache_value_t id;
00277 
00278 
00279     id=cch___string_to_cv(key);
00280     STOPIF( cch__add(cache, id, key, strlen(key), NULL), NULL);
00281     cache->entries[ cache->lru ]->hash_data = value;
00282 
00283 ex:
00284     return status;
00285 }
00286 
00287