#include "dualsrv_pub.h"

extern int ems_debug_flag;
extern char debug_message[MAX_ASCOUT_BUF_LEN];

_sync_hb sync_hb;
extern _config_info config_info;
extern _config_info other_config_info;
int dual_status;
unsigned int dual_timeout;
unsigned int EMS_HB_OID[12]={1,3,6,1,4,1,1373,2,4,1,0};
int EMS_DUAL_OID_OIDLEN=11;
static int check_proc_status_timeout=0;
static int upgrade_to_master_timeout=0;
static int degrade_to_slave_timeout=0;

/* by simon at 23/9/26 */
struct timeval starttime, endtime;
int nouse;

int dualsrv_init()
{
	debug_log("dualsrv is starting ......");

	dualsrv_debug_init();
	inquire_trapmsg(receive_trap_message);	
	
	memset(&sync_hb,0,sizeof(sync_hb));
	memset(&config_info,0,sizeof(_config_info));

	read_conf_file();
	read_server_conf();
	
	if(config_info.run_mode == RUN_MODE_SINGLE)	
	{
		dual_status=DUAL_STATE_SINGLE;
	}
	else
	{
		if(config_info.sys_no == PLAT_0)
		{
			dual_status=DUAL_STATE_MASTER;
		}
		else
		{
			dual_status=DUAL_STATE_SLAVE;
		}
	}
	report_status();

	return 1;
}

int dualsrv_timer()
{
	
	dualsrv_debug_timer();
	
	if(check_proc_status_timeout++ >= TEN_SECOND_COUNT)
	{
		check_proc_status_timeout=0;
		check_proc_status();
	}
	
	switch(dual_status)
	{
	case DUAL_STATE_SINGLE:
		break;
	case DUAL_STATE_MASTER:
		if(config_info.sys_no == PLAT_1)
		{
			if(degrade_to_slave_timeout <= 0)
			{
				debug_log("Have received HB from EMS-0, degrade to slave");
				degrade_to_slave_timeout=0;
				dual_status=DUAL_STATE_SLAVE;
				upgrade_to_master_timeout=0;
				report_status();
			}
		}
		
		break;
	case DUAL_STATE_SLAVE:
		if(config_info.sys_no == PLAT_1)
		{
			if(upgrade_to_master_timeout++ >= ONE_MINUTE_COUNT)
			{
				debug_log("Can not receive HB from EMS-0 for 1 minute, upgrade to master");
				upgrade_to_master_timeout=0;
				dual_status=DUAL_STATE_MASTER;
				degrade_to_slave_timeout=DEGRADE_HB_COUNT;
				report_status();
			}
		}
		
		break;
	}
	if(dual_status == DUAL_STATE_MASTER)
		return 1;
	else
		return 0;
}

void receive_trap_message(BYTE oidlen,DWORD* oid,BYTE* pdata,WORD len,snmp_addr * addr)
{
	int i;
	
	for(i=0;i<11;i++)
	{
		if(oid[i] != EMS_HB_OID[i])
			return;
	}
	
	if(addr->remote_ip == other_config_info.ip)
	{
		if(config_info.sys_no == PLAT_1)
		{
			if(dual_status == DUAL_STATE_SLAVE)
			{
				upgrade_to_master_timeout=0;
			}
			else if(dual_status == DUAL_STATE_MASTER)
			{
				degrade_to_slave_timeout--;
				if(degrade_to_slave_timeout<0)
					degrade_to_slave_timeout=0;
			}
		}
		
		
		//printf("recv %08lX %08lX\n",addr->local_ip,addr->remote_ip);
	}
}


void check_proc_status()
{
	unsigned char procstatus[64];
	unsigned char rb;
	int procnum;
	FILE *handle;
	
	memset(procstatus,0,64);
	handle=fopen("./dual/procstatus","r");
	if(!handle)
	{
		debug_log("[WARNING]porcstatus file not exist, will try later");
		return;
	}
	procnum=0;
	while(fread(&rb,1,1,handle) == 1)
	{
		procstatus[procnum]=rb-'0';
		if(procstatus[procnum] == 218)
			break;
		procnum++;
	}
	fclose(handle);
	fillProcStatus(procnum,procstatus);
}

void report_status()
{
	FILE *handle;
	char statestr[32];
	
	switch(dual_status)
	{
	case DUAL_STATE_SINGLE:
		debug_log("Change to SINGLE");
		sprintf(statestr,"State=Single");
		break;
	case DUAL_STATE_MASTER:
		debug_log("Change to MASTER");
		sprintf(statestr,"State=Master");
		break;
	case DUAL_STATE_SLAVE:
		debug_log("Change to SLAVE");
		sprintf(statestr,"State=Slave");
		break;
	default:
		debug_log("[ERROR]Change to unknown state, change to MASTER");
		dual_status=DUAL_STATE_MASTER;
		sprintf(statestr,"State=Master");
		break;
	}
	chOmcStatus(dual_status);
	
	
	handle=fopen("./dual/dualstate","w");
	if(!handle)
	{
		debug_log("[ERROR]Can not open file dualstate, please check the disk space");
		exit(1);
	}
	fwrite(statestr,strlen(statestr),1,handle);
	fclose(handle);
}

