blob: d11fb195072b078da47f01dc75f9b396a2c333c3 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * AppSession functions.
3 *
4 * Copyright 2004-2006 Alexander Lazic, Klaus Wagner
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020014#include <string.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020015
Willy Tarreau2dd0d472006-06-29 17:53:05 +020016#include <common/appsession.h>
17#include <common/chtbl.h>
Willy Tarreaue3ba5f02006-06-29 18:54:54 +020018#include <common/config.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020019#include <common/list.h>
20#include <common/time.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020021
22#include <types/buffers.h>
23#include <types/global.h>
24#include <types/proxy.h>
25#include <types/server.h>
26
27#include <proto/task.h>
28
29
30void **pool_appsess = NULL;
31struct app_pool apools;
32int have_appsession;
33
34#if defined(DEBUG_HASH)
35void print_table(const CHTbl *htbl)
36{
37 ListElmt *element;
38 int i;
39 appsess *asession;
40
41 /*********************************************************************
42 * *
43 * Display the chained hash table. *
44 * *
45 *********************************************************************/
46
47 fprintf(stdout, "Table size is %d\n", chtbl_size(htbl));
48
49 for (i = 0; i < TBLSIZ; i++) {
50 fprintf(stdout, "Bucket[%03d]\n", i);
51
52 for (element = list_head(&htbl->table[i]);
53 element != NULL; element = list_next(element)) {
54 //fprintf(stdout, "%c", *(char *)list_data(element));
55 asession = (appsess *)list_data(element);
56 fprintf(stdout, "ELEM :%s:", asession->sessid);
57 fprintf(stdout, " Server :%s: \n", asession->serverid);
58 //fprintf(stdout, " Server request_count :%li:\n",asession->request_count);
59 }
60
61 fprintf(stdout, "\n");
62 }
63 return;
64} /* end print_table */
65#endif
66
67int appsession_init(void)
68{
69 static int initialized = 0;
70 int idlen;
71 struct server *s;
72 struct proxy *p = proxy;
73
74 if (!initialized) {
75 if (!appsession_task_init()) {
76 apools.sessid = NULL;
77 apools.serverid = NULL;
78 apools.ser_waste = 0;
79 apools.ser_use = 0;
80 apools.ser_msize = sizeof(void *);
81 apools.ses_waste = 0;
82 apools.ses_use = 0;
83 apools.ses_msize = sizeof(void *);
84 while (p) {
85 s = p->srv;
86 if (apools.ses_msize < p->appsession_len)
87 apools.ses_msize = p->appsession_len;
88 while (s) {
89 idlen = strlen(s->id);
90 if (apools.ser_msize < idlen)
91 apools.ser_msize = idlen;
92 s = s->next;
93 }
94 p = p->next;
95 }
96 /* we use strings, so reserve space for '\0' */
97 apools.ser_msize ++;
98 apools.ses_msize ++;
99 }
100 else {
101 fprintf(stderr, "appsession_task_init failed\n");
102 return -1;
103 }
104 initialized ++;
105 }
106 return 0;
107}
108
109int appsession_task_init(void)
110{
111 static int initialized = 0;
112 struct task *t;
113 if (!initialized) {
114 if ((t = pool_alloc(task)) == NULL)
115 return -1;
Willy Tarreau964c9362007-01-07 00:38:00 +0100116 t->wq = NULL;
Willy Tarreau96bcfd72007-04-29 10:41:56 +0200117 t->qlist.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200118 t->state = TASK_IDLE;
119 t->context = NULL;
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200120 tv_ms_add(&t->expire, &now, TBLCHKINT);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200121 task_queue(t);
122 t->process = appsession_refresh;
123 initialized ++;
124 }
125 return 0;
126}
127
128int appsession_refresh(struct task *t)
129{
130 struct proxy *p = proxy;
131 CHTbl *htbl;
132 ListElmt *element, *last;
133 int i;
134 appsess *asession;
135 void *data;
136
137 while (p) {
138 if (p->appsession_name != NULL) {
139 htbl = &p->htbl_proxy;
140 /* if we ever give up the use of TBLSIZ, we need to change this */
141 for (i = 0; i < TBLSIZ; i++) {
142 last = NULL;
143 for (element = list_head(&htbl->table[i]);
144 element != NULL; element = list_next(element)) {
145 asession = (appsess *)list_data(element);
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200146 if (tv_ms_le2(&asession->expire, &now)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200147 if ((global.mode & MODE_DEBUG) &&
148 (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
149 int len;
150 /*
151 on Linux NULL pointers are catched by sprintf, on solaris -> segfault
152 */
153 len = sprintf(trash, "appsession_refresh: cleaning up expired Session '%s' on Server %s\n",
154 asession->sessid, asession->serverid?asession->serverid:"(null)");
155 write(1, trash, len);
156 }
157 /* delete the expired element from within the hash table */
158 if ((list_rem_next(&htbl->table[i], last, (void **)&data) == 0)
159 && (htbl->table[i].destroy != NULL)) {
160 htbl->table[i].destroy(data);
161 }
162 if (last == NULL) {/* patient lost his head, get a new one */
163 element = list_head(&htbl->table[i]);
164 if (element == NULL) break; /* no heads left, go to next patient */
165 }
166 else
167 element = last;
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200168 }/* end if (tv_ms_le2(&asession->expire, &now)) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200169 else
170 last = element;
171 }/* end for (element = list_head(&htbl->table[i]); element != NULL; element = list_next(element)) */
172 }
173 }
174 p = p->next;
175 }
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200176 tv_ms_add(&t->expire, &now, TBLCHKINT); /* check expiration every 5 seconds */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177 return TBLCHKINT;
178} /* end appsession_refresh */
179
180int match_str(const void *key1, const void *key2)
181{
182 appsess *temp1,*temp2;
183 temp1 = (appsess *)key1;
184 temp2 = (appsess *)key2;
185
186 //fprintf(stdout,">>>>>>>>>>>>>>temp1->sessid :%s:\n",temp1->sessid);
187 //fprintf(stdout,">>>>>>>>>>>>>>temp2->sessid :%s:\n",temp2->sessid);
188
189 return (strcmp(temp1->sessid,temp2->sessid) == 0);
190}/* end match_str */
191
192void destroy(void *data) {
193 appsess *temp1;
194
195 //printf("destroy called\n");
196 temp1 = (appsess *)data;
197
198 if (temp1->sessid)
199 pool_free_to(apools.sessid, temp1->sessid);
200
201 if (temp1->serverid)
202 pool_free_to(apools.serverid, temp1->serverid);
203
204 pool_free(appsess, temp1);
205} /* end destroy */
206
207void appsession_cleanup( void )
208{
209 struct proxy *p = proxy;
210
211 while(p) {
212 chtbl_destroy(&(p->htbl_proxy));
213 p = p->next;
214 }
215}/* end appsession_cleanup() */
216
217
218
219/*
220 * Local variables:
221 * c-indent-level: 8
222 * c-basic-offset: 8
223 * End:
224 */