/*************************************************
File name:	nrtrde.c
Author: 		JianHui Zheng
Version:		9:00:00 
Date:  			2007-11-09
Description:The application file about nrtrde.When the time slot is reached,it
			generate the NRTRDE files in ASN format.Then it sends NRTRDE files 
			to the remote HPMNs and receives NRTDE files from the HPMNs.
			
			When it receives the NRTRDE files from HPMNs,it will generate the
			NRTRDE File Delivery Report and NRTRDE Error Report if necessary.
			Then it sends the reports to the remote HPMNs.
			
			It also receives reports from the remote HPMNs and backups them.
			
			Note:(1)This version not supports the GPRS CDR.
			     (2)When send files to the remote servers,it uses SFTP protocol.
				   (3)It supports 100 HPMNs.
			
												
History:               
No. 		
Author:		  
Date:		 
Version:	   
Description:
*************************************************/
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "nrtrde.h"

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

/******************************************************/
/******           Function Declaration           ******/
/******************************************************/
/*******   From conv_prefix.c  ******/
extern int readConvPrefixConf();

/*******   From decodeASN.c   *******/
extern int parseAsnFile(char *fileName);
extern void makeNEFile(void);

/*******   From encodeASN.c   *******/
extern int hasCdrForServer(HpmnServer* server);
extern int makeNRFile(HpmnServer* server);

/*******   From seq_num_mng.c  *******/
extern seq_buffer seq_buf;
extern int add_seq_obj(seq_buffer *seq_buf,seq_object *add_obj);
extern unsigned long find_seq_obj(seq_buffer *seq_buf,char *keyvalue);
extern int get_seq_num(char *tadig,int type,char *out_seq);
extern int init_seq();
extern int store_seq();

/*******   From nrtrde.c   ********/
void nrtrdeInit(void);

int getLocalUTCTimeOffset(char *timeOffset);
int hpmnServersInfoUpdate(void);
void checkBackupFile(char* directory);
void checkToRecv(void);
int initDatabase(void);
void initDirectory(void);
int initTagConf(void);
int initNRConf(void);
//void getLastSquence(void);
void logMessage(const char *fmt,...);
int isHour(int hour);
int getDate(int flag);
//void getSequenceNumber(char* squenceNumber,int type);
int getTagByName(char* name);
//2009-06-10
int sendHeartbeat();


/* Use for creating delivery reports */
void makeNDFile(void);
int addNDNode(char* tadig,char* fileName);
int addNDNodeInDB(char* tadig,char* fileName);

static struct itimerval itimer, old_itimer;
static void On_Timer();
static void SetTimer();

/******************************************************/
/******                For Test                  ******/
/******************************************************/
void printfInColor(char *message,int color);
void printfHPMNServer(HpmnServer* server);

/******************************************************/
/******       Public Parameter Declaration       ******/
/******************************************************/
/* The hpmn servers info will be updated every minute */
int g_hpmn_update_timeout;

/* The total count of hpmn servers in the hpmnConf table */
int g_hpmn_server_count;

/* The OMC_PUB database connection */
MYSQL *g_omcPubConn;

/* The CDR_DB database connection */
MYSQL *g_cdrConn;

/* The local UTC timeOffset */
char g_local_utc[8];

/* The local MCC */
char g_local_mcc[6];

/* The local MNC */
char g_local_mnc[6];

/* The max value of the CallEventDuration */
int g_maxCallDuration;

/* The tadig of local server */
char LOCAL_TADIG[8];

/* The time to make NRTRDE Delivery Report and Error Report (Hour) */
int MAKE_REPORT_TIME;

/* The version of the NRTRDE Delivery report */
char ND_VERSION[8];
/* The version of the NRTRDE Error report */
char NE_VERSION[8];
/* The specificationVersionNumber of the NRTRDE file */
int NR_SVN;
/* The ReleaseVersionNumber of the NRTRDE file */
int NR_RVN;

/* The source directory to send the file */
char SEND_DIR[256];
/* The directory to receive the file */
char RECV_DIR[256];

/* The backup directory */
char NR_RECV_BAK_DIR[256];
char NR_SEND_BAK_DIR[256];
char ND_RECV_BAK_DIR[256];
char ND_SEND_BAK_DIR[256];
char NE_RECV_BAK_DIR[256];
char NE_SEND_BAK_DIR[256];
char LOCAL_CSV_DIR[256];


/* The hpmn servers array, now suport 100 servers */
HpmnServer servers[HPMN_SERVER_COUNT];

/* The information of tag */
TagNode tags[50];

/* The date of make report last time */
int g_next_date_mk_rep;

/* The Sequence Number of the NRTRDE file */
//long g_nr_squence_number;
//long g_nd_squence_number;
//long g_ne_squence_number;


/* Use to create NRTRDE Delivery report */
NDRepNode* pNDHead=NULL;
NDRepNode* pNDTail=NULL;


/* Use to check the receive files */
long recvfileSize;
char recvFileName[512]="NoFile";

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


/*************************************************
Function:        // main
Description:     // The main function of the module
Calls:           // 
Called By:       // 
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 
Others:          // 
*************************************************/
int main(int argc, char *argv[])
{
	pid_t pid;

	if (argc == 2 && strstr(argv[1], "-d")) {
		if ((pid = fork()) != 0)
			exit(0);
		setsid();
	}
	
	nrtrdeInit();
	
	SetTimer();
	while (1) {
		usleep(50);
	}
	return 1;
}

#define TEST_CDR_DECODE 0
int test_func()
{
#if TEST_CDR_DECODE == 1
	BYTE msg[1024];
	unsigned long msglen;
	int pos=0;
	char strmsg[2048];
	int len,i;
	int high,low;
	ASN_BUF asn_buf;
	int errpos;
	unsigned int tempint;
	
	sprintf(strmsg,"A081A18001008309916857950063F700008409916857950063F70000890A916857950210F2FFFFFF9608100701010355000897081007010103550008980810070101044900089904000000369E01909F230E3135352E3232362E3230322E37359F240E3135352E3232362E3230322E34359F250F3235352E3235352E3235352E3235359F2604000000139F8100018E9F810104000000029F81020400000F379F81030100");
	len=strlen(strmsg)/2;
	for(i=0;i<len;i++)
	{
		switch(strmsg[2*i])
		{
		case 'A':
		case 'a':
			high=10;break;
		case 'B':
		case 'b':
			high=11;break;
		case 'C':
		case 'c':
			high=12;break;
		case 'D':
		case 'd':
			high=13;break;
		case 'E':
		case 'e':
			high=14;break;
		case 'F':
		case 'f':
			high=15;break;
		default:
			high=strmsg[2*i]-'0';
			break;
		}
		
		switch(strmsg[2*i+1])
		{
		case 'A':
		case 'a':
			low=10;break;
		case 'B':
		case 'b':
			low=11;break;
		case 'C':
		case 'c':
			low=12;break;
		case 'D':
		case 'd':
			low=13;break;
		case 'E':
		case 'e':
			low=14;break;
		case 'F':
		case 'f':
			low=15;break;
		default:
			low=strmsg[2*i+1]-'0';
			break;
		}
		
		msg[pos]=high*16 + low;
		pos++;
	}
	msglen=len;
	 

	printf("%s\n\n",strmsg);
	for(i=0;i<msglen;i++)
		printf("%02X",msg[i]);
	printf("\n");
	
	AsnDecode(msg, msglen, 1, &errpos, &asn_buf);
	
	if(AsnDecode(msg,msglen, 1, &errpos, &asn_buf) < 0 && errpos < msglen) 
	{
		printf("AsnDecode error\n");
	}
	
	if((get_int_v2("0.30", &tempint, &asn_buf)) >= 0)
				printf("int=%d\n", tempint);
				
	
	len=get_int_v2("0.30", &tempint, &asn_buf);
	if(len > 0)
	{
		switch(len)
		{
		case 1:
			printf("int=%u\n", 0x000000ff & tempint);
			break;
		case 2:
			printf("int=%u\n", 0x0000ffff & tempint);
			break;
		case 3:
			printf("int=%u\n", 0x00ffffff & tempint);
			break;
		case 4:
			printf("int=%u\n",tempint);
			break;
		}
	}
	
	
	exit(1);
#endif
	return 0;
}

