mirror of
http://git.haproxy.org/git/haproxy.git
synced 2026-02-11 04:02:44 +02:00
src/chtbl.c, src/hashpjw.c and src/list.c are distributed under an obscure license. While Aleks and I believe that this license is OK for haproxy, other people think it is not compatible with the GPL. Whether it is or not is not the problem. The fact that it rises a doubt is sufficient for this problem to be addressed. Arnaud Cornet rewrote the unclear parts with clean GPLv2 and LGPL code. The hash algorithm has changed too and the code has been slightly simplified in the process. A lot of care has been taken in order to respect the original API as much as possible, including the LGPL for the exportable parts. The new code has not been thoroughly tested but it looks OK now.
125 lines
2.6 KiB
C
125 lines
2.6 KiB
C
/*
|
|
* HashTable functions.
|
|
*
|
|
* Copyright 2007 Arnaud Cornet
|
|
*
|
|
* This file is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License, version 2.1 as published by the Free Software Foundation.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* quick and dirty AppSession hash table, using sessid as key
|
|
*/
|
|
|
|
#include <common/sessionhash.h>
|
|
#include <string.h>
|
|
#ifdef TEST
|
|
#include <stdio.h>
|
|
#endif
|
|
|
|
/*
|
|
* This is a bernstein hash derivate
|
|
* returns unsigned int between 0 and (TABLESIZE - 1) inclusive
|
|
*/
|
|
unsigned int appsession_hash_f(char *ptr)
|
|
{
|
|
unsigned int h = 5381;
|
|
|
|
while (*ptr) {
|
|
h = (h << 5) + h + *ptr;
|
|
ptr++;
|
|
}
|
|
return ((h >> 16) ^ h) & TABLEMASK;
|
|
}
|
|
|
|
int appsession_hash_init(struct appsession_hash *hash,
|
|
void(*destroy)(appsess*))
|
|
{
|
|
int i;
|
|
|
|
hash->destroy = destroy;
|
|
hash->table = malloc(TABLESIZE * sizeof(struct list));
|
|
if (hash->table == NULL)
|
|
return 0;
|
|
for (i = 0; i < TABLESIZE; i++)
|
|
LIST_INIT(&hash->table[i]);
|
|
return 1;
|
|
}
|
|
|
|
void appsession_hash_insert(struct appsession_hash *hash, appsess *session)
|
|
{
|
|
unsigned int idx;
|
|
|
|
idx = appsession_hash_f(session->sessid);
|
|
LIST_ADDQ(&hash->table[idx], &session->hash_list);
|
|
}
|
|
|
|
appsess *appsession_hash_lookup(struct appsession_hash *hash, char *sessid)
|
|
{
|
|
unsigned int idx;
|
|
appsess *item;
|
|
|
|
idx = appsession_hash_f(sessid);
|
|
|
|
list_for_each_entry(item, &hash->table[idx], hash_list) {
|
|
if (strcmp(item->sessid, sessid) == 0)
|
|
return item;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void appsession_hash_remove(struct appsession_hash *hash, appsess *session)
|
|
{
|
|
unsigned int idx;
|
|
appsess *item;
|
|
|
|
idx = appsession_hash_f(session->sessid);
|
|
|
|
/* we don't even need to call _safe because we return at once */
|
|
list_for_each_entry(item, &hash->table[idx], hash_list) {
|
|
if (strcmp(item->sessid, session->sessid) == 0) {
|
|
LIST_DEL(&item->hash_list);
|
|
hash->destroy(item);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void appsession_hash_destroy(struct appsession_hash *hash)
|
|
{
|
|
unsigned int i;
|
|
appsess *item;
|
|
|
|
for (i = 0; i < TABLESIZE; i++) {
|
|
while (!LIST_ISEMPTY(&hash->table[i])) {
|
|
item = LIST_ELEM(hash->table[i].n, appsess *,
|
|
hash_list);
|
|
hash->destroy(item);
|
|
LIST_DEL(&item->hash_list);
|
|
}
|
|
}
|
|
free(hash->table);
|
|
hash->table = NULL;
|
|
hash->destroy = NULL;
|
|
}
|
|
|
|
#if defined(DEBUG_HASH)
|
|
void appsession_hash_dump(struct appsession_hash *hash)
|
|
{
|
|
unsigned int idx;
|
|
appsess *sess_head, *item;
|
|
|
|
printf("Dumping hashtable 0x%x\n", hash);
|
|
for (idx = 0; idx < TABLESIZE; idx++) {
|
|
/* we don't even need to call _safe because we return at once */
|
|
list_for_each_entry(item, &hash->table[idx], hash_list) {
|
|
printf("\ttable[%d]:\t%s\t-> 0x%x\n", idx, item->sessid,
|
|
item);
|
|
}
|
|
}
|
|
printf(".\n");
|
|
}
|
|
#endif
|