/* Title:	logColl.c
 * Description:	process the subscriber command
 * Author:	
 * Date:	
 */

#include <stdlib.h>
#include <string.h>
#include "logCollector.h"
#include "mysql.h"

/******************************************************/
/******            Heartbeat Parameter           ******/
/******************************************************/
DWORD PROC_HEARTBEAT_OID[12]={1,3,6,1,4,1,1373,2,4,10,3};
int PROC_HEARTBEAT_OIDLEN=11;
int sendHeartbeat();


/***********Private Functions Declare***********************/
int logColl_initLogSrcArr();
int logColl_initAttrDefnArr();
int logColl_getIp(int logSrcArrNo, char *dstIP);
int logColl_mainProc();
int logColl_sendMsg(int logSrcArrNo, snmp_pdu * pdu, snmp_addr * addr);
int logColl_recvMsg(int *logSrcArrNo, snmp_pdu * pdu, snmp_addr * addr);
int logColl_mkPdu(int logSrcArrNo, snmp_pdu * pdu);
int logColl_mkAddr(int logSrcArrNo, snmp_addr * addr);
int logColl_mkVarArr(int logSrcArrNo, var_list * varArr);
int logColl_procResp(int *oldlogSrcArrNo, snmp_pdu * pdu);

/***********Global Var Declare And Init*********************/
int logColl_timerCount = 0;
static MYSQL *dbConn;
static char errorStatusDescArr[19][30] =
	{ "NoError", "TooBig", "NoSuchName", "BadValue", "ReadOnly",
	"GenErr", "NoAccess", "WrongType", "WrongLength", "WrongEncoding",
	"wrongValue", "noCreation", "inconsistentValue", "resourceUnavailabe",
		"commitFailed",
	"UndoFailed", "AuthorizationError", "NoWritable", "inconsistentName"
};
static int MaxErrorStatusNum = 19;
static unitLogSrc logSrcArr[MaxLogSrcNum];
static unitAttrDefn attrDefnArr[MaxAttrDefnNum];

//log file pointer
static FILE *logFp;
int old_day;

/*
*Function	:logCollInit
*Input		:Null
*Output		:Return 1: ok, 0:failed
*Descript	:Must call this function at first.
*/
int logCollectorInit()
{
	long l_time;
	struct tm *t;

	l_time = time(NULL);
	t = localtime(&l_time);
	old_day = t->tm_mday;

	//init snmp port
	snmp_init(4960);

	//init write log
	omcLogInit("../log", "logColl", &logFp);
	
	omcLog(logFp,"Module start....");

	//init db connect
	dbConn = mysql_conn(HOSTNAME, PUB_DB);
	if (dbConn == NULL) {
		omcLog(logFp, " Fail to init database connection");
		return (0);
	}
	//init system configuration array
	if (!logColl_initLogSrcArr()) {
		omcLog(logFp, " Fail to init system configuration array");
		return (0);
	}
	//init parameter configuration array
	if (!logColl_initAttrDefnArr()) {
		omcLog(logFp, " Fail to init Attributes Define array");
		return (0);
	}
	return (1);
}

/*************************************************
Function:        // sendHeartbeat
Description:     // Send process heartbeat to beatProc
Calls:           // snmp_send
Called By:       // logCollectorTimer
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 1:OK; 0:Fail
Others:          // 
*************************************************/
int sendHeartbeat()
{
	snmp_pdu pdu;
	snmp_addr addr;
	char proc_name[16];
	
	memset(proc_name,0,16);
	sprintf(proc_name,"logCollector");
	
	//pdu
	memset(&pdu,0,sizeof(snmp_pdu));
	pdu.pdu_type=7;
	pdu.request_id=0;
	sprintf(pdu.community,"public");
	pdu.var_num=1;
	pdu.error_status=0;
	pdu.error_index=0;
	
	//Addr
	addr.local_port = 4957;
	//addr.remote_ip = inet_addr("127.0.0.1");
	addr.remote_ip = GetLocalIP();
	addr.broadcast = 0;
	addr.remote_port = 4957;
	
	//Varlist
	memcpy(pdu.var[0].oid,PROC_HEARTBEAT_OID,PROC_HEARTBEAT_OIDLEN*sizeof(DWORD));

	pdu.var[0].oidlen=PROC_HEARTBEAT_OIDLEN;
	pdu.var[0].vartype=0x04;
	pdu.var[0].msglen=16;
	memcpy(pdu.var[0].msg,proc_name,16);
	
	if(snmp_send(&pdu, &addr) <= 0)
	{
		omcLog(logFp,"Send heartbeat fail");
		return 0;
	}
	return 1;
}

/*
*Function	:logCollTimer
*Input		:Null
*Output		:Return 1: ok, 0:failed
*Descript	:call this function ever 100ms
*/
unsigned long heartbeat_timeout=0;
int logCollectorTimer()
{
	
	
	if(time(NULL) - heartbeat_timeout > 5)
	{
		if(mysql_ping(dbConn))
		{
			mysql_close(dbConn);
			dbConn=mysql_conn("localhost","OMC_PUB");
			if(dbConn == NULL)
			{
				omcLog(logFp,"Mysql connection lost");
				return 0;
			}
		}
		
		
		heartbeat_timeout=time(NULL);
		sendHeartbeat();
	}
	
	if (logColl_timerCount < 5000) {
		logColl_timerCount++;
	} else {
		long l_time;
		struct tm *t;
		int arrayNo;
		//check ip
		for (arrayNo = 0; arrayNo < MaxLogSrcNum; arrayNo++) {
			if (logSrcArr[arrayNo].sysTypeNo > 0
				&& logSrcArr[arrayNo].isEnable < 1) {
				if (logColl_getIp(arrayNo, logSrcArr[arrayNo].dstIP)) {
					logSrcArr[arrayNo].isEnable = 1;
					omcLog(logFp,
						   "Find sysId(%d_%d_%d)'s IP ok,Let's get it's log",
						   logSrcArr[arrayNo].sysTypeNo,
						   logSrcArr[arrayNo].sysNo,
						   logSrcArr[arrayNo].subSysNo);
				} else {
					omcLog(logFp, "Still cannot find sysId(%d_%d_%d)'s IP",
						   logSrcArr[arrayNo].sysTypeNo,
						   logSrcArr[arrayNo].sysNo,
						   logSrcArr[arrayNo].subSysNo);
				}
			}
		}
		//check log
		l_time = time(NULL);
		t = localtime(&l_time);
		if (t->tm_mday != old_day) {
			omcLog(logFp, "Check time nowDay[%d] != oldDay[%d],change!",
				   t->tm_mday, old_day);
			omcLogInit("../log", "logColl", &logFp);
			old_day = t->tm_mday;
		}
		logColl_timerCount = 0;
	}

	if (logColl_mainProc()) {
		return (1);
	} else {
		return (0);
	}
}


