/*************************************************
File name:	subsComm.c
Author: 	
Version:	9:00:00 
Date:  		2007-7-27
Description:该文件实现了用户数据管理模块的主要功能，包括添加，获取，修改，删除一个用户数据，
			或者进行批量读取和批量添加用户数据
			
			调用snmp模块的函数
			void snmp_init(WORD nport);
			int snmp_receive(snmp_pdu *msgbuf,snmp_addr *addr);
			int snmp_send(snmp_pdu *msgbuf,snmp_addr *addr);
			
												
History:               
No. 		
Author:		  
Date:		 
Version:	   
Description:
*************************************************/
#include <stdlib.h>
#include <string.h>
#include "subsComm.h"
#include "mysql.h"

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

/***********Private Functions Declare***********************/
int subsComm_initSysConfArr();
int subsComm_initParamConfArr();
int subsComm_initUnitComm();
int subsCommScan();
int subsCommProc();
int subsComm_procResp();
int subsComm_getIp();
int subsComm_mkAddr();
int subsComm_mkPdu();
int subsComm_mkVarArr();
int subsComm_updateCommTable();
void subsComm_freeParamSet();
int encodeKeyValue();
int decodeKeyValue();

/**********       全局变量定义申明      ************/
int		subsComm_timerCount = 0;
static	FILE *subsCommLog;
int		oldDay = 0; //1-31
static	MYSQL *dbConn;

// for smcli
static	char errorStatusDescArr[19][50]={"Operation completed","The value is too big","No such field","Error field value",
										"The field is read only","General error (not defined error)","No access to the field",
										"Wrong value type","Wrong value length","Wrong encoding of the value","Wrong value of the field",
										"Cannot create the record","The value is incosistent","Resource unavailable","Commit failed(try again)",
										"Undo failed","Error authorization info","The field is not writable","Inconsistent field name"};
static	int MaxErrorStatusNum = 19;
static	unitComm			commArr[MaxCommNum];
static	unitSysConf		sysConfArr[MaxSysConfNum];
static	unitParamConf	paramConfArr[MaxParamConfNum];

/*************************************************
Function:        // subsCommInit
Description:     // 初始化subsComm模块，打开日志文件，初始化数据库链接，初始化数据.
Calls:           // omcLogInit; mysql_conn; mysql_getnores; subsComm_initSysConfArr; subsComm_initParamConfArr;
Called By:       // subsCommMain.c:main;
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 1:successful; 0:failed;
Others:          // 必须首先调用该函数
*************************************************/
int subsCommInit()
{
	char commQuery[100]	= "\0";
	long		nowTime;
	struct tm	*nowTm;


	//创建或打开日志文件
	omcLogInit(subsComm_LogPath,subsComm_LogFile,&subsCommLog);
	nowTime	= time(NULL);
	nowTm	= localtime(&nowTime);
	oldDay = nowTm->tm_mday;

	
	//初始化数据库连接
	dbConn = mysql_conn(HOSTNAME,PUB_DB);
	if(dbConn == NULL){
		omcLog(subsCommLog,"[ERR][subsCommInit]connection OMC_PUB");
		exitLog("subsComm:subsCommInit, Connect to OMC_PUB error");
		exit(1);
	}
	
	//清空用户命令表
	sprintf(commQuery,"DELETE FROM %s", CommTable);
	mysql_getnores(dbConn,commQuery);
	//if(!mysql_getnores(dbConn,commQuery)){
		//printf(stderr,"Fail to init command table");
		//omcLog(subsCommLog,"Fail to init command table");
		//exit(1);
	//}
	
	//初始化系统配置参数
	if(!subsComm_initSysConfArr()){
		//printf(stderr,"Fail to init system configuration array");
		omcLog(subsCommLog,"Fail to init system configuration array");
		exitLog("subsComm:subsCommInit, subsComm_initSysConfArr function error");
		exit(1);
	}

	//初始化用户数据子对象
	if(!subsComm_initParamConfArr()){
		//printf(stderr,"Fail to init parameter configuration array");
		omcLog(subsCommLog,"Fail to init parameter configuration array");
		exitLog("subsComm:subsCommInit, subsComm_initParamConfArr function error");
		exit(1);
	}
	return(1);
}//end subsCommInit

/*************************************************
Function:        // sendHeartbeat
Description:     // Send process heartbeat to beatProc
Calls:           // snmp_send
Called By:       // subsCommTimer
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,"subsComm");
	
	//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(subsCommLog,"Send heartbeat fail");
		return 0;
	}
	return 1;
}

/*************************************************
Function:        // subsCommTimer
Description:     // subsComm模块定时器函数，扫描用户数据命令表，并对命令进行处理
Calls:           // subsCommScan; subsCommProc; omcLogInit;
Called By:       // cdrmain.c:onTimer;
Table Accessed:  // OMC_PUB.subsDataBackupTable;
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 1:successful; 0:failed;
Others:          // 每4*20ms调用该函数一次
*************************************************/
unsigned long heartbeat_timeout=0;
int subsCommTimer()
{
	
	
	if(time(NULL) - heartbeat_timeout > 5)
	{
		heartbeat_timeout=time(NULL);
		sendHeartbeat();
	}
	
	//扫描用户数据命令表
	subsCommScan();
	
	if(subsComm_timerCount < 300){//300*4*20/1000=24S
		subsComm_timerCount++;
	}else{
		long			l_time;
		struct tm		*t;
		l_time=time(NULL);
		t=localtime(&l_time);
		
		//如果程序运行到新的一天
		if(t->tm_mday != oldDay){
			int i;
			char loadoutSql[400];
			char loadoutFile[100];
			char tmpSql[1024];
			MYSQL_RES *tmpResult = NULL;
			omcLog(subsCommLog,"Check time nowDay[%d] != oldDay[%d]",t->tm_mday,oldDay);
			//backup subscriber's data to subsComm_backupPath
			for(i=0;i<MaxSysConfNum;i++){
				if(!sysConfArr[i].isEnable){
					continue;
				}

				sprintf(tmpSql,"SELECT * FROM %s WHERE sysTypeNo=\'%d\' AND dataTypeNo=\'%d\' AND flag >'0'",subsDataBackupTable,sysConfArr[i].sysTypeNo,sysConfArr[i].dataTypeNo);
				tmpResult = (MYSQL_RES *) mysql_getres(dbConn, tmpSql);
				
				//不对PPS用户数据进行备份，由另外一个程序处理PPS的备份
				if (tmpResult != NULL && mysql_num_rows(tmpResult) > 0) {
					mysql_free_result(tmpResult);
					//Please wait this command finished 
					continue ;
				}else
					mysql_free_result(tmpResult);
				
				//对前一天的用户数据进行备份
				sprintf(loadoutFile,"%s/%s_%d_%d.csv",subsComm_backupPath,
					sysConfArr[i].paramTableName,t->tm_mon + 1,t->tm_mday-1);
				unlink(loadoutFile);
				sprintf(loadoutSql,"SELECT * INTO OUTFILE '%s' "\
							" FIELDS TERMINATED BY ',' FROM %s",loadoutFile,sysConfArr[i].paramTableName);
				mysql_getnores(dbConn,loadoutSql);
				omcLog(subsCommLog,"backup %s finished",sysConfArr[i].paramTableName);
			
			}
			
			//对新的一天创建一个新的日志文件来保存当天的日志
			omcLogInit(subsComm_LogPath,subsComm_LogFile,&subsCommLog);
			oldDay = t->tm_mday;
		}
		subsComm_timerCount = 0;
	}
	
	//处理用户数据命令表
	if(subsCommProc()){
		return(1);
	}else{
		return(0);
	}
}//end subsCommTimer