/*************************************************
Function:        // nrtrdeInit
Description:     // Initial the HPMN infomation
Calls:           // 
Called By:       // 
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 
Others:          // 
*************************************************/
void nrtrdeInit()
{
	
	int i;
	struct tm *now;
	time_t t;
	char message[256];


#if TEST_CDR_DECODE == 1	
	test_func();
#endif
	
	
	t=time(NULL);
	now=localtime(&t);

	printfInColor("NRTRDE Module initial......\n",5);
	sprintf(message,"NRTRDE Module is starting......\n");
	logMessage(message);
	
	//debug_init(1);
	iptrans_init();
	snmp_init(4957);
	//heartbeat_init(0);
	
	if(!readConvPrefixConf())
	{
		printfInColor("Read ./conf/conv_prefix.conf error\n",1);
		sprintf(message,"Read ./conf/conv_prefix.conf error\n");
		logMessage(message);
	}
	else
	{
		printfInColor("Read ./conf/conv_prefix.conf successfully\n",5);
		sprintf(message,"Read ./conf/conv_prefix.conf successfully\n");
		logMessage(message);
	}
	
	//Init the database connections
	initDatabase();
	//Init the HPMN servers info update time
	g_hpmn_update_timeout=HPMN_INFO_UPDATE_TIME;
	//Init the HPMN servers information
	hpmnServersInfoUpdate();
	//Init the tag information
	initTagConf();
	//Init the NR.conf file
	initNRConf();
	//Init the local utc timeOffset
	getLocalUTCTimeOffset(g_local_utc);
	sprintf(message,"The local UTCTimeOffset=%s\n",g_local_utc);
	logMessage(message);
	printfInColor(message,3);
	
	//Init the directory
	initDirectory();
	
	
	//Init the HPMN send file timeout
	for(i=0; i<g_hpmn_server_count; i++)
	{
		servers[i].sendFileTimeout=servers[i].timeSlot;
	}
	
	//Init the next date to make reports
	if(now->tm_hour < MAKE_REPORT_TIME)
		g_next_date_mk_rep=getDate(0);
	else
		g_next_date_mk_rep=getDate(1);
		
	//Get the last squence_number of NR,ND,NE
	//getLastSquence();	
	init_seq();
	
//for test		
/*
{	
	time_t start;
	start=time(NULL);
	
	for(i=0;i<1;i++)
		parseAsnFile("NRLZSHEFEAKE1000000");	
		
	makeNEFile();	
	printf("The execute time is %ld\n",time(NULL)-start);	
	sleep(1);	
}
*/
}

/*************************************************
Function:        // getLastSquence
Description:     // Get the last squence_number of NR,ND,NE
Calls:           // 
Called By:       // nrtrdeInit
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 
Others:          // 
*************************************************/
/*
void getLastSquence()
{
	char fullFileName[512];
	char message[256];
	char lastFile[256];
	struct dirent* pDirEnt;
	struct stat fileStat;
	DIR* srcDir;
	time_t maxtime;
	int res;
	
	g_nr_squence_number=0;
	g_nd_squence_number=0;
	g_ne_squence_number=0;
	
	//open the NR_SEND_BAK_DIR directory
	srcDir = opendir(NR_SEND_BAK_DIR);
	if(srcDir!=NULL)
	{
		maxtime=0;
		memset(lastFile,0,sizeof(lastFile));
		while((pDirEnt = readdir(srcDir))!=NULL)
		{
			if(strlen(pDirEnt->d_name) != 19)
				continue;
			if(strstr(pDirEnt->d_name,"NR") == NULL)
				continue;

			sprintf(fullFileName,"%s%s",NR_SEND_BAK_DIR,pDirEnt->d_name);
			res=stat(fullFileName,&fileStat);
			if(maxtime < fileStat.st_mtime)
			{
				maxtime=fileStat.st_mtime;
				sprintf(lastFile,"%s",pDirEnt->d_name);
			}
		}
		if(maxtime > 0)
		{
			sprintf(message,"The last NR file=%s\n",lastFile);
			logMessage(message);
			g_nr_squence_number=atol(&lastFile[12])+1;
			g_nr_squence_number%=10000000;
		}
		closedir(srcDir);
	}
	
	//open the ND_SEND_BAK_DIR directory
	srcDir = opendir(ND_SEND_BAK_DIR);
	if(srcDir!=NULL)
	{
		maxtime=0;
		memset(lastFile,0,sizeof(lastFile));
		while((pDirEnt = readdir(srcDir))!=NULL)
		{
			if(strlen(pDirEnt->d_name) != 17)
				continue;
			if(strstr(pDirEnt->d_name,"ND") == NULL)
				continue;

			sprintf(fullFileName,"%s%s",ND_SEND_BAK_DIR,pDirEnt->d_name);
			res=stat(fullFileName,&fileStat);
			if(maxtime < fileStat.st_mtime)
			{
				maxtime=fileStat.st_mtime;
				sprintf(lastFile,"%s",pDirEnt->d_name);
			}
		}
		if(maxtime > 0)
		{
			sprintf(message,"The last ND file=%s\n",lastFile);
			logMessage(message);
			g_nd_squence_number=atol(&lastFile[12])+1;
			g_nd_squence_number%=100000;
		}
		closedir(srcDir);
	}
	
	//open the NE_SEND_BAK_DIR directory
	srcDir = opendir(NE_SEND_BAK_DIR);
	if(srcDir!=NULL)
	{
		maxtime=0;
		memset(lastFile,0,sizeof(lastFile));
		while((pDirEnt = readdir(srcDir))!=NULL)
		{
			if(strlen(pDirEnt->d_name) != 17)
				continue;
			if(strstr(pDirEnt->d_name,"NE") == NULL)
				continue;

			sprintf(fullFileName,"%s%s",NE_SEND_BAK_DIR,pDirEnt->d_name);
			res=stat(fullFileName,&fileStat);
			if(maxtime < fileStat.st_mtime)
			{
				maxtime=fileStat.st_mtime;
				sprintf(lastFile,"%s",pDirEnt->d_name);
			}
		}
		if(maxtime > 0)
		{
			sprintf(message,"The last NE file=%s\n",lastFile);
			logMessage(message);
			g_ne_squence_number=atol(&lastFile[12])+1;
			g_ne_squence_number%=100000;
		}
		closedir(srcDir);
	}

}
*/
/*************************************************
Function:        // On_Timer
Description:     // Timer function for NRTRDE
Calls:           // 
Called By:       // 
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 
Others:          // 
*************************************************/
long maxTime=0;
unsigned long heartbeat_timeout=0;
void On_Timer()
{
	int i;
	char message[256];
	

	static struct timeval tv1, tv2;
	struct timezone tz;
	long elapse;
	
	
	gettimeofday(&tv2, &tz);
	tv1.tv_sec = tv2.tv_sec;
	tv1.tv_usec = tv2.tv_usec;

	if(time(NULL) - heartbeat_timeout > 5)
	{
		heartbeat_timeout=time(NULL);
		sendHeartbeat();
	}

	//Begin to make NRTRDE Delivery Report and Error Report
	if(isHour(MAKE_REPORT_TIME) && g_next_date_mk_rep == getDate(0))
	{
		sprintf(message,"Now start to make reports\n");
		logMessage(message);
		printfInColor(message,3);
		//Make the NRTRDE reports,the makeNEFile must in the front of makeNDFile
		makeNEFile();
		makeNDFile();
		
		
		g_next_date_mk_rep=getDate(1);
		sprintf(message,"The next time to make report is %02d-%02d:00:00\n",g_next_date_mk_rep,MAKE_REPORT_TIME);
		logMessage(message);
		printfInColor(message,3);
		
		//check the backup directory and delete the overtime files
		/*
		checkBackupFile(NR_SEND_BAK_DIR);
		checkBackupFile(NR_RECV_BAK_DIR);
		checkBackupFile(ND_RECV_BAK_DIR);
		checkBackupFile(ND_SEND_BAK_DIR);
		checkBackupFile(NE_RECV_BAK_DIR);
		checkBackupFile(NE_SEND_BAK_DIR);
		checkBackupFile(LOCAL_CSV_DIR);
		*/
	}

		
	
	g_hpmn_update_timeout--;
	sprintf(message,"Update the HPMN infomation timeout=%d\n",g_hpmn_update_timeout);
	printfInColor(message,0);
	//Start to update the HPMN servers info
	if(g_hpmn_update_timeout < 0)
	{
		g_hpmn_update_timeout=HPMN_INFO_UPDATE_TIME;
		hpmnServersInfoUpdate();
		
		sprintf(message,"Update the HPMN infomation\n");
		logMessage(message);
		printfInColor(message,3);
		
		sprintf(message,"Now the HPMN server count=%d\n",g_hpmn_server_count);
		logMessage(message);
		printfInColor(message,3);
		
		
		
		//check mysql connections
		//Init the OMC_PUB database connection
		if(mysql_ping(g_omcPubConn))
		{
			logMessage("[ERR 2006][On_Timer]:mysql OMC_PUB has gone away,reconnect");
			mysql_close(g_omcPubConn);
			g_omcPubConn=mysql_conn("localhost","OMC_PUB");
			if(g_omcPubConn == NULL)
			{
			  logMessage("[ERR][On_Timer]:reconnect OMC_PUB");
			}
		}
		
		//Init the CDR_DB database connection
		if(mysql_ping(g_cdrConn))
		{
			logMessage("[ERR 2006][On_Timer]:mysql CDR_DB has gone away,reconnect");
			mysql_close(g_cdrConn);
			g_cdrConn=mysql_conn("localhost","CDR_DB");
			if(g_cdrConn == NULL)
			{
				logMessage("[ERR][On_Timer]:mysql_conn CDR_DB");
			}
		}
		
	}
	
	//If the timeSlot is arrived, then generate the NRTRDE files
	for(i=0; i<g_hpmn_server_count; i++)
	{
		servers[i].sendFileTimeout--;
		sprintf(message,"%s,sendFileTimeout=%d\n",servers[i].tadig,servers[i].sendFileTimeout);
		printfInColor(message,0);
		if(servers[i].sendFileTimeout < 0)
		{
			servers[i].sendFileTimeout=servers[i].timeSlot;
			sprintf(message,"Prepare to send files to %s\n",servers[i].tadig);			
			logMessage(message);
			printfInColor(message,3);
			
			//For test
			/*
			if(strcmp(servers[i].tadig,"LZSHE") == 0)
			{
				//sprintf(message,"./createCDRs");
				//system(message);
				//makeNEFile();
				//makeNDFile();
				
			}
			*/
			
			//start to generate NRTRDE file
			makeNRFile(&servers[i]);
			

		}
	}
	
	//Check the receive directory to get the NRTRDE file and reports
	checkToRecv();
	
	//test the running time of the program
	gettimeofday(&tv2, &tz);
	elapse =
		(tv2.tv_sec - tv1.tv_sec) * (10 ^ 6) + tv2.tv_usec - tv1.tv_usec;
	
	if(elapse>maxTime)
	{
		maxTime=elapse;	
		sprintf(message,"The max time of timer is %.6f seconds\n",(double)(elapse/1000)/1000);
		logMessage(message);
		//printf("maxTime=%ld\n",elapse);	
	}
	
}

