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