#include "raid_agent.h"

static int getline_local(FILE *handle,char *line,int max_size);
static int read_conffile();
static void system_timer(raid_server *pserver,raid_system *psys);
static int recv_raid_response();
static int make_pdu(int type,raid_server *pserver,raid_system *psys,snmp_pdu *pdu);
static int make_addr(raid_system *psys,snmp_addr *addr);
static int pdu_analyze(snmp_pdu *pdu);
static int store_status(snmp_pdu *pdu,raid_server *pserver,raid_system *psys);
static int record_status(int sysTypeNo,int sysNo,int instance,char *fieldName,char *fieldValue);
static int operate_record(char *db,char *tb,char *sqlstr);
static int decode_int(int msglen,unsigned char *msg,int *out);
static int decode_string(int msglen,unsigned char *msg,char *out);
static int analyze_alarm(int alarm_id,int sysNo,int disk_index);
static int analyze_alarm_id(raid_server *pserver);
static int operate_alarm(int opt,int compCode,int alarmCode);

int raid_update_system();
int check_raid_function_flag();
//-------------- Intel ---------------------------
//summary
unsigned long I_CARDNAME_OID[]={1,3,6,1,4,1,3582,4,1,4,1,3,1,12,0};
int I_CARDNAME_OIDLEN=15;
unsigned long I_DISKNUM_OID[]={1,3,6,1,4,1,3582,4,1,4,2,1,1,0};
int I_DISKNUM_OIDLEN=14;
//detail
unsigned long I_DISKSLOT_POID[]={1,3,6,1,4,1,3582,4,1,4,2,1,2,1,2};
int I_DISKSLOT_POIDLEN=15;
unsigned long I_DISKSTATE_POID[]={1,3,6,1,4,1,3582,4,1,4,2,1,2,1,10};
int I_DISKSTATE_POIDLEN=15;
unsigned long I_OPTPROC_POID[]={1,3,6,1,4,1,3582,4,1,4,2,1,2,1,21};
int I_OPTPROC_POIDLEN=15;
unsigned long I_VENID_POID[]={1,3,6,1,4,1,3582,4,1,4,2,1,2,1,24};
int I_VENID_POIDLEN=15;
unsigned long I_PROID_POID[]={1,3,6,1,4,1,3582,4,1,4,2,1,2,1,25};
int I_PROID_POIDLEN=15;
unsigned long I_DISKSIZE_POID[]={1,3,6,1,4,1,3582,4,1,4,2,1,2,1,15};
int I_DISKSIZE_POIDLEN=15;
unsigned long I_DISKERRORCOUNT_POID[]={1,3,6,1,4,1,3582,4,1,4,2,1,2,1,7};
int I_DISKERRORCOUNT_POIDLEN=15;
//--------------- Dell --------------------------
//summary
unsigned long D_CARDNAME_OID[]={1,3,6,1,4,1,674,10893,1,20,130,1,1,2,0};
int D_CARDNAME_OIDLEN=15;
unsigned long D_DISKNUM_OID[]={1,3,6,1,4,1,674,10893,1,20,130,1,1,11,0};
int D_DISKNUM_OIDLEN=15;
//detail
unsigned long D_DISKSLOT_POID[]={1,3,6,1,4,1,674,10893,1,20,130,4,1,2};
int D_DISKSLOT_POIDLEN=14;
unsigned long D_DISKSTATE_POID[]={1,3,6,1,4,1,674,10893,1.20,130,4,1,4};
int D_DISKSTATE_POIDLEN=15;
unsigned long D_VENID_POID[]={1,3,6,1,4,1,674,10893,1,20,130,4,1,3};
int D_VENID_POIDLEN=14;
unsigned long D_PROID_POID[]={1,3,6,1,4,1,674,10893,1,20,130,4,1,7};
int D_PROID_POIDLEN=14;
unsigned long D_DISKSIZE_POID[]={1,3,6,1,4,1,674,10893,1,20,130,4,1,11};
int D_DISKSIZE_POIDLEN=14;

raid_param raidParam;
int raidSysNo;

int raid_agent_init(int omcSysNo)
{
	logRaid("raidAgent is starting ...");
	raidSysNo=omcSysNo;
	
	read_conffile();
	raid_agent_task_init();
	raidParam.enable_flag=check_raid_function_flag();
	if(!raidParam.enable_flag)
		logRaid("raid service is closed");
	return 1;
}

void raid_agent_timer()
{
	int i,j;

	if(!raidParam.enable_flag)
		return;

	for(i=0;i<raidParam.server_count;i++)
	{
		if(!raidParam.server[i].enable_flag)
			continue;
		for(j=0;j<raidParam.server[i].system_count;j++)
		{
			system_timer(&raidParam.server[i],&raidParam.server[i].system[j]);
		}
	}
	recv_raid_response();
	raid_agent_task_timer();
}