/*
*Function	:logColl_initLogSrcArr
*Input		:Null
*Output		:Return 1: ok, 0:failed
*Descript	:
*/
int logColl_initLogSrcArr()
{
	char confQuery[400] = "\0";
	MYSQL_RES *confResult = NULL;
	MYSQL_ROW confRow;
	int arrayNo = 0, i = 0;
	char *oneOid;

	//init array first
	for (i = 0; i < MaxLogSrcNum; i++) {
		logSrcArr[i].isEnable = 0;
	}

	//find sysTypeNo which need subscriber manage
	sprintf(confQuery, "SELECT maxMsgLen,snmpCommunity,snmpPort,"
			" sysLogSourceConf.sysTypeNo,sysNo,subSysNo,dataTypeNo,preObjId,"
			" maxSizeOfRec,maxRecNumOfBuf,maxRecNumOfDay,dataStoreTable,isIncremental"
			" FROM sysConf,sysLogSourceConf "
			" WHERE sysConf.sysTypeNo = sysLogSourceConf.sysTypeNo AND sysLogSourceConf.isEnable > '0' "
			" ORDER BY sysTypeNo");
	confResult = (MYSQL_RES *) mysql_getres(dbConn, confQuery);
	if (confResult == NULL) {
		omcLog(logFp, " Database may be stopped,Please check!");
		return (-1);
	} else if (mysql_num_rows(confResult) == 0) {
		omcLog(logFp, "There is 0 record in the OMC_PUB.sysLogSourceConf");
		mysql_free_result(confResult);
		return (0);
	}
	if (mysql_num_rows(confResult) >= MaxLogSrcNum) {	//sizeof logSrcArr is 16
		omcLog(logFp,
			   "The records count in the OMC_PUB.sysLogSourceConf is larger than %d",MaxLogSrcNum);
		mysql_free_result(confResult);
		return (-1);
	}
	//fill into config array
	while ((confRow = mysql_fetch_row(confResult)) != NULL) {
		logSrcArr[arrayNo].maxMsgLen = atol(confRow[0]);	//<--
		sprintf(logSrcArr[arrayNo].snmpCommunity, "%s", confRow[1]);	//<--
		logSrcArr[arrayNo].dstPort = atol(confRow[2]);	//<--
		logSrcArr[arrayNo].sysTypeNo = atol(confRow[3]);	//<--
		logSrcArr[arrayNo].sysNo = atol(confRow[4]);	//<--
		logSrcArr[arrayNo].subSysNo = atol(confRow[5]);	//<--
		logSrcArr[arrayNo].dataTypeNo = atol(confRow[6]);	//<--

		if (logColl_getIp(arrayNo, logSrcArr[arrayNo].dstIP) < 1) {	//<--
			logSrcArr[arrayNo].isEnable = 0;
			omcLog(logFp, "Can not get the IP,%d-%d-%d",logSrcArr[arrayNo].sysTypeNo,logSrcArr[arrayNo].sysNo,logSrcArr[arrayNo].subSysNo);
		} else {
			logSrcArr[arrayNo].isEnable = 1;	//<--
		}

		i = 0;
		while ((oneOid = strsep(&(confRow[7]), "."))) {
			logSrcArr[arrayNo].preObjId[i] = atol(oneOid);	//<--
			i++;
		}
		logSrcArr[arrayNo].preObjIdLen = i;	//<--
		if (i < 1) {
			mysql_free_result(confResult);
			omcLog(logFp, "get preObjId error!!");
			return (0);
		}

		logSrcArr[arrayNo].maxSizeOfRec = atol(confRow[8]);	//<--
		logSrcArr[arrayNo].maxRecNumOfBuf = atol(confRow[9]);	//<--
		logSrcArr[arrayNo].maxRecNumOfDay = atol(confRow[10]);	//<--
		sprintf(logSrcArr[arrayNo].dataStoreTable, "%s", confRow[11]);	//<--
		//logSrcArr[arrayNo].isIncremental  = atol(confRow[11]);    //<--

		logSrcArr[arrayNo].requestId = arrayNo + 1;	//<--
		logSrcArr[arrayNo].sleepTime = 3600 * 24 * 10 / logSrcArr[arrayNo].maxRecNumOfDay;	//<--
		logSrcArr[arrayNo].sleepCount = logSrcArr[arrayNo].sleepTime;	//<--

		omcLog(logFp, "Get source define: %d %d-%d-%d  %s %s", arrayNo,
			   logSrcArr[arrayNo].sysTypeNo, logSrcArr[arrayNo].sysNo,
			   logSrcArr[arrayNo].subSysNo, logSrcArr[arrayNo].dstIP,
			   logSrcArr[arrayNo].dataStoreTable);
		arrayNo++;
	}
	mysql_free_result(confResult);
	return (1);
}

