blob: 80683900a1085e6f8e0d84555495576fd77ed423 [file] [log] [blame]
Willy Tarreau51041c72007-09-09 21:56:53 +02001/*
2 * HashTable functions.
3 *
4 * Copyright 2007 Arnaud Cornet
5 *
6 * This file is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License, version 2.1 as published by the Free Software Foundation.
9 *
10 */
11
12/*
13 * quick and dirty AppSession hash table, using sessid as key
14 */
15
16#include <common/sessionhash.h>
17#include <string.h>
Aleksandar Lazic697bbb02008-08-13 19:57:02 +020018#ifdef DEBUG_HASH
Willy Tarreau51041c72007-09-09 21:56:53 +020019#include <stdio.h>
20#endif
21
22/*
23 * This is a bernstein hash derivate
24 * returns unsigned int between 0 and (TABLESIZE - 1) inclusive
25 */
26unsigned int appsession_hash_f(char *ptr)
27{
28 unsigned int h = 5381;
29
30 while (*ptr) {
31 h = (h << 5) + h + *ptr;
32 ptr++;
33 }
34 return ((h >> 16) ^ h) & TABLEMASK;
35}
36
37int appsession_hash_init(struct appsession_hash *hash,
38 void(*destroy)(appsess*))
39{
40 int i;
41
42 hash->destroy = destroy;
43 hash->table = malloc(TABLESIZE * sizeof(struct list));
44 if (hash->table == NULL)
45 return 0;
46 for (i = 0; i < TABLESIZE; i++)
47 LIST_INIT(&hash->table[i]);
48 return 1;
49}
50
51void appsession_hash_insert(struct appsession_hash *hash, appsess *session)
52{
53 unsigned int idx;
54
55 idx = appsession_hash_f(session->sessid);
56 LIST_ADDQ(&hash->table[idx], &session->hash_list);
57}
58
59appsess *appsession_hash_lookup(struct appsession_hash *hash, char *sessid)
60{
61 unsigned int idx;
62 appsess *item;
63
64 idx = appsession_hash_f(sessid);
65
66 list_for_each_entry(item, &hash->table[idx], hash_list) {
67 if (strcmp(item->sessid, sessid) == 0)
68 return item;
69 }
70 return NULL;
71}
72
73void appsession_hash_remove(struct appsession_hash *hash, appsess *session)
74{
75 unsigned int idx;
76 appsess *item;
77
78 idx = appsession_hash_f(session->sessid);
79
80 /* we don't even need to call _safe because we return at once */
81 list_for_each_entry(item, &hash->table[idx], hash_list) {
82 if (strcmp(item->sessid, session->sessid) == 0) {
83 LIST_DEL(&item->hash_list);
84 hash->destroy(item);
85 return;
86 }
87 }
88}
89
90void appsession_hash_destroy(struct appsession_hash *hash)
91{
92 unsigned int i;
93 appsess *item;
94
Willy Tarreau177a16a2007-10-15 20:04:22 +020095 if (!hash->table)
96 return;
97
Willy Tarreau51041c72007-09-09 21:56:53 +020098 for (i = 0; i < TABLESIZE; i++) {
99 while (!LIST_ISEMPTY(&hash->table[i])) {
100 item = LIST_ELEM(hash->table[i].n, appsess *,
101 hash_list);
102 hash->destroy(item);
103 LIST_DEL(&item->hash_list);
104 }
105 }
106 free(hash->table);
107 hash->table = NULL;
108 hash->destroy = NULL;
109}
110
111#if defined(DEBUG_HASH)
112void appsession_hash_dump(struct appsession_hash *hash)
113{
114 unsigned int idx;
Aleksandar Lazic697bbb02008-08-13 19:57:02 +0200115 appsess *item;
Willy Tarreau51041c72007-09-09 21:56:53 +0200116
Aleksandar Lazic697bbb02008-08-13 19:57:02 +0200117 printf("Dumping hashtable 0x%p\n", hash);
Willy Tarreau51041c72007-09-09 21:56:53 +0200118 for (idx = 0; idx < TABLESIZE; idx++) {
119 /* we don't even need to call _safe because we return at once */
120 list_for_each_entry(item, &hash->table[idx], hash_list) {
Aleksandar Lazic697bbb02008-08-13 19:57:02 +0200121 printf("\ttable[%d]:\t%s\t-> %s request_count %lu\n", idx, item->sessid,
122 item->serverid, item->request_count);
Willy Tarreau51041c72007-09-09 21:56:53 +0200123 }
124 }
125 printf(".\n");
126}
127#endif