void system_timer(raid_server *pserver,raid_system *psys)
{
	unsigned long cur_time;
	snmp_pdu pdu;
	snmp_addr addr;

	cur_time=time(NULL);

#if RAIDAGENT_DEBUG
static int pre_state;
if(pserver->related_system_type == 320)
{
	if(pre_state != psys->state)
	{
		if(psys->state == STATE_IDLE)
			logRaid("omc system become STATE_IDLE");
		else if(psys->state == STATE_GET_SUMMARY)
			logRaid("omc system become STATE_GET_SUMMARY");
		else if(psys->state == STATE_RESPONSE_SUMMARY)
			logRaid("omc system become STATE_RESPONSE_SUMMARY");
		else if(psys->state == STATE_GET_DETAIL)
			logRaid("omc system become STATE_GET_DETAIL");
		else if(psys->state == STATE_RESPONSE_DETAIL)
			logRaid("omc system become STATE_RESPONSE_DETAIL");
		else if(psys->state == STATE_FINISH)
			logRaid("omc system become STATE_FINISH");
	}
	pre_state=psys->state;
}
#endif

	//printf("%d,state=%d\n",pserver->related_system_type,psys->state);
	
	
	switch(psys->state)
	{
	case STATE_IDLE:
		if(cur_time - psys->last_update_time > GET_STATUS_INTERVAL)
		{
			psys->last_update_time=cur_time;
			psys->state=STATE_GET_SUMMARY;
		}
		break;
	case STATE_GET_SUMMARY:
		make_pdu(PDU_SUMMARG,pserver,psys,&pdu);
		make_addr(psys,&addr);
		psys->request_id=snmp_send(&pdu,&addr);
		psys->state=STATE_RESPONSE_SUMMARY;
		psys->timeout=cur_time;
		break;
	case STATE_RESPONSE_SUMMARY:
		if(cur_time - psys->timeout > RESPONSE_TIMEOUT)
		{
			logRaid("Response timeout when get summary,%s-%d",pserver->server_name,psys->sys_id);
			psys->state=STATE_FINISH;
			if(psys->last_alarm_value[psys->cur_disk_num] != ALARM_RESPONSE_TIMEOUT)
			{
				psys->last_alarm_value[psys->cur_disk_num]=ALARM_RESPONSE_TIMEOUT;
				operate_alarm(ALARM_ADD,analyze_alarm(analyze_alarm_id(pserver),psys->sys_id,9),ALARM_RESPONSE_TIMEOUT);
				logRaid("Response timeout when get summary,add alarm,%s-%d",pserver->server_name,psys->sys_id);
			}
		}
		break;
	case STATE_GET_DETAIL:
		make_pdu(PDU_DETAIL,pserver,psys,&pdu);
		make_addr(psys,&addr);
		psys->request_id=snmp_send(&pdu,&addr);
		psys->state=STATE_RESPONSE_DETAIL;
		psys->timeout=cur_time;
		break;
	case STATE_RESPONSE_DETAIL:
		if(cur_time - psys->timeout > RESPONSE_TIMEOUT)
		{
			psys->state=STATE_FINISH;
			if(psys->last_alarm_value[psys->cur_disk_num] != ALARM_RESPONSE_TIMEOUT)
			{
				psys->last_alarm_value[psys->cur_disk_num]=ALARM_RESPONSE_TIMEOUT;
				operate_alarm(ALARM_ADD,analyze_alarm(analyze_alarm_id(pserver),psys->sys_id,psys->cur_disk_num),ALARM_RESPONSE_TIMEOUT);
				logRaid("Response timeout when get detail");
			}
		}
		break;
	case STATE_FINISH:
		psys->cur_disk_num=0;
		psys->state=STATE_IDLE;
		break;
	}
	
}

/*
return 
1-open, 0-close
*/
int check_raid_function_flag()
{
	MYSQL *dbConn;
	MYSQL_RES *res;
	MYSQL_ROW row;

	char sqlstr[512];
		
	dbConn=mysql_conn("localhost","OMC_PUB");
	if(dbConn == NULL)
	{
		logRaid("Connect to OMC_PUB fail");
		return 0;
	}
	sprintf(sqlstr,"select existFlag from OMC_PUB.elementExistConf where elementName='RAID' ");
	res=mysql_getres(dbConn,sqlstr);
	if(res == NULL)
	{
		logRaid("mysql_getres fail,%s",sqlstr);
		return 0;
	}
	if((row = mysql_fetch_row(res)) == NULL)
	{
		mysql_free_result(res);
		logRaid("mysql_fetch_row fail,%s",sqlstr);
		return 0;
	}
	
	mysql_free_result(res);
	mysql_close(dbConn);
	
	if(atoi(row[0]) == 1)
		return 1;
	
	return 0;
}

int make_addr(raid_system *psys,snmp_addr *addr)
{
	addr->remote_ip=psys->remote_ip;		
	addr->local_port=RAID_LOCAL_PORT;
	addr->remote_port=raidParam.server_snmp_port;
	return 1;
}