/*
*Function	:logColl_initAttrDefnArr
*Input		:Null
*Output		:Return 1: ok, 0:failed
*Descript	:
*/
int logColl_initAttrDefnArr()
{
	char confQuery[400] = "\0";
	MYSQL_RES *confResult = NULL;
	MYSQL_ROW confRow;
	int arrayNo = 0, logSrcArrNo = 0, i = 0, j = 0;
	char oneOid[8];
	char *levelSelect = " level_1,level_2,level_3,level_4,level_5,"
		"level_6,level_7,level_8,level_9,level_10";
	char *queryOrderBy = " level_1,level_2,level_3,level_4,level_5,"
		"level_6,level_7,level_8,level_9,level_10";
	//init if first
	for (i = 0; i < MaxAttrDefnNum; i++) {
		attrDefnArr[arrayNo].sysTypeNo = 0;
		attrDefnArr[arrayNo].fieldObjIdStr[0] = 0;
		attrDefnArr[arrayNo].fieldName[0] = 0;
		attrDefnArr[arrayNo].valueType = 0;
		attrDefnArr[arrayNo].valueLen = 0;
		//attrDefnArr[arrayNo].initValue;
	}

	//load subscriber data into array one bye one sysTypeNo
	for (logSrcArrNo = 0; logSrcArrNo < MaxLogSrcNum; logSrcArrNo++) {
		//if (logSrcArr[logSrcArrNo].isEnable <= 0) {
		if (logSrcArr[logSrcArrNo].sysTypeNo <= 0) {
			continue;
		}
		logSrcArr[logSrcArrNo].attrDefnArrOffset = arrayNo;	//<--<--
		sprintf(confQuery,
				"SELECT %s,fieldName,valueType,length,initValue "
				"FROM OBJ_%d.logAttrDef_%d WHERE operType > '0' ORDER BY %s",
				levelSelect, logSrcArr[logSrcArrNo].sysTypeNo,
				logSrcArr[logSrcArrNo].dataTypeNo, queryOrderBy);
		confResult = (MYSQL_RES *) mysql_getres(dbConn, confQuery);
		if (confResult == NULL) {
			omcLog(logFp, " Database may be stopped,Please check!");
			return (0);
		} else if (mysql_num_rows(confResult) == 0) {
			mysql_free_result(confResult);
			return (0);
		}
		if ((logSrcArrNo + mysql_num_rows(confResult)) >= MaxAttrDefnNum) {	//sizeof attrDefnArr is 512
			omcLog(logFp, "The number of parameter type is too much!");
			mysql_free_result(confResult);
			return (0);
		}
		logSrcArr[logSrcArrNo].attrDefnNum = mysql_num_rows(confResult);
		while ((confRow = mysql_fetch_row(confResult)) != NULL) {
			j = 0;
			attrDefnArr[arrayNo].sysTypeNo = logSrcArr[logSrcArrNo].sysTypeNo;	//<--
			attrDefnArr[arrayNo].dataTypeNo = logSrcArr[logSrcArrNo].dataTypeNo;	//<--
			attrDefnArr[arrayNo].fieldObjIdStr[0] = 0;
			while (atoi(confRow[j]) > 0 && j < 10) {
				if (j == 0) {
					sprintf(oneOid, "%d", atoi(confRow[j]));
				} else {
					sprintf(oneOid, ".%d", atoi(confRow[j]));
				}
				strcat(attrDefnArr[arrayNo].fieldObjIdStr, oneOid);
				j++;
			}
			sprintf(attrDefnArr[arrayNo].fieldName, "%s", confRow[10]);
			attrDefnArr[arrayNo].valueType = atoi(confRow[11]);
			attrDefnArr[arrayNo].valueLen = atoi(confRow[12]);
			arrayNo++;
		}
		mysql_free_result(confResult);
	}
	return (1);
}

/*
*Function	:logColl_getIp
*Input		:Null
*Output		:Return 1: ok, 0:failed
*Descript	:
*/
int logColl_getIp(int logSrcArrNo, char *dstIP)
{
	MYSQL_RES *tmpResult;
	MYSQL_ROW tmpRow;
	char tmpQuery[400] = "\0";
	sprintf(tmpQuery, "SELECT ip FROM %s WHERE sysTypeNo='%d' "
			"AND sysNo='%d' AND subsysNo='%d' ORDER BY updateTime DESC",
			IpTable, logSrcArr[logSrcArrNo].sysTypeNo,
			logSrcArr[logSrcArrNo].sysNo, logSrcArr[logSrcArrNo].subSysNo);
	tmpResult = (MYSQL_RES *) mysql_getres(dbConn, tmpQuery);
	if (tmpResult == NULL) {
		omcLog(logFp, " Can not get sysId(%d_%d_%d)'s IP",
			   logSrcArr[logSrcArrNo].sysTypeNo,
			   logSrcArr[logSrcArrNo].sysNo,
			   logSrcArr[logSrcArrNo].subSysNo);
		mysql_free_result(tmpResult);
		return (0);
	}
	if ((tmpRow = mysql_fetch_row(tmpResult)) != NULL) {
		strcpy(dstIP, tmpRow[0]);
#if logColl_DEBUG
		omcLog(logFp, " dstIP=%s", dstIP);
#endif
		mysql_free_result(tmpResult);
		return (1);
	} else {
		omcLog(logFp, " Can not get sysId(%d_%d_%d)'s IP",
			   logSrcArr[logSrcArrNo].sysTypeNo,
			   logSrcArr[logSrcArrNo].sysNo,
			   logSrcArr[logSrcArrNo].subSysNo);
		return (0);
	}
}