/*************************************************
Function:        // subsCommScan
Description:     // 从用户数据命令表中查询要执行的操作命令，并且保存在命令缓冲区里
Calls:           // mysql_getres; mysql_num_rows; subsComm_updateCommTable; subsComm_getIp;
Called By:       // subsCommTimer;
Table Accessed:  // OMC_PUB.subscriberComm
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // >=1:command number; 0:no command; -1:failed
Others:          // 
*************************************************/
int subsCommScan()
{
	char commQuery[2048]		= "\0";
	char replaceSql[2048]	= "\0";
	char paramQuery[2048]	= "\0";	
	char queryWhere[2048]	= "\0";
	char tmpStr[2048]		= "\0";
	MYSQL_RES *commResult=NULL;
	MYSQL_ROW commRow=NULL;
	int i=0, commArrNo=0;	
	
	CheckMysqlConnect(&dbConn);
		
		
	//从用户数据命令表中查找出正在等待执行的命令	
	sprintf(commQuery,"SELECT commId,commType,dataTypeNo,sysTypeNo,sysNo,subSysNo,paramType,indexValueList,fieldNameList,remark"\
				" FROM %s WHERE commState = '%d' ORDER BY sysTypeNo,sysNo,subSysNo",CommTable,nWaitProc);
	commResult=(MYSQL_RES*)mysql_getres(dbConn,commQuery);
	if(commResult == NULL){
		omcLog(subsCommLog,"Database may be stopped,In scan command");
		return(-1);
	}	
	//没有要执行的命令，停止扫描
	else if(mysql_num_rows(commResult) == 0){
		mysql_free_result(commResult);
		return(0);
	}
	
	//找到正在等待执行的命令记录
	while((commRow=mysql_fetch_row(commResult)) > 0){
		MYSQL_RES *paramResult=NULL;
		//At first,If there are loadIndexComm,Can not process other type comamnd
		for(commArrNo = 0; commArrNo < loadDataCommStartNo; commArrNo++){
			//先检查命令数组里面有没有get index的命令，有的话让该命令继续进行处理，结束命令扫描
			if(commArr[commArrNo].commType == nLoadIndexComm && atoi(commRow[1]) == nLoadIndexComm
						&& (commArr[commArrNo].commState == nWaitProc || commArr[commArrNo].commState == nInProc)){
				#if subsComm_DEBUG
					omcLog(subsCommLog,"Uploading data,ignore another Upload command");
				#endif
				sprintf(commQuery,"UPDATE  %s SET commState='%d',remark='Uploading other subscribers,please wait...' "\
										" WHERE commId = '%s' "\
						,CommTable,nProcFail,commRow[0]);
				mysql_getnores(dbConn,commQuery);

				mysql_free_result(commResult);
				return(-1);
			}
		}

		for(commArrNo = 0; commArrNo < loadDataCommStartNo; commArrNo++){
			//在命令缓冲区找到空闲的命令对象
			if(commArr[commArrNo].procState == nIdle 
						&& commArr[commArrNo].commState != nWaitProc
							&&  commArr[commArrNo].commState != nInProc){
				//对该命令对象的值进行初始化置零				
				subsComm_initUnitComm(commArrNo);
				break;
			}else{
				//命令缓冲区没有空闲的命令对象，结束命令扫描
				if(commArrNo == (loadDataCommStartNo - 1)){
					#if subsComm_DEBUG
						omcLog(subsCommLog,"System busy,please wait..");
					#endif
					/*
					sprintf(commQuery,"UPDATE  %s SET commState='%d',remark='CommBuf is full,please wait..' "\
							" WHERE commId = '%s'"\
							,CommTable,nProcFail,commRow[0]);
					mysql_getnores(dbConn,commQuery);
					*/
					mysql_free_result(commResult);
					return(-1);
				}
			}
		}//end of for(..)

		
		//把用户数据命令表的命令记录的值赋到命令缓冲区的命令对象里
		commArr[commArrNo].commState	= nInProc;
		commArr[commArrNo].commNo		= atoi(commRow[0]);			//<--
		commArr[commArrNo].commType		= atoi(commRow[1]);			//<--
		commArr[commArrNo].dataTypeNo	= atoi(commRow[2]);			//<--
		commArr[commArrNo].sysTypeNo	= atoi(commRow[3]);			//<--
		commArr[commArrNo].sysNo		= atoi(commRow[4]);			//<--
		commArr[commArrNo].subSysNo		= atoi(commRow[5]);			//<--
		//commArr[commArrNo].paramType	= (BYTE)atoi(commRow[6]);	//<--
		//change this,can support delete more one subscriber 
		if(strlen(commRow[7]) < sizeof(commArr[commArrNo].indexBuffer[0])){
			strcpy(commArr[commArrNo].indexBuffer[0],commRow[7]);	//<--
		}
		sprintf(commArr[commArrNo].fieldNameList,"%s",commRow[8]);	//<--

		//找到该命令对象对应的系统参数对象的索引号
		for(i=0;i<MaxSysConfNum;i++){
			//由于VSS有系统号的区分，所以另外处理
			if(commArr[commArrNo].sysTypeNo==VMS_No ||
			   commArr[commArrNo].sysTypeNo==UDM_No ||
			   commArr[commArrNo].sysTypeNo==AUSF_No){
				if((sysConfArr[i].isEnable) 
					&& (sysConfArr[i].sysTypeNo == commArr[commArrNo].sysTypeNo)
					&& (sysConfArr[i].dataTypeNo == commArr[commArrNo].dataTypeNo)
					&&(sysConfArr[i].sysNo==commArr[commArrNo].sysNo)){
					commArr[commArrNo].sysConfArrNo = i;
					break;
				}
			}
			else{
				if((sysConfArr[i].isEnable)
					&&(sysConfArr[i].sysTypeNo==commArr[commArrNo].sysTypeNo)
					&&(sysConfArr[i].dataTypeNo==commArr[commArrNo].dataTypeNo)){
					commArr[commArrNo].sysConfArrNo=i;
					break;
				}
			}
		}

		//获取每个系统设备的IP地址
		if(!subsComm_getIp(commArr[commArrNo].sysTypeNo,commArr[commArrNo].sysNo,
						commArr[commArrNo].subSysNo,commArr[commArrNo].dstIP)){
			//无法在sysInfo表里获取该系统设备的IP				
			sprintf(commArr[commArrNo].desc,"Cannot get this system s IP");
			commArr[commArrNo].commState = nProcFail;
			subsComm_updateCommTable(commArrNo);
			commArr[commArrNo].procState = nIdle;
			break;
		}
		
		//check commType
		switch(commArr[commArrNo].commType){
			case  nReadComm:
				break;
			case  nChangeComm:
				break;
			case  nCreateComm:
				break;
			case  nDeleteComm:
				/*modified by cuiticun 2005-8-18
				
				commArr[commArrNo].totalNum = 1;
				subsComm_updateCommTable(commArrNo);
				mysql_free_result(commResult);
				return(1);
				*/
				break;
			case  nLoadIndexComm:
				break;
			case  nReplaceIndexComm:			
				commArr[commArrNo].totalNum = 1;
				strcpy(commArr[commArrNo].indexBuffer[1],commRow[9]);
				subsComm_updateCommTable(commArrNo);
				mysql_free_result(commResult);
				return(1);
				break;
			default:
				mysql_free_result(commResult);
				omcLog(subsCommLog,"unknown command type");
				return(-1);
		}

		//获取全部的用户数据参数子对象
		if(strcmp(commArr[commArrNo].fieldNameList,"ALL") == 0){
			int paramConfBgn	= sysConfArr[commArr[commArrNo].sysConfArrNo].paramConfArrOffset;
			int paramConfEnd	= sysConfArr[commArr[commArrNo].sysConfArrNo].paramConfArrOffset 
									+ sysConfArr[commArr[commArrNo].sysConfArrNo].paramConfNum;
			commArr[commArrNo].fieldNameList[0] = 0;
			for(i=paramConfBgn;i<paramConfEnd;i++){
				tmpStr[0]=0;
				if(i == paramConfBgn){
					sprintf(tmpStr,"%s",paramConfArr[i].fieldName);
				}else{
					sprintf(tmpStr,",%s",paramConfArr[i].fieldName);
				}
				strcat(commArr[commArrNo].fieldNameList,tmpStr);
			}
		}
		#if subsComm_DEBUG
		omcLog(subsCommLog,"commArr[%d].fieldNameList = %s",commArrNo,commArr[commArrNo].fieldNameList);
		#endif

		//获取用户数据索引时，把命令的任务总容量置为系统的最大段数，此时一般是getall操作命令
		if(commArr[commArrNo].commType == nLoadIndexComm){
			paramResult = NULL;
			commArr[commArrNo].totalNum = sysConfArr[commArr[commArrNo].sysConfArrNo].maxSegmentNum; //<--
		}else{
			if((commArr[commArrNo].sysTypeNo==330)&&(commArr[commArrNo].dataTypeNo==1))
				sprintf(queryWhere," %s LIKE '91%sE%%' ",sysConfArr[commArr[commArrNo].sysConfArrNo].indexFieldName,commArr[commArrNo].indexBuffer[0]);
			else
				sprintf(queryWhere," %s='%s' ",sysConfArr[commArr[commArrNo].sysConfArrNo].indexFieldName,commArr[commArrNo].indexBuffer[0]);


			sprintf(paramQuery,"SELECT %s FROM %s WHERE %s ",
						commArr[commArrNo].fieldNameList,
						sysConfArr[commArr[commArrNo].sysConfArrNo].tmpTableName,
						queryWhere);

			if(paramResult!=NULL)
			{
				mysql_free_result(paramResult);
				paramResult=NULL;
			}
			
			paramResult=NULL;
			paramResult=(MYSQL_RES*)mysql_getres(dbConn,paramQuery); //<--

	//mysql_free_result(commResult);


			if(paramResult == NULL){
				mysql_free_result(commResult);
				omcLog(subsCommLog,"Database may be stopped,when get paramSet");
				return(0);
			}
			commArr[commArrNo].totalNum = mysql_num_rows(paramResult);//<--	
		}
		if(commArr[commArrNo].totalNum <= 0){
			/*modified by cuiticun 2005-8-18

			omcLog(subsCommLog,"totalNum <= 0");
			commArr[commArrNo].commState = nProcFail;
			commArr[commArrNo].procState = nIdle;
			sprintf(commArr[commArrNo].desc,"Cannot get this object value record!");
			subsComm_updateCommTable(commArrNo);
			mysql_free_result(paramResult);
			commArr[commArrNo].paramSet = NULL;
			return(0);
			*/

			mysql_free_result(paramResult);
			
			//修改用户数据的index的值
			sprintf(replaceSql,"REPLACE %s SET %s='%s'",sysConfArr[commArr[commArrNo].sysConfArrNo].tmpTableName,sysConfArr[commArr[commArrNo].sysConfArrNo].indexFieldName,commArr[commArrNo].indexBuffer[0]);
			mysql_getnores(dbConn, replaceSql);
			
			sprintf(queryWhere," %s='%s' ",sysConfArr[commArr[commArrNo].sysConfArrNo].indexFieldName,commArr[commArrNo].indexBuffer[0]);
			sprintf(paramQuery,"SELECT %s FROM %s WHERE %s ",
						commArr[commArrNo].fieldNameList,
						sysConfArr[commArr[commArrNo].sysConfArrNo].tmpTableName,
						queryWhere);
			paramResult=(MYSQL_RES*)mysql_getres(dbConn,paramQuery); //<--

			if(paramResult == NULL){
				mysql_free_result(commResult);
				omcLog(subsCommLog,"Database may be stopped,when get paramSet");
				return(0);
			}
			commArr[commArrNo].totalNum = mysql_num_rows(paramResult);//<--

			commArr[commArrNo].finishNum	= 0;//<--
			if(commArr[commArrNo].paramSet != NULL)
			{
				mysql_free_result(commArr[commArrNo].paramSet);
				commArr[commArrNo].paramSet=NULL;
			}
			commArr[commArrNo].paramSet	= paramResult;//<--	
			subsComm_updateCommTable(commArrNo);

		}else{
			commArr[commArrNo].finishNum	= 0;//<--
			
			if(commArr[commArrNo].paramSet != NULL)
			{
				mysql_free_result(commArr[commArrNo].paramSet);
				commArr[commArrNo].paramSet=NULL;
			}
			
			commArr[commArrNo].paramSet	= paramResult;//<--		
			subsComm_updateCommTable(commArrNo);
		}
	}//end of while(..)
	mysql_free_result(commResult);
	return(1);
}//end subsCommScan

