3proxy/src/hash.c

167 lines
4.6 KiB
C

#include "proxy.h"
#include "libs/blake2.h"
static unsigned hashindex(struct hashtable *ht, const uint8_t* hash){
return (*(unsigned *)hash ) % (ht->tablesize);
}
void destroyhashtable(struct hashtable *ht){
pthread_mutex_lock(&hash_mutex);
if(ht->ihashtable){
myfree(ht->ihashtable);
ht->ihashtable = NULL;
}
if(ht->hashvalues){
myfree(ht->hashvalues);
ht->hashvalues = NULL;
}
ht->hashsize = 0;
ht->tablesize = 0;
pthread_mutex_unlock(&hash_mutex);
}
#define hvalue(ht,I) ((struct hashentry *)(ht->hashvalues + (I-1)*(sizeof(struct hashentry) + ht->recsize - 4)))
int inithashtable(struct hashtable *ht, unsigned nhashsize){
unsigned i;
clock_t c;
#ifdef _WIN32
struct timeb tb;
ftime(&tb);
#else
struct timeval tb;
struct timezone tz;
gettimeofday(&tb, &tz);
#endif
c = clock();
if(nhashsize<4) return 1;
pthread_mutex_lock(&hash_mutex);
if(ht->ihashtable){
myfree(ht->ihashtable);
ht->ihashtable = NULL;
}
if(ht->hashvalues){
myfree(ht->hashvalues);
ht->hashvalues = NULL;
}
ht->hashsize = 0;
if(!(ht->ihashtable = myalloc((nhashsize>>2) * sizeof(int)))){
pthread_mutex_unlock(&hash_mutex);
return 2;
}
if(!(ht->hashvalues = myalloc(nhashsize * (sizeof(struct hashentry) + (ht->recsize-4))))){
myfree(ht->ihashtable);
ht->ihashtable = NULL;
pthread_mutex_unlock(&hash_mutex);
return 3;
}
ht->hashsize = nhashsize;
ht->tablesize = (nhashsize>>2);
ht->rnd[0] = myrand(&tb, sizeof(tb));
ht->rnd[1] = myrand(ht->ihashtable, sizeof(ht->ihashtable));
ht->rnd[2] = myrand(&c, sizeof(c));
ht->rnd[3] = myrand(ht->hashvalues,sizeof(ht->hashvalues));
memset(ht->ihashtable, 0, ht->tablesize * sizeof(struct hashentry *));
memset(ht->hashvalues, 0, ht->hashsize * (sizeof(struct hashentry) + ht->recsize - 4));
for(i = 1; i < ht->hashsize; i++) {
hvalue(ht,i)->inext = i+1;
}
ht->ihashempty = 1;
pthread_mutex_unlock(&hash_mutex);
return 0;
}
static void hashcompact(struct hashtable *ht){
int i;
int he, *hep;
if((conf.time - ht->compacted) < 60 || !ht->tablesize || !ht->hashsize || ht->hashsize/ht->tablesize >= 4 ) return;
for(i = 0; i < ht->tablesize; i++){
for(hep = ht->ihashtable + i; (he = *hep) != 0; ){
if(hvalue(ht,he)->expires < conf.time ) {
(*hep) = hvalue(ht,he)->inext;
hvalue(ht,he)->expires = 0;
hvalue(ht,he)->inext = ht->ihashempty;
ht->ihashempty = he;
}
else hep=&(hvalue(ht,he)->inext);
}
}
ht->compacted = conf.time;
}
void hashadd(struct hashtable *ht, const void* name, const void* value, time_t expires){
int hen, he;
int *hep;
unsigned index;
pthread_mutex_lock(&hash_mutex);
if(!ht->ihashempty){
hashcompact(ht);
}
if(!ht||!value||!name||!ht->ihashtable||!ht->ihashempty) {
pthread_mutex_unlock(&hash_mutex);
return;
}
hen = ht->ihashempty;
ht->ihashempty = hvalue(ht,ht->ihashempty)->inext;
ht->index2hash(name, hvalue(ht,hen)->hash, (unsigned char *)ht->rnd);
memcpy(hvalue(ht,hen)->value, value, ht->recsize);
hvalue(ht,hen)->expires = expires;
hvalue(ht,hen)->inext = 0;
index = hashindex(ht, hvalue(ht,hen)->hash);
for(hep = ht->ihashtable + index; (he = *hep)!=0; ){
if(hvalue(ht,he)->expires < conf.time || !memcmp(hvalue(ht,hen)->hash, hvalue(ht,he)->hash, HASH_SIZE)) {
(*hep) = hvalue(ht,he)->inext;
hvalue(ht,he)->expires = 0;
hvalue(ht,he)->inext = ht->ihashempty;
ht->ihashempty = he;
}
else hep=&(hvalue(ht,he)->inext);
}
hvalue(ht,hen)->inext = ht->ihashtable[index];
ht->ihashtable[index] = hen;
pthread_mutex_unlock(&hash_mutex);
}
int hashresolv(struct hashtable *ht, const void* name, void* value, uint32_t *ttl){
uint8_t hash[HASH_SIZE];
int *hep;
int he;
unsigned index;
pthread_mutex_lock(&hash_mutex);
if(!ht || !ht->ihashtable || !name) {
pthread_mutex_unlock(&hash_mutex);
return 0;
}
ht->index2hash(name, hash, (unsigned char *)ht->rnd);
index = hashindex(ht, hash);
for(hep = ht->ihashtable + index; (he = *hep)!=0; ){
if(hvalue(ht, he)->expires < conf.time) {
(*hep) = hvalue(ht,he)->inext;
hvalue(ht,he)->expires = 0;
hvalue(ht,he)->inext = ht->ihashempty;
ht->ihashempty = he;
}
else if(!memcmp(hash, hvalue(ht,he)->hash, HASH_SIZE)){
if(ttl) *ttl = (uint32_t)(hvalue(ht,he)->expires - conf.time);
memcpy(value, hvalue(ht,he)->value, ht->recsize);
pthread_mutex_unlock(&hash_mutex);
return 1;
}
else hep=&(hvalue(ht,he)->inext);
}
pthread_mutex_unlock(&hash_mutex);
return 0;
}