/*
type
0-get summary,include raid card name and disk count
1-get detail,include the detail information of the disk
*/
int make_pdu(int type,raid_server *pserver,raid_system *psys,snmp_pdu *pdu)
{
	int var_index=0;
	unsigned long disk_num_oid;
	
	//Intel
	if(pserver->server_type == SERVER_TYPE_INTEL)
		disk_num_oid=psys->cur_disk_num;
	else
		disk_num_oid=psys->cur_disk_num+1;
	
	pdu->pdu_type=PDU_GET;
	sprintf(pdu->community,"public");
	pdu->request_id=0;
	if(type == PDU_SUMMARG)
	{
		pdu->var_num=2;
		if(pserver->server_type == SERVER_TYPE_INTEL)
		{
			//card name
			memcpy(pdu->var[var_index].oid,I_CARDNAME_OID,I_CARDNAME_OIDLEN * 4);
			pdu->var[var_index].oidlen=I_CARDNAME_OIDLEN;
			var_index++;
			//disk num
			memcpy(pdu->var[var_index].oid,I_DISKNUM_OID,I_DISKNUM_OIDLEN * 4);
			pdu->var[var_index].oidlen=I_DISKNUM_OIDLEN;
			var_index++;
		}
		else
		{
			//card name
			memcpy(pdu->var[var_index].oid,D_CARDNAME_OID,D_CARDNAME_OIDLEN * 4);
			pdu->var[var_index].oidlen=D_CARDNAME_OIDLEN;
			var_index++;
			//disk num
			memcpy(pdu->var[var_index].oid,D_DISKNUM_OID,D_DISKNUM_OIDLEN * 4);
			pdu->var[var_index].oidlen=D_DISKNUM_OIDLEN;
			var_index++;
		}
	}
	else
	{
		if(pserver->server_type == SERVER_TYPE_INTEL)
		{
			pdu->var_num=7;
			//disk slot
			memcpy(pdu->var[var_index].oid,I_DISKSLOT_POID,I_DISKSLOT_POIDLEN * 4);
			pdu->var[var_index].oid[I_DISKSLOT_POIDLEN]=disk_num_oid;
			pdu->var[var_index].oidlen=I_DISKSLOT_POIDLEN + 1;
			var_index++;
			//disk state
			memcpy(pdu->var[var_index].oid,I_DISKSTATE_POID,I_DISKSTATE_POIDLEN * 4);
			pdu->var[var_index].oid[I_DISKSTATE_POIDLEN]=disk_num_oid;
			pdu->var[var_index].oidlen=I_DISKSTATE_POIDLEN + 1;
			var_index++;
			//operation process
			memcpy(pdu->var[var_index].oid,I_OPTPROC_POID,I_OPTPROC_POIDLEN * 4);
			pdu->var[var_index].oid[I_OPTPROC_POIDLEN]=disk_num_oid;
			pdu->var[var_index].oidlen=I_OPTPROC_POIDLEN + 1;
			var_index++;
			//vendor id
			memcpy(pdu->var[var_index].oid,I_VENID_POID,I_VENID_POIDLEN * 4);
			pdu->var[var_index].oid[I_VENID_POIDLEN]=disk_num_oid;
			pdu->var[var_index].oidlen=I_VENID_POIDLEN + 1;
			var_index++;
			//product id
			memcpy(pdu->var[var_index].oid,I_PROID_POID,I_PROID_POIDLEN * 4);
			pdu->var[var_index].oid[I_PROID_POIDLEN]=disk_num_oid;
			pdu->var[var_index].oidlen=I_PROID_POIDLEN + 1;
			var_index++;	
			//disk size
			memcpy(pdu->var[var_index].oid,I_DISKSIZE_POID,I_DISKSIZE_POIDLEN * 4);
			pdu->var[var_index].oid[I_DISKSIZE_POIDLEN]=disk_num_oid;
			pdu->var[var_index].oidlen=I_DISKSIZE_POIDLEN + 1;
			var_index++;
			//disk error count
			memcpy(pdu->var[var_index].oid,I_DISKERRORCOUNT_POID,I_DISKERRORCOUNT_POIDLEN * 4);
			pdu->var[var_index].oid[I_DISKERRORCOUNT_POIDLEN]=disk_num_oid;
			pdu->var[var_index].oidlen=I_DISKERRORCOUNT_POIDLEN + 1;
			var_index++;
		}
		else
		{
			pdu->var_num=5;
			//disk slot
			memcpy(pdu->var[var_index].oid,D_DISKSLOT_POID,D_DISKSLOT_POIDLEN * 4);
			pdu->var[var_index].oid[D_DISKSLOT_POIDLEN]=disk_num_oid;
			pdu->var[var_index].oidlen=D_DISKSLOT_POIDLEN + 1;
			var_index++;
			//disk state
			memcpy(pdu->var[var_index].oid,D_DISKSTATE_POID,D_DISKSTATE_POIDLEN * 4);
			pdu->var[var_index].oid[D_DISKSTATE_POIDLEN]=disk_num_oid;
			pdu->var[var_index].oidlen=D_DISKSTATE_POIDLEN + 1;
			var_index++;
			//vendor id
			memcpy(pdu->var[var_index].oid,D_VENID_POID,D_VENID_POIDLEN * 4);
			pdu->var[var_index].oid[D_VENID_POIDLEN]=disk_num_oid;
			pdu->var[var_index].oidlen=D_VENID_POIDLEN + 1;
			var_index++;
			//product id
			memcpy(pdu->var[var_index].oid,D_PROID_POID,D_PROID_POIDLEN * 4);
			pdu->var[var_index].oid[D_PROID_POIDLEN]=disk_num_oid;
			pdu->var[var_index].oidlen=D_PROID_POIDLEN + 1;
			var_index++;
			//disk size
			memcpy(pdu->var[var_index].oid,D_DISKSIZE_POID,D_DISKSIZE_POIDLEN * 4);
			pdu->var[var_index].oid[D_DISKSIZE_POIDLEN]=disk_num_oid;
			pdu->var[var_index].oidlen=D_DISKSIZE_POIDLEN + 1;
			var_index++;
		}
	}
	
	return 1;
}

int recv_raid_response()
{
	snmp_pdu pdu;
	snmp_addr addr;
	int loop=20;
	
	addr.local_port=RAID_LOCAL_PORT;
	while(loop-->0)
	{
		if(snmp_receive(&pdu,&addr) == 0)
			continue;

		if(pdu.pdu_type != PDU_RSP)	
			continue;

		pdu_analyze(&pdu);
	}
	
	return 1;
}