/*************************************************
Function:        // subsCommProc
Description:     // 处理命令结构体数组内的命令，根据命令发送接收消息，判断命令响应超时
Calls:           // subsComm_updateCommTable; subsComm_mkAddr; subsComm_mkVarArr; subsComm_mkPdu; snmp_receive; snmp_send;
Called By:       // subsCommTimer;
Table Accessed:  // OMC_PUB.subscriberComm
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 1:successful; 0:failed;
Others:          // 
*************************************************/
int subsCommProc()
{
	int i = 0,j = 0;
	int idleCommCount = 0;
	snmp_pdu	tmpPdu;
	var_list	tmpVarArr[MaxVarNum];
	// memset(&tmpPdu, 0, sizeof(tmpPdu));
	// memset(&tmpVarArr[0], 0, sizeof(var_list)*MaxVarNum);
	snmp_addr	tmpAddr;
	#if subsComm_DEBUG
		clrscr();
		printf("\n commId  systemId  systemIp comm/procState finish/total Desc");
	#endif
	
	//遍历命令对象，以便执行命令
	for(i=0;i<MaxCommNum;i++){
		#if subsComm_DEBUG
		printf("\n %d \t %d-%d-%d  %s \t %d/%d \t %d/%d  \t%s ",i,
				commArr[i].sysTypeNo,commArr[i].sysNo,commArr[i].subSysNo,
				commArr[i].dstIP,
				commArr[i].commState,commArr[i].procState,
				commArr[i].finishNum,commArr[i].totalNum,
				commArr[i].desc);
		#endif
		//正在执行的命令
		if(commArr[i].commState == nInProc){
			//write_paralport(7,1);
			#if subsComm_DEBUG
				//omcLog(subsCommLog,"commArr[%d]:",i);
				//omcLog(subsCommLog,"commState = %d \t procState = %d",
				//			commArr[i].commState,commArr[i].procState);
			#endif
			switch(commArr[i].procState){
				case nIdle:
					//构造IP地址以及端口
					if(subsComm_mkAddr(i,&tmpAddr) < 1){
						// add by simon, at 2024/07/03
						sprintf(commArr[i].desc, "failed to get ip");
						commArr[i].commState = nProcFail;
						commArr[i].procState = nIdle;
						// end by simon
						subsComm_updateCommTable(i);
						break;
					}
					//构造参数
					if(subsComm_mkVarArr(i,tmpVarArr) < 1){
						// add by simon, at 2024/07/03
						sprintf(commArr[i].desc, "failed to make var list");
						commArr[i].commState = nProcFail;
						commArr[i].procState = nIdle;
						// end by simon
						subsComm_updateCommTable(i);
						break;
					}
					//构造snmp协议数据包
					if(subsComm_mkPdu(i,tmpVarArr,&tmpPdu) < 1){
						// add by simon, at 2024/07/03
						commArr[i].commState = nProcFail;
						commArr[i].procState = nIdle;
						// end by simon
						subsComm_updateCommTable(i);
						break;
					}
					//发送snmp包
					if((commArr[i].requestId = snmp_send(&tmpPdu,&tmpAddr)) > 0){
						sprintf(commArr[i].desc,"send snmp message ok!");
						commArr[i].waitTimeCount	= 0;
						commArr[i].timeoutCount		= 0;
						commArr[i].procState		= nWaitResponse;
					}else{
						sprintf(commArr[i].desc,"failed to send snmp message!");
						commArr[i].commState= nProcFail;
						commArr[i].procState = nIdle;
						subsComm_updateCommTable(i);
					}
					break;
				//该命令等待应答消息	
				case nWaitResponse:
					subsComm_mkAddr(i,&tmpAddr);
					if(snmp_receive(&tmpPdu,&tmpAddr) > 0){ //received msg ok
						int respProcReturn = 0;
						//获得对应命令的应答消息
						respProcReturn = subsComm_procResp(&i,&tmpPdu); //here maybe changed i's value
						//有效的消息
						if(respProcReturn > 0){//vaild message
							if(commArr[i].finishNum >= commArr[i].totalNum){
								//释放该命令对应的数据库资源连接
								subsComm_freeParamSet(i);
								if(commArr[i].commType != nLoadIndexComm){
									commArr[i].commState = nOutProc;
								}
							}
							if(commArr[i].commType == nLoadDataComm&&commArr[i].waitTimeCount>0)
								omcLog(subsCommLog,"waitTimeCount=%d;timeoutConut=%d",commArr[i].waitTimeCount,commArr[i].timeoutCount);
							commArr[i].waitTimeCount = 0;
							commArr[i].timeoutCount = 0;
						}
						//无效的消息
						else if(respProcReturn == 0){//invaild message
							if(commArr[i].commType == nLoadIndexComm){
								commArr[i].waitTimeCount = commArr[i].waitTimeCount ++;
							}else{
								commArr[i].waitTimeCount++;
								//send once and receive more
								//it is useful for avoid more invaild message
								if(commArr[i].waitTimeCount % 3){
									continue;
								}
							}
						}else{//error report message
							if(commArr[i].commType == nLoadDataComm){
								#if subsComm_DEBUG
								omcLog(subsCommLog,"get [%s]'s data error!,try to next",commArr[i].indexBuffer[commArr[i].finishNum]);
								#endif
								if(commArr[i].finishNum < MaxIndexNumPerSeg){
									commArr[i].finishNum++;
									continue;
								}
							}
							commArr[i].procState = nIdle;
							commArr[i].commState = nProcFail;
							subsComm_updateCommTable(i);
							break;
						}
						
						if(commArr[i].commType == nLoadIndexComm 
							&& commArr[i].tlvFinishNum == MaxIndexNumPerSeg){
							//insert a loadData command to command array
							commArr[i].procState = nWaitIdleComm;
							break;
						}
						//等待超时
						if(commArr[i].waitTimeCount == 20){
							commArr[i].waitTimeCount = 0;
							commArr[i].timeoutCount++;
							if(commArr[i].timeoutCount > 2){
								if(commArr[i].commType == nLoadIndexComm){
									omcLog(subsCommLog,"Received: get segumentNo [%d] tlv bgn No[%d] timeout!",commArr[i].finishNum,commArr[i].tlvFinishNum);
								}
								if(commArr[i].commType == nLoadDataComm){
									if(commArr[i].finishNum < MaxIndexNumPerSeg){
										omcLog(subsCommLog,"Received: get [%s]'s data timeout,jump to next!",commArr[i].indexBuffer[commArr[i].finishNum]);
										commArr[i].finishNum++;
										continue;
									}
								}
								commArr[i].commState = nProcFail;
								commArr[i].procState = nIdle;
								sprintf(commArr[i].desc,"response timeout");
								subsComm_updateCommTable(i);
								break;
							}
						}
						switch(commArr[i].commState){
							case nInProc:
								if(commArr[i].finishNum < commArr[i].totalNum){
									// fj
									// printf("[subsComm] loading2 segment[%d]\n", commArr[i].finishNum);
									
									if(subsComm_mkAddr(i,&tmpAddr) < 1){
										subsComm_updateCommTable(i);
										break;
									}
									if(subsComm_mkVarArr(i,tmpVarArr) < 1){
										subsComm_updateCommTable(i);
										break;
									}
									if(subsComm_mkPdu(i,tmpVarArr,&tmpPdu) < 1){
										subsComm_updateCommTable(i);
										break;
									}

									if((commArr[i].requestId = snmp_send(&tmpPdu,&tmpAddr)) > 0){
										sprintf(commArr[i].desc,"send snmp message ok!");
										commArr[i].procState = nWaitResponse;
									}else{
										sprintf(commArr[i].desc,"failed to send snmp message!");
										commArr[i].commState = nProcFail;
										commArr[i].procState = nIdle;
									}
								}

								// fj
								#if 0
								if(commArr[i].commType == nLoadIndexComm){
									printf("[subsComm] reget. commArrNo[%d] segument[%d][%d]\n", i, commArr[i].finishNum, commArr[i].tlvFinishNum);
								}else if(commArr[i].commType == nLoadDataComm){
									printf("[subsComm] reget. data[%s]\n", commArr[i].indexBuffer[commArr[i].finishNum]);
								}
								#endif
								#if subsComm_DEBUG
								if(commArr[i].commType == nLoadIndexComm){
									omcLog(subsCommLog,"Try to reget segument [%d][%d] ",commArr[i].finishNum,commArr[i].tlvFinishNum);
								}else if(commArr[i].commType == nLoadDataComm){
									omcLog(subsCommLog,"Try to reget data [%s]",commArr[i].indexBuffer[commArr[i].finishNum]);
								}
								#endif
								break;
							case nOutProc:
								sprintf(commArr[i].desc,"process finished");
								commArr[i].procState = nIdle;
								break;
							default : //nProcFail or unknown commState
								sprintf(commArr[i].desc,"response error");
								commArr[i].procState = nIdle;
								commArr[i].commState = nProcFail;
								break;
						}
						subsComm_updateCommTable(i);
					}else{	//not received msg
						sprintf(commArr[i].desc,"Receive snmp message failed!");
						commArr[i].waitTimeCount++;
						
						//time out
						if(commArr[i].waitTimeCount == 20){
							commArr[i].waitTimeCount = 0;
							commArr[i].timeoutCount++;
							if(commArr[i].timeoutCount > 2){
								if(commArr[i].commType == nLoadIndexComm){
									omcLog(subsCommLog,"Not Receiced get segumentNo [%d] tlv bgn No[%d] timeout!",commArr[i].finishNum,commArr[i].tlvFinishNum);
								}
								if(commArr[i].commType == nLoadDataComm){
									if(commArr[i].finishNum < MaxIndexNumPerSeg){
										omcLog(subsCommLog,"Not Receiced get [%s]'s data timeout,jump to next!",commArr[i].indexBuffer[commArr[i].finishNum]);
										commArr[i].waitTimeCount = 0;
										commArr[i].timeoutCount  = 0;
										commArr[i].finishNum++;
										continue;
									}
								}
								commArr[i].commState = nProcFail;
								sprintf(commArr[i].desc,"response timeout");
								subsComm_updateCommTable(i);
								commArr[i].procState = nIdle;
							}else{ //resend msg
								if(subsComm_mkAddr(i,&tmpAddr) < 1){
									subsComm_updateCommTable(i);
									break;
								}
								if(subsComm_mkVarArr(i,tmpVarArr) < 1){
									subsComm_updateCommTable(i);
									break;
								}
								if(subsComm_mkPdu(i,tmpVarArr,&tmpPdu) < 1){
									subsComm_updateCommTable(i);
									break;
								}
								if((commArr[i].requestId = snmp_send(&tmpPdu,&tmpAddr)) > 0){
									sprintf(commArr[i].desc,"send snmp message ok!");	
									commArr[i].procState = nWaitResponse;
								}else{
									sprintf(commArr[i].desc,"failed to send snmp message!");	
									commArr[i].commState = nProcFail;
									subsComm_updateCommTable(i);
									commArr[i].procState = nIdle;
								}
							}//end of if(commArr[i].waitTimeCount == 20)
						}//end of time out handle
					}//end of not received msg
					break;
				case nWaitIdleComm:
					if(commArr[i].commType == nLoadIndexComm){
						//insert a new Load Data Comm to command array
						for(j=loadDataCommStartNo;j<MaxCommNum;j++){
							if(commArr[j].procState == nIdle && commArr[j].commState != nInProc){
								//copy this command's data to new command
								memcpy(&commArr[j],&commArr[i],sizeof(commArr[i]));
								memset(commArr[i].indexBuffer,0,sizeof(commArr[i].indexBuffer));

								// fj
								// 重点: 收到获取用户索引消息的回复后:
								//       1. 分出一个命令来，加载用户详细信息
								//       2. 当前索引请求消息还没发完(<100)，就继续发送
								//set new command,make it ready to be processed
								commArr[j].commNo		= commArr[i].commNo + FlagCode + MaxIndexNumPerSeg*commArr[i].finishNum;
								commArr[j].commType		= nLoadDataComm;
								commArr[j].commState	= nInProc;
								commArr[j].procState	= nIdle;
								commArr[j].totalNum		= commArr[i].tlvTotalNum;
								commArr[j].finishNum	= 0;
								sprintf(commArr[j].desc,"loading segment %d",commArr[i].finishNum);
								// fj
								// printf("[subsComm] loading segment[%d]\n", commArr[i].finishNum);
								commArr[j].tlvInvaildNum= 0;
								commArr[j].tlvFinishNum	= 0;
								commArr[j].tlvTotalNum	= 0;

								//change this command's state
								commArr[i].procState	= nWaitResponse;
								commArr[i].tlvFinishNum	= 0;
								commArr[i].tlvInvaildNum= 0;
								sprintf(commArr[i].desc,"Set a new commond %d",j);
								commArr[i].finishNum++;
								
								if(commArr[i].finishNum >= commArr[i].totalNum)
									commArr[i].commState = nOutProc;
								
								//get next indexBuffer,same with the nWaitResponse
								switch(commArr[i].commState){
									case nInProc:
										if(subsComm_mkAddr(i,&tmpAddr) < 1){
											subsComm_updateCommTable(i);
											break;
										}
										if(subsComm_mkVarArr(i,tmpVarArr) < 1){
											subsComm_updateCommTable(i);
											break;
										}
										if(subsComm_mkPdu(i,tmpVarArr,&tmpPdu) < 1){
											subsComm_updateCommTable(i);
											break;
										}

										if((commArr[i].requestId = snmp_send(&tmpPdu,&tmpAddr)) > 0){
											commArr[i].procState = nWaitResponse;
										}else{
											commArr[i].commState = nProcFail;
											commArr[i].procState = nIdle;
											sprintf(commArr[i].desc,"failed to send message!");
										}
										break;
									case nOutProc:
										commArr[i].procState = nIdle;
										sprintf(commArr[i].desc,"process finished");
										break;
									default: //error
										commArr[i].procState = nIdle;
										commArr[i].commState = nProcFail;
										sprintf(commArr[i].desc,"response error");
										break;
								}
								subsComm_updateCommTable(i);
								break;
							}//enf of if(commArr[j].procState == nIdle && commArr[j].commState != nInProc)
						}
						
						#if subsComm_DEBUG
							if(j == MaxCommNum){
								sprintf(commArr[i].desc,"Can not find idle comm");
							}
						#endif
					}
					break;
				default:
					commArr[i].procState = nIdle;
					commArr[i].commState = nProcFail;
					sprintf(commArr[i].desc,"unknown procState,Please check!");
					break;
			}//end of switch(..)
		}else{
			idleCommCount++;
		}
	}//end of for(..)
	#if subsComm_DEBUG
		printf("\n");
	#endif
	//如果全部命令都执行完毕，等待回复结果
	if(idleCommCount == MaxCommNum){
		//write_paralport(7,0);
		snmp_receive(&tmpPdu,&tmpAddr);
		return(2);
	}else{
		return(1);
	}
}//end subsCommProc


