11static unsigned char siphash_key[16];
42#define MAXDATALEN 1000000
44static void cache_impossible(
void)
49static void set4(uint32 pos,uint32 u)
51 if (pos > size - 4) cache_impossible();
52 uint32_pack(x + pos,u);
55static uint32 get4(uint32 pos)
59 if (pos > size - 4) cache_impossible();
60 uint32_unpack (x + pos,&result);
65static unsigned int hash (
const char *key,
unsigned int keylen)
68 siphash24((
unsigned char *)&
h,(
const unsigned char *)key,keylen,siphash_key);
70 return ((uint32)
h) & (hsize - 4);
73char *
cache_get(
const char *key,
unsigned int keylen,
unsigned int *datalen,uint32 *ttl)
78 uint32
u = 0, pos = 0;
79 uint32 prevpos = 0, nextpos = 0;
82 unsigned int loop = 0;
87 prevpos = hash (key, keylen);
91 if (get4(pos + 4) == keylen) {
92 if (pos + 20 + keylen > size) cache_impossible();
93 if (byte_equal(key, keylen,
x + pos + 20)) {
94 tai_unpack (
x + pos + 12,&expire);
96 if (tai_less (&expire,&
now))
return 0;
98 tai_sub (&expire,&expire,&
now);
99 d = tai_approx (&expire);
100 if (
d > 604800)
d = 604800;
104 if (
u > size - pos - 20 - keylen) cache_impossible();
107 return x + pos + 20 + keylen;
110 nextpos = prevpos ^ get4 (pos);
113 if (++loop > 100)
return 0;
119void cache_set(
const char *key,
unsigned int keylen,
const char *
data,
unsigned int datalen, uint32 ttl)
125 unsigned int keyhash = 0;
126 unsigned int entrylen = 0;
133 if (ttl > 604800) ttl = 604800;
135 entrylen = keylen + datalen + 20;
137 while (writer + entrylen > oldest) {
138 if (oldest == unused) {
139 if (writer <= hsize)
return;
145 set4 (pos,get4(pos) ^ oldest);
147 oldest += get4(oldest + 4) + get4(oldest + 8) + 20;
148 if (oldest > unused) cache_impossible();
149 if (oldest == unused) {
155 keyhash = hash (key,keylen);
158 tai_uint(&expire,ttl);
159 tai_add(&expire,&expire,&
now);
163 set4(pos,get4(pos) ^ keyhash ^ writer);
165 set4(writer,pos ^ keyhash);
166 set4(writer + 4,keylen);
167 set4(writer + 8,datalen);
168 tai_pack (
x + writer + 12,&expire);
169 byte_copy (
x + writer + 20,keylen,key);
170 byte_copy (
x + writer + 20 + keylen,datalen,
data);
172 set4(keyhash,writer);
182 siphash_key[i] = (
unsigned char)
dns_random(0x100);
183 }
while (++i <
sizeof(siphash_key));
185 if (
x) { alloc_free (
x);
x = 0; }
187 if (cachesize > 1000000000) cachesize = 1000000000;
188 if (cachesize < 100) cachesize = 100;
192 while (hsize <= (size >> 5)) hsize <<= 1;
unsigned int dns_random(unsigned int n)
void h(const char *home, int uid, int gid, int mode)
void d(const char *home, const char *subdir, int uid, int gid, int mode)
int cache_init(unsigned int cachesize)
void cache_set(const char *key, unsigned int keylen, const char *data, unsigned int datalen, uint32 ttl)
char * cache_get(const char *key, unsigned int keylen, unsigned int *datalen, uint32 *ttl)
int siphash24(unsigned char *out, const unsigned char *in, unsigned long long inlen, const unsigned char *k)