/*
*Function	:logCollProc
*Input		:Null
*Output		:Return 1: ok, 0:failed
*Descript	:
*/
int logColl_mainProc()
{
	int i = 0;
	int idleLogSrcCount = 0;
	snmp_pdu tmpPdu;
	//var_list  tmpVarArr[MaxVarNum];
	snmp_addr tmpAddr;

#if logColl_DEBUG
	//system("clear");
	clrscr();
	printf
		("\nId  sysId   systemIp log/msgStat bgnNo/logNo/endNo sleepCount/sleepTime  Desc");
#endif
	for (i = 0; i < MaxLogSrcNum; i++) {
#if logColl_DEBUG
		printf("\n%d %d-%d-%d  %s  %d/%d \t %lu/%lu/%lu %d/%d \t%s ", i,
			   logSrcArr[i].sysTypeNo, logSrcArr[i].sysNo,
			   logSrcArr[i].subSysNo, logSrcArr[i].dstIP,
			   logSrcArr[i].logState, logSrcArr[i].msgState,
			   logSrcArr[i].bgnNo, logSrcArr[i].logNo, logSrcArr[i].endNo,
			   logSrcArr[i].sleepCount, logSrcArr[i].sleepTime,
			   logSrcArr[i].desc);
#endif
		if (logSrcArr[i].isEnable < 1) {
			continue;
		}
		switch (logSrcArr[i].logState) {
		case nGetInfo:
			if (logSrcArr[i].msgState == nIdle) 
			{
				logColl_sendMsg(i, &tmpPdu, &tmpAddr);
				logSrcArr[i].msgState = nWaitResponse;
				continue;
			} 
			else 
			{			//nWaitResponse
				if (!logColl_recvMsg(&i, &tmpPdu, &tmpAddr)) 
				{
					//not receive message or received invaild message
					//write log
					/*
					   #if logColl_DEBUG
					   omcLog(logFp,"%d %d-%d-%d  %s  %d/%d \t %lu/%lu/%lu %d/%d \t%s ", i,
					   logSrcArr[i].sysTypeNo,logSrcArr[i].sysNo,logSrcArr[i].subSysNo,
					   logSrcArr[i].dstIP,
					   logSrcArr[i].logState,logSrcArr[i].msgState,
					   logSrcArr[i].bgnNo,logSrcArr[i].logNo,logSrcArr[i].endNo,
					   logSrcArr[i].sleepCount,logSrcArr[i].sleepTime,
					   logSrcArr[i].desc);
					   #endif
					 */
					continue;
				}
			}

			if (logSrcArr[i].bgnNo >= logSrcArr[i].endNo) 
			{
				if (logSrcArr[i].bgnNo > logSrcArr[i].endNo && logSrcArr[i].bgnNo > (0x80000000 - logSrcArr[i].maxRecNumOfBuf)) 
				{
					//endNo overflow

					if (logSrcArr[i].logNo >= logSrcArr[i].bgnNo && logSrcArr[i].logNo > logSrcArr[i].endNo) 
					{
						//when endNo overflow.omc running normal
						omcLog(logFp, "LogNo is overflow,logNo=%ld,bgnNo=%ld,endNo=%ld,%s",logSrcArr[i].logNo,logSrcArr[i].bgnNo,logSrcArr[i].endNo,logSrcArr[i].dataStoreTable);
						logSrcArr[i].logState = nGetLog;
						logSrcArr[i].msgState = nIdle;
					} 
					else if (logSrcArr[i].logNo < logSrcArr[i].bgnNo && logSrcArr[i].logNo <= logSrcArr[i].endNo) 
					{
						logSrcArr[i].logState = nGetLog;
						logSrcArr[i].msgState = nIdle;
					} 
					else 
					{
						//logSrcArr[i].logNo < logSrcArr[i].bgnNo 
						//  && logSrcArr[i].logNo > logSrcArr[i].endNo

						//when endNo overflow,omc reset or network broke
						logSrcArr[i].logNo = logSrcArr[i].bgnNo;
						logSrcArr[i].logState = nGetLog;
						logSrcArr[i].msgState = nIdle;
					}
				} 
				else 
				{
					//no find new log
					sprintf(logSrcArr[i].desc, "No new log");
					logSrcArr[i].logState = nWaitLog;
					logSrcArr[i].msgState = nIdle;
#if logColl_DEBUG
					omcLog(logFp, "No new log  %s %lu/%lu/%lu  \t%s ",
						   logSrcArr[i].dstIP, logSrcArr[i].bgnNo,
						   logSrcArr[i].logNo, logSrcArr[i].endNo,
						   logSrcArr[i].dataStoreTable);
#endif
				}

			} 
			else if (logSrcArr[i].logNo > logSrcArr[i].endNo || logSrcArr[i].logNo < logSrcArr[i].bgnNo) 
			{
				//log source system be reset
				logSrcArr[i].logNo = logSrcArr[i].bgnNo;
				logSrcArr[i].logState = nGetLog;
				logSrcArr[i].msgState = nIdle;

			} 
			else 
			{
				// if(logSrcArr[i].logNo > logSrcArr[i].bgnNo 
				//      && logSrcArr[i].logNo < logSrcArr[i].endNo)                 
				if (logSrcArr[i].logNo == logSrcArr[i].endNo) 
				{
					//no find new log
					sprintf(logSrcArr[i].desc, "No new log");
					logSrcArr[i].logState = nWaitLog;
					logSrcArr[i].msgState = nIdle;
#if logColl_DEBUG
					omcLog(logFp, "No new log  %s %lu/%lu/%lu  \t%s ",
						   logSrcArr[i].dstIP, logSrcArr[i].bgnNo,
						   logSrcArr[i].logNo, logSrcArr[i].endNo,
						   logSrcArr[i].dataStoreTable);
#endif
				} 
				else 
				{
					//find new log
					omcLog(logFp, "Prepare to get log,logNo=%ld,bgnNo=%ld,endNo=%ld,%s",logSrcArr[i].logNo,logSrcArr[i].bgnNo,logSrcArr[i].endNo,logSrcArr[i].dataStoreTable);
					logSrcArr[i].logState = nGetLog;
					logSrcArr[i].msgState = nIdle;
				}
			}
			break;
		case nGetLog:
			if (logSrcArr[i].msgState == nIdle) {
				logColl_sendMsg(i, &tmpPdu, &tmpAddr);
				logSrcArr[i].msgState = nWaitResponse;
				omcLog(logFp, "Send snmp package to get log,logNo=%ld,bgnNo=%ld,endNo=%ld,%s",logSrcArr[i].logNo,logSrcArr[i].bgnNo,logSrcArr[i].endNo,logSrcArr[i].dataStoreTable);
				continue;
			} else {
				//nWaitResponse
				if (!logColl_recvMsg(&i, &tmpPdu, &tmpAddr)) {
					//write log
					omcLog(logFp,
						   "%d %d-%d-%d  %s  %d/%d \t %lu/%lu/%lu %d/%d \t%s ",
						   i, logSrcArr[i].sysTypeNo, logSrcArr[i].sysNo,
						   logSrcArr[i].subSysNo, logSrcArr[i].dstIP,
						   logSrcArr[i].logState, logSrcArr[i].msgState,
						   logSrcArr[i].bgnNo, logSrcArr[i].logNo,
						   logSrcArr[i].endNo, logSrcArr[i].sleepCount,
						   logSrcArr[i].sleepTime, logSrcArr[i].desc);
					continue;
				}
			}

			if (logSrcArr[i].logNo == logSrcArr[i].endNo) {
				//finish
				logSrcArr[i].logState = nGetInfo;
				logSrcArr[i].msgState = nIdle;
			}
			logSrcArr[i].msgState = nIdle;
			break;
		case nWaitLog:
			logSrcArr[i].sleepCount--;
			if (logSrcArr[i].sleepCount == 0) {
				logSrcArr[i].logState = nGetInfo;
				logSrcArr[i].sleepCount = logSrcArr[1].sleepTime;
			}
			break;
		default:				//nLogFail or unknown logState
			sprintf(logSrcArr[i].desc, "Unknown logState");
			logSrcArr[i].msgState = nIdle;
			logSrcArr[i].logState = nWaitLog;
			break;
		}						//end of switch()
	}							//end of for(..)
#if logColl_DEBUG
	printf("\n");
#endif
	if (idleLogSrcCount == MaxLogSrcNum) {
		//clear the msg buffer
		snmp_receive(&tmpPdu, &tmpAddr);
		return (2);
	} else {
		return (1);
	}
}