/*************************************************
Function:        // subsComm_initSysConfArr
Description:     // 初始化系统对象
Calls:           // mysql_fetch_row; mysql_getres; mysql_num_rows;
Called By:       // subsCommInit;
Table Accessed:  // OMC_PUB.sysSubsConf
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 1:successful; 0:failed;
Others:          // 
*************************************************/
int subsComm_initSysConfArr()
{	
	char confQuery[800]	= "\0";
	MYSQL_RES *confResult=NULL;
	MYSQL_ROW confRow;
	int arrayNo = 0,i = 0;
	char *oneOid; 
	
	//init array first
	for(i=0;i<MaxSysConfNum;i++){
		sysConfArr[i].isEnable = 0;
	}
	
	//find sysTypeNo which need subscriber manage
	sprintf(confQuery,"SELECT sysSubsConf.sysTypeNo,dataTypeNo,sysNo,snmpCommunity,preObjId,indexObjId,"\
				" maxSegmentNum,maxIndexNumPerSeg,maxMsgLen,indexFieldName,subsDataTable,tmpDataTable"\
				" FROM sysConf,sysSubsConf "\
				" WHERE sysConf.sysTypeNo = sysSubsConf.sysTypeNo AND sysSubsConf.isEnable > '0' "\
				" AND sysConf.needSubscriberConf > '0' ORDER BY sysTypeNo");
	confResult=(MYSQL_RES*)mysql_getres(dbConn,confQuery);
	if(confResult == NULL){
		omcLog(subsCommLog,"Database may be stopped,Please check!");
		return(0);
	}else if(mysql_num_rows(confResult) == 0){
		mysql_free_result(confResult);
		return(0);
	}
	if(mysql_num_rows(confResult) > MaxSysConfNum){ //max size of sysConfArr is 24
		mysql_free_result(confResult);
		omcLog(subsCommLog,"The number of need subscriber manage system is too much!(MaxSysConfNum=%d)",
					MaxSysConfNum);
		return(0);
	}

	//遍历表的记录，填充系统对象
	while((confRow = mysql_fetch_row(confResult)) != NULL){
		sysConfArr[arrayNo].sysTypeNo=atol(confRow[0]);  //<--
		sysConfArr[arrayNo].dataTypeNo=atol(confRow[1]);  //<--
		if(sysConfArr[arrayNo].sysTypeNo==VMS_No ||
		   sysConfArr[arrayNo].sysTypeNo==UDM_No ||
		   sysConfArr[arrayNo].sysTypeNo==AUSF_No)
		{
			sysConfArr[arrayNo].sysNo=atol(confRow[2]);
		}
		sprintf(sysConfArr[arrayNo].snmpCommunity,"%s",confRow[3]);  //<--
	
		//sysConfArr[i].preObjId[20];
		i = 0;
		while((oneOid = strsep(&(confRow[4]), "."))){
			sysConfArr[arrayNo].preObjId[i]		= atol(oneOid);	//<--
			i++;
		}
		sysConfArr[arrayNo].preObjIdLen=i;					//<--
		if(i < 1){
			mysql_free_result(confResult);
			omcLog(subsCommLog,"get preObjId error!!");
			return(0);
		}
		
		//sysConfArr[i].indexObjId[20];
		//把字符串OID转换成OID数组形式
		i = 0;
		while((oneOid = strsep(&(confRow[5]), "."))){
			sysConfArr[arrayNo].indexObjId[i]	= atol(oneOid);	//<--
			i++;
		}
		sysConfArr[arrayNo].indexObjIdLen=i;					//<--
		if(i < 1){
			mysql_free_result(confResult);
			omcLog(subsCommLog,"get indexObjId error!!");
			return(0);
		}
		sysConfArr[arrayNo].maxSegmentNum		= atol(confRow[6]);		//<--
		sysConfArr[arrayNo].maxIndexNumPerSeg	= atol(confRow[7]);		//<--
		sysConfArr[arrayNo].maxMsgLen			= atol(confRow[8]);		//<--
		strcpy(sysConfArr[arrayNo].indexFieldName,	confRow[9]);		//<--
		strcpy(sysConfArr[arrayNo].paramTableName,	confRow[10]);		//<--
		strcpy(sysConfArr[arrayNo].tmpTableName,	confRow[11]);		//<--
		sysConfArr[arrayNo].isEnable			= 1;					//<--
		arrayNo++;
	}
	mysql_free_result(confResult);
	return(1);
}//end subsComm_initSysConfArr

/*************************************************
Function:        // subsComm_initParamConfArr
Description:     // 初始化参数对象，并且把每个参数分配给每个系统对象
Calls:           // mysql_fetch_row; mysql_getres; mysql_num_rows;
Called By:       // subsComm_initSysConfArr;
Table Accessed:  // subsParamConf_X;
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 1:successful; 0:failed;
Others:          // 
*************************************************/
int subsComm_initParamConfArr()
{	
	//
	char confQuery[800]	= "\0";
	MYSQL_RES *confResult=NULL;
	MYSQL_ROW confRow;
	int arrayNo=0,sysConfArrNo=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";
	//对每个参数对象置零
	for(i=0;i<MaxParamConfNum;i++){
		paramConfArr[i].sysTypeNo			= 0;
		paramConfArr[i].fieldObjIdStr[0]	= 0;
		paramConfArr[i].fieldName[0]		= 0;
		paramConfArr[i].valueType			= 0;
		paramConfArr[i].valueLen			= 0;
		//paramConfArr[i].initValue;
	}

	//遍历每个系统对象，分配参数对象
	for(sysConfArrNo=0;sysConfArrNo < MaxSysConfNum;sysConfArrNo++){
		if(sysConfArr[sysConfArrNo].isEnable <= 0){
			continue;
		}
		sysConfArr[sysConfArrNo].paramConfArrOffset = arrayNo;	//<--<--
		sprintf(confQuery,"SELECT %s,fieldName,valueType,length,initValue " \
				"FROM OBJ_%d.subsParamConf_%d WHERE operType > '0' ORDER BY %s",
				levelSelect,sysConfArr[sysConfArrNo].sysTypeNo,sysConfArr[sysConfArrNo].dataTypeNo,queryOrderBy);
		confResult=(MYSQL_RES*)mysql_getres(dbConn,confQuery);
		if(confResult == NULL){
			omcLog(subsCommLog,"Database may be stopped,Please check!");
			return(0);
		}else if(mysql_num_rows(confResult) == 0){
			omcLog(subsCommLog,"sysTypeNo(%d)'s result is null.(sql=%s)",sysConfArr[sysConfArrNo].sysTypeNo,confQuery);
			mysql_free_result(confResult);
			return(0);
		}
	// fj
	#if 1 /*subsComm_DEBUG*/
		int curNum,totalNum;
		curNum = mysql_num_rows(confResult);
		totalNum = arrayNo+curNum;
		/*printf("%s\n",confQuery);*/
		// printf("sysTypeNo=%3d,sysConfArrNo=%d,arrayNo=%d,curParamNum=%d,totalParamNum=%d\n",sysConfArr[sysConfArrNo].sysTypeNo,sysConfArrNo,arrayNo,curNum,totalNum);
	#endif
		if((arrayNo+mysql_num_rows(confResult)) > MaxParamConfNum){ //300
			mysql_free_result(confResult);
			omcLog(subsCommLog,"The number of parameter type is too much!(MaxParamConfNum=%d)",MaxParamConfNum);
			return(0);
		}
		sysConfArr[sysConfArrNo].paramConfNum = mysql_num_rows(confResult);
		while((confRow = mysql_fetch_row(confResult)) != NULL){
			j=0; 
			paramConfArr[arrayNo].sysTypeNo = sysConfArr[sysConfArrNo].sysTypeNo; //<--
			paramConfArr[arrayNo].fieldObjIdStr[0]=0;
			//把level的值的字符串连接赋给fieldObjIdStr
			while(atoi(confRow[j]) > 0 && j <10){
				if(j == 0){
					sprintf(oneOid,"%d",atoi(confRow[j]));
				}else{
					sprintf(oneOid,".%d",atoi(confRow[j]));
				}
				strcat(paramConfArr[arrayNo].fieldObjIdStr,oneOid);
				j++;
			}
			sprintf(paramConfArr[arrayNo].fieldName,"%s",confRow[10]);
			paramConfArr[arrayNo].valueType=atoi(confRow[11]);
			paramConfArr[arrayNo].valueLen=atoi(confRow[12]);
			//给系统的关键参数赋值
			if(strcmp(paramConfArr[arrayNo].fieldName,sysConfArr[sysConfArrNo].indexFieldName) == 0){
				sprintf(sysConfArr[sysConfArrNo].indexFieldSubOid,"%s",paramConfArr[arrayNo].fieldObjIdStr);
				sysConfArr[sysConfArrNo].indexValueLen=paramConfArr[arrayNo].valueLen;

				// fj
				#if 0
				printf("[subsComm] sysConfArrNo[%d] filedName[%s] fileObjIDStr[%s] indexValLen[%d]\n",
									sysConfArrNo,
									sysConfArr[sysConfArrNo].indexFieldName,
									sysConfArr[sysConfArrNo].indexFieldSubOid,
									sysConfArr[sysConfArrNo].indexValueLen);				
				#endif
			}
			//initValue isn't needed
			//paramConfArr[arrayNo].initValue=atoi(tmpRow[13]);
			arrayNo++;
		}
		mysql_free_result(confResult);
	}
	return(1);
}//end subsComm_initParamConfArr