int pdu_analyze(snmp_pdu *pdu)
{
	raid_server *pserver;
	raid_system *psys;
	int i,j;
	
	for(i=0;i<raidParam.server_count;i++)
	{
		pserver=&raidParam.server[i];
		for(j=0;j<pserver->system_count;j++)
		{
			psys=&pserver->system[j];
			if(psys->state == STATE_RESPONSE_SUMMARY || psys->state == STATE_RESPONSE_DETAIL)
			{
				if(pdu->request_id == psys->request_id)
				{
					if(!store_status(pdu,pserver,psys))
						return 0;
					if(psys->state == STATE_RESPONSE_SUMMARY)
					{
						psys->state=STATE_GET_DETAIL;
						psys->cur_disk_num=0;
					}
					else
					{
						psys->cur_disk_num++;
						if(psys->cur_disk_num >= psys->total_disk_num)
						{
							psys->state=STATE_FINISH;
							psys->cur_disk_num=0;
						}
						else
						{
							psys->state=STATE_GET_DETAIL;
						}
					}
						
					break;
				}
			}
		}
	}
	return 1;
}

int store_status(snmp_pdu *pdu,raid_server *pserver,raid_system *psys)
{
	int i;
	char sValue[512];
	int iValue;

	for(i=0;i<pdu->var_num;i++)
	{
		//check nosuchinstance
		if(pdu->var[i].vartype == 0x81)
			return 0;

		switch(pdu->var[i].oid[6])
		{
		case 3582:
			if(pdu->var[i].oid[7]==4 && pdu->var[i].oid[8]==1 && pdu->var[i].oid[9]==4)
			{
				switch(pdu->var[i].oid[10])
				{
				case 1:
					//Intel card name
					if(pdu->var[i].oid[11]==3 && pdu->var[i].oid[12]==1 && pdu->var[i].oid[13]==12 && pdu->var[i].oid[14]==0)
					{
						decode_string(pdu->var[i].msglen,pdu->var[i].msg,sValue);
						record_status(pserver->related_system_type,psys->sys_id,0,FIELD_CARDNAME,sValue);
					}
					else
					{
						logRaid("Receive unknown snmp package(4)");
					}
					break;
				case 2:
					if(pdu->var[i].oid[11] == 1)
					{
						switch(pdu->var[i].oid[12])
						{
						case 1:
							//Intel disk num
							if(pdu->var[i].oid[13]==0)
							{
								decode_int(pdu->var[i].msglen,pdu->var[i].msg,&iValue);
								psys->total_disk_num=iValue;
								if(psys->total_disk_num >= MAX_DISK_COUNT)
								{
									psys->total_disk_num=MAX_DISK_COUNT;
									logRaid("There is too much disk in %s-%d",pserver->server_name,psys->sys_id);
								}
								sprintf(sValue,"%d",psys->total_disk_num);
								record_status(pserver->related_system_type,psys->sys_id,0,FIELD_DISKNUM,sValue);
							}
							else
							{
								logRaid("intel receive unknown snmp package(6)");
							}
							break;
						case 2:
							if(pdu->var[i].oid[13]==1)
							{
								switch(pdu->var[i].oid[14])
								{
								//Intel disk slot
								case 2:
									decode_int(pdu->var[i].msglen,pdu->var[i].msg,&iValue);
									sprintf(sValue,"%d",iValue);
									record_status(pserver->related_system_type,psys->sys_id,pdu->var[i].oid[15],FIELD_DISKSLOT,sValue);
									break;
								//Intel disk error count
								case 7:
									decode_int(pdu->var[i].msglen,pdu->var[i].msg,&iValue);
									sprintf(sValue,"%d",iValue);
									record_status(pserver->related_system_type,psys->sys_id,pdu->var[i].oid[15],FIELD_DISKERRCOUNT,sValue);
									break;
								//Intel disk state
								case 10:
									decode_int(pdu->var[i].msglen,pdu->var[i].msg,&iValue);
									sprintf(sValue,"%d",iValue);
									record_status(pserver->related_system_type,psys->sys_id,pdu->var[i].oid[15],FIELD_DISKSTATE,sValue);
									
									switch(iValue)
									{
									case INTEL_STATE_ONLINE_VALUE:
										if(psys->last_alarm_value[psys->cur_disk_num] != ALARM_NONE)
										{
											psys->last_alarm_value[psys->cur_disk_num]=ALARM_NONE;
											operate_alarm(ALARM_CLEAR,analyze_alarm(analyze_alarm_id(pserver),psys->sys_id,psys->cur_disk_num),ALARM_NONE);
											logRaid("%s-%d disk-%d restore to normal, clear the alarm",pserver->server_name,psys->sys_id,psys->cur_disk_num);
										}
										break;
									case INTEL_STATE_OFFLINE_VALUE:
										if(psys->last_alarm_value[psys->cur_disk_num] != ALARM_DISK_OFFLINE)
										{
											psys->last_alarm_value[psys->cur_disk_num]=ALARM_DISK_OFFLINE;
											operate_alarm(ALARM_ADD,analyze_alarm(analyze_alarm_id(pserver),psys->sys_id,psys->cur_disk_num),ALARM_DISK_OFFLINE);
											logRaid("%s-%d disk-%d is offline",pserver->server_name,psys->sys_id,psys->cur_disk_num);
										}
										break;
									case INTEL_STATE_FAILED_VALUE:
										if(psys->last_alarm_value[psys->cur_disk_num] != ALARM_DISK_FAILED)
										{
											psys->last_alarm_value[psys->cur_disk_num]=ALARM_DISK_FAILED;
											operate_alarm(ALARM_ADD,analyze_alarm(analyze_alarm_id(pserver),psys->sys_id,psys->cur_disk_num),ALARM_DISK_FAILED);
											logRaid("%s-%d disk-%d is failed",pserver->server_name,psys->sys_id,psys->cur_disk_num);
										}
										break;
									case INTEL_STATE_REBUILD_VALUE:
										if(psys->last_alarm_value[psys->cur_disk_num] != ALARM_DISK_REBUILD)
										{
											psys->last_alarm_value[psys->cur_disk_num]=ALARM_DISK_REBUILD;
											operate_alarm(ALARM_ADD,analyze_alarm(analyze_alarm_id(pserver),psys->sys_id,psys->cur_disk_num),ALARM_DISK_REBUILD);
											logRaid("%s-%d disk-%d rebuild",pserver->server_name,psys->sys_id,psys->cur_disk_num);
										}
										break;
									default:
										if(psys->last_alarm_value[psys->cur_disk_num] != ALARM_UNKNOWN)
										{
											psys->last_alarm_value[psys->cur_disk_num]=ALARM_UNKNOWN;
											operate_alarm(ALARM_ADD,analyze_alarm(analyze_alarm_id(pserver),psys->sys_id,psys->cur_disk_num),ALARM_UNKNOWN);
											logRaid("%s-%d disk-%d unknown error",pserver->server_name,psys->sys_id,psys->cur_disk_num);
										}
										break;
									}
									break;
								//Intel disk size
								case 15:
									decode_int(pdu->var[i].msglen,pdu->var[i].msg,&iValue);
									sprintf(sValue,"%d",iValue);
									record_status(pserver->related_system_type,psys->sys_id,pdu->var[i].oid[15],FIELD_DISKSIZE,sValue);
									break;
								//Intel operation progress
								case 21:
									decode_string(pdu->var[i].msglen,pdu->var[i].msg,sValue);
									record_status(pserver->related_system_type,psys->sys_id,pdu->var[i].oid[15],FIELD_OPTPROG,sValue);
									break;
								//Intel vendor id
								case 24:
									decode_string(pdu->var[i].msglen,pdu->var[i].msg,sValue);
									record_status(pserver->related_system_type,psys->sys_id,pdu->var[i].oid[15],FIELD_VENDORID,sValue);
									break;
								//Intel product id
								case 25:
									decode_string(pdu->var[i].msglen,pdu->var[i].msg,sValue);
									record_status(pserver->related_system_type,psys->sys_id,pdu->var[i].oid[15],FIELD_PRODUCTID,sValue);
									break;
								default:
									logRaid("Receive unknown snmp package(9)");
									break;
								}
							}
							else
							{
								logRaid("Receive unknown snmp package(8)");
							}
							break;
						default:							
							logRaid("Receive unknown snmp package(7)");
							break;
						}
						
					}
					else
					{
						logRaid("Receive unknown snmp package(5)");
					}
					break;
				default:
					logRaid("Receive unknown snmp package(3)");
					break;
				}
			}
			else
			{
				logRaid("Receive unknown snmp package(2)");
			}
			break;
		case 674:
			if(pdu->var[i].oid[7]==10893 &&pdu->var[i].oid[8]==1 && pdu->var[i].oid[9]==20 && pdu->var[i].oid[10]==130)
			{
				switch(pdu->var[i].oid[11])
				{
				case 1:
					//Dell card name
					if(pdu->var[i].oid[12]==1 && pdu->var[i].oid[13]==2 && pdu->var[i].oid[14]==0)
					{
						decode_string(pdu->var[i].msglen,pdu->var[i].msg,sValue);
						record_status(pserver->related_system_type,psys->sys_id,0,FIELD_CARDNAME,sValue);
					}
					//Dell disk num
					else if(pdu->var[i].oid[12]==1 && pdu->var[i].oid[13]==11 && pdu->var[i].oid[14]==0)
					{
						decode_int(pdu->var[i].msglen,pdu->var[i].msg,&iValue);
						sprintf(sValue,"%d",iValue-1);
						psys->total_disk_num=iValue-1;
						if(psys->total_disk_num >= MAX_DISK_COUNT)
						{
							psys->total_disk_num=MAX_DISK_COUNT;
							logRaid("There is too much disk in %s-%d",pserver->server_name,psys->sys_id);
						}
						record_status(pserver->related_system_type,psys->sys_id,0,FIELD_DISKNUM,sValue);
					}
					else
					{
						logRaid("Receive unknown snmp package(12)");
					}
					break;
				case 4:
					if(pdu->var[i].oid[12] == 1)
					{
						switch(pdu->var[i].oid[13])
						{
						//Dell disk slot
						case 2:
							decode_string(pdu->var[i].msglen,pdu->var[i].msg,sValue);
							record_status(pserver->related_system_type,psys->sys_id,pdu->var[i].oid[14],FIELD_DISKSLOT,sValue);
							break;
						//Dell vendor id
						case 3:
							decode_string(pdu->var[i].msglen,pdu->var[i].msg,sValue);
							record_status(pserver->related_system_type,psys->sys_id,pdu->var[i].oid[14],FIELD_VENDORID,sValue);
							break;
						//Dell disk state
						case 4:
							decode_int(pdu->var[i].msglen,pdu->var[i].msg,&iValue);
							sprintf(sValue,"%d",iValue);
							record_status(pserver->related_system_type,psys->sys_id,pdu->var[i].oid[14],FIELD_DISKSTATE,sValue);
							
							switch(iValue)
							{
							case DELL_STATE_ONLINE_VALUE:
								if(psys->last_alarm_value[psys->cur_disk_num] != ALARM_NONE)
								{
									psys->last_alarm_value[psys->cur_disk_num]=ALARM_NONE;
									operate_alarm(ALARM_CLEAR,analyze_alarm(analyze_alarm_id(pserver),psys->sys_id,psys->cur_disk_num),ALARM_NONE);
									logRaid("%s-%d disk-%d restore to normal, clear the alarm",pserver->server_name,psys->sys_id,psys->cur_disk_num);
								}
								break;
							case DELL_STATE_OFFLINE_VALUE:
								if(psys->last_alarm_value[psys->cur_disk_num] != ALARM_DISK_OFFLINE)
								{
									psys->last_alarm_value[psys->cur_disk_num]=ALARM_DISK_OFFLINE;
									operate_alarm(ALARM_ADD,analyze_alarm(analyze_alarm_id(pserver),psys->sys_id,psys->cur_disk_num),ALARM_DISK_OFFLINE);
									logRaid("%s-%d disk-%d is offline",pserver->server_name,psys->sys_id,psys->cur_disk_num);
								}
								break;
							case DELL_STATE_FAILED_VALUE:
								if(psys->last_alarm_value[psys->cur_disk_num] != ALARM_DISK_FAILED)
								{
									psys->last_alarm_value[psys->cur_disk_num]=ALARM_DISK_FAILED;
									operate_alarm(ALARM_ADD,analyze_alarm(analyze_alarm_id(pserver),psys->sys_id,psys->cur_disk_num),ALARM_DISK_FAILED);
									logRaid("%s-%d disk-%d is failed",pserver->server_name,psys->sys_id,psys->cur_disk_num);
								}
								break;
							case DELL_STATE_REBUILD_VALUE:
								if(psys->last_alarm_value[psys->cur_disk_num] != ALARM_DISK_REBUILD)
								{
									psys->last_alarm_value[psys->cur_disk_num]=ALARM_DISK_REBUILD;
									operate_alarm(ALARM_ADD,analyze_alarm(analyze_alarm_id(pserver),psys->sys_id,psys->cur_disk_num),ALARM_DISK_REBUILD);
									logRaid("%s-%d disk-%d rebuild",pserver->server_name,psys->sys_id,psys->cur_disk_num);
								}
								break;
							default:
								if(psys->last_alarm_value[psys->cur_disk_num] != ALARM_UNKNOWN)
								{
									psys->last_alarm_value[psys->cur_disk_num]=ALARM_UNKNOWN;
									operate_alarm(ALARM_ADD,analyze_alarm(analyze_alarm_id(pserver),psys->sys_id,psys->cur_disk_num),ALARM_UNKNOWN);
									logRaid("%s-%d disk-%d unknown error",pserver->server_name,psys->sys_id,psys->cur_disk_num);
								}
								break;
							}
							
							break;
						//Dell product id
						case 7:
							decode_string(pdu->var[i].msglen,pdu->var[i].msg,sValue);
							record_status(pserver->related_system_type,psys->sys_id,pdu->var[i].oid[14],FIELD_PRODUCTID,sValue);
							break;
						//Dell disk size
						case 11:
							decode_int(pdu->var[i].msglen,pdu->var[i].msg,&iValue);
							sprintf(sValue,"%d",iValue);
							record_status(pserver->related_system_type,psys->sys_id,pdu->var[i].oid[14],FIELD_DISKSIZE,sValue);
							break;
						default:
							logRaid("Receive unknown snmp package(14)");
							break;
						}
					}
					else
					{
						logRaid("Receive unknown snmp package(13)");
					}
					break;
				default:
					logRaid("Receive unknown snmp package(11)");
					break;
				}
			}
			else
			{
				logRaid("Receive unknown snmp package(10)");
			}
			break;
		default:
			logRaid("Receive unknown snmp package(1)");
			break;
		}
	}
	return 1;
}

