blob: 50554a50d07e2f064b12b787505e74728a6dc21a [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * AppSession functions.
3 *
4 * Copyright 2004-2006 Alexander Lazic, Klaus Wagner
Willy Tarreau63963c62007-05-13 21:29:55 +02005 * Copyright 2006-2007 Willy Tarreau
Willy Tarreaubaaee002006-06-26 02:48:02 +02006 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 *
12 */
13
14#include <stdio.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020015#include <string.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020016
Willy Tarreau2dd0d472006-06-29 17:53:05 +020017#include <common/appsession.h>
18#include <common/chtbl.h>
Willy Tarreaue3ba5f02006-06-29 18:54:54 +020019#include <common/config.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020020#include <common/list.h>
Willy Tarreau63963c62007-05-13 21:29:55 +020021#include <common/memory.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020022#include <common/time.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020023
24#include <types/buffers.h>
25#include <types/global.h>
26#include <types/proxy.h>
27#include <types/server.h>
28
29#include <proto/task.h>
30
31
Willy Tarreau63963c62007-05-13 21:29:55 +020032struct pool_head *pool2_appsess;
Willy Tarreaubaaee002006-06-26 02:48:02 +020033struct app_pool apools;
34int have_appsession;
35
36#if defined(DEBUG_HASH)
37void print_table(const CHTbl *htbl)
38{
39 ListElmt *element;
40 int i;
41 appsess *asession;
42
43 /*********************************************************************
44 * *
45 * Display the chained hash table. *
46 * *
47 *********************************************************************/
48
49 fprintf(stdout, "Table size is %d\n", chtbl_size(htbl));
50
51 for (i = 0; i < TBLSIZ; i++) {
52 fprintf(stdout, "Bucket[%03d]\n", i);
53
54 for (element = list_head(&htbl->table[i]);
55 element != NULL; element = list_next(element)) {
56 //fprintf(stdout, "%c", *(char *)list_data(element));
57 asession = (appsess *)list_data(element);
58 fprintf(stdout, "ELEM :%s:", asession->sessid);
59 fprintf(stdout, " Server :%s: \n", asession->serverid);
60 //fprintf(stdout, " Server request_count :%li:\n",asession->request_count);
61 }
62
63 fprintf(stdout, "\n");
64 }
65 return;
66} /* end print_table */
67#endif
68
69int appsession_init(void)
70{
71 static int initialized = 0;
72 int idlen;
73 struct server *s;
74 struct proxy *p = proxy;
75
76 if (!initialized) {
Willy Tarreau63963c62007-05-13 21:29:55 +020077 pool2_appsess = create_pool("appsess", sizeof(appsess), MEM_F_SHARED);
78 if (pool2_appsess == NULL)
79 return -1;
80
Willy Tarreaubaaee002006-06-26 02:48:02 +020081 if (!appsession_task_init()) {
Willy Tarreau63963c62007-05-13 21:29:55 +020082 int ser_msize, ses_msize;
83
Willy Tarreaubaaee002006-06-26 02:48:02 +020084 apools.sessid = NULL;
85 apools.serverid = NULL;
Willy Tarreau63963c62007-05-13 21:29:55 +020086
87 ser_msize = sizeof(void *);
88 ses_msize = sizeof(void *);
Willy Tarreaubaaee002006-06-26 02:48:02 +020089 while (p) {
90 s = p->srv;
Willy Tarreau63963c62007-05-13 21:29:55 +020091 if (ses_msize < p->appsession_len)
92 ses_msize = p->appsession_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +020093 while (s) {
94 idlen = strlen(s->id);
Willy Tarreau63963c62007-05-13 21:29:55 +020095 if (ser_msize < idlen)
96 ser_msize = idlen;
Willy Tarreaubaaee002006-06-26 02:48:02 +020097 s = s->next;
98 }
99 p = p->next;
100 }
101 /* we use strings, so reserve space for '\0' */
Willy Tarreau63963c62007-05-13 21:29:55 +0200102 ser_msize ++;
103 ses_msize ++;
104
105 apools.sessid = create_pool("sessid", ses_msize, MEM_F_SHARED);
106 if (!apools.sessid)
107 return -1;
108 apools.serverid = create_pool("serverid", ser_msize, MEM_F_SHARED);
109 if (!apools.serverid)
110 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200111 }
112 else {
113 fprintf(stderr, "appsession_task_init failed\n");
114 return -1;
115 }
116 initialized ++;
117 }
118 return 0;
119}
120
121int appsession_task_init(void)
122{
123 static int initialized = 0;
124 struct task *t;
125 if (!initialized) {
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200126 if ((t = pool_alloc2(pool2_task)) == NULL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200127 return -1;
Willy Tarreau964c9362007-01-07 00:38:00 +0100128 t->wq = NULL;
Willy Tarreau96bcfd72007-04-29 10:41:56 +0200129 t->qlist.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200130 t->state = TASK_IDLE;
131 t->context = NULL;
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200132 tv_ms_add(&t->expire, &now, TBLCHKINT);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200133 t->process = appsession_refresh;
Willy Tarreau63963c62007-05-13 21:29:55 +0200134 task_queue(t);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200135 initialized ++;
136 }
137 return 0;
138}
139
Willy Tarreaud825eef2007-05-12 22:35:00 +0200140void appsession_refresh(struct task *t, struct timeval *next)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200141{
142 struct proxy *p = proxy;
143 CHTbl *htbl;
144 ListElmt *element, *last;
145 int i;
146 appsess *asession;
147 void *data;
148
149 while (p) {
150 if (p->appsession_name != NULL) {
151 htbl = &p->htbl_proxy;
152 /* if we ever give up the use of TBLSIZ, we need to change this */
153 for (i = 0; i < TBLSIZ; i++) {
154 last = NULL;
155 for (element = list_head(&htbl->table[i]);
156 element != NULL; element = list_next(element)) {
157 asession = (appsess *)list_data(element);
Willy Tarreaua8b55e32007-05-13 16:08:19 +0200158 if (tv_isle(&asession->expire, &now)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200159 if ((global.mode & MODE_DEBUG) &&
160 (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
161 int len;
162 /*
163 on Linux NULL pointers are catched by sprintf, on solaris -> segfault
164 */
165 len = sprintf(trash, "appsession_refresh: cleaning up expired Session '%s' on Server %s\n",
166 asession->sessid, asession->serverid?asession->serverid:"(null)");
167 write(1, trash, len);
168 }
169 /* delete the expired element from within the hash table */
170 if ((list_rem_next(&htbl->table[i], last, (void **)&data) == 0)
171 && (htbl->table[i].destroy != NULL)) {
172 htbl->table[i].destroy(data);
173 }
174 if (last == NULL) {/* patient lost his head, get a new one */
175 element = list_head(&htbl->table[i]);
176 if (element == NULL) break; /* no heads left, go to next patient */
177 }
178 else
179 element = last;
Willy Tarreaua8b55e32007-05-13 16:08:19 +0200180 }/* end if (tv_isle(&asession->expire, &now)) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200181 else
182 last = element;
183 }/* end for (element = list_head(&htbl->table[i]); element != NULL; element = list_next(element)) */
184 }
185 }
186 p = p->next;
187 }
Willy Tarreau42aae5c2007-04-29 17:43:56 +0200188 tv_ms_add(&t->expire, &now, TBLCHKINT); /* check expiration every 5 seconds */
Willy Tarreau63963c62007-05-13 21:29:55 +0200189 task_queue(t);
Willy Tarreaud825eef2007-05-12 22:35:00 +0200190 *next = t->expire;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200191} /* end appsession_refresh */
192
193int match_str(const void *key1, const void *key2)
194{
195 appsess *temp1,*temp2;
196 temp1 = (appsess *)key1;
197 temp2 = (appsess *)key2;
198
199 //fprintf(stdout,">>>>>>>>>>>>>>temp1->sessid :%s:\n",temp1->sessid);
200 //fprintf(stdout,">>>>>>>>>>>>>>temp2->sessid :%s:\n",temp2->sessid);
201
202 return (strcmp(temp1->sessid,temp2->sessid) == 0);
203}/* end match_str */
204
205void destroy(void *data) {
206 appsess *temp1;
207
208 //printf("destroy called\n");
209 temp1 = (appsess *)data;
210
211 if (temp1->sessid)
Willy Tarreau63963c62007-05-13 21:29:55 +0200212 pool_free2(apools.sessid, temp1->sessid);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200213
214 if (temp1->serverid)
Willy Tarreau63963c62007-05-13 21:29:55 +0200215 pool_free2(apools.serverid, temp1->serverid);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200216
Willy Tarreau63963c62007-05-13 21:29:55 +0200217 pool_free2(pool2_appsess, temp1);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200218} /* end destroy */
219
220void appsession_cleanup( void )
221{
222 struct proxy *p = proxy;
223
224 while(p) {
225 chtbl_destroy(&(p->htbl_proxy));
226 p = p->next;
227 }
228}/* end appsession_cleanup() */
229
230
231
232/*
233 * Local variables:
234 * c-indent-level: 8
235 * c-basic-offset: 8
236 * End:
237 */