/*************************************************
Function:        // subsComm_initUnitComm
Description:     // 初始化化一个命令对象
Calls:           // omcLog;
Called By:       // subsCommScan;
Table Accessed:  // OMC_PUB.sysInfo;
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 1:successful; 0:failed;
Others:          // 
*************************************************/
int subsComm_initUnitComm(int commArrNo){
	
	//超出了最大的命令数
	if(commArrNo > MaxCommNum){
		return(0);
	}
	
	//command info
	commArr[commArrNo].commNo		= 0;
	commArr[commArrNo].commType		= 0;
	commArr[commArrNo].sysConfArrNo	= 0;
		
	commArr[commArrNo].sysTypeNo	= 0;
	commArr[commArrNo].sysNo		= 0;
	commArr[commArrNo].subSysNo		= 0;
	commArr[commArrNo].dstIP[16]	= 0;
	commArr[commArrNo].dstPort		= 4957;
	
	if(commArr[commArrNo].paramSet != NULL)
		mysql_free_result(commArr[commArrNo].paramSet);
	commArr[commArrNo].paramSet		= NULL;
	memset(commArr[commArrNo].indexBuffer,0,sizeof(commArr[commArrNo].indexBuffer));
	commArr[commArrNo].tlvTotalNum		= 0;
	commArr[commArrNo].tlvFinishNum		= 0;
	commArr[commArrNo].tlvInvaildNum	= 0;
	commArr[commArrNo].fieldNameList[0]	= 0; //64*32

	//command process info
	commArr[commArrNo].commState		= 0;		//-1:nFailed,0:nWaitProc,1:nNoFinish,2:nFinished 
	commArr[commArrNo].procState		= 0;		//command process state:0=idle,1=waitResponse 
	commArr[commArrNo].waitTimeCount	= 0;		//the times number of timeout
	commArr[commArrNo].timeoutCount		= 0;		//the timeCount
	commArr[commArrNo].totalNum			= 0;
	commArr[commArrNo].finishNum		= 0;
	commArr[commArrNo].desc[200]		= 0;
		
	//var_list info
	commArr[commArrNo].varNum			= 0;
	#if subsComm_DEBUG
		omcLog(subsCommLog,"init commArr[%d] ok",commArrNo);
	#endif
	return(1);
}//end subsComm_initUnitComm

/*************************************************
Function:        // subsComm_getIp
Description:     // 根据系统设备号，系统号，子系统号获取该设备的IP地址
Calls:           // mysql_getres; mysql_fetch_row; mysql_free_result;
Called By:       // subsCommScan
Table Accessed:  // OMC_PUB.sysInfo
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 1:successful; 0:failed;
Others:          // 
*************************************************/
int subsComm_getIp(int sysTypeNo,int sysNo,int subSysNo,char *dstIP)
{
	int nReturn = 0;
	MYSQL_RES *tmpResult;
	MYSQL_ROW tmpRow;
	char tmpQuery[400]="\0";
	
	//从OMC_PUB.sysInfo表里获取每个系统的IP地址
	sprintf(tmpQuery,"SELECT ip FROM %s WHERE sysTypeNo='%d' "\
				 "AND sysNo='%d' AND subsysNo='%d' ORDER BY updateTime DESC",\
				 IpTable,sysTypeNo,sysNo,subSysNo);
	tmpResult=(MYSQL_RES*)mysql_getres(dbConn,tmpQuery);
	if(tmpResult == NULL){
		omcLog(subsCommLog,"Database may be stopped,when get IP address from IpTable");
		return(0);
	}
	if((tmpRow=mysql_fetch_row(tmpResult)) !=NULL){
		strcpy(dstIP,tmpRow[0]);
		nReturn = 1;
	}else{
		nReturn = 0;
	}
	mysql_free_result(tmpResult);
	return(nReturn);
}//end subsComm+getIp

/*************************************************
Function:        // subsComm_mkPdu
Description:     // 构造snmp协议数据包
Calls:           // memcpy; 
Called By:       // subsCommProc
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 1:successful; 0:failed;
Others:          // 
*************************************************/
int subsComm_mkPdu(int commArrNo,var_list *varArr,snmp_pdu *pdu)
{
	pdu->pdu_type	= nSet;
	pdu->request_id = 0;
	pdu->var_num	= commArr[commArrNo].varNum;
	strcpy(pdu->community,sysConfArr[commArr[commArrNo].sysConfArrNo].snmpCommunity);

	//把变量列表赋值给snmp协议数据包
	memcpy(pdu->var,varArr,sizeof(var_list)*BIND_MAX);
	pdu->error_status	= 0x0; //0:no error 1:too big 2:nosuchname 3:badvalue 4:readonly 5:generr
	pdu->error_index	= 0x0;
	return(1);
}//end subsComm_mkPdu

/*************************************************
Function:        // subsComm_mkAddr
Description:     // 构造snmp_addr地址结构
Calls:           // inet_addr; 
Called By:       // subsCommProc
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 1:successful; 0:failed;
Others:          // 
*************************************************/
int subsComm_mkAddr(int commArrNo,snmp_addr *addr)
{
	//没有IP地址，无法构造snmp_addr结构
	if(strlen(commArr[commArrNo].dstIP) <= 0 ){
		omcLog(subsCommLog,"\n Initing snmp_addr error: Cannot get ip");
		commArr[commArrNo].commState = nProcFail;
		return(0);
	}
	
	//给地址结构填值
	//addr->local_ip	= ;
	addr->local_port	= DefPort;
	addr->remote_ip		= inet_addr(commArr[commArrNo].dstIP);
	addr->remote_port	= commArr[commArrNo].dstPort;
	addr->broadcast		= 0;
	return(1);
}//end subsComm_mkAddr