int record_status(int sysTypeNo,int sysNo,int instance,char *fieldName,char *fieldValue)
{
	MYSQL *dbConn;

	char sqlstr[512];
		
	dbConn=mysql_conn("localhost","RAID_DB");
	if(dbConn == NULL)
	{
		logRaid("Connect to RAID_DB fail");
		return 0;
	}
	sprintf(sqlstr,"replace into RAID_DB.raid_status(sysTypeNo,sysNo,instance,fieldName,fieldValue,updateTime)values(%d,%d,%d,'%s','%s',CURRENT_TIMESTAMP)",
		sysTypeNo,sysNo,instance,fieldName,fieldValue);
	if(mysql_getnores(dbConn,sqlstr) != 0)
	{
		logRaid("Record status fail,%s",sqlstr);
		mysql_close(dbConn);
		return 0;
	}
	mysql_close(dbConn);
	return 1;
}

int operate_record(char *db,char *tb,char *sqlstr)
{
	MYSQL *dbConn;
	dbConn=mysql_conn("localhost",db);
	if(dbConn == NULL)
	{
		logRaid("Connect to %s fail",db);
		return 0;
	}
	if(mysql_getnores(dbConn,sqlstr) != 0)
	{
		logRaid("Excute sql fail,%s",sqlstr);
		mysql_close(dbConn);
		return 0;
	}
	mysql_close(dbConn);
	return 1;
}