/*************************************************
Function:        // getLocalUTCTimeOffset
Description:     // Get the timezone of local system in string
Calls:           // 
Called By:       // 
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // timeOffset:the timezone in string
Return:          // 0:failed; 1:successful
Others:          // exe. +0200,-1200. The linux operate system must set the timezone
*************************************************/
int getLocalUTCTimeOffset(char *timeOffset)
{
	struct tm *local,*utc;
	time_t t;
	long offset,t1,t2,d1,d2,m1,m2,y1,y2;
	//For test
	char message[256];
	
	
	if(timeOffset == NULL)
		return FAIL;
	
	t=time(NULL);
	local=localtime(&t);
	t1=local->tm_hour;
	d1=local->tm_mday;
	m1=local->tm_mon;
	y1=local->tm_year;
	
	//sprintf(message,"Local hour=%ld,date=%ld,month=%ld,year=%ld\n",t1,d1,m1,y1);
	//printfInColor(message,5);
	t=time(NULL);
	utc=gmtime(&t);
	t2=utc->tm_hour;
	d2=utc->tm_mday;
	m2=utc->tm_mon;
	y2=utc->tm_year;
	//sprintf(message,"UTC hour=%ld,date=%ld,month=%ld,year=%ld\n",t2,d2,m2,y2);
	//printfInColor(message,5);
	offset=y1*365*12*30*24+m1*30*24+d1*24+t1-(y2*365*12*30*24+m2*30*24+d2*24+t2);
	
	
	if(offset >= 0)
	{
		if(offset >9)
			sprintf(timeOffset,"+%ld00",offset);
		else
			sprintf(timeOffset,"+0%ld00",offset);	
	}
	else
	{
		if(offset < -9)
			sprintf(timeOffset,"-%ld00",-offset);
		else
			sprintf(timeOffset,"-0%ld00",-offset);	
	}	
	sprintf(message,"UTCoffset=%s\n",timeOffset);	
	printfInColor(message,5);
	return SUCCESSFUL;
}