/*************************************************
Function:        // subsComm_mkVarArr
Description:     // 构造var_list结构，用ASN编码
Calls:           // decodeKeyValue; AsnEncode;
Called By:       // subsCommProc
Table Accessed:  // 
Table Updated:   // 
Input:           // commArrNo:命令对象序号, varArr:参数列表结构体
Output:          // 
Return:          // 1:successful; 0:failed;
Others:          // 
*************************************************/
int subsComm_mkVarArr(int commArrNo,var_list *varArr)
{	
	var_list *unitVar;
	ASN_BUF asnbuf;
	int i,varCount=0,asnBufLen=0, tmp_len;
	char	tlvTag[32]	= "\0";
	int		tlvNo		= 0;
	int		tlvCount	= 0;
	int		tlvLen		= 0;
	int		tlvIntValue = 0;
	char			tlvAscValue[512]	= "\0";
	unsigned char	tlvBcdValue[256];
	//int		tlvIntValue			= 0;
	MYSQL_ROW tmpRow	=NULL;
	char *oneFieldName;
	char *tmpFieldList;
	char tmpFieldListBuf[2048]	= "\0";
	int msgLenCount		= 0;
	int	sysConfArrNo	= commArr[commArrNo].sysConfArrNo;
	int paramConfBgn	= sysConfArr[sysConfArrNo].paramConfArrOffset;
	int paramConfEnd	= sysConfArr[sysConfArrNo].paramConfArrOffset 
							+ sysConfArr[sysConfArrNo].paramConfNum;

	unitVar = varArr + varCount;
	//填充OID，最后一部分是段号
	if(commArr[commArrNo].commType == nLoadIndexComm){
		msgLenCount = sysConfArr[sysConfArrNo].indexObjIdLen + 1;
		for(i=0;i<sysConfArr[sysConfArrNo].indexObjIdLen;i++){
			unitVar->oid[i]	 = sysConfArr[sysConfArrNo].indexObjId[i];
		}
		// fj 
		// 重点: 索引OID = 关键字 + 分片编号
		//last oid is segument number
		unitVar->oid[i] = commArr[commArrNo].finishNum + 1;
		#if subsComm_DEBUG
		omcLog(subsCommLog,"Now geting segment %ld 's index",unitVar->oid[i]);
		#endif
		// fj
		// printf("[subsComm] loadIndex. commArrNo[%d] segment[%d]\n", commArrNo, unitVar->oid[i]);
		unitVar->oidlen	= i+1;
	}else{
		msgLenCount = sysConfArr[sysConfArrNo].preObjIdLen + 8;
		for(i=0;i<sysConfArr[sysConfArrNo].preObjIdLen;i++){
			unitVar->oid[i]	 = sysConfArr[sysConfArrNo].preObjId[i];
		}
		//check index's value is vaild,and use this index to make pdu
		for(;commArr[commArrNo].finishNum < commArr[commArrNo].totalNum;){
			if(commArr[commArrNo].indexBuffer[commArr[commArrNo].finishNum][0] == 0){
				sprintf(commArr[commArrNo].desc,"indexBuffer[%d] is Null",commArr[commArrNo].finishNum);
				commArr[commArrNo].finishNum++;
				continue;
			}
			break;
		}
		if(commArr[commArrNo].finishNum >= commArr[commArrNo].totalNum){
			commArr[commArrNo].commState = nOutProc;
			commArr[commArrNo].procState = nIdle;
			subsComm_freeParamSet(commArrNo);
			return(0);
		}
		decodeKeyValue(commArr[commArrNo].indexBuffer[commArr[commArrNo].finishNum],
								&(unitVar->oid[i]),&(unitVar->oid[i+1]));
	
		#if subsComm_DEBUG
		omcLog(subsCommLog,"Now get -> %s 's data(%ld-%ld)",
				commArr[commArrNo].indexBuffer[commArr[commArrNo].finishNum],
				unitVar->oid[i],unitVar->oid[i+1]);
		#endif
		
		if(unitVar->oid[i] == 0 && unitVar->oid[i+1] == 0){
			commArr[commArrNo].indexBuffer[commArr[commArrNo].finishNum][0]=0;
			return(0);
		}
		unitVar->oid[i+2] = FlagCode;
		unitVar->oid[i+3] = 1;//init to read operation
		unitVar->oidlen	  = i+4;
	}
	
	//设置命令类型的OID
	switch(commArr[commArrNo].commType){
		case nReadComm:	//Read
			unitVar->oid[i+3] = 1; //set to read operation
			unitVar->vartype  = 0x04; //OCTET STRING
			break;
		case nChangeComm:	
			unitVar->oid[i+3] = 2; //change to read operation
			unitVar->vartype  = 0x04; //OCTET STRING
			break;
		case nCreateComm:	
			unitVar->oid[i+3] = 3; //set to create operation
			unitVar->vartype  = 0x04; //OCTET STRING
			break;
		case nDeleteComm:	
			unitVar->oid[i+3] = 4; //set to delete operation
			unitVar->vartype  = 0x04; //OCTET STRING
			break;
		case nLoadIndexComm:
			unitVar->vartype  = 0x04; //OCTET STRING
			break;
		case nReplaceIndexComm:
			unitVar->oid[i+3] = 6; //set to read operation
			unitVar->vartype  = 0x04; //OCTET STRING	
			break;
		case nLoadDataComm:
			unitVar->oid[i+3] = 1; //set to read operation
			unitVar->vartype  = 0x04; //OCTET STRING	
			break;
		default:
			//Unknow commType
			return(0);
	}
	
	//init asnbuff
	AsnEncode(unitVar->msg,1024,&asnbuf);
			
	//fill unitVar->msg by asn format
	asnBufLen = 0;
	if(commArr[commArrNo].commType == nLoadIndexComm){
		for(tlvCount = (commArr[commArrNo].tlvFinishNum+1); tlvCount <= sysConfArr[sysConfArrNo].maxIndexNumPerSeg; tlvCount++){	
			if((msgLenCount + asnBufLen + sysConfArr[sysConfArrNo].indexValueLen) < sysConfArr[sysConfArrNo].maxMsgLen){
				sprintf(tlvTag,"%d",tlvCount);
				int 
				tmp_len = AddTLV(tlvTag,sysConfArr[sysConfArrNo].indexValueLen,(u_char*)tlvAscValue,0x80,&asnbuf);
				if(tmp_len >= 0)
				{
					asnBufLen = tmp_len;
				}
				else
				{
					// fj, 这里 获取每个segment下最多55个索引
					// printf("[subsComm] setReq-index. segment[%d] tagNum[%d]\n", commArr[commArrNo].finishNum, tlvCount);
					break;
				}
				commArr[commArrNo].tlvTotalNum=tlvCount;
			}else{
				// fj
				// printf("[subsComm] setReq. segment[%d] tagNum[%d]\n", commArr[commArrNo].indexBuffer[commArr[commArrNo].finishNum], tlvCount);
				break;
			}
		}//end of for(..)
	}else{
		//read
		switch(commArr[commArrNo].commType){
			case nLoadDataComm: 
			case nReadComm:
				for(tlvCount = paramConfBgn; tlvCount < paramConfEnd; tlvCount++){
					if((msgLenCount + asnBufLen + sysConfArr[sysConfArrNo].indexValueLen) < sysConfArr[sysConfArrNo].maxMsgLen){
						if(strcmp(paramConfArr[tlvCount].fieldObjIdStr,sysConfArr[sysConfArrNo].indexFieldSubOid) == 0){
							asnBufLen=AddTLV(paramConfArr[tlvCount].fieldObjIdStr,
								sizeof(commArr[commArrNo].indexBuffer[commArr[commArrNo].finishNum]),
								(u_char*)commArr[commArrNo].indexBuffer[commArr[commArrNo].finishNum],0x80,&asnbuf);

							// fj
							// printf("[subsComm] setReq-Usr. segment[%d] filedObjVal[%s,%s]\n", 
							//						commArr[commArrNo].finishNum, paramConfArr[tlvCount].fieldObjIdStr, commArr[commArrNo].indexBuffer[commArr[commArrNo].finishNum]);
						}else{
							asnBufLen=AddTLV(paramConfArr[tlvCount].fieldObjIdStr,paramConfArr[tlvCount].valueLen,tlvBcdValue,0x80,&asnbuf);

							// fj
							 // printf("[subsComm] setReq-Usr2. segment[%d] filedObjVal[%s,%s]\n", 
								//					commArr[commArrNo].finishNum, paramConfArr[tlvCount].fieldObjIdStr, tlvBcdValue);
						}
						commArr[commArrNo].tlvTotalNum=tlvCount - paramConfBgn;
					}else{
						sprintf(commArr[commArrNo].desc,"The data can not fill to one msg");
						break;
					}
				}//end of for(..)
				break;
			case nChangeComm:
			case nCreateComm:					
				mysql_data_seek(commArr[commArrNo].paramSet,commArr[commArrNo].finishNum);
				tmpRow = mysql_fetch_row(commArr[commArrNo].paramSet);
				if(!tmpRow){
					break;
				}
				// fj
				#if 0
				printf("[subsComm] setReq-Change. commArrNo[%d] segment[%d] filedName[%s]\n", 
										commArrNo,
										commArr[commArrNo].finishNum, commArr[commArrNo].fieldNameList);				
				#endif
				strcpy(tmpFieldListBuf,commArr[commArrNo].fieldNameList);
				tmpFieldList=tmpFieldListBuf;
				tlvNo = 0;
				while((oneFieldName = strsep(&(tmpFieldList), ",")) != NULL){
					//find tlvTag by fieldName
					for(tlvCount = paramConfBgn; tlvCount < paramConfEnd; tlvCount++){
						if(strcmp(oneFieldName,paramConfArr[tlvCount].fieldName) == 0){
							sprintf(tlvTag,"%s",paramConfArr[tlvCount].fieldObjIdStr);
							//tlvLen = paramConfArr[tlvCount].valueLen;
							switch(paramConfArr[tlvCount].valueType){
								case 0x02:
									tlvIntValue = atoi(tmpRow[tlvNo]);
									asnBufLen = AddInteger(tlvTag,tlvIntValue,0x80,&asnbuf);
									break;
								case 0x03:
									sprintf(tlvAscValue,"%s",tmpRow[tlvNo]);
									tlvLen = strlen(tlvAscValue);
									asnBufLen = AddTLV(tlvTag,tlvLen,(u_char*)tlvAscValue,0x80,&asnbuf);
									break;
								case 0x04:
									sprintf(tlvAscValue,"%s",tmpRow[tlvNo]);
									omc_AsciiToRbcd(tlvBcdValue,tmpRow[tlvNo],strlen(tlvAscValue));
									if(strlen(tlvAscValue) % 2){
										tlvLen = strlen(tlvAscValue) / 2 + 1;
									}else{
										tlvLen = strlen(tlvAscValue) / 2;
									}
									asnBufLen = AddTLV(tlvTag,tlvLen,tlvBcdValue,0x80,&asnbuf);
									break;
								default:
									return(0);
							}
							break;
						}//end of switch
						if(tlvCount == paramConfEnd - 1){
							sprintf(commArr[commArrNo].desc,"Can not find this field name(%s) in field list",oneFieldName);
							return(0);
						}
					}
					tlvNo++;
				}//end of while
				break;
			case nDeleteComm:
				asnBufLen=AddInteger("1",1,0x80,&asnbuf);
				break;
			case nReplaceIndexComm:
				sprintf(tlvAscValue,"%s",commArr[commArrNo].indexBuffer[1]);
				tlvLen = strlen(tlvAscValue);
				sprintf(tlvTag,"%s",sysConfArr[sysConfArrNo].indexFieldSubOid);
				asnBufLen = AddTLV(tlvTag,tlvLen,(u_char*)tlvAscValue,0x80,&asnbuf);
				break;
			default:
				return(0);
		}//end of switch(commArr[commArrNo].commType)
	}//end of if(commArr[commArrNo].commType == nLoadIndexComm)

	unitVar->msglen	= asnBufLen;
	commArr[commArrNo].varNum = 1;
	return(1);
}//end subsComm_mkVarArr