int read_conffile()
{
	FILE *handle;
	char line[512];
	char *pchr;
	int i;
	
	int g_f,mcms_f,mcss_f;
	
	//initial database
	operate_record("RAID_DB","raid_status","delete from RAID_DB.raid_status");
	sprintf(line,"update OMC_PUB.sysAlarmLog set clearTime=CURRENT_TIMESTAMP,clearMode=1,clearBy='System' where sysTypeNo=%d and sysNo=%d and clearMode=0",
		RAID_SYSTYPENO,raidSysNo);
	operate_record("OMC_PUB","sysAlarmLog",line);
	
	handle=fopen(CONF_FILE,"r");
	if(handle == NULL)
	{
		printf("Can not open %s\n",CONF_FILE);
		logRaid("Can not open %s",CONF_FILE);
		exit(1);
	}
	
	logRaid("Read conf file %s",CONF_FILE);
	
	memset(&raidParam,0,sizeof(raidParam));
	g_f=mcms_f=mcss_f=0;
	while(getline_local(handle,line,512))
	{
		if(line[0] == '#' || strlen(line) < 4)
			continue;
		if(strcasecmp(line,"[Global]") == 0)
		{
			g_f=1;
			mcms_f=0;
			mcss_f=0;
			continue;
		}
		else if(strcasecmp(line,"[MCSS Server]") == 0)
		{
			g_f=0;
			mcms_f=0;
			mcss_f=1;
			continue;
		}
		else if(strcasecmp(line,"[MCMS Server]") == 0)
		{
			g_f=0;
			mcms_f=1;
			mcss_f=0;
			continue;
		}
		
		if(g_f)
		{
			if((pchr=strstr(line,"EnableFlag=")))
			{
				if(strcasecmp(pchr+strlen("EnableFlag="),"On") == 0)
					raidParam.enable_flag=1;
				else
					raidParam.enable_flag=0;
			}
			if((pchr=strstr(line,"ServerSNMPPort=")))
			{
				raidParam.server_snmp_port=atoi(pchr+strlen("ServerSNMPPort="));
			}
			if((pchr=strstr(line,"SystemType=")))
			{
				if(strcasecmp(pchr+strlen("SystemType="),"MCSS") == 0)
					raidParam.system_type=0;
				else
					raidParam.system_type=1;
			}
		}
		
		if( (mcss_f && raidParam.system_type == 0) || (mcms_f && raidParam.system_type == 1) )
		{
			pchr=strtok(line,",");
			if(strcasecmp(pchr,"EMS") == 0)
			{
				sprintf(raidParam.server[raidParam.server_count].server_name,"%s",pchr);
				raidParam.server[raidParam.server_count].related_system_type=0;
			}
			else if(strcasecmp(pchr,"MSS") == 0)
			{
				sprintf(raidParam.server[raidParam.server_count].server_name,"%s",pchr);
				raidParam.server[raidParam.server_count].related_system_type=320;
			}
			else if(strcasecmp(pchr,"VMS") == 0)
			{
				sprintf(raidParam.server[raidParam.server_count].server_name,"%s",pchr);
				raidParam.server[raidParam.server_count].related_system_type=390;
			}
			else if(strcasecmp(pchr,"RCM") == 0)
			{
				sprintf(raidParam.server[raidParam.server_count].server_name,"%s",pchr);
				raidParam.server[raidParam.server_count].related_system_type=395;
			}
			else if(strcasecmp(pchr,"MCMS") == 0)
			{
				sprintf(raidParam.server[raidParam.server_count].server_name,"%s",pchr);
				raidParam.server[raidParam.server_count].related_system_type=0;
			}
			pchr=strtok(NULL,",");
			if(strcasecmp(pchr,"Intel") == 0)
				raidParam.server[raidParam.server_count].server_type=SERVER_TYPE_INTEL;
			else
				raidParam.server[raidParam.server_count].server_type=SERVER_TYPE_DELL;
			pchr=strtok(NULL,",");
			if(strcasecmp(pchr,"On") == 0)
				raidParam.server[raidParam.server_count].enable_flag=1;
			else
				raidParam.server[raidParam.server_count].enable_flag=0;
			raidParam.server_count++;
		}
	}
	fclose(handle);
	
	logRaid("enable_flag=%d",raidParam.enable_flag);
	logRaid("server_snmp_port=%d",raidParam.server_snmp_port);
	logRaid("system_type=%d",raidParam.system_type);
	logRaid("server_count=%d",raidParam.server_count);
	for(i=0;i<raidParam.server_count;i++)
		logRaid("%s,%d,%d",raidParam.server[i].server_name,raidParam.server[i].server_type,raidParam.server[i].enable_flag);
	
	raid_update_system();
	return 1;
}

