#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <glib.h>
#include <sys/time.h>
#include <time.h>


typedef unsigned char  u8;
typedef unsigned int   u32;
typedef unsigned short u16;

#define PLAN_RECORDS  60000
#define INVALID_PLAN_INDEX 0xFFFFFFFF

typedef struct plan_record
{
	u32	index;
	u8	used_flag;
	u32 plan_id;
	u32	updated_time;	
}__attribute__((packed)) _plan_record;

typedef struct plan_table
{
    u32    record_num;
    u32    cur_index;
    _plan_record  plan_record[PLAN_RECORDS+1];	
}__attribute__((packed)) _plan_table;

/* ------------ Variables --------------*/
static GHashTable *htb_plan = NULL;  

static _plan_table  plan_table;

extern struct timeval tv;

/* ------------ resouce functions --------------*/

void free_mem(gpointer data)
{
	free(data);
}

int crm_pxy_init_hash_table()
{

	if(htb_plan != NULL)
		g_hash_table_destroy(htb_plan);
    
	htb_plan = g_hash_table_new(g_direct_hash,g_direct_equal);
	
	return 1;	
}


int hash_add_plan_entity(_plan_record *plan_ptr)
{
	if(plan_ptr != NULL)
		g_hash_table_insert(htb_plan, GINT_TO_POINTER(plan_ptr->plan_id), plan_ptr);
    
	return 1;
}

int hash_clean_plan_entity(_plan_record *plan_ptr)
{
	if(plan_ptr != NULL)    
		g_hash_table_remove(htb_plan, GINT_TO_POINTER(plan_ptr->plan_id));
    
	return 1;
}

int crm_pxy_get_plan_index(u32 plan_id)
{
	u32 index = INVALID_PLAN_INDEX;
	_plan_record *ptr=NULL;
  	
	ptr = (_plan_record *)g_hash_table_lookup(htb_plan, GINT_TO_POINTER(plan_id));
	if(ptr != NULL)
		index = ptr->index;
        
	return index;
}

int crm_pxy_get_plan_record(u32 plan_id, _plan_record *plan_ptr)
{
	u32 index = crm_pxy_get_plan_index(plan_id);

	return index;
	
	if(index != INVALID_PLAN_INDEX)
	{
		plan_ptr = &plan_table.plan_record[index];
		return 1;
	}
	
	return 0;
}

_plan_record *crm_pxy_assign_plan_index(u32 plan_id)
{
	register int loop;
	int	index;
	_plan_record *plan_ptr;
	
	for(loop = 0; loop < PLAN_RECORDS; loop++)
	{
		index = plan_table.cur_index++;
		plan_table.cur_index %= PLAN_RECORDS;
		if(plan_table.plan_record[index].used_flag == 0)
		{
			plan_table.record_num ++;
			
			plan_ptr = &plan_table.plan_record[index];
			plan_ptr->used_flag = 1;
			plan_ptr->index = index;
			plan_ptr->plan_id = plan_id;
			plan_ptr->updated_time = tv.tv_sec;
			return plan_ptr;
		}
	}
	
	return NULL;
}

int	crm_pxy_purge_plan_record(_plan_record *plan_ptr)
{

	hash_clean_plan_entity(plan_ptr);

	plan_ptr->used_flag = 0;
	plan_table.record_num --;
	
	return 1;
}

int	crm_pxy_add_plan_record(u32 plan_id)
{
	_plan_record *plan_ptr = NULL;
	
	plan_ptr = crm_pxy_assign_plan_index(plan_id);
	
	if(plan_ptr == NULL)
		return 0;
	
	hash_add_plan_entity(plan_ptr);
		
	return 1;
}

int crm_pxy_check_plan_record(u32 plan_id)
{
	u32 index = crm_pxy_get_plan_index(plan_id);
	
	if(index != INVALID_PLAN_INDEX)
	{
		return 1;
	}
	
	return 0;

}

void crm_pxy_plan_record_init()
{
	crm_pxy_init_hash_table();
}

static int EXPIRED_TIME_SEC = (86400)*(15);

void crm_pxy_plan_record_timer()
{
	static int crm_pxy_scan_ptr=0;
	int i;
	_plan_record *plan_ptr = NULL;
	
	for(i=0; i<1000; i++)
	{
		plan_ptr = &plan_table.plan_record[crm_pxy_scan_ptr++];
		crm_pxy_scan_ptr %= PLAN_RECORDS;
		
		if(plan_ptr->used_flag == 1)
		{
			if((plan_ptr->updated_time + EXPIRED_TIME_SEC)<tv.tv_sec) 
				hash_clean_plan_entity(plan_ptr);
		}
	}
}