/*************************************************
Function:        // subsComm_procResp
Description:     // 处理回复消息，并把用户数据更新到数据库里
Calls:           // 
Called By:       // subsCommProc;
Table Accessed:  // tmpSubsData_x
Table Updated:   // tmpSubsData_x
Input:           // pdu:接收到的snmp数据包,oldcommArrNo:发送该消息的命令对象的序号
Output:          // 
Return:          // 1:successful; 0:failed;
Others:          // 
*************************************************/
int subsComm_procResp(int *oldcommArrNo,snmp_pdu *pdu)
{
	int i,j,commArrNo,tlvCount;
	char	tmpQuery[3500]	= "\0";
	char	tmpValue[3000]	= "\0";
	char	tmpWhere[200]	= "\0";
	int		nSqlReturn		= 0;
	char	tagStr[32]		= "\0";
	int		tlvLen			= 0;
	int		tlvIntValue		= 0;
	char	tlvAscValue[512]="\0";
	BYTE	tlvBcdValue[256];
	char    tmpStr[128]="\0";
	
	int loadIndexFinishFlag=0;

	ASN_BUF asnBuffer;

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

	#if subsComm_DEBUG
		omcLog(subsCommLog,"----- Processing commArr[%d]'s response message ",commArrNo);
	#endif

	//错误的数据包
	if(pdu->pdu_type != nResp){
		omcLog(subsCommLog,"Error pdu type:%d(!=Resp%d)",pdu->pdu_type,nResp);	
		sprintf(commArr[commArrNo].desc,"Error pdu type:%d(!=Resp%d)",pdu->pdu_type,nResp);
		return(0);
	}

	//判断request Id是属于哪个命令对象的
	if(pdu->request_id != commArr[commArrNo].requestId){
		int isRequestIdMatch=0;

		for(i=0;i<MaxCommNum;i++){
			if(pdu->request_id == commArr[i].requestId){
				isRequestIdMatch = 1;
				*oldcommArrNo = i;
				commArrNo = i;
				break;
			}
		}
		//request id发生错误
		if(isRequestIdMatch == 0){
			omcLog(subsCommLog,"unknown pdu->request_id(%ld)",pdu->request_id);
			sprintf(commArr[commArrNo].desc,"unknown pdu->request_id(%ld)",pdu->request_id);
			return(0);
		}
	}
	
	//获取数据包里的全部参数
	// fj
	// printf("[subsComm] varNum[%d]\n", pdu->var_num);
	for(i = 0; i < pdu->var_num; i++){
		int errStr;
		
		//check value type
		switch(pdu->var[i].vartype){
			case 0x02: //INTEGER
				sprintf(commArr[commArrNo].desc,"INTEGER");
				return(-1);
			case 0x04: //OCTET STRING
				break;
			case 0x05: //NULL(unSpecified)
				sprintf(commArr[commArrNo].desc,"NULL");
				if(commArr[commArrNo].commType == nLoadIndexComm){
					loadIndexFinishFlag=1;
					break;
					//return(0);
				}else{
					return(-1);
				}
			case 0x06: //OBJECT IDENTIFIER
				sprintf(commArr[commArrNo].desc,"OBJECT IDENTIFIER");
				return(-1);
			case 0x80: //noSuchObject
				sprintf(commArr[commArrNo].desc,"noSuchObject");
				if(commArr[commArrNo].commType == nLoadIndexComm){
					loadIndexFinishFlag=1;
					break;
					//return(0);
				}else{
					return(-1);
				}
			case 0x81: //NoSuchInstance
				sprintf(commArr[commArrNo].desc,"NoSuchInstance");
				if(commArr[commArrNo].commType == nLoadIndexComm){
					loadIndexFinishFlag=1;
					break;
					//return(0);
				}else{
					return(-1);
				}
			case 0x82: //endOfMibView
				sprintf(commArr[commArrNo].desc,"endOfMibView");
				return(-1);
			default:
				sprintf(commArr[commArrNo].desc,"Invailed vartype(%d)",pdu->var[i].vartype);
				omcLog(subsCommLog,"Invailed vartype(pdu->var[%d].vartype=%d)",i,pdu->var[i].vartype);
				return(-1);
		}
	
		//check error status and error index
		if((pdu->error_status > 0) && (pdu->error_index == (i+1))){
			if(commArr[commArrNo].commType == nLoadIndexComm&&loadIndexFinishFlag==1){
				sprintf(commArr[commArrNo].desc,"process finished");
				commArr[commArrNo].tlvFinishNum = MaxIndexNumPerSeg;
				// fj
				// printf("[subsComm] errStatus begin. segment[%d]\n", commArr[commArrNo].finishNum);
				commArr[commArrNo].finishNum=commArr[commArrNo].totalNum;
				// fj
				// printf("[subsComm] errStatus end. segment[%d]\n", commArr[commArrNo].finishNum);
				return(1);
			}
					
			omcLog(subsCommLog,"Error message: pdu->error_status =%d  pdu->error_index =%d",pdu->error_status,pdu->error_index);
			if(strlen((char*)pdu->var[i].msg) > 0 && strlen((char*)pdu->var[i].msg) < sizeof(commArr[commArrNo].desc)){
				strncpy(commArr[commArrNo].desc,(char*)pdu->var[i].msg,pdu->var[i].msglen);
				commArr[commArrNo].desc[pdu->var[i].msglen]='\0';
				//modify for smcli
				if(pdu->error_status <  MaxErrorStatusNum)
					sprintf(tmpStr,"%d:%s:%s",pdu->error_status,errorStatusDescArr[pdu->error_status],commArr[commArrNo].desc);
				else
					sprintf(tmpStr,"%d:%s",pdu->error_status,commArr[commArrNo].desc);
				sprintf(commArr[commArrNo].desc,"%s",tmpStr);
				omcLog(subsCommLog,"Error: %s",commArr[commArrNo].desc);
			}else if(pdu->error_status <  MaxErrorStatusNum){
				//modify for smcli
				sprintf(commArr[commArrNo].desc,"Error:%d:%s",pdu->error_status,errorStatusDescArr[pdu->error_status]);
			}else{
				sprintf(commArr[commArrNo].desc,"Error:Unknown snmp error status");
			}
			return(-1);
		}
		
		//Don not check the zero imsi
		if(pdu->var[i].msglen < 1 && pdu->var[i].vartype == 0x04){
			if(commArr[commArrNo].commType == nLoadIndexComm&&loadIndexFinishFlag==1){
				sprintf(commArr[commArrNo].desc,"process finished");
				commArr[commArrNo].tlvFinishNum = MaxIndexNumPerSeg;
				commArr[commArrNo].finishNum=commArr[commArrNo].totalNum;
				return(1);
			}
			sprintf(commArr[commArrNo].desc,"Resp Msg len = 0");
			omcLog(subsCommLog,"Resp Msg len = 0");
			return(0);
		}
		if(pdu->var[i].msglen >= (sizeof(tmpValue)/2)){
			if(commArr[commArrNo].commType == nLoadIndexComm&&loadIndexFinishFlag==1){
				sprintf(commArr[commArrNo].desc,"process finished");
				commArr[commArrNo].tlvFinishNum = MaxIndexNumPerSeg;
				commArr[commArrNo].finishNum=commArr[commArrNo].totalNum;
				return(1);
			}
			sprintf(commArr[commArrNo].desc,"Msg is too long(%d)",pdu->var[i].msglen);
			omcLog(subsCommLog,"Msg is too long(%d)",pdu->var[i].msglen);
			return(0);
		}

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

		if(commArr[commArrNo].commType == nLoadIndexComm){
			/* get data and input to indexBuffer */
			//check oid
			if(pdu->var[i].oidlen <= sysConfArr[commArr[commArrNo].sysConfArrNo].indexObjIdLen){
				sprintf(commArr[commArrNo].desc,"Oid is too short (oidlen =%d)",pdu->var[i].oidlen);
				omcLog(subsCommLog,"Oid is too short (oidlen =%d)",pdu->var[i].oidlen);
				return(-1);
			}
			for(j=0;j<sysConfArr[commArr[commArrNo].sysConfArrNo].indexObjIdLen;j++){
				if(sysConfArr[commArr[commArrNo].sysConfArrNo].indexObjId[j] != pdu->var[i].oid[j]){
					int k;
					omcLog(subsCommLog,"Oid is not match!");	
					for(k=0; k < sysConfArr[commArr[commArrNo].sysConfArrNo].indexObjIdLen; k++){
						omcLog(subsCommLog,"%d: %ld [%ld]", k, sysConfArr[commArr[commArrNo].sysConfArrNo].indexObjId[k], pdu->var[i].oid[k]);
					}
					sprintf(commArr[commArrNo].desc,"Oid is not match!");
					return(-1);
				}
			}
			tlvLen = sysConfArr[commArr[commArrNo].sysConfArrNo].indexValueLen;
			for(;commArr[commArrNo].tlvFinishNum < commArr[commArrNo].tlvTotalNum;){
				sprintf(tagStr,"%d",commArr[commArrNo].tlvFinishNum+1);
				memset(tlvAscValue,0,sizeof(tlvAscValue));
				//tlvLen=GetTLV(tagStr,sizeof(tlvAscValue),tlvAscValue,0x80,&asnBuffer);
				tlvLen=GetTLV(tagStr,16,(u_char*)tlvAscValue,0x80,&asnBuffer);
				if(tlvLen > 0){
				
					sprintf(commArr[commArrNo].indexBuffer[commArr[commArrNo].tlvFinishNum],"%s",tlvAscValue);
					commArr[commArrNo].tlvFinishNum++;
					//commArr[commArrNo].tlvInvaildNum = 0;
					#if subsComm_DEBUG
					omcLog(subsCommLog,"segmnet[%d] tlvTag[%s]'s \t tlvValue = %s",commArr[commArrNo].finishNum,tagStr,tlvAscValue);
					#endif
					// fj
					// printf("[subsComm] commArrNo[%d] segment[%d] tlvTag[%s] tlvVal[%s]\n", commArrNo, commArr[commArrNo].finishNum, tagStr, tlvAscValue);
				}else{
					
					commArr[commArrNo].indexBuffer[commArr[commArrNo].tlvFinishNum][0] = 0;
					commArr[commArrNo].tlvFinishNum++;
					if(tlvLen == 0){ 	
						commArr[commArrNo].tlvInvaildNum++;
						//Don not check the zero imsi
						loadIndexFinishFlag=1;
						#if subsComm_DEBUG
						omcLog(subsCommLog,"segmnet[%d] tlvTag[%s]'s \t tlvValue = Null",commArr[commArrNo].finishNum,tagStr);
						#endif
					}else{
						
						if(commArr[commArrNo].commType == nLoadIndexComm&&loadIndexFinishFlag==1){
							sprintf(commArr[commArrNo].desc,"process finished");
							commArr[commArrNo].tlvFinishNum = MaxIndexNumPerSeg;
							commArr[commArrNo].finishNum=commArr[commArrNo].totalNum;
							return(1);
						}
						if(commArr[commArrNo].tlvFinishNum > 0){
							omcLog(subsCommLog,"can not get tlvTag[%s]'s tlvValue,after[%s]",tagStr,
										commArr[commArrNo].indexBuffer[commArr[commArrNo].tlvFinishNum - 1]);
						}else{
							omcLog(subsCommLog,"can not get tlvTag[%s]'s tlvValue,segment[%d]",
										tagStr,commArr[commArrNo].finishNum);
						}
						return(0);
					}
				}
			}//end of for()
			
			//if(commArr[commArrNo].tlvFinishNum == sysConfArr[commArr[commArrNo].sysConfArrNo].maxIndexNumPerSeg){
				if(loadIndexFinishFlag==1)
					commArr[commArrNo].finishNum=commArr[commArrNo].totalNum;
			//}
		}else{/*get data and update to database*/
			//char tmpKeyValue[32]	="\0";
			char tmpUnitValue[1024]	="\0";
			char tmpSetStr[1024]	="\0";
			int paramConfBgn	= sysConfArr[commArr[commArrNo].sysConfArrNo].paramConfArrOffset;
			int paramConfEnd	= sysConfArr[commArr[commArrNo].sysConfArrNo].paramConfArrOffset 
									+ sysConfArr[commArr[commArrNo].sysConfArrNo].paramConfNum;
			int sysConfArrNo	= commArr[commArrNo].sysConfArrNo;
			int varCount=0;

			//check preObjId
			if(pdu->var[i].oidlen <= sysConfArr[sysConfArrNo].preObjIdLen){
				sprintf(commArr[commArrNo].desc,"Oid is too short (oidlen =%d)",pdu->var[i].oidlen);
				return(0);
			}
			for(j=0;j<sysConfArr[sysConfArrNo].preObjIdLen;j++){
				if(sysConfArr[sysConfArrNo].preObjId[j] != pdu->var[i].oid[j]){
					int k=0;
					sprintf(commArr[commArrNo].desc," Oid is not match!");
					for(k=0;k<sysConfArr[sysConfArrNo].preObjIdLen;k++){
						omcLog(subsCommLog,"%d: %ld [%ld]",k,sysConfArr[sysConfArrNo].preObjId[k],pdu->var[i].oid[k]);
					}
					return(-1);
				}
			}

			//check keyValue in oid
			if((pdu->var[i].oid[sysConfArr[sysConfArrNo].preObjIdLen] <= 0) 
				&& (pdu->var[i].oid[sysConfArr[commArr[commArrNo].sysConfArrNo].preObjIdLen+1] <= 0)){
				sprintf(commArr[commArrNo].desc,"x = 0 and y = 0");
				return(-1);
			}

			//check operation code
			if(pdu->var[i].oid[sysConfArr[sysConfArrNo].preObjIdLen+2] != FlagCode){
				sprintf(commArr[commArrNo].desc," can find operation code(1373)");
				return(-1);
			}

			//get keyValue from oid
			//encodeKeyValue(tmpKeyValue,
			//		pdu->var[i].oid[sysConfArr[sysConfArrNo].preObjIdLen],
			//		pdu->var[i].oid[sysConfArr[sysConfArrNo].preObjIdLen+1]);
			
			sprintf(tmpWhere," %s = '%s'",sysConfArr[sysConfArrNo].indexFieldName,commArr[commArrNo].indexBuffer[0]);
			// fj
			// printf("procResp\n");
			// fj
			// 重点: 这里获取用户的详细信息。按参数oid从回复报文中取出值并
			//       构造 imsi=imsi, msisdn=1234567类型的字符串
			if(commArr[commArrNo].commType != nDeleteComm){
				//get value form asnbuffer and make SQL string
				for(tlvCount = paramConfBgn; tlvCount < paramConfEnd; tlvCount++){
					tmpSetStr[0]=0;
					switch(paramConfArr[tlvCount].valueType){
						case 0x02: //INTEGER
							 tlvLen= GetInteger(paramConfArr[tlvCount].fieldObjIdStr,&tlvIntValue,
													0x80,&asnBuffer);
							 sprintf(tmpSetStr,"%s = '%d'",paramConfArr[tlvCount].fieldName,tlvIntValue);
							 //fj
							 printf("int. oid[%s] %s\n", paramConfArr[tlvCount].fieldObjIdStr, tmpSetStr);
							break;
						case 0x03: //OCTET STRING -> Asc
							memset(tlvAscValue,0,sizeof(tlvAscValue));
							tlvLen=GetTLV(paramConfArr[tlvCount].fieldObjIdStr,paramConfArr[tlvCount].valueLen,
									(u_char*)tlvAscValue,0x80,&asnBuffer);
							sprintf(tmpSetStr,"%s = '%s'",paramConfArr[tlvCount].fieldName,tlvAscValue);
							// fj
							// printf("str. oid[%s] %s\n", paramConfArr[tlvCount].fieldObjIdStr, tmpSetStr);
							break;
						case 0x04: //OCTET STRING -> Hex
							memset(tlvBcdValue,0,sizeof(tlvBcdValue));
							memset(tmpUnitValue,0,sizeof(tmpUnitValue));
							tlvLen=GetTLV(paramConfArr[tlvCount].fieldObjIdStr,paramConfArr[tlvCount].valueLen,
									tlvBcdValue,0x80,&asnBuffer);
							if(tlvLen >= 0){
								omc_RbcdToAscii(tmpUnitValue, tlvBcdValue, tlvLen*2);
								sprintf(tmpSetStr,"%s = '%s'",paramConfArr[tlvCount].fieldName,tmpUnitValue);
							}
							// fj
							// printf("hex. oid[%s] %s\n", paramConfArr[tlvCount].fieldObjIdStr, tmpSetStr);
							break;
						default:
							// printf("err type.[%d]\n", paramConfArr[tlvCount].valueType);
							sprintf(commArr[commArrNo].desc," Invailed vartype(paramConfArr[%d].valueType=%d)",
											tlvCount,paramConfArr[tlvCount].valueType);
							return(-1);
					}
					if(tlvLen >= 0){
						if(varCount == 0){
							strcat(tmpValue,tmpSetStr);
						}else{
							strcat(tmpValue,", ");
							strcat(tmpValue,tmpSetStr);
						}
						varCount++;
					}
					#if subsComm_DEBUG
					else{
						omcLog(subsCommLog,"can not get tlvTag[%s]'s tlvValue",paramConfArr[tlvCount].fieldObjIdStr);
					}
					#endif
				}//end of for(..)
			}else{
			
			}//end of if(commArr[commArrNo].commType != nDeleteComm)

			//Query SQL
			switch(commArr[commArrNo].commType){
				case nReadComm:
				case nCreateComm:
					if(strlen(sysConfArr[sysConfArrNo].tmpTableName) > 1 && strlen(tmpValue) > 3){
						sprintf(tmpQuery,"REPLACE %s SET %s",
								sysConfArr[sysConfArrNo].tmpTableName,
								tmpValue);
						mysql_getnores(dbConn,tmpQuery);
					}
					sprintf(tmpQuery,"REPLACE %s SET %s",
							sysConfArr[sysConfArrNo].paramTableName,
							tmpValue);
					mysql_getnores(dbConn,tmpQuery);
					// fj
					// printf("[subsComm] readComm/CreateComm. sql[%s]\n", tmpQuery);
					break;
				case nChangeComm:
					//update to tmp subscriber database
					if(strlen(sysConfArr[sysConfArrNo].tmpTableName) > 1 && strlen(tmpValue) > 3){
						sprintf(tmpQuery,"UPDATE %s SET %s WHERE %s",
								sysConfArr[sysConfArrNo].tmpTableName,
								tmpValue,tmpWhere);
						nSqlReturn=mysql_getnores(dbConn,tmpQuery);
					}
					//update to subscriber database
					//if(nSqlReturn == 0){
						sprintf(tmpQuery,"UPDATE %s SET %s WHERE %s",
								sysConfArr[sysConfArrNo].paramTableName,
								tmpValue,tmpWhere);
						mysql_getnores(dbConn,tmpQuery);
					//}
					break;
				case nDeleteComm:
					//update to tmp subscriber database
					if(strlen(sysConfArr[sysConfArrNo].tmpTableName) > 1 && strlen(tmpWhere) > 3){
						sprintf(tmpQuery,"DELETE FROM %s WHERE %s",
								sysConfArr[sysConfArrNo].tmpTableName,tmpWhere);
						nSqlReturn=mysql_getnores(dbConn,tmpQuery);
					}
					//update to subscriber database
					//if(nSqlReturn == 0){
						sprintf(tmpQuery,"DELETE FROM %s WHERE %s",
								sysConfArr[sysConfArrNo].paramTableName,tmpWhere);
						mysql_getnores(dbConn,tmpQuery);
					//}
					break;
				case nLoadDataComm:
					if(strlen(sysConfArr[sysConfArrNo].tmpTableName) > 1 && strlen(tmpValue) > 3){
						sprintf(tmpQuery,"INSERT INTO %s SET %s",
								sysConfArr[sysConfArrNo].tmpTableName,
								tmpValue);
						nSqlReturn=mysql_getnores(dbConn,tmpQuery);
						// fj
						// printf("[subsComm] insertTab. sql[%s]\n\n", tmpQuery);
					}
					if(nSqlReturn == 0){
						sprintf(tmpQuery,"INSERT INTO %s SET %s",
							sysConfArr[sysConfArrNo].paramTableName,
							tmpValue);
						mysql_getnores(dbConn,tmpQuery);
					}else{
						omcLog(subsCommLog,"Process [%s]'s data error!",commArr[commArrNo].indexBuffer[commArr[commArrNo].finishNum]);
						omcLog(subsCommLog,"SQL=%s",tmpQuery);
						omcLog(subsCommLog,"Error number:%d", mysql_errno(dbConn));
   						omcLog(subsCommLog,"Description: %s", mysql_error(dbConn));
						return(0);
					}
					break;
				case nReplaceIndexComm:
					sprintf(tmpQuery,"UPDATE %s SET %s WHERE %s",
							sysConfArr[sysConfArrNo].tmpTableName,
							tmpValue,tmpWhere);
					nSqlReturn=mysql_getnores(dbConn,tmpQuery);
						
					sprintf(tmpQuery,"UPDATE %s SET %s WHERE %s",
							sysConfArr[sysConfArrNo].paramTableName,
							tmpValue,tmpWhere);
					nSqlReturn=mysql_getnores(dbConn,tmpQuery);
					break;
				default:
					omcLog(subsCommLog,"Unknown commType");
					return(0);
			}
			commArr[commArrNo].finishNum++;
		}//end of if(commArr[commArrNo].commType == nLoadIndex)
	}//end of for(i = 0; i < pdu->var_num; i++)
	return(1);
}//end subsComm_procResp