/*
*Function	:logColl_sendMsg
*Input		:Null
*Output		:Return 1: ok, 0:failed
*Descript	:
*/
int logColl_sendMsg(int logSrcArrNo, snmp_pdu * pdu, snmp_addr * addr)
{
	if (logColl_mkAddr(logSrcArrNo, addr) < 1) {
		return (0);
	}
	if (logColl_mkPdu(logSrcArrNo, pdu) < 1) {
		return (0);
	}
	if (snmp_send(pdu, addr) > 0) {
		sprintf(logSrcArr[logSrcArrNo].desc, "send snmp message ok!");
		omcLog(logFp, "Send request snmp package wait for response, %s",logSrcArr[logSrcArrNo].dataStoreTable);
		logSrcArr[logSrcArrNo].msgState = nWaitResponse;
		return (1);
	} else {
		//write log 
		omcLog(logFp,
			   "failed to send snmp msg,remote ip=%x,remote port=%d",
			   addr->remote_ip, addr->remote_port);

		sprintf(logSrcArr[logSrcArrNo].desc,
				"failed to send snmp message!");
		logSrcArr[logSrcArrNo].logState = nWaitLog;
		logSrcArr[logSrcArrNo].msgState = nIdle;
		return (0);
	}
}

/*
*Function	:logColl_recvMsg
*Input		:Null
*Output		:Return 1: ok, 0:failed
*Descript	:
*/
int logColl_recvMsg(int *logSrcArrNo, snmp_pdu * pdu, snmp_addr * addr)
{
	int i = *logSrcArrNo;
	int respProcReturn = 0;

	logColl_mkAddr(i, addr);
	if (snmp_receive(pdu, addr) > 0) {
		//received msg ok
		respProcReturn = logColl_procResp(logSrcArrNo, pdu);	//here maybe changed *logSrcArrNo's value
		i = *logSrcArrNo;
		if (respProcReturn > 0) {
			//vaild message
			logSrcArr[i].waitTimeCount = 0;
			logSrcArr[i].timeoutCount = 0;
			omcLog(logFp, "Receive log success,logNo=%ld,bgnNo=%ld,endNo=%ld,%s",logSrcArr[i].logNo,logSrcArr[i].bgnNo,logSrcArr[i].endNo,logSrcArr[i].dataStoreTable);
			return (1);
		} else if (respProcReturn == 0) {
			//invaild message
			logSrcArr[i].waitTimeCount++;
			omcLog(logFp, "Receive invalid snmp package,logNo=%ld,bgnNo=%ld,endNo=%ld,%s",logSrcArr[i].logNo,logSrcArr[i].bgnNo,logSrcArr[i].endNo,logSrcArr[i].dataStoreTable);
			//time out
			if (logSrcArr[i].waitTimeCount == 20) {
				logSrcArr[i].waitTimeCount = 0;
				logSrcArr[i].timeoutCount++;
				if (logSrcArr[i].timeoutCount > 2) {
					sprintf(logSrcArr[i].desc, "response timeout");
					logSrcArr[i].logState = nWaitLog;
					logSrcArr[i].msgState = nIdle;
				} else {		//send msg again
					logColl_sendMsg(i, pdu, addr);
				}				//end of if(logSrcArr[i].timeoutCount > 2)
			}					//end of if(logSrcArr[i].waitTimeCount == 20)
		} else {
			//error report message
			logSrcArr[i].logState = nGetInfo;
			logSrcArr[i].msgState = nIdle;
		}
	} else {
		//not received msg

		sprintf(logSrcArr[i].desc, "Receive snmp message failed!");
		logSrcArr[i].waitTimeCount++;

		//time out
		if (logSrcArr[i].waitTimeCount == 20) {
			logSrcArr[i].waitTimeCount = 0;
			logSrcArr[i].timeoutCount++;
			if (logSrcArr[i].timeoutCount > 2) {
				sprintf(logSrcArr[i].desc, "response timeout");
				logSrcArr[i].logState = nWaitLog;
				logSrcArr[i].msgState = nIdle;
			} else {			//send msg again
				logColl_sendMsg(i, pdu, addr);
			}					//end of if(logSrcArr[i].timeoutCount > 2)
		}						//end of if(logSrcArr[i].waitTimeCount == 20)
	}							//end of not received msg
	return (0);
}