int raid_update_system()
{
	MYSQL *dbConn;
	MYSQL_RES *res;
	MYSQL_ROW row;
	char sqlstr[512];
	int i,j;
	raid_server *pserver;
	raid_system *psys;
	
	unsigned long tmp_ip;
	int tmp_sysno;

	/*
	operate_record("RAID_DB","raid_status","delete from RAID_DB.raid_status");
	sprintf(sqlstr,"update OMC_PUB.sysAlarmLog set clearTime=CURRENT_TIMESTAMP,clearMode=1,clearBy='System' where sysTypeNo=%d and sysNo=%d and clearMode=0",
		RAID_SYSTYPENO,raidSysNo);
	operate_record("OMC_PUB","sysAlarmLog",sqlstr);
	*/
	
	dbConn=mysql_conn("localhost","OMC_PUB");
	if(dbConn == NULL)
	{
		logRaid("Connect to OMC_PUB fail");
		return 0;
	}
	for(i=0;i<raidParam.server_count;i++)
	{
		pserver=&raidParam.server[i];
		sprintf(sqlstr,"select sysNo,ip from OMC_PUB.sysInfo where sysTypeNo=%d order by sysNo asc ",pserver->related_system_type);
		res=mysql_getres(dbConn,sqlstr);
		if(res == NULL)
		{
			logRaid("mysql_getres fail,%s",sqlstr);
			continue;
		}
		while((row = mysql_fetch_row(res)) != NULL)
		{
			tmp_sysno=atoi(row[0]);
			tmp_ip=inet_addr(row[1]);
			for(j=0;j<pserver->system_count;j++)
			{
				psys=&pserver->system[j];
				if(psys->sys_id == tmp_sysno)
				{
					if(psys->remote_ip != tmp_ip)
					{
						psys->remote_ip=tmp_ip;
						logRaid("Connect to %s-%d for new ip %s",pserver->server_name,psys->sys_id,row[1]);
					}
					break;
				}
			}
			if(j == pserver->system_count)
			{
				psys=&pserver->system[pserver->system_count];
				psys->sys_id=tmp_sysno;
				psys->remote_ip=tmp_ip;
				psys->state=STATE_IDLE;
				psys->last_update_time=time(NULL);
				pserver->system_count++;
				logRaid("Connect to %s-%d %s",pserver->server_name,psys->sys_id,row[1]);
			}
		}
		mysql_free_result(res);
	}
	mysql_close(dbConn);
	return 1;
}