/*************************************************
Function:        // subsComm_updateCommTable
Description:     // 修改用户数据命令表中指定命令的状态，说明信息，完成进度
Calls:           // mysql_getnores;
Called By:       // subsCommScan; subsCommProc;
Table Accessed:  // OMC_PUB.subscriberComm
Table Updated:   // OMC_PUB.subscriberComm
Input:           // 
Output:          // 
Return:          // 1:successful; 0:failed;
Others:          // 
*************************************************/
int subsComm_updateCommTable(int commArrNo)
{
	char tmpQuery[500] = "\0";

	//如果该命令对象是nLoadDataComm类型，则不对用户数据命令表进行更新
	if(commArr[commArrNo].commType == nLoadDataComm){
		return(1);
	}
	
	//刚启动，或处于等待的命令
	if(commArr[commArrNo].procState == nIdle 
			&& (commArr[commArrNo].commState == nInProc	|| commArr[commArrNo].commState == nWaitProc)){
		sprintf(tmpQuery,"UPDATE %s SET commState = '%d',finishNum= '0', totalNum= '%d',"\
				"bgnTime = CURRENT_TIMESTAMP WHERE commId = '%d'",\
				CommTable, commArr[commArrNo].commState,
				commArr[commArrNo].totalNum, commArr[commArrNo].commNo);
	}
	//正在执行当中或执行完毕的命令，更新该命令的完成度
	else{
		sprintf(tmpQuery,"UPDATE %s SET commState='%d',finishNum='%d', "\
				"endTime = CURRENT_TIMESTAMP, remark='%s' WHERE commId = '%d'",\
				CommTable, commArr[commArrNo].commState, \
				commArr[commArrNo].finishNum,commArr[commArrNo].desc,commArr[commArrNo].commNo);
	}
	mysql_getnores(dbConn,tmpQuery);
	return(1);
}//end subsComm_updateCommTable

/*************************************************
Function:        // decodeKeyValue
Description:     // 把一个16位的字符串按前8后8的方法，变成两个整形
Calls:           // 
Called By:       // subsComm_mkVarArr
Table Accessed:  // 
Table Updated:   // 
Input:           // keyValue:源字符串; bgn_8,end_8:转换后的两个整形;
Output:          // 
Return:          // 1:successful; 0:failed;
Others:          // 
*************************************************/
int decodeKeyValue(const char *keyValue,unsigned long *bgn_8,unsigned long *end_8)
{
	int	keyValueLen;
	char tmpStr[16]= "\0";
	keyValueLen=strlen(keyValue);
	if(keyValueLen <= 0 || keyValueLen > 16){
		return(0);
	}
	if(keyValueLen <= 8){
		*bgn_8 = 0;
		*end_8 = atol(keyValue);
	}else{
		memset(tmpStr,0,sizeof(tmpStr));
		strncpy(tmpStr,keyValue,(keyValueLen - 8));
		*bgn_8 = atol(tmpStr);
		*end_8 = atol(keyValue+(keyValueLen - 8));
	}
	return(1);
}//end decodeKeyValue

/*************************************************
Function:        // encodeKeyValue
Description:     // 把两个整形按前8后8的方法，变成一个16位的字符串
Calls:           // 
Called By:       // subsComm_procResp
Table Accessed:  // 
Table Updated:   // 
Input:           // keyValue:转换字符串; bgn_8,end_8:待转换的两个整型;
Output:          // 
Return:          // 1:successful; 0:failed;
Others:          // 
*************************************************/
int encodeKeyValue(char *keyValue,int bgn_8,int end_8)
{
	char tmpStr[16]	= "\0";
	//int i,tmpLen;
	memset(keyValue,0,sizeof(keyValue));
	if(bgn_8 > 0){
		sprintf(keyValue,"%d",bgn_8);
		sprintf(tmpStr,"%08d",end_8);
		/*
		tmpLen=strlen(tmpStr);
		for(i=tmpLen;i<8;i++){
			strcat(keyValue,"0");
		}
		*/
	}else{
		sprintf(tmpStr,"%d",end_8);
	}
	strcat(keyValue,tmpStr);
	return(1);
}//end encodeKeyValue

/*************************************************
Function:        // subsComm_freeParamSet
Description:     // 释放命令对象对应的用户数据集
Calls:           // mysql_free_result;
Called By:       // subsCommProc; subsComm_mkVarArr;
Table Accessed:  // 
Table Updated:   // 
Input:           // commArrNo:命令对象序号
Output:          // 
Return:          // 1:successful; 0:failed;
Others:          // 
*************************************************/
void subsComm_freeParamSet(int commArrNo)
{
	int i;
	if(commArr[commArrNo].paramSet != NULL){
		int isCanFree = 1;
		//because same sql's resultSet's address will be same,so it is must check other command's state 
		for(i=0;i<MaxCommNum;i++){
			if((i != commArrNo) && (commArr[i].paramSet == commArr[commArrNo].paramSet)){
				if((commArr[i].commState == nWaitProc) || (commArr[i].commState == nInProc)){
					isCanFree = 0;
				}else{
					//omcLog(subsCommLog,"Set commArr[%d].paramSet (%x) = NULL",i,commArr[i].paramSet);
					commArr[i].paramSet = NULL;
				}
			}
		}
		if(isCanFree > 0){
			mysql_free_result(commArr[commArrNo].paramSet);
		}
		commArr[commArrNo].paramSet = NULL;
	}
}//end subsComm_freeParamSet
