Allow different hash lengths; fix bug on hashtable grow

This commit is contained in:
Vladimir Dubrovin 2026-04-20 18:49:53 +03:00
parent ee00956b74
commit 3957210609
2 changed files with 24 additions and 9 deletions

View File

@ -3,7 +3,6 @@
struct hashentry { struct hashentry {
uint8_t hash[HASH_SIZE];
time_t expires; time_t expires;
uint32_t inext; uint32_t inext;
char value[4]; char value[4];
@ -24,12 +23,17 @@ void destroyhashtable(struct hashtable *ht){
myfree(ht->hashvalues); myfree(ht->hashvalues);
ht->hashvalues = NULL; ht->hashvalues = NULL;
} }
if(ht->hashhashvalues){
myfree(ht->hashvalues);
ht->hashvalues = NULL;
}
ht->poolsize = 0; ht->poolsize = 0;
ht->tablesize = 0; ht->tablesize = 0;
pthread_mutex_unlock(&hash_mutex); pthread_mutex_unlock(&hash_mutex);
} }
#define hvalue(ht,I) ((struct hashentry *)(ht->hashvalues + (I-1)*(sizeof(struct hashentry) + ht->recsize - 4))) #define hvalue(ht,I) ((struct hashentry *)(ht->hashvalues + (I-1)*(sizeof(struct hashentry) + ht->recsize - 4)))
#define hhash(ht,I) ((ht->hashhashvalues + (I-1)*(ht->hash_size)))
int inithashtable(struct hashtable *ht, unsigned npoolsize){ int inithashtable(struct hashtable *ht, unsigned npoolsize){
unsigned i; unsigned i;
@ -59,15 +63,20 @@ int inithashtable(struct hashtable *ht, unsigned npoolsize){
myfree(ht->hashvalues); myfree(ht->hashvalues);
ht->hashvalues = NULL; ht->hashvalues = NULL;
} }
if(ht->hashhashvalues){
myfree(ht->hashvalues);
ht->hashvalues = NULL;
}
ht->poolsize = 0; ht->poolsize = 0;
ht->tablesize = 0; ht->tablesize = 0;
if(!(ht->ihashtable = myalloc(tablesize * sizeof(uint32_t)))){ if(!(ht->ihashtable = myalloc(tablesize * sizeof(uint32_t)))
pthread_mutex_unlock(&hash_mutex); || !(ht->hashvalues = myalloc(poolsize * (sizeof(struct hashentry) + (ht->recsize-4))))
return 2; || !(ht->hashhashvalues = myalloc(poolsize * ht->hash_size))
} ){
if(!(ht->hashvalues = myalloc(poolsize * (sizeof(struct hashentry) + (ht->recsize-4))))){
myfree(ht->ihashtable); myfree(ht->ihashtable);
ht->ihashtable = NULL; ht->ihashtable = NULL;
myfree(ht->hashvalues);
ht->hashvalues = NULL;
pthread_mutex_unlock(&hash_mutex); pthread_mutex_unlock(&hash_mutex);
return 3; return 3;
} }
@ -117,6 +126,10 @@ static void hashgrow(struct hashtable *ht){
if(newsize > ht->growlimit) newsize = ht->growlimit; if(newsize > ht->growlimit) newsize = ht->growlimit;
newvalues = myrealloc(ht->hashvalues, newsize * (sizeof(struct hashentry) + ht->recsize - 4)); newvalues = myrealloc(ht->hashvalues, newsize * (sizeof(struct hashentry) + ht->recsize - 4));
if(!newvalues) return; if(!newvalues) return;
ht->hashvalues = newvalues;
newvalues = myrealloc(ht->hashhashvalues, newsize * ht->hash_size);
if(!newvalues) return;
ht->hashhashvalues = newvalues;
memset(ht->hashvalues + (ht->poolsize * (sizeof(struct hashentry) + ht->recsize - 4)), 0, (newsize - ht->poolsize) * (sizeof(struct hashentry) + ht->recsize - 4)); memset(ht->hashvalues + (ht->poolsize * (sizeof(struct hashentry) + ht->recsize - 4)), 0, (newsize - ht->poolsize) * (sizeof(struct hashentry) + ht->recsize - 4));
for(i = ht->poolsize + 1; i < newsize; i++) { for(i = ht->poolsize + 1; i < newsize; i++) {
hvalue(ht,i)->inext = i+1; hvalue(ht,i)->inext = i+1;
@ -145,7 +158,7 @@ void hashadd(struct hashtable *ht, const void* name, const void* value, time_t e
index = hashindex(ht, hash); index = hashindex(ht, hash);
for(hep = ht->ihashtable + index; (he = *hep)!=0; ){ for(hep = ht->ihashtable + index; (he = *hep)!=0; ){
if(hvalue(ht,he)->expires < conf.time || !memcmp(hash, hvalue(ht,he)->hash, ht->hash_size)) { if(hvalue(ht,he)->expires < conf.time || !memcmp(hash, hhash(ht,he), ht->hash_size)) {
(*hep) = hvalue(ht,he)->inext; (*hep) = hvalue(ht,he)->inext;
hvalue(ht,he)->expires = 0; hvalue(ht,he)->expires = 0;
hvalue(ht,he)->inext = ht->ihashempty; hvalue(ht,he)->inext = ht->ihashempty;
@ -171,7 +184,7 @@ void hashadd(struct hashtable *ht, const void* name, const void* value, time_t e
hen = last; hen = last;
} }
if(hen){ if(hen){
memcpy(hvalue(ht,hen)->hash, hash, ht->hash_size); memcpy(hhash(ht,hen), hash, ht->hash_size);
memcpy(hvalue(ht,hen)->value, value, ht->recsize); memcpy(hvalue(ht,hen)->value, value, ht->recsize);
hvalue(ht,hen)->expires = expires; hvalue(ht,hen)->expires = expires;
} }
@ -198,7 +211,7 @@ int hashresolv(struct hashtable *ht, const void* name, void* value, uint32_t *tt
hvalue(ht,he)->inext = ht->ihashempty; hvalue(ht,he)->inext = ht->ihashempty;
ht->ihashempty = he; ht->ihashempty = he;
} }
else if(!memcmp(hash, hvalue(ht,he)->hash, ht->hash_size)){ else if(!memcmp(hash, hhash(ht,he), ht->hash_size)){
if(ttl) *ttl = (uint32_t)(hvalue(ht,he)->expires - conf.time); if(ttl) *ttl = (uint32_t)(hvalue(ht,he)->expires - conf.time);
memcpy(value, hvalue(ht,he)->value, ht->recsize); memcpy(value, hvalue(ht,he)->value, ht->recsize);
pthread_mutex_unlock(&hash_mutex); pthread_mutex_unlock(&hash_mutex);

View File

@ -765,7 +765,9 @@ struct hashtable {
void (*index2hash)(const void *index, unsigned char *hash); void (*index2hash)(const void *index, unsigned char *hash);
uint32_t * ihashtable; uint32_t * ihashtable;
uint8_t * hashvalues; uint8_t * hashvalues;
uint8_t * hashhashvalues;
time_t compacted; time_t compacted;
uint32_t ihashhashempty;
uint32_t ihashempty; uint32_t ihashempty;
}; };