/*
*Function	:logColl_mkPdu
*Input		:Null
*Output		:Return 1: ok, 0:failed
*Descript	:
*/
int logColl_mkPdu(int logSrcArrNo, snmp_pdu * pdu)
{
	if (logColl_mkVarArr(logSrcArrNo, pdu->var) < 1) {
		return (0);
	}
	pdu->pdu_type = nGet;
	pdu->request_id = logSrcArr[logSrcArrNo].requestId;
	pdu->var_num = logSrcArr[logSrcArrNo].varNum;
	strcpy(pdu->community, logSrcArr[logSrcArrNo].snmpCommunity);
	pdu->error_status = 0x0;	//0:no error 1:too big 2:nosuchname 3:badvalue 4:readonly 5:generr
	pdu->error_index = 0x0;
	return (1);
}


/*
*Function	:logColl_mkAddr
*Input		:Null
*Output		:Return 1: ok, 0:failed
*Descript	:
*/
int logColl_mkAddr(int logSrcArrNo, snmp_addr * addr)
{
	if (strlen(logSrcArr[logSrcArrNo].dstIP) <= 0) {
		omcLog(logFp, "Initing snmp_addr error: Cannot get ip");
		logSrcArr[logSrcArrNo].logState = nWaitLog;
		return (0);
	}
	//addr->local_ip    = ;
	addr->local_port = DefPort;
	addr->remote_ip = inet_addr(logSrcArr[logSrcArrNo].dstIP);
	addr->remote_port = logSrcArr[logSrcArrNo].dstPort;
	addr->broadcast = 0;
	return (1);
}

/*
*Function	:logColl_mkVarArr
*Input		:int logSrcArrNo,var_list *varArr
*Output		:Return 1: ok, 0:failed
*Descript	:
*/
int logColl_mkVarArr(int logSrcArrNo, var_list * varArr)
{
	var_list *unitVar;
	int i, varCount = 0;
	int totalMsgLen = 0;

	for (varCount = 0; varCount < MaxVarNum; varCount++) {
		unitVar = varArr + varCount;

		for (i = 0; i < logSrcArr[logSrcArrNo].preObjIdLen; i++) {
			unitVar->oid[i] = logSrcArr[logSrcArrNo].preObjId[i];
		}

		if (logSrcArr[logSrcArrNo].logState == nGetInfo) {
			unitVar->vartype = nInteger;
			unitVar->oidlen = logSrcArr[logSrcArrNo].preObjIdLen + 1;
			unitVar->msglen = 4;
			if (varCount == 0) {
				unitVar->oid[i] = nBgnOid;
			} else {
				unitVar->oid[i] = nEndOid;
				break;
			}
		} else {				//nGetLog
			unitVar->msglen = logSrcArr[logSrcArrNo].maxSizeOfRec;
			unitVar->vartype = nOctetString;
			unitVar->oidlen = logSrcArr[logSrcArrNo].preObjIdLen + 2;
			unitVar->oid[i] = nDataOid;
			if (logSrcArr[logSrcArrNo].logNo + varCount >= 0x80000000) {
				unitVar->oid[i + 1] =
					logSrcArr[logSrcArrNo].logNo + varCount - 0x80000000;
			} else {
				unitVar->oid[i + 1] =
					logSrcArr[logSrcArrNo].logNo + varCount;
				if(unitVar->oid[i + 1] < (0x80000000 - logSrcArr[logSrcArrNo].maxRecNumOfBuf)) 
				{
					if(unitVar->oid[i + 1] >= (logSrcArr[logSrcArrNo].endNo - 1)) 
					{
						break;
					}
				}
			}
			omcLog(logFp, "Make Var,logNo=%ld,%s",logSrcArr[logSrcArrNo].logNo,logSrcArr[logSrcArrNo].dataStoreTable);
		}
		totalMsgLen = totalMsgLen + unitVar->oidlen + unitVar->msglen;

		//check the message len
		if ((totalMsgLen + unitVar->oidlen + unitVar->msglen) >
			logSrcArr[logSrcArrNo].maxMsgLen) {
			break;
		}
	}							//end of for()
	logSrcArr[logSrcArrNo].finishVarNum = 0;
	logSrcArr[logSrcArrNo].totalVarNum = varCount;
	logSrcArr[logSrcArrNo].varNum = varCount + 1;
	return (1);
}