/*************************************************
Function:        // hpmnServersInfoUpdate
Description:     // Update the HPMN servers information
Calls:           // initDatabase; printfHPMNServer;
Called By:       // 
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 0:failed; 1:successful;
Others:          // This function will modify the 'g_hpmn_server_count' and 'servers' value
*************************************************/
int hpmnServersInfoUpdate()
{
	MYSQL_RES *res;
	MYSQL_ROW row;
	char sqlstr[256];
	char message[256];
	int server_count;
	int len;
	
	seq_buffer tmp_seq_buf;
	seq_object tmp_seq_obj;
	unsigned long find_index;
	
	sprintf(sqlstr,"SELECT mcc,mnc,tadig,serverIP,loginName,loginPass,timeslot,reportDir,nrtrdeDir FROM OMC_PUB.hpmnConf");
	
	res=mysql_getres(g_omcPubConn,sqlstr);
	if(res == NULL)
	{
		sprintf(message,"[ERR %d][hpmnServersInfoUpdate]:%s\n",mysql_errno(g_omcPubConn),sqlstr);
	  logMessage(message);
		return FAIL;
	}
	
	memcpy(&tmp_seq_buf,&seq_buf,sizeof(seq_buf));
	memset(&seq_buf,0,sizeof(seq_buf));
	memset(&tmp_seq_obj,0,sizeof(tmp_seq_obj));
	
	//Update the HPMN servers information
	server_count=0;
	while((row = mysql_fetch_row(res)) != NULL)
	{
		//Get the mcc
		sprintf(servers[server_count].mcc,"%s",row[0]);
		//Get the mnc
		sprintf(servers[server_count].mnc,"%s",row[1]);
		//Get the tadig
		sprintf(servers[server_count].tadig,"%s",row[2]);
		
		//----------------------
		sprintf(tmp_seq_obj.tadig,"%s",row[2]);
		find_index=find_seq_obj(&tmp_seq_buf,tmp_seq_obj.tadig);
		if(find_index != NO_FIND)
		{
			tmp_seq_obj.nr_seq_num=tmp_seq_buf.seq_obj[find_index].nr_seq_num;
			tmp_seq_obj.nd_seq_num=tmp_seq_buf.seq_obj[find_index].nd_seq_num;
			tmp_seq_obj.ne_seq_num=tmp_seq_buf.seq_obj[find_index].ne_seq_num;
		}
		if(add_seq_obj(&seq_buf,&tmp_seq_obj) == 0)
			continue;
		//----------------------
		
		//Get the serverIP
		sprintf(servers[server_count].serverIP,"%s",row[3]);
		//Get the loginName
		sprintf(servers[server_count].loginName,"%s",row[4]);
		//Get the loginPass
		sprintf(servers[server_count].loginPass,"%s",row[5]);
		//Get the timeSlot
		servers[server_count].timeSlot=atoi(row[6]);
		//Get the reportDir
		sprintf(servers[server_count].reportDir,"%s",row[7]);
		//Get the nrtrdeDir
		sprintf(servers[server_count].nrtrdeDir,"%s",row[8]);
		
		len = strlen(servers[server_count].reportDir);
		if (servers[server_count].reportDir[len-1] != '/'&&len<127)
		{
			servers[server_count].reportDir[len]='/';
			servers[server_count].reportDir[len+1]='\0';
		}
		
		len = strlen(servers[server_count].nrtrdeDir);
		if (servers[server_count].nrtrdeDir[len-1] != '/'&&len<127)
		{
			servers[server_count].nrtrdeDir[len]='/';
			servers[server_count].nrtrdeDir[len+1]='\0';
		}
		printfHPMNServer(&servers[server_count]);
		server_count++;
	}
	//Update the server count
	g_hpmn_server_count=server_count;
	//Free the database resource
	mysql_free_result(res);

	
	return SUCCESSFUL;
}

/*************************************************
Function:        // checkBackupFile
Description:     // Check the files and delete the files when its store for more than 7 days
Calls:           // 
Called By:       // 
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 
Others:          // 
*************************************************/
void checkBackupFile(char* directory)
{
	struct dirent* pDirEnt;
	struct stat fileStat;
	DIR* srcDir;
	char command[512];
	char message[512];
	char fullFileName[512];
	struct tm* file_tm,*now;
	time_t file_t,temp_t;
	long now_date,file_date;
	
	//check the NR files receive backup directory
	srcDir = opendir(directory);
	if(srcDir != NULL)
	{
		while((pDirEnt = readdir(srcDir))!=NULL)
		{
			if(strlen(pDirEnt->d_name)<3)
				continue;	
	
			temp_t=time(NULL);
			now=localtime(&temp_t);
			now_date=360*now->tm_year+30*now->tm_mon+now->tm_mday-MAX_BAK_DAY;
			
			sprintf(fullFileName,"%s%s",directory,pDirEnt->d_name);
			stat(fullFileName,&fileStat);
			file_t=fileStat.st_mtime;
			file_tm=localtime(&file_t);
			file_date=360*file_tm->tm_year+30*file_tm->tm_mon+file_tm->tm_mday;
			
			if(file_date<now_date)
			{	
				sprintf(message,"The file=%s has exceed the backup time(%d days),now delete\n",fullFileName,MAX_BAK_DAY);
				printfInColor(message,4);
				logMessage(message);
				
				sprintf(command,"rm -rf %s",fullFileName);
				system(command);
			}
		}	
		
		closedir(srcDir);
	}	
	
}

/*************************************************
Function:        // checkToRecv
Description:     // To check the receive directory to get the NRTRDE file and reports
Calls:           // 
Called By:       // 
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 
Others:          // The 'RECV_DIR' define the receive directory in the head file
*************************************************/
void checkToRecv()
{
	char command[256];
	char message[256];
	struct dirent* pDirEnt;
	struct stat fileStat;
	DIR* srcDir;
	char tmpFileName[512];
	char fullFileName[512];
	char recipientTadig[8];
	char senderTadig[8];
	int i;
	
	
	//open the receive directory
	srcDir = opendir(RECV_DIR);
	if(srcDir==NULL)
	{	
		return;
	}

	while((pDirEnt = readdir(srcDir))!=NULL)
	{
		
		if(strlen(pDirEnt->d_name)<3)
			continue;	
			
		if(!(strlen(pDirEnt->d_name)==17 || strlen(pDirEnt->d_name)==19))
			continue;

		if(strcmp(recvFileName,"NoFile") == 0)
		{
			sprintf(recvFileName,"%s",pDirEnt->d_name);
			sprintf(fullFileName,"%s%s",RECV_DIR,pDirEnt->d_name);
			stat(fullFileName,&fileStat);
			recvfileSize=fileStat.st_size;
			break;;
		}
		else
		{
			if(strcmp(recvFileName,pDirEnt->d_name) == 0)
			{
				sprintf(fullFileName,"%s%s",RECV_DIR,pDirEnt->d_name);
				stat(fullFileName,&fileStat);
				if(recvfileSize == fileStat.st_size)
				{
					//printf("recvFileName=%s\n",recvFileName);
					//printf("fullFileName=%s\n",fullFileName);
					recvfileSize=0;
					sprintf(recvFileName,"NoFile");
					
					memset(tmpFileName,0,256);
					sprintf(tmpFileName,"%s",pDirEnt->d_name);	

					memset(recipientTadig,0,8);
					for(i=7;i<12;i++)
					{
						recipientTadig[i-7]=tmpFileName[i];
					}
					recipientTadig[i]='\0';
		
					memset(senderTadig,0,8);
					for(i=2;i<7;i++)
					{
						senderTadig[i-2]=tmpFileName[i];
					}
					senderTadig[i]='\0';
					
					//printf("recipientTadig=%s,senderTadig=%s\n",recipientTadig,senderTadig);
					
					if(tmpFileName[1] == 'R')
					{
						sprintf(message,"Receive the NR=%s from %s\n",tmpFileName,senderTadig);
						logMessage(message);
						printfInColor(message,3);
						//parse the nrtrde file
						parseAsnFile(tmpFileName);
						
						//add the record to the delivery report
						addNDNodeInDB(senderTadig,tmpFileName);
						//backup the NRTRDE files
						sprintf(fullFileName,"%s%s",RECV_DIR,pDirEnt->d_name);
						sprintf(command,"mv %s %s",fullFileName,NR_RECV_BAK_DIR);
						system(command);
						
					}
					//if the file is NRTRDE Delivery report, then backup it
					else if(tmpFileName[1] == 'D')
					{
						sprintf(message,"Receive the ND=%s from %s\n",tmpFileName,senderTadig);
						logMessage(message);
						printfInColor(message,3);
						//backup the delivery report
						sprintf(fullFileName,"%s%s",RECV_DIR,pDirEnt->d_name);
						sprintf(command,"mv %s %s",fullFileName,ND_RECV_BAK_DIR);
						system(command);
					}
					//if the file is NRTRDE Error report, then backup it
					else if(tmpFileName[1] == 'E')
					{
						sprintf(message,"Receive the NE=%s from %s\n",tmpFileName,senderTadig);
						logMessage(message);
						printfInColor(message,3);
						//backup the error report
						sprintf(fullFileName,"%s%s",RECV_DIR,pDirEnt->d_name);
						sprintf(command,"mv %s %s",fullFileName,NE_RECV_BAK_DIR);
						system(command);
					}
					
				}	
				else
				{
					recvfileSize=fileStat.st_size;
				}	
			}	
		}			
				
		

	}	
	
	closedir(srcDir);
}