/*
return 
alarm compCode
*/
int analyze_alarm(int alarm_id,int sysNo,int disk_index)
{
	return alarm_id*100 + sysNo*10 + disk_index;
}

/*
return
alarm id, for define the alarm compCode for MCMS,EMS,MSS,VMS
*/
int analyze_alarm_id(raid_server *pserver)
{
	//MCSS
	if(raidParam.system_type == 0)
	{
		//EMS raid alarm
		if(pserver->related_system_type == 0)
			return 2;
		//MSS raid alarm
		else if(pserver->related_system_type == 320)
			return 3;
		//VMS raid system
		else if(pserver->related_system_type == 390)
			return 4;
		//RCM raid system
		else if(pserver->related_system_type == 395)
			return 5;
	}
	//MCMS
	else
	{
		return 1;
	}
	return 1;
}

/*
opt
0-clear
1-add
*/
int operate_alarm(int opt,int compCode,int alarmCode)
{
	char sqlstr[512];
	int tmpComCode;
	
	if(opt == ALARM_CLEAR)
	{
		if(alarmCode > 0)
			sprintf(sqlstr,"update OMC_PUB.sysAlarmLog set clearTime=CURRENT_TIMESTAMP,clearMode=1,clearBy='System' where sysTypeNo=%d and sysNo=%d and compCode=%d and alarmCode=%d and clearMode=0",
				RAID_SYSTYPENO,raidSysNo,compCode,alarmCode);
		else
			sprintf(sqlstr,"update OMC_PUB.sysAlarmLog set clearTime=CURRENT_TIMESTAMP,clearMode=1,clearBy='System' where sysTypeNo=%d and sysNo=%d and compCode=%d and clearMode=0",
				RAID_SYSTYPENO,raidSysNo,compCode);
		//printf("%s\n",sqlstr);
		operate_record("OMC_PUB","sysAlarmLog",sqlstr);
		
		//clear the timeout alarm,it not belong the disk alarm
		if(alarmCode == 0)
		{
			tmpComCode=compCode/10*10+9;
			sprintf(sqlstr,"update OMC_PUB.sysAlarmLog set clearTime=CURRENT_TIMESTAMP,clearMode=1,clearBy='System' where sysTypeNo=%d and sysNo=%d and compCode=%d and clearMode=0",
				RAID_SYSTYPENO,raidSysNo,tmpComCode);
			operate_record("OMC_PUB","sysAlarmLog",sqlstr);
		}
	}
	else
	{
		sprintf(sqlstr,"update OMC_PUB.sysAlarmLog set clearMode=1,clearBy='System',clearTime=CURRENT_TIMESTAMP where sysTypeNo=%d and sysNo=%d and compCode=%d and alarmCode=%d and clearMode=0",
				RAID_SYSTYPENO,raidSysNo,compCode,alarmCode);
			operate_record("OMC_PUB","sysAlarmLog",sqlstr);
		
		sprintf(sqlstr,"insert into OMC_PUB.sysAlarmLog(sysTypeNo,sysNo,subSysNo,compCode,alarmCode,alarmTime,clearTime,clearMode,clearInfo,clearBy)values(%d,%d,0,%d,%d,CURRENT_TIMESTAMP,'0000-00-00 00:00:00',0,'','')",
			RAID_SYSTYPENO,raidSysNo,compCode,alarmCode);
		//printf("%s\n",sqlstr);
		operate_record("OMC_PUB","sysAlarmLog",sqlstr);
	}
	return 1;
}

int decode_int(int msglen,unsigned char *msg,int *out)
{
	int i;
	
	*out=0;
	i=msglen;
	
	for(i=msglen-1;i>=0;i--)
		(*out)+=msg[i] << ((msglen-1-i)*8);
	
	return 1;
}

int decode_string(int msglen,unsigned char *msg,char *out)
{
	memcpy(out,msg,msglen);
	out[msglen]=0;
	return 1;
}

void logRaid(const char *fmt,...)
{
	char logFile[64];
	FILE *fp;
	time_t l_time;
	va_list ap;
	char buf[8192];
	struct tm *t;
	char timestr[64];
	
	l_time=time(NULL);
	t=localtime(&l_time);
	sprintf(logFile,"/usr/local/omc/log/raid%04d%02d%02d.log",t->tm_year+1900,t->tm_mon+1,t->tm_mday);
	fp=fopen(logFile,"a");
	if(fp!=NULL)
	{
		va_start(ap,fmt);
		vsprintf(buf,fmt,ap);
		sprintf(timestr,"%02d:%02d:%02d: ",t->tm_hour,t->tm_min,t->tm_sec);
		fputs(timestr,fp);
		fputs(buf,fp);
		fputs("\n",fp);
		fflush(fp);
		va_end(ap);
		fclose(fp);
	}
}

/*
return
1: continue
0: finish,EOF
*/
int getline_local(FILE *handle,char *line,int max_size)
{
	unsigned char rb;
	int pos=0;
	
	memset(line,0,max_size);
	while(fread(&rb,1,1,handle) == 1)
	{
		if(rb == '\n')
			return 1;
		line[pos]=rb;
		pos++;
		if(pos >= max_size)
			return 1;
	}
	return 0;
}