/*
*Function	:logColl_procResp
*Input		:Null
*Output		: 1 : ok, 
*			: 0 : invailed message(unmatched requestId,objectId,pduType or message format error)
*			:-1 : error message(varType or errorState > 0)
*Descript	:
*/
int logColl_procResp(int *oldlogSrcArrNo, snmp_pdu * pdu)
{
	int i, j, logSrcArrNo, tlvCount;
	char tmpQuery[3500] = "\0";
	char tmpValue[3000] = "\0";
	int tlvLen = 0;
	int tlvIntValue = 0;
	char tlvAscValue[512] = "\0";
	BYTE tlvBcdValue[256];
	ASN_BUF asnBuffer;
	unsigned long tmpInstanceNo = 0;

	//here if oldlogSrcArrNo's address cannot be access,will core down
	if (*oldlogSrcArrNo >= MaxLogSrcNum) {
		omcLog(logFp, " Error: oldlogSrcArrNo is too big (%d)",
			   *oldlogSrcArrNo);
		return (0);
	}
	logSrcArrNo = *oldlogSrcArrNo;

#if logColl_DEBUG
	//  omcLog(logFp," ----- Processing logSrcArr[%d]'s response message ",logSrcArrNo);
#endif
	//check pdu_type
	if (pdu->pdu_type != nResp) {
		sprintf(logSrcArr[logSrcArrNo].desc, "Error pdu type:%d(!=Resp%d)",
				pdu->pdu_type, nResp);
		omcLog(logFp, "logColl_procResp:Error pdu type:%d(!=Resp%d)",
			   pdu->pdu_type, nResp);
		return (0);
	}
	//check request_id
	if (pdu->request_id != logSrcArr[logSrcArrNo].requestId) {
		int isRequestIdMatch = 0;

		for (i = 0; i < MaxLogSrcNum; i++) {
			if (pdu->request_id == logSrcArr[i].requestId) {
				isRequestIdMatch = 1;
				*oldlogSrcArrNo = i;
				logSrcArrNo = i;
				break;
			}
		}
		if (isRequestIdMatch == 0) {
			sprintf(logSrcArr[logSrcArrNo].desc,
					"unknown pdu->request_id(%ld)", pdu->request_id);
			omcLog(logFp, "unknown snmp package to receive,logNo=%ld,bgnNo=%ld,endNo=%ld,%s",logSrcArr[i].logNo,logSrcArr[i].bgnNo,logSrcArr[i].endNo,logSrcArr[i].dataStoreTable);
			return (0);
		}
	}

	for (i = 0; i < pdu->var_num; i++) {
		int errStr;

		//check ObjId len
		if (pdu->var[i].oidlen <= logSrcArr[logSrcArrNo].preObjIdLen) {
			sprintf(logSrcArr[logSrcArrNo].desc,
					"Oid is too short (oidlen =%d)", pdu->var[i].oidlen);
			omcLog(logFp, "Oid is too short (oidlen =%d)",
				   pdu->var[i].oidlen);
			return (0);
		}
		//check preObjId
		for (j = 0; j < logSrcArr[logSrcArrNo].preObjIdLen; j++) {
			if (logSrcArr[logSrcArrNo].preObjId[j] != pdu->var[i].oid[j]) {
				int k = 0;
				sprintf(logSrcArr[logSrcArrNo].desc, " Oid is not match!");
				omcLog(logFp, "Oid is not match!");
				for (k = 0; k < logSrcArr[logSrcArrNo].preObjIdLen; k++) {
					omcLog(logFp, " %d: %ld [%ld]", k,
						   logSrcArr[logSrcArrNo].preObjId[k],
						   pdu->var[i].oid[k]);
				}
				return (0);
			}
		}
		//check msgbuffer len
		//if(pdu->var[i].msglen >= (sizeof(tmpValue)/2)){
		//  sprintf(logSrcArr[logSrcArrNo].desc,"Msg is too long(%d)",pdu->var[i].msglen);
		//  return(0);
		//}

		//check value type
		switch (pdu->var[i].vartype) {
		case 0x02:				//INTEGER
			if (logSrcArr[logSrcArrNo].logState == nGetInfo) {
				break;
			} else {
				sprintf(logSrcArr[logSrcArrNo].desc, "INTEGER");
				return (-1);
			}
		case 0x04:				//OCTET STRING
			break;
		case 0x05:				//NULL(unSpecified)
			sprintf(logSrcArr[logSrcArrNo].desc, "NULL");
			return (-1);
		case 0x06:				//OBJECT IDENTIFIER
			sprintf(logSrcArr[logSrcArrNo].desc, "OBJECT IDENTIFIER");
			return (-1);
		case 0x80:				//noSuchObject
			sprintf(logSrcArr[logSrcArrNo].desc, "noSuchObject");
			return (-1);
		case 0x81:				//NoSuchInstance
			sprintf(logSrcArr[logSrcArrNo].desc, "NoSuchInstance");
			return (-1);
		case 0x82:				//endOfMibView
			sprintf(logSrcArr[logSrcArrNo].desc, "endOfMibView");
			return (-1);
		default:
			sprintf(logSrcArr[logSrcArrNo].desc, "Invailed vartype(%d)",
					pdu->var[i].vartype);
			return (-1);
		}

		//check error status and error index
		if ((pdu->error_status > 0) && (pdu->error_index == (i + 1))) {
			omcLog(logFp,
				   "Error message: pdu->error_status =%d  pdu->error_index =%d",
				   pdu->error_status, pdu->error_index);
			if (pdu->error_status < MaxErrorStatusNum) {
				sprintf(logSrcArr[logSrcArrNo].desc, "Error:%s",
						errorStatusDescArr[pdu->error_status]);
			} else {
				sprintf(logSrcArr[logSrcArrNo].desc,
						"Error:Unknown snmp error status");
			}
			return (-1);
		}

		if (logSrcArr[logSrcArrNo].logState == nGetInfo
			&& pdu->var[i].oid[logSrcArr[logSrcArrNo].preObjIdLen] !=
			nDataOid) {
			if (pdu->var[i].oid[logSrcArr[logSrcArrNo].preObjIdLen] ==
				nBgnOid) {
				logSrcArr[logSrcArrNo].bgnNo =
					decode_integer(pdu->var[i].msg, pdu->var[i].msglen);
			} else if (pdu->var[i].
					   oid[logSrcArr[logSrcArrNo].preObjIdLen] ==
					   nEndOid) {
				logSrcArr[logSrcArrNo].endNo =
					decode_integer(pdu->var[i].msg, pdu->var[i].msglen);
			} else {
				//error report
				omcLog(logFp, "Error message: last oid != 1,2,3");
				return (-1);
			}
		} else {				/*get data and update to database */
			char tmpUnitValue[1024] = "\0";
			char tmpSetStr[1024] = "\0";
			int attrDefnBgn = logSrcArr[logSrcArrNo].attrDefnArrOffset;
			int attrDefnEnd = logSrcArr[logSrcArrNo].attrDefnArrOffset
				+ logSrcArr[logSrcArrNo].attrDefnNum;
			int varCount = 0;

			tmpValue[0] = 0;

			tmpInstanceNo =
				pdu->var[i].oid[logSrcArr[logSrcArrNo].preObjIdLen + 1];

			//decode msg to asn buffer
			AsnDecode(pdu->var[i].msg, pdu->var[i].msglen, 1024, &errStr,
					  &asnBuffer);

			//get value form asnbuffer and make SQL string
			for (tlvCount = attrDefnBgn; tlvCount < attrDefnEnd;
				 tlvCount++) {
				tmpSetStr[0] = 0;
				switch (attrDefnArr[tlvCount].valueType) {
				case 0x02:		//INTEGER
					tlvLen =
						GetInteger(attrDefnArr[tlvCount].fieldObjIdStr,
								   &tlvIntValue, 0x80, &asnBuffer);
					sprintf(tmpSetStr, "%s = '%d'",
							attrDefnArr[tlvCount].fieldName, tlvIntValue);
					break;
				case 0x03:		//OCTET STRING -> Asc
					memset(tlvAscValue, 0, sizeof(tlvAscValue));
					tlvLen =
						GetTLV(attrDefnArr[tlvCount].fieldObjIdStr,
							   attrDefnArr[tlvCount].valueLen, (u_char*)tlvAscValue,
							   0x80, &asnBuffer);
					sprintf(tmpSetStr, "%s = '%s'",
							attrDefnArr[tlvCount].fieldName, tlvAscValue);
					break;
				case 0x04:		//OCTET STRING -> Hex
					memset(tlvBcdValue, 0, sizeof(tlvBcdValue));
					memset(tmpUnitValue, 0, sizeof(tmpUnitValue));
					tlvLen =
						GetTLV(attrDefnArr[tlvCount].fieldObjIdStr,
							   attrDefnArr[tlvCount].valueLen, tlvBcdValue,
							   0x80, &asnBuffer);
					if (tlvLen >= 0) {
						omc_RbcdToAscii(tmpUnitValue, tlvBcdValue,
										tlvLen * 2);
						sprintf(tmpSetStr, "%s = '%s'",
								attrDefnArr[tlvCount].fieldName,
								tmpUnitValue);
					}
					break;
				default:
					sprintf(logSrcArr[logSrcArrNo].desc,
							" Invailed vartype(attrDefnArr[%d].valueType=%d)",
							tlvCount, attrDefnArr[tlvCount].valueType);
					return (-1);
				}
				if (tlvLen >= 0) {
					if (varCount == 0) {
						strcat(tmpValue, tmpSetStr);
					} else {
						strcat(tmpValue, ", ");
						strcat(tmpValue, tmpSetStr);
					}
					varCount++;
				} else {
					omcLog(logFp, " can not get tlvTag[%s]'s tlvValue",
						   attrDefnArr[tlvCount].fieldObjIdStr);
					return (0);
				}
			}					//end of for(..)

			//Query SQL
			if (strlen(logSrcArr[logSrcArrNo].dataStoreTable) > 1
				&& strlen(tmpValue) > 3) {
				int errorNo=0;
				int result=0;
				tmpQuery[0] = 0;
				sprintf(tmpQuery, "REPLACE %s SET %s",
						logSrcArr[logSrcArrNo].dataStoreTable, tmpValue);
				omcLog(logFp, "Replace log into %s",logSrcArr[logSrcArrNo].dataStoreTable);
				result=mysql_getnores(dbConn, tmpQuery);
				
				errorNo = mysql_errno(dbConn);
				if (errorNo > 0) 
				{
					omcLog(logFp, "\n Error number:%d", mysql_errno(dbConn));
					omcLog(logFp, "\n Description: %s", mysql_error(dbConn));
					if(errorNo == 2006)
					{
						mysql_close(dbConn);
						omcLog(logFp, "Mysql has gone away");
						dbConn = mysql_conn(HOSTNAME, PUB_DB);
						if (dbConn == NULL) {
							omcLog(logFp, " Fail to reconnect");
						}
						result=0;
						result=mysql_getnores(dbConn, tmpQuery);
						if(result == -1)
						{
							omcLog(logFp, " Reconnect,but fail too");
							omcLog(logFp,"\n%s\n", tmpQuery);
						}
					}
				}
			}
			//if(tmpInstanceNo >= 0x80000000){
			//  logSrcArr[logSrcArrNo].logNo = tmpInstanceNo - 0x80000000;
			//}else{
			if (tmpInstanceNo + 1 <= logSrcArr[logSrcArrNo].endNo) {
				logSrcArr[logSrcArrNo].logNo = tmpInstanceNo + 1;
			}
			//}
		}						//end of if(logSrcArr[logSrcArrNo].logState == nGetInfo)
	}							//end of for(i = 0; i < pdu->var_num; i++)

	return (1);
}								//end of function

