File: sessionhash.c

package info (click to toggle)
haproxy 1.5.8-3
  • links: PTS, VCS
  • area: main
  • in suites: jessie-kfreebsd
  • size: 7,732 kB
  • sloc: ansic: 62,860; xml: 1,754; python: 925; makefile: 551; perl: 550; sh: 491
file content (127 lines) | stat: -rw-r--r-- 2,767 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*
 * 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 DEBUG_HASH
#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;

	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