/*************************************************
Function:        // getDate
Description:     // Get today's date
Calls:           // 
Called By:       // 
Table Accessed:  // 
Table Updated:   // 
Input:           // flag:0-today,>0:tomorrow
Output:          // 
Return:          // The date of today
Others:          // 
*************************************************/
int getDate(int flag)
{
	struct tm *local;
	time_t t;
	int nowDate;
	
	t=time(NULL);
	if(flag)
	{
		t=t+24*60*60;
	}	
	local=localtime(&t);
	nowDate=local->tm_mday;
	return nowDate;
}

/*************************************************
Function:        // initDirectory
Description:     // Make the directory for the module
Calls:           // 
Called By:       // 
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 
Others:          // 
*************************************************/
void initDirectory()
{
	char oldDir[512];
	char message[512];
	char command[512];
	
	getcwd(oldDir,512);
	//printf("nowDir=%s\n",oldDir);
	//make SEND_DIR
	if(chdir(SEND_DIR) == -1)
	{
		chdir(oldDir);
		sprintf(command,"mkdir -p -m755 %s",SEND_DIR);
		system(command);
		sprintf(message,"Make directory SEND_DIR=%s\n",SEND_DIR);
		logMessage(message);
		printfInColor(message,3);
		if(chdir(SEND_DIR) == -1)
		{
			chdir(oldDir);
			sprintf(message,"Make directory SEND_DIR=%s failed\n",SEND_DIR);
			logMessage(message);
			printfInColor(message,3);
			exitLog("nrtrde:initDirectory, Make directory SEND_DIR=%s failed",SEND_DIR);
			exit(1);
		}	
	}	
	
	//make RECV_DIR
	if(chdir(RECV_DIR) == -1)
	{
		chdir(oldDir);
		sprintf(command,"mkdir -p -m755 %s",RECV_DIR);
		system(command);
		sprintf(message,"Make directory RECV_DIR=%s\n",RECV_DIR);
		logMessage(message);
		printfInColor(message,3);
		if(chdir(RECV_DIR) == -1)
		{
			chdir(oldDir);
			sprintf(message,"Make directory RECV_DIR=%s failed\n",RECV_DIR);
			logMessage(message);
			printfInColor(message,3);
			exitLog("nrtrde:initDirectory, Make directory RECV_DIR=%s failed",RECV_DIR);
			exit(1);
		}	
	}
	
	//make NR_RECV_BAK_DIR
	if(chdir(NR_RECV_BAK_DIR) == -1)
	{
		chdir(oldDir);
		sprintf(command,"mkdir -p -m755 %s",NR_RECV_BAK_DIR);
		system(command);
		sprintf(message,"Make directory NR_RECV_BAK_DIR=%s\n",NR_RECV_BAK_DIR);
		logMessage(message);
		printfInColor(message,3);
		if(chdir(NR_RECV_BAK_DIR) == -1)
		{
			chdir(oldDir);
			sprintf(message,"Make directory NR_RECV_BAK_DIR=%s failed\n",NR_RECV_BAK_DIR);
			logMessage(message);
			printfInColor(message,3);
			exitLog("nrtrde:initDirectory, Make directory NR_RECV_BAK_DIR=%s failed",NR_RECV_BAK_DIR);
			exit(1);
		}	
	}
	
	//make NR_SEND_BAK_DIR
	if(chdir(NR_SEND_BAK_DIR) == -1)
	{
		chdir(oldDir);
		sprintf(command,"mkdir -p -m755 %s",NR_SEND_BAK_DIR);
		system(command);
		sprintf(message,"Make directory NR_SEND_BAK_DIR=%s\n",NR_SEND_BAK_DIR);
		logMessage(message);
		printfInColor(message,3);
		if(chdir(NR_SEND_BAK_DIR) == -1)
		{
			chdir(oldDir);
			sprintf(message,"Make directory NR_SEND_BAK_DIR=%s failed\n",NR_SEND_BAK_DIR);
			logMessage(message);
			printfInColor(message,3);
			exitLog("nrtrde:initDirectory, Make directory NR_SEND_BAK_DIR=%s failed",NR_SEND_BAK_DIR);
			exit(1);
		}	
	}
	
	//make ND_RECV_BAK_DIR
	if(chdir(ND_RECV_BAK_DIR) == -1)
	{
		chdir(oldDir);
		sprintf(command,"mkdir -p -m755 %s",ND_RECV_BAK_DIR);
		system(command);
		sprintf(message,"Make directory ND_RECV_BAK_DIR=%s\n",ND_RECV_BAK_DIR);
		logMessage(message);
		printfInColor(message,3);
		if(chdir(ND_RECV_BAK_DIR) == -1)
		{
			chdir(oldDir);
			sprintf(message,"Make directory ND_RECV_BAK_DIR=%s failed\n",ND_RECV_BAK_DIR);
			logMessage(message);
			printfInColor(message,3);
			exitLog("nrtrde:initDirectory, Make directory ND_RECV_BAK_DIR=%s failed",ND_RECV_BAK_DIR);
			exit(1);
		}	
	}
	
	//make ND_SEND_BAK_DIR
	if(chdir(ND_SEND_BAK_DIR) == -1)
	{
		chdir(oldDir);
		sprintf(command,"mkdir -p -m755 %s",ND_SEND_BAK_DIR);
		system(command);
		sprintf(message,"Make directory ND_SEND_BAK_DIR=%s\n",ND_SEND_BAK_DIR);
		logMessage(message);
		printfInColor(message,3);
		if(chdir(ND_SEND_BAK_DIR) == -1)
		{
			chdir(oldDir);
			sprintf(message,"Make directory ND_SEND_BAK_DIR=%s failed\n",ND_SEND_BAK_DIR);
			logMessage(message);
			printfInColor(message,3);
			exitLog("nrtrde:initDirectory, Make directory ND_SEND_BAK_DIR=%s failed",ND_SEND_BAK_DIR);
			exit(1);
		}	
	}
	
	//make NE_RECV_BAK_DIR
	if(chdir(NE_RECV_BAK_DIR) == -1)
	{
		chdir(oldDir);
		sprintf(command,"mkdir -p -m755 %s",NE_RECV_BAK_DIR);
		system(command);
		sprintf(message,"Make directory NE_RECV_BAK_DIR=%s\n",NE_RECV_BAK_DIR);
		logMessage(message);
		printfInColor(message,3);
		if(chdir(NE_RECV_BAK_DIR) == -1)
		{
			chdir(oldDir);
			sprintf(message,"Make directory NE_RECV_BAK_DIR=%s failed\n",NE_RECV_BAK_DIR);
			logMessage(message);
			printfInColor(message,3);
			exitLog("nrtrde:initDirectory, Make directory NE_RECV_BAK_DIR=%s failed",NE_RECV_BAK_DIR);
			exit(1);
		}	
	}
	
	//make ND_SEND_BAK_DIR
	if(chdir(NE_SEND_BAK_DIR) == -1)
	{
		chdir(oldDir);
		sprintf(command,"mkdir -p -m755 %s",NE_SEND_BAK_DIR);
		system(command);
		sprintf(message,"Make directory NE_SEND_BAK_DIR=%s\n",NE_SEND_BAK_DIR);
		logMessage(message);
		printfInColor(message,3);
		if(chdir(NE_SEND_BAK_DIR) == -1)
		{
			chdir(oldDir);
			sprintf(message,"Make directory NE_SEND_BAK_DIR=%s failed\n",NE_SEND_BAK_DIR);
			logMessage(message);
			printfInColor(message,3);
			exitLog("nrtrde:initDirectory, Make directory NE_SEND_BAK_DIR=%s failed",NE_SEND_BAK_DIR);
			exit(1);
		}	
	}
	
	//make SEND_DIR
	if(chdir(LOCAL_CSV_DIR) == -1)
	{
		chdir(oldDir);
		sprintf(command,"mkdir -p -m755 %s",LOCAL_CSV_DIR);
		system(command);
		sprintf(message,"Make directory LOCAL_CSV_DIR=%s\n",LOCAL_CSV_DIR);
		logMessage(message);
		printfInColor(message,3);
		if(chdir(LOCAL_CSV_DIR) == -1)
		{
			chdir(oldDir);
			sprintf(message,"Make directory LOCAL_CSV_DIR=%s failed\n",LOCAL_CSV_DIR);
			logMessage(message);
			printfInColor(message,3);
			exitLog("nrtrde:initDirectory, Make directory LOCAL_CSV_DIR=%s failed",LOCAL_CSV_DIR);
			exit(1);
		}	
	}	
	
	chdir(oldDir);
	
}

