/* * 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 #include #ifdef DEBUG_HASH #include #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; if (!hash->table) return; 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 *item; printf("Dumping hashtable 0x%p\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-> %s request_count %lu\n", idx, item->sessid, item->serverid, item->request_count); } } printf(".\n"); } #endif