/*
 * AppSession functions.
 *
 * Copyright 2004-2006 Alexander Lazic, Klaus Wagner
 *
 * 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/chtbl.h>
#include <common/config.h>
#include <common/list.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>


void **pool_appsess = NULL;
struct app_pool apools;
int have_appsession;

#if defined(DEBUG_HASH)
void print_table(const CHTbl *htbl)
{
	ListElmt           *element;
	int                i;
	appsess *asession;

	/*********************************************************************
	 *                                                                    *
	 *  Display the chained hash table.                                   *
	 *                                                                    *
	 *********************************************************************/
    
	fprintf(stdout, "Table size is %d\n", chtbl_size(htbl));
    
	for (i = 0; i < TBLSIZ; i++) {
		fprintf(stdout, "Bucket[%03d]\n", i);
	
		for (element = list_head(&htbl->table[i]);
		     element != NULL; element = list_next(element)) {
			//fprintf(stdout, "%c", *(char *)list_data(element));
			asession = (appsess *)list_data(element);
			fprintf(stdout, "ELEM :%s:", asession->sessid);
			fprintf(stdout, " Server :%s: \n", asession->serverid);
			//fprintf(stdout, " Server request_count :%li:\n",asession->request_count);
		}
	
		fprintf(stdout, "\n");
	}
	return;
} /* end print_table */
#endif

int appsession_init(void)
{
	static int          initialized = 0;
	int                 idlen;
	struct server       *s;
	struct proxy        *p = proxy;
    
	if (!initialized) {
		if (!appsession_task_init()) {
			apools.sessid = NULL;
			apools.serverid = NULL;
			apools.ser_waste = 0;
			apools.ser_use = 0;
			apools.ser_msize = sizeof(void *);
			apools.ses_waste = 0;
			apools.ses_use = 0;
			apools.ses_msize = sizeof(void *);
			while (p) {
				s = p->srv;
				if (apools.ses_msize < p->appsession_len)
					apools.ses_msize = p->appsession_len;
				while (s) {
					idlen = strlen(s->id);
					if (apools.ser_msize < idlen)
						apools.ser_msize = idlen;
					s = s->next;
				}
				p = p->next;
			}
			/* we use strings, so reserve space for '\0' */
			apools.ser_msize ++;
			apools.ses_msize ++;
		}
		else {
			fprintf(stderr, "appsession_task_init failed\n");
			return -1;
		}
		initialized ++;
	}
	return 0;
}

int appsession_task_init(void)
{
	static int initialized = 0;
	struct task *t;
	if (!initialized) {
		if ((t = pool_alloc(task)) == NULL)
			return -1;
		t->wq = NULL;
		t->qlist.p = NULL;
		t->state = TASK_IDLE;
		t->context = NULL;
		tv_ms_add(&t->expire, &now, TBLCHKINT);
		task_queue(t);
		t->process = appsession_refresh;
		initialized ++;
	}
	return 0;
}

int appsession_refresh(struct task *t)
{
	struct proxy       *p = proxy;
	CHTbl              *htbl;
	ListElmt           *element, *last;
	int                i;
	appsess            *asession;
	void               *data;

	while (p) {
		if (p->appsession_name != NULL) {
			htbl = &p->htbl_proxy;
			/* if we ever give up the use of TBLSIZ, we need to change this */
			for (i = 0; i < TBLSIZ; i++) {
				last = NULL;
				for (element = list_head(&htbl->table[i]);
				     element != NULL; element = list_next(element)) {
					asession = (appsess *)list_data(element);
					if (tv_ms_le2(&asession->expire, &now)) {
						if ((global.mode & MODE_DEBUG) &&
						    (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
							int len;
							/*
							  on Linux NULL pointers are catched by sprintf, on solaris -> segfault 
							*/
							len = sprintf(trash, "appsession_refresh: cleaning up expired Session '%s' on Server %s\n", 
								      asession->sessid,  asession->serverid?asession->serverid:"(null)");
							write(1, trash, len);
						}
						/* delete the expired element from within the hash table */
						if ((list_rem_next(&htbl->table[i], last, (void **)&data) == 0)
						    && (htbl->table[i].destroy != NULL)) {
							htbl->table[i].destroy(data);
						}
						if (last == NULL) {/* patient lost his head, get a new one */
							element = list_head(&htbl->table[i]);
							if (element == NULL) break; /* no heads left, go to next patient */
						}
						else
							element = last;
					}/* end if (tv_ms_le2(&asession->expire, &now)) */
					else
						last = element;
				}/* end  for (element = list_head(&htbl->table[i]); element != NULL; element = list_next(element)) */
			}
		}
		p = p->next;
	}
	tv_ms_add(&t->expire, &now, TBLCHKINT); /* check expiration every 5 seconds */
	return TBLCHKINT;
} /* 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(void *data) {
    appsess *temp1;

    //printf("destroy called\n");
    temp1 = (appsess *)data;

    if (temp1->sessid)
	pool_free_to(apools.sessid, temp1->sessid);

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

    pool_free(appsess, temp1);
} /* end destroy */

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

	while(p) {
		chtbl_destroy(&(p->htbl_proxy));
		p = p->next;
	}
}/* end appsession_cleanup() */



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