/*************************************************
Function:        // initNRConf
Description:     // Get the information in file NR.conf 
Calls:           // 
Called By:       // nrtrdeInit;
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // SUCCESSFUL; FAIL;
Others:          // 
*************************************************/
int initNRConf(void)
{
	char fileName[512];
	char message[512];
	unsigned char buf[4096];
	unsigned char param[32][512];
	char paramName[128];
	char paramValue[384];
	char* temp;
	FILE* fp;
	int fi;
	int i;
	//int j;
	int paramCount;
	int byteCount;
	
	paramCount=0;
	byteCount=0;
	memset(buf,0,4096);
	memset(param,0,32*512);
	sprintf(fileName,"./conf/NR.conf");
	fp=fopen(fileName,"r");
	if(fp)
	{
		sprintf(message,"Read the NR.conf\n");
		logMessage(message);
		printfInColor(message,6);
		
		fi=fileno(fp);
		if(read(fi,buf,4096))
		{
			for(i=0;i<4096;i++)
			{
				
				if(buf[i] == 0x0A)
				{
					//printf("\n");
					if(byteCount<512 && param[paramCount][0] != 0x00 && param[paramCount][0] != 0x23)
						paramCount++;
					else
						memset(param[paramCount],0,512);	
					byteCount=0;
				}	
				else
				{	
					param[paramCount][byteCount]=buf[i];
					byteCount++;
				}
				
				//printf("%02x ",buf[i]);
			}
			/*for test
			printf("\n=================================\n");
			printf("paramCount=%d\n",paramCount);
			for(i=0;i<paramCount;i++)
			{
				for(j=0;j<512;j++)
				{
					printf("%02x ",param[i][j]);
				}
				printf("\n");
			}
			*/
			
			sprintf(message,"==================================================\n");
			logMessage(message);
			printfInColor(message,0);
			
			for(i=0;i<paramCount;i++)
			{
				temp=strtok((char*)param[i],"=");
				sprintf(paramName,"%s",temp);
				//printf("Name=%s,",temp);
				temp=strtok(NULL,"=");
				sprintf(paramValue,"%s",temp);
				//printf("Value=%s\n",temp);
				
				
				if(strcasecmp(paramName,"MCC") == 0)
				{
					sprintf(g_local_mcc,"%s",paramValue);
				}	
				else if(strcasecmp(paramName,"MNC") == 0)
				{
					sprintf(g_local_mnc,"%s",paramValue);
				}	
				else if(strcasecmp(paramName,"CallEventDurationMax") == 0)
				{
					g_maxCallDuration=atoi(paramValue);
				}	
				else if(strcasecmp(paramName,"LOCAL_TADIG") == 0)
				{
					sprintf(LOCAL_TADIG,"%s",paramValue);
				}	
				else if(strcasecmp(paramName,"MAKE_REPORT_TIME") == 0)
				{
					MAKE_REPORT_TIME=atoi(paramValue);
				}
				else if(strcasecmp(paramName,"NR_RECV_BAK_DIR") == 0)
				{
					sprintf(NR_RECV_BAK_DIR,"%s",paramValue);
				}	
				else if(strcasecmp(paramName,"NR_SEND_BAK_DIR") == 0)
				{
					sprintf(NR_SEND_BAK_DIR,"%s",paramValue);
				}	
				else if(strcasecmp(paramName,"ND_RECV_BAK_DIR") == 0)
				{
					sprintf(ND_RECV_BAK_DIR,"%s",paramValue);
				}	
				else if(strcasecmp(paramName,"ND_SEND_BAK_DIR") == 0)
				{
					sprintf(ND_SEND_BAK_DIR,"%s",paramValue);
				}
				else if(strcasecmp(paramName,"NE_RECV_BAK_DIR") == 0)
				{
					sprintf(NE_RECV_BAK_DIR,"%s",paramValue);
				}
				else if(strcasecmp(paramName,"NE_SEND_BAK_DIR") == 0)
				{
					sprintf(NE_SEND_BAK_DIR,"%s",paramValue);
				}
				else if(strcasecmp(paramName,"LOCAL_CSV_DIR") == 0)
				{
					sprintf(LOCAL_CSV_DIR,"%s",paramValue);
				}
				else if(strcasecmp(paramName,"ND_VERSION") == 0)
				{
					sprintf(ND_VERSION,"%s",paramValue);
				}	
				else if(strcasecmp(paramName,"NE_VERSION") == 0)
				{
					sprintf(NE_VERSION,"%s",paramValue);
				}	
				else if(strcasecmp(paramName,"NR_SVN") == 0)
				{
					NR_SVN=atoi(paramValue);
				}	
				else if(strcasecmp(paramName,"NR_RVN") == 0)
				{
					NR_RVN=atoi(paramValue);
				}	
				else if(strcasecmp(paramName,"SEND_DIR") == 0)
				{
					sprintf(SEND_DIR,"%s",paramValue);
				}	
				else if(strcasecmp(paramName,"RECV_DIR") == 0)
				{
					sprintf(RECV_DIR,"%s",paramValue);
				}	

				sprintf(message,"%s=%s\n",paramName,paramValue);
				logMessage(message);
				printfInColor(message,0);
			}
			sprintf(message,"==================================================\n");
			logMessage(message);
			printfInColor(message,0);
			
		}	
		close(fi);
		fclose(fp);
	}	
	else
	{
		sprintf(message,"Fatal Error: The NR.conf does not exist!\n");
		logMessage(message);
		printfInColor(message,1);
		printf("%s",message);
		exitLog("nrtrde:initNRConf, The NR.conf does not exist");
		exit(1);
	}		
	
	return SUCCESSFUL;
}

/*************************************************
Function:        // initTagConf
Description:     // Initial the tag information
Calls:           // 
Called By:       // 
Table Accessed:  // CDR_DB.roamCdrConf
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 
Others:          // 
*************************************************/
int initTagConf()
{
	MYSQL_RES *res;
	MYSQL_ROW row;
	char sqlstr[256];
	char message[256];
	int tag;
	
	sprintf(sqlstr,"SELECT * FROM CDR_DB.roamCdrConf");
	
	res=mysql_getres(g_cdrConn,sqlstr);
	if(res == NULL)
	{
		sprintf(message,"[ERR %d][initTagConf]:%s\n",mysql_errno(g_cdrConn),sqlstr);
	  logMessage(message);
		return FAIL;
	}
	
	sprintf(message,"Init the tag configuration\n");
	logMessage(message);
	printfInColor(message,3);
	
	//Init the tag information
	while((row = mysql_fetch_row(res)) != NULL)
	{
		//get the tag
		tag=atoi(row[1]);
		//Get the field name
		sprintf(tags[tag].fieldName,"%s",row[0]);
		//Get the value of the tag
		tags[tag].tagValue=tag;
		//The tag is structed or not
		tags[tag].isStructed=atoi(row[2]);
		//Get the code method of the tag
		tags[tag].code=atoi(row[3]);
		//Get the min size of the field
		tags[tag].minSize=atoi(row[4]);
		//Get the max size of the field
		tags[tag].maxSize=atoi(row[5]);
		//printf("fieldName=%s,tagValue=%d,isStructed=%d,code=%d,minSize=%d,maxSize=%d\n",tags[tag].fieldName,tags[tag].tagValue,tags[tag].isStructed,tags[tag].code,tags[tag].minSize,tags[tag].maxSize);
	}
	mysql_free_result(res);
	return SUCCESSFUL;
}

/*************************************************
Function:        // initDatabase
Description:     // Connection the OMC_PUB, CDR_DB databases
Calls:           // 
Called By:       // hpmnServersInfoUpdate;
Table Accessed:  // OMC_PUB.hpmnConf
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 0:failed; 1:successful;
Others:          // 
*************************************************/
int initDatabase()
{
	//Init the OMC_PUB database connection
	g_omcPubConn=mysql_conn("localhost","OMC_PUB");
	if(g_omcPubConn == NULL)
	{
	  logMessage("[ERR][initDatabase]:mysql_conn OMC_PUB");
		return FAIL;
	}
	
	//Init the CDR_DB database connection
	g_cdrConn=mysql_conn("localhost","CDR_DB");
	if(g_cdrConn == NULL)
	{
		logMessage("[ERR][initDatabase]:mysql_conn CDR_DB");
		return FAIL;
	}
	
	return SUCCESSFUL;
}

/*************************************************
Function:        // isHour
Description:     // Wether the current time is arrived
Calls:           // 
Called By:       // 
Table Accessed:  // 
Table Updated:   // 
Input:           // hour:the specific time;
Output:          // 
Return:          // 1:arrive; 0:not arrive;
Others:          // 
*************************************************/
int isHour(int hour)
{
	struct tm *local;
	time_t t;
	int nowHour;
		

	if(hour<0 || hour>23)
	{
		return 0;
	}
	
	t=time(NULL);
	local=localtime(&t);
	nowHour=local->tm_hour;

	if(nowHour == hour)
	{	
		return 1;
	}
	else
	{
		return 0;
	}		
}

/*************************************************
Function:        // addNDNode
Description:     // Add the NRTRDE delivery report node the link
Calls:           // 
Called By:       // 
Table Accessed:  // 
Table Updated:   // 
Input:           // tadig:the tadig of the record; 
										fileName:the file name of the record; 
										recvTime:the time when to receive the file;
Output:          // 
Return:          // 
Others:          // This function change value 'pNDHead' and 'pNDTail'
*************************************************/
int addNDNode(char* tadig,char* fileName)
{
	NDRepNode* node;
	struct tm *now;
	char recvTime[32];
	time_t t;

	t=time(NULL);
	now=localtime(&t);
	
	//get the receive time
	sprintf(recvTime,"%04d%02d%02d%02d%02d%02d%s",
	      		now->tm_year+1900,
	      		now->tm_mon+1,
	      		now->tm_mday,
	      		now->tm_hour,
	      		now->tm_min,
	      		now->tm_sec,
	      		g_local_utc);

	//printf("recvTime=%s\n",recvTime);
	
	node=malloc(sizeof(NDRepNode));
	if(node)
	{
		sprintf(node->tadig,tadig);
		sprintf(node->fileName,fileName);
		sprintf(node->recvTime,recvTime);
		node->next=NULL;
		
		if(pNDHead == NULL || pNDTail == NULL)
		{
			pNDHead=pNDTail=node;
		}	
		else
		{
			pNDTail->next=node;
			pNDTail=node;
		}	
		return SUCCESSFUL;
	}
	else
	{
		return FAIL;
	}		
}

/*************************************************
Function:        // addNDNodeInDB
Description:     // Add the delievery report info to the CDR_DB.reportNRInfo
Calls:           // 
Called By:       // 
Table Accessed:  // CDR_DB.reportNRInfo
Table Updated:   // CDR_DB.reportNRInfo
Input:           // tadig:the tadig of the record; 
										fileName:the file name of the record; 
										recvTime:the time when to receive the file;
Output:          // 
Return:          // 
Others:          // 
*************************************************/
int addNDNodeInDB(char* tadig,char* fileName)
{
	char sqlstr[512];
	
	//printf("tadig=%s,fileName=%s,type=%d,recordNumber=%d,errorCode=%s\n",senderTadig,fileName,type,recordNumber,errorCode);
	
	sprintf(sqlstr,"INSERT INTO reportNRInfo (tadig, fileName, type, errorType, recordNumber, errorCode) VALUES ('%s', '%s', '%d', '0', '0', 'NULL')",
					tadig,fileName,1);
	mysql_getnores(g_cdrConn,sqlstr);
	
	
	return SUCCESSFUL;
}

/*************************************************
Function:        // makeNDFile
Description:     // Make the Delivery report for sending to VPMNs, then free the link of delivery report
Calls:           // 
Called By:       // 
Table Accessed:  // 
Table Updated:   // 
Input:           // The delivery reports
Output:          // 
Return:          // 
Others:          // This function will change the value 'pNDHead' and 'pNDTail'
*************************************************/
void makeNDFile()
{
	struct tm *now;
	char createTime[32];
	char startTime[32];
	char endTime[32];
	char fileName[512];
	char squenceNumber[8];
	char command[512];
	char message[256];
	time_t t;
	NDRepNode* tmpNode,*tmpN;
	int recordCount;
	int i;
	
	t=time(NULL);
	now=localtime(&t);
	
	//get the create time
	sprintf(createTime,"%04d%02d%02d%02d%02d%02d%s",
	      		now->tm_year+1900,
	      		now->tm_mon+1,
	      		now->tm_mday,
	      		now->tm_hour,
	      		now->tm_min,
	      		now->tm_sec,
	      		g_local_utc);
	      		
	//get the start time       		
	sprintf(endTime,"%04d%02d%02d%02d%02d%02d%s",
	      		now->tm_year+1900,
	      		now->tm_mon+1,
	      		now->tm_mday,
	      		now->tm_hour,
	      		now->tm_min,
	      		now->tm_sec,
	      		g_local_utc);      	 
	      		     		
	//get the start time    
	t=time(NULL)-24*60*60;
	now=localtime(&t);       		
	sprintf(startTime,"%04d%02d%02d%02d%02d%02d%s",
	      		now->tm_year+1900,
	      		now->tm_mon+1,
	      		now->tm_mday,
	      		now->tm_hour,
	      		now->tm_min,
	      		now->tm_sec,
	      		g_local_utc);    
			
	 
	for(i=0;i<g_hpmn_server_count;i++)
	{
		//write the head of the delivery report
		//getSequenceNumber(squenceNumber,1);
		get_seq_num(servers[i].tadig,1,squenceNumber);
		sprintf(fileName,"%sND%s%s%s",SEND_DIR,LOCAL_TADIG,servers[i].tadig,squenceNumber);
		sprintf(command,"echo 'ND,%s,%s,%s,%s,%s,%s,%s'>>%s",
							ND_VERSION,
							LOCAL_TADIG,
							servers[i].tadig,
							squenceNumber,
							createTime,startTime,endTime,
							fileName);
				
		system(command);	
		
		sprintf(message,"Make Delivery report %s\n",fileName);
		logMessage(message);			
		
		tmpNode=pNDHead;
		recordCount=0;
		//write the content of the delivery report
		while(tmpNode)
		{
			//printf("tadig=%s,fileName=%s,recvTime=%s\n",tmpNode->tadig,tmpNode->fileName,tmpNode->recvTime);
			
			if(strcmp(servers[i].tadig,tmpNode->tadig) == 0)
			{
				sprintf(command,"echo '%s,%s'>>%s",tmpNode->fileName,tmpNode->recvTime,fileName);
				system(command);
				recordCount++;
			}	
			
			tmpNode=tmpNode->next;
		}
		//write the tail of the delivery report
		sprintf(command,"echo 'END,%d'>>%s",recordCount+2,fileName);
		system(command);
		
	}	
	
	//free the link	  	
	tmpNode=pNDHead;
	while(tmpNode)
	{
		tmpN=tmpNode->next;
		free(tmpNode);
		tmpNode=tmpN;
	}
	pNDHead=NULL;
	pNDTail=NULL;
}

