/*
 * AppSession functions.
 *
 * Copyright 2004-2006 Alexander Lazic, Klaus Wagner
 * Copyright 2006-2007 Willy Tarreau
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 *
 */

#include <stdio.h>
#include <string.h>

#include <common/appsession.h>
#include <common/config.h>
#include <common/memory.h>
#include <common/sessionhash.h>
#include <common/ticks.h>
#include <common/time.h>

#include <types/buffers.h>
#include <types/global.h>
#include <types/proxy.h>
#include <types/server.h>

#include <proto/task.h>

static struct task *appsess_refresh = NULL;
struct pool_head *pool2_appsess;
struct app_pool apools;
int have_appsession;

int appsession_init(void)
{
	static int          initialized = 0;
	int                 idlen;
	struct server       *s;
	struct proxy        *p = proxy;
    
	if (!initialized) {
		pool2_appsess = create_pool("appsess", sizeof(appsess), MEM_F_SHARED);
		if (pool2_appsess == NULL)
			return -1;

		if (!appsession_task_init()) {
			int ser_msize, ses_msize;

			apools.sessid = NULL;
			apools.serverid = NULL;

			ser_msize = sizeof(void *);
			ses_msize = sizeof(void *);
			while (p) {
				s = p->srv;
				if (ses_msize < p->appsession_len)
					ses_msize = p->appsession_len;
				while (s) {
					idlen = strlen(s->id);
					if (ser_msize < idlen)
						ser_msize = idlen;
					s = s->next;
				}
				p = p->next;
			}
			/* we use strings, so reserve space for '\0' */
			ser_msize ++;
			ses_msize ++;

			apools.sessid = create_pool("sessid", ses_msize, MEM_F_SHARED);
			if (!apools.sessid)
				return -1;
			apools.serverid = create_pool("serverid", ser_msize, MEM_F_SHARED);
			if (!apools.serverid)
				return -1;
		}
		else {
			fprintf(stderr, "appsession_task_init failed\n");
			return -1;
		}
		initialized ++;
	}
	return 0;
}

int appsession_task_init(void)
{
	static int initialized = 0;
	if (!initialized) {
		if ((appsess_refresh = pool_alloc2(pool2_task)) == NULL)
			return -1;

		task_init(appsess_refresh);
		appsess_refresh->context = NULL;
		appsess_refresh->expire = tick_add(now_ms, MS_TO_TICKS(TBLCHKINT));
		appsess_refresh->process = appsession_refresh;
		task_queue(appsess_refresh);
		initialized ++;
	}
	return 0;
}

void appsession_refresh(struct task *t, int *next)
{
	struct proxy           *p = proxy;
	struct appsession_hash *htbl;
	appsess                *element, *back;
	int                    i;

	while (p) {
		if (p->appsession_name != NULL) {
			htbl = &p->htbl_proxy;
			as_hash_for_each_entry_safe(i, element, back, &p->htbl_proxy, hash_list) {
				if (tick_is_expired(element->expire, now_ms)) {
					if ((global.mode & MODE_DEBUG) &&
					    (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
						int len;
						/*
						  on Linux NULL pointers are caught by sprintf, on solaris -> segfault 
						*/
						len = sprintf(trash, "appsession_refresh: cleaning up expired Session '%s' on Server %s\n", 
							      element->sessid, element->serverid?element->serverid:"(null)");
						write(1, trash, len);
					}
					/* delete the expired element from within the hash table */
					LIST_DEL(&element->hash_list);
					htbl->destroy(element);
				}/* end if (tv_isle(&asession->expire, &now)) */
			}
		}
		p = p->next;
	}
	t->expire = tick_add(now_ms, MS_TO_TICKS(TBLCHKINT)); /* check expiration every 5 seconds */
	task_queue(t);
	*next = t->expire;
} /* end appsession_refresh */

int match_str(const void *key1, const void *key2)
{
    appsess *temp1,*temp2;
    temp1 = (appsess *)key1;
    temp2 = (appsess *)key2;

    //fprintf(stdout,">>>>>>>>>>>>>>temp1->sessid :%s:\n",temp1->sessid);
    //fprintf(stdout,">>>>>>>>>>>>>>temp2->sessid :%s:\n",temp2->sessid);
  
    return (strcmp(temp1->sessid,temp2->sessid) == 0);
}/* end match_str */

void destroy(appsess *temp1) {
    if (temp1->sessid)
	pool_free2(apools.sessid, temp1->sessid);

    if (temp1->serverid)
	pool_free2(apools.serverid, temp1->serverid);

    pool_free2(pool2_appsess, temp1);
} /* end destroy */

void appsession_cleanup( void )
{
	struct proxy *p = proxy;

	while(p) {
		appsession_hash_destroy(&(p->htbl_proxy));
		p = p->next;
	}

	if (appsess_refresh) {
		task_delete(appsess_refresh);
		task_free(appsess_refresh);
		appsess_refresh = NULL;
	}

}/* end appsession_cleanup() */



/*
 * Local variables:
 *  c-indent-level: 8
 *  c-basic-offset: 8
 * End:
 */