/*************************************************
Function:        // getSequenceNumber
Description:     // Get the squence number of NR, ND, NE
Calls:           // 
Called By:       // 
Table Accessed:  // 
Table Updated:   // 
Input:           // type:0-NR, 1-ND, 2-NE;
Output:          // squenceNumber:store the squence number
Return:          // 
Others:          // Change the value 'g_nr_squence_number'
																		 'g_nd_squence_number'
																		 'g_ne_squence_number'
*************************************************/
/*
void getSequenceNumber(char* squenceNumber,int type)
{
	switch(type)
	{
		case 0:
			if(g_nr_squence_number == 0)
			{	
				g_nr_squence_number++;
			}
			sprintf(squenceNumber,"%07ld",g_nr_squence_number);
			g_nr_squence_number++;
			g_nr_squence_number%=10000000;
			break;
	
		case 1:
			if(g_nd_squence_number == 0)
			{
				g_nd_squence_number++;
			}		
			sprintf(squenceNumber,"%05ld",g_nd_squence_number);
			g_nd_squence_number++;
			g_nd_squence_number%=100000;
			break;
			
		case 2:
			if(g_ne_squence_number == 0)
			{
				g_ne_squence_number++;
			}		
			sprintf(squenceNumber,"%05ld",g_ne_squence_number);
			g_ne_squence_number++;
			g_ne_squence_number%=100000;
			break;
			
		default:
			break;
	}
}
*/
/*************************************************
Function:        // getTagByName
Description:     // Get the tag value by the field name
Calls:           // 
Called By:       // 
Table Accessed:  // CDR_DB.roamCdrConf
Table Updated:   // 
Input:           // name:field name;
Output:          // 
Return:          // the tag value of the field
Others:          // 
*************************************************/
int getTagByName(char* name)
{
	int i;
	int tagValue;
	
	tagValue=0;
	if(name == NULL)
	{
		return tagValue;
	}	
	else
	{
		for(i=0;i<50;i++)
		{
			if(tags[i].fieldName && strcmp(tags[i].fieldName,name) == 0)
			{
				tagValue=i;
				break;
			}	
		}
	}	
	
	return tagValue;
}

/*************************************************
Function:        // logMessage
Description:     // Write log message to the log file
Calls:           // 
Called By:       // 
Table Accessed:  // 
Table Updated:   // 
Input:           // fmt:the message to write
Output:          // 
Return:          // 
Others:          //
*************************************************/
void logMessage(const char *fmt,...)
{
	char logFile[64];
	FILE *fp;
	time_t l_time;
	va_list ap;
	char buf[8192];
	struct tm *t;
	char timestr[64];
	
	l_time=time(NULL);
	t=localtime(&l_time);
	sprintf(logFile,"/usr/local/omc/log/nrtrde%04d%02d%02d.log",t->tm_year+1900,t->tm_mon+1,t->tm_mday);
	fp=fopen(logFile,"a");
	if(fp!=NULL)
	{
		va_start(ap,fmt);
		vsprintf(buf,fmt,ap);
		sprintf(timestr,"%02d:%02d:%02d: ",t->tm_hour,t->tm_min,t->tm_sec);
		fputs(timestr,fp);
		fputs(buf,fp);
		fputs("\n",fp);
		fflush(fp);
		va_end(ap);
		fclose(fp);
	}
}


/*************************************************
Function:        // printfHPMNServer
Description:     // Print the information of the specific HPMN server
Calls:           // 
Called By:       // 
Table Accessed:  // 
Table Updated:   // 
Input:           // server:the HPMN server to print
Output:          // 
Return:          // 
Others:          // This funtion is for test
*************************************************/
void printfHPMNServer(HpmnServer* server)
{
#if NRTRDE_DEBUG
	printf("=======================================\n");
	printf("tadig=%s\n",server->tadig);
	printf("mcc=%s\n",server->mcc);
	printf("mnc=%s\n",server->mnc);
	printf("serverIP=%s\n",server->serverIP);
	printf("loginName=%s\n",server->loginName);
	printf("loginPass=%s\n",server->loginPass);
	printf("timeSlot=%d\n",server->timeSlot);
	printf("reportDir=%s\n",server->reportDir);
	printf("nrtrdeDir=%s\n",server->nrtrdeDir);
	printf("\tsendFileTimeout=%d\n",server->sendFileTimeout);
	printf("=======================================\n");
#endif	
}

/*************************************************
Function:        // printfInColor
Description:     // Print the message in specific color to the standand output
Calls:           // 
Called By:       // 
Table Accessed:  // 
Table Updated:   // 
Input:           // message:the message to print; color:the color in printing
Output:          // 
Return:          // 
Others:          // For test,only the NRTRDE_DEBUG flag is open when it show the debug infomation
*************************************************/
void printfInColor(char *message,int color)
{
	
#if NRTRDE_DEBUG

	if(message==NULL)
		return;
	switch(color)
	{
		//white
		case 0:
			printf("\033[37m%s",message);
			break;
		//red	
		case 1:
			printf("\033[31m%s",message);
			break;
		//green
		case 2:
			printf("\033[32m%s",message);
			break;
		//yellow
		case 3:
			printf("\033[33m%s",message);	
			break;
		//blue
		case 4:
			printf("\033[34m%s",message);		
			break;
		//light green
		case 5:	
			printf("\033[36m%s",message);
			break;
		//pink	
		case 6:
			printf("\033[35m%s",message);
			break;
		//white	
		default:
			printf("\033[37m%s",message);			
	}	
	printf("\033[37m");
#endif	
}

/*************************************************
Function:        // SetTimer
Description:     // Timer function
Calls:           // On_Timer
Called By:       // 
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 
Others:          // 
*************************************************/
void SetTimer()
{
	struct sigaction act;
	act.sa_handler = On_Timer;
	sigemptyset(&act.sa_mask);
	act.sa_flags = 0;
	if (sigaction(SIGALRM, &act, NULL) < 0) 
	{
		perror("Produce Sigaction");
		exitLog("nrtrde:SetTimer, sigaction function error");
		exit(1);
	}

//	itimer.it_interval.tv_sec = 0;
//	itimer.it_interval.tv_usec = 1000 * 1000;
//	itimer.it_value.tv_sec = 0;
//	itimer.it_value.tv_usec = 1000 * 1000;
	
	itimer.it_interval.tv_sec = 1;
	itimer.it_interval.tv_usec = 0;
	itimer.it_value.tv_sec = 1;
	itimer.it_value.tv_usec = 0;

	if (setitimer(ITIMER_REAL, &itimer, &old_itimer) != 0) 
	{
		printf("Setting Timer  error! \n");
		exitLog("nrtrde:SetTimer, setitimer function error");
		exit(1);
	}
}

