#include "../include/includes.h"
#include "../include/ramdata.h"
#include "../include/ppsm.h"
#include "../include/param.h"
#include "../include/tariff.h"

#include "../../../../plat/iptrans/src/include/iptrans.h"

#include "../include/plat_inc.h"

/*------------------------------------------------*/
extern _ram_data    *ramshm_ptr;
extern _tariff_private *blf_shmp;

extern char	masterFlag;
extern u_long	PPS_OID_PREFIX[]; //
extern u_long	primary_data_server,
		second_data_server;	
extern u_long	LOCAL_IP;
extern u_char	stopPeriodicSync;
extern int	stopReceivePeriodicSyncFlag ;
extern int	totalPeriodSyncPackets;
/*------------------------------------------------*/
//u_char   ram_oper[4] = {0xaa,0x01,0x00,0x00};
/*1=read,2=send,3=periodic sync,4=real sync*/
u_long   peer_server_ip;
DWORD    PPS_RAM_OID_PREFIX[]={1,3,6,1,4,1,1373,2,3,3,6,2,PPSOID_InitRequest};
static int   readResponseCount=0;
u_short	 tftp_port;
u_long   tftp_ip;

extern int   time_now[7];
extern struct		timeval tvnow;
extern int ValidateAsciiMSISDN(char *msisdn, int len);
extern void PrepaidCardRealSyncMessageProc();
extern int  GetDailyReportResponse();
extern int  dataSyncCallProc();
int pps_real_update_file_init();
/*------------------------------------------------*/
static int  readPacketNo=0;
static int  syncFlag = 1;
char	peer_server_in_init = 0;
/*------------------------------------------------*/
int GetAccountInfoBySortIndex(int index, char *msisdn);
extern int scf_update_rcm_card_data_ack(snmp_pdu *pdu, snmp_addr *addr);
/*------------------------------------------------*/
extern int dataSyncCallPro();
extern void SaveTariffPlan();
extern void SaveRechargeCard();
extern void SaveSubsData();
int pps_real_update_file_close();
/*------------------------------------------------*/
int SetSyncFlag(int flag)
{
	/* manually set sync funtion on/off */
	if(flag<0) return 0;

	syncFlag = flag;
	return 1;
}

int SetPeriodicSyncFlag(int flag)
{
	if(flag)
		stopPeriodicSync = 0;
	else
		stopPeriodicSync = 1;
	return 1;
}

int ReadPeroidicSyncData()
{
	snmp_pdu	snmpbuf;
	snmp_addr	snmpaddr;

	PutLogFunID("ReadPeroidicSyncData");


	snmpaddr.local_port = PPS_REALSYNC_PORT;
	if(snmp_receive(&snmpbuf,&snmpaddr))
	{
		peer_server_ip = snmpaddr.remote_ip;
		return 1;
	}
	return 0;
}

void ReadSyncMessageForInit()
{
	
	int	i,reflag=0;
//	int	instance=0;
	int	dataType;
	snmp_pdu	snmpbuf;
	snmp_addr	snmpaddr;
	var_list	*varptr=NULL;

	PutLogFunID("ReadSyncMessageForInit");

	snmpaddr.local_port = PPS_REALSYNC_PORT;
	
	for(i=0;i<4;i++)
	{
		if(!snmp_receive(&snmpbuf,&snmpaddr))
		{
			break;
		}
		varptr = &snmpbuf.var[0];
		dataType = varptr->oid[12];
     
		if(dataType == 2) 
		{//real sync message			
			switch(varptr->oid[13])
			{
				case 2: //user data
					dataSyncCallPro(varptr->oidlen,
						varptr->oid,varptr->msg,varptr->msglen,reflag);
				break;
				case 3: //prepaid card
					PrepaidCardRealSyncMessageProc(varptr->oidlen,
						varptr->oid,varptr->msg,varptr->msglen,reflag);
				break;
				case 4: //tariff data
				break;
				default:
					DebugMsg(debugmib.display.asciiOut,
						"Error sync message received");
				break;
			}
		}
	}//for
}

void SyncMessageProc()
{
	static int	noPeriodicSyncCount=0;
	//void		*ptr = (void *)ramshm_ptr;
	int		i,periodicFlag=0,reflag=0;
	int		instance=0,dataType;
	snmp_pdu	snmpbuf;
	snmp_addr	snmpaddr;
	var_list	*varptr=NULL;

	u_long		masterIP=LOCAL_IP;

	PutLogFunID("SyncMessageProc");

	snmpaddr.local_port = PPS_REALSYNC_PORT;
	
	if(debugmib.display.sysState != _SYS_STATE_NORMAL)
	{
		return ;
	}/* not sure about this function, 10-13 */

	for(i=0;i<MAX_READFILE_NUM*16;i++)
	{
		if(!snmp_receive(&snmpbuf,&snmpaddr))
		{
			break;
		}
		varptr = &snmpbuf.var[0];
		dataType = varptr->oid[12];
     
		if(dataType == 2) {//real sync message
			if(snmpaddr.remote_ip !=LOCAL_IP && masterFlag) reflag=1;

			switch(varptr->oid[13])
			{
				case 2: //user data
					dataSyncCallPro(varptr->oidlen,
						varptr->oid,varptr->msg,varptr->msglen,reflag);
				break;
				case 3: //prepaid card
					PrepaidCardRealSyncMessageProc(varptr->oidlen,
						varptr->oid,varptr->msg,varptr->msglen,reflag);
				break;
				case 4: //tariff data
				break;
				default:
					DebugMsg(debugmib.display.asciiOut,
						"Error sync message received");
				break;
			}
		}
		else
		{
     //periodic sync message
		//if(stopReceivePeriodicSyncFlag ) continue;
			instance = varptr->oid[13];
			if(varptr->msglen == RAMDATA_PACK_SIZE)
			{
				if(instance>=RAMDATA_PACK_NUM) continue ;
				/*
				memcpy(ptr+instance*RAMDATA_PACK_SIZE,
						varptr->msg,
						RAMDATA_PACK_SIZE);				
						*/
			}
			/*
			else if(varptr->msglen == sizeof(_prepaid_info))
			{
				if(instance>=MAX_SUBS_RECORD) continue;
				ModifyPPSSubsData((_prepaid_info *)varptr->msg);								
			}
			else
			{
				continue;
			}
			*/
			masterIP = snmpaddr.remote_ip;
			debugmib.display.masterIP = masterIP;
			periodicFlag = 1;
		}
	}//for


	if(debugmib.measurement.peer_usernumber <
			debugmib.measurement.usernumber) 
		return;

	if(periodicFlag)
	{
		if(masterFlag && (masterIP <LOCAL_IP))
		{
			masterFlag = 0;
		}
		noPeriodicSyncCount = 0;
	}
	else if(noPeriodicSyncCount++>MAX_RAM_INIT_RETRY*100)
	{
		masterFlag = 1;
		masterIP = LOCAL_IP;
		debugmib.display.masterIP = masterIP;
	}
}

void TrapPPSSubsData(_prepaid_info *shmp,int store_pos)
{
	snmp_pdu	snmpbuf;
	snmp_addr	snmpaddr;
	var_list	*varlist;

	snmpbuf.pdu_type = 0x07; //trap 
	snmpbuf.var_num	 = 0x01;

	snmpaddr.remote_ip = peer_server_ip;

//	snmpaddr.local_ip  = LOCAL_IP;
	snmpaddr.remote_port = PPS_REALSYNC_PORT;
	snmpaddr.local_port  = PPS_REALSYNC_PORT;
	snmpaddr.broadcast   = 0x00;

	varlist = snmpbuf.var;
 	varlist->oidlen   = 13 + 1;
	varlist->vartype  = 0x04;

	memcpy(&varlist->oid,PPS_OID_PREFIX,11*4);
	varlist->oid[11] = 0x02; //configuration
	varlist->oid[12] = 0x04; //sync ram
	varlist->oid[13] = store_pos; //account_db
	varlist->msglen  = sizeof(_prepaid_info);
	memcpy(varlist->msg, shmp, sizeof(_prepaid_info));
	snmp_send(&snmpbuf,&snmpaddr);
 	
}

int  PeriodicSyncSubsData()
{
	static int  packetPeriodicNoOfSubs=0;
	
	_prepaid_info *shmp;
	
	int	loop = 0,head,tail;
		

	for(loop=0;loop<UNIT_STORE_ACCOUNT;loop++)
	{
		head = packetPeriodicNoOfSubs / UNIT_STORE_ACCOUNT;
		tail = packetPeriodicNoOfSubs % UNIT_STORE_ACCOUNT;		
		if(packetPeriodicNoOfSubs++>=MAX_SUBS_RECORD)
 		{
 			packetPeriodicNoOfSubs = 0;
 			return 1;
 		}		
		shmp = &ramshm_ptr->prepaid_data.prepaid_info[head][tail];
		if(shmp->msisdn[MAX_MSISDN_BLEN-1] > 2 &&
			shmp->msisdn[MAX_MSISDN_BLEN-1] <18)
		{
			TrapPPSSubsData(shmp,packetPeriodicNoOfSubs);
			break;
		}
	}
	return 0;
}

void PeriodicSyncRamData()
{
	static int	packetPeriodicNo=0;
	void	*ptr = (void *)ramshm_ptr;

 	snmp_pdu         snmpbuf;
	snmp_addr		 snmpaddr;
 	var_list		 *varlist;

	PutLogFunID("PeriodicSyncRamData");
	
	if(stopPeriodicSync) 
	{
		return ;		
	}
	if(!syncFlag) /* stop sync function by command */
	{
		return ;		
	}

 	if(!masterFlag) 
		return;
	//send periodic sync message
	/*
	if(packetPeriodicNo>=totalPeriodSyncPackets)
 	{    	
	    	if(!PeriodicSyncSubsData())
	    	{
	    		return;
	    	}
	    	packetPeriodicNo = 0;
	}
	*/
	
	snmpbuf.pdu_type = 0x07; //trap 
	snmpbuf.var_num	 = 0x01;

	snmpaddr.remote_ip = peer_server_ip;

//	snmpaddr.local_ip  = LOCAL_IP;
	snmpaddr.remote_port = PPS_REALSYNC_PORT;
	snmpaddr.local_port  = PPS_REALSYNC_PORT;
	snmpaddr.broadcast   = 0x00;

	varlist = snmpbuf.var;
	varlist->oidlen   = 13 + 1;
	varlist->vartype  = 0x04;

	memcpy(&varlist->oid,PPS_OID_PREFIX,11*4);
	varlist->oid[11] = 0x02; //configuration
	varlist->oid[12] = 0x04; //sync ram
	varlist->oid[13] = packetPeriodicNo; //account_db
	varlist->msglen  = RAMDATA_PACK_SIZE;
	memcpy(varlist->msg, 
 		ptr+packetPeriodicNo*RAMDATA_PACK_SIZE, 
		RAMDATA_PACK_SIZE);
	snmp_send(&snmpbuf,&snmpaddr);
//	snmpaddr.remote_ip = LOCAL_IP;
//	snmp_send(&snmpbuf,&snmpaddr); 
	packetPeriodicNo++;
	packetPeriodicNo %= RAMDATA_PACK_NUM;
 
}


int ReadDataFromPeerSever()
{
	int	retval = 0;
	static int  readState=0;
	int	i;
	static int  trytimes = 0;
	static int  reReadTimes = 0;

	snmp_pdu	snmpbuf;
	snmp_addr	snmpaddr;
	var_list	*varlist;

	PutLogFunID("ReadDataFromPeerSever");

	switch(readState)
	{ 
		case 0: //send request
			if(readPacketNo>=RAMDATA_PACK_NUM)
			{  //init over
				readState = 0;
				readResponseCount = 0;
				trytimes = 0;
				reReadTimes = 0;
				readPacketNo = 0;
				return 1;
			}

			snmpbuf.pdu_type = PDU_GET; //trap 
			snmpbuf.var_num	 = 0x01;

			snmpaddr.remote_ip = peer_server_ip;
//			snmpaddr.local_ip  = LOCAL_IP;
			snmpaddr.remote_port = HEART_BEATING_PORT;
			snmpaddr.local_port  = HEART_BEATING_PORT;
			snmpaddr.broadcast   = 0x00;

 			varlist = snmpbuf.var;
			varlist->oidlen   = 14;
			varlist->vartype  = 0x04;

			memcpy(&varlist->oid,PPS_RAM_OID_PREFIX,13*4);
			varlist->msglen  = 0;
			for(i=0;i<MAX_READ_PACKET_NUM;i++)
			{
				varlist->oid[13] = readPacketNo+i; 
				snmp_send(&snmpbuf,&snmpaddr);
			}
			readState = 1;
			readResponseCount = 0;
			trytimes = 0;
		break;
		case 1: //wait response
			if(readResponseCount>=MAX_READ_PACKET_NUM)
			{
				readState = 0;
				reReadTimes = 0;
 				readPacketNo +=MAX_READ_PACKET_NUM;
			}
			else if(trytimes++>=MAX_RAM_INIT_RETRY)
			{
				readState = 0;
				readResponseCount = 0;
				trytimes = 0;		  
				if(reReadTimes++>=MAX_RAM_INIT_RETRY){
					reReadTimes = 0;
					readPacketNo = 0;	 
					return -1;
				}
			}
		break;
		default:
			readState = 0;
		break;
	}
	return retval;
}

int snmpResponse(snmp_pdu *pdu, snmp_addr *addr)
{
	//int	request_id;//,pdu_type;
	int	instance,dataType;
	void *ptr = (void *)ramshm_ptr;

	PutLogFunID("snmpResponse");

	//pdu_type = pdu->pdu_type;
	//request_id = pdu->request_id;
   
	dataType = pdu->var[0].oid[11];

	if(dataType == 1)
	{ //statistics 
 		switch(pdu->var[0].oid[12])
		{
			case 4:
			return GetDailyReportResponse(pdu,addr);
			break;
			default:
			return 0;
			break;
		}
	}
	if(dataType == 5)
	{
		return scf_update_rcm_card_data_ack(pdu,addr);
	}
	
	instance = pdu->var[0].oid[13]; //for init 

	switch(pdu->var[0].oid[12])
	{
		case PPSOID_InitRequest: //ram data init
		if(instance>=RAMDATA_PACK_NUM) 
			return 0;
		if(instance<readPacketNo || instance>readPacketNo+MAX_READ_PACKET_NUM) 
			return 0;
		if(pdu->var[0].msglen != RAMDATA_PACK_SIZE) 
			return 0;

		debugmib.display.initProgress = (instance+1)*100/RAMDATA_PACK_NUM;

		memcpy(ptr+instance*RAMDATA_PACK_SIZE,
			   pdu->var[0].msg,
			   pdu->var[0].msglen);
  		readResponseCount++;
		break;
		default:
		break;
	}
	return 1;
}

int PeerServerRamInitRequest(u_char oidLen, DWORD *oid, u_char *pdata,BYTE *vartype)
{
	u_long instance;
	void *ptr = (void *)ramshm_ptr;

	PutLogFunID("PeerServerRamInitRequest");

	peer_server_in_init = 1;

	if(debugmib.display.sysState != _SYS_STATE_NORMAL)
	{
		return 0;
	}

	if(!syncFlag)  /* stop sync function by command */
		return 0;

	instance = oid[13];
	if(instance>=RAMDATA_PACK_NUM) 
	{
	   return 0;
	}
	*vartype = 0x04;

	memcpy(pdata,ptr+instance*RAMDATA_PACK_SIZE,RAMDATA_PACK_SIZE);
	return RAMDATA_PACK_SIZE;
}

int LoadDataFromBackfile()
{
   //int i;
   FILE *fp=NULL;
   //void *ptr=(void *)blf_shmp;

   struct stat fileinfo;

	PutLogFunID("LoadDataFromBackfile");

	fp = fopen(PPS_TARIFF_DATA_NAME,"r");
	if(fp !=NULL)
	{
		stat(PPS_TARIFF_DATA_NAME,&fileinfo);
		if(fileinfo.st_size == sizeof(_tariff_data))
		{
   			fread(&ramshm_ptr->tariff_data, sizeof(_tariff_data), 1, fp);
   		}
   		/*
		stat(PPS_TARIFF_DATA_NAME,&fileinfo);
		if(fileinfo.st_size == sizeof(_tariff_data))
		{ //check length
			fread(&ramshm_ptr->tariff_data,sizeof(_tariff_data),1,fp);
		}
		else if(fileinfo.st_size == sizeof(_tariff_data_old))
		{
			_tariff_data_old oldTariffData;
			memset(&ramshm_ptr->tariff_data,0,sizeof(_tariff_data));
			fread(&oldTariffData,sizeof(_tariff_data_old),1,fp);
			memcpy(&ramshm_ptr->tariff_data.comm_tariff,
					&oldTariffData.comm_tariff,
					sizeof(_comm_tariff)*MAX_ZONE_NUM_OLD);
			memcpy(&ramshm_ptr->tariff_data.bill_discount,
					&oldTariffData.bill_discount,
					sizeof(_bill_discount)*MAX_DISCOUNT_ID*24);
			memcpy(&ramshm_ptr->tariff_data.holiday_flag,
					&oldTariffData.holiday_flag,
					sizeof(_bill_holiday)*12*31);
			
			memcpy(&ramshm_ptr->tariff_data.rent_tariff,
				&oldTariffData.rent_tariff,
				sizeof(_rent_tariff)*MAX_ZONE_NUM_OLD*MAX_RENT_TARIFF);
			memcpy(&ramshm_ptr->tariff_data.bill_tariff,
				&oldTariffData.bill_tariff,
				sizeof(_bill_tariff)*BILLING_BASE_NUM*MAX_ZONE_NUM_OLD);
			memcpy(&ramshm_ptr->tariff_data.called_tariff,
				&oldTariffData.called_tariff,
				sizeof(_bill_tariff)*MAX_ZONE_NUM_OLD*CALLED_BASE_NUM);
			memcpy(&ramshm_ptr->tariff_data.bill_sms,
				&oldTariffData.bill_sms,
				sizeof(_bill_sms)*MAX_ZONE_NUM_OLD*MAX_SMS_PREFIX);
	
		}
		*/
		fclose(fp);
   }

    fp=fopen(PPS_RECHARGE_CARD_BACKUP_NAME,"r");
    if(fp !=NULL)
    {
		stat(PPS_RECHARGE_CARD_BACKUP_NAME,&fileinfo);
		if(fileinfo.st_size == sizeof(_card_data))
		{ //check length
			fread(&ramshm_ptr->card_data,sizeof(_card_data),1,fp);
		}
		fclose(fp);
    }
   
	fp=fopen(PPS_USER_BACKUP_NAME,"r");
	if(fp !=NULL)
	{
		stat(PPS_USER_BACKUP_NAME,&fileinfo);
		if(fileinfo.st_size == sizeof(_prepaid_data))
		{ //check length
			fread(&ramshm_ptr->prepaid_data,sizeof(_prepaid_data),1,fp);
		}		

		fclose(fp);
	}
	

    return 1;
}

static int base_prefix_index = 0;

int ocs_set_crm_base_prefix_record(char *prefix, char *area, int call_type, int base_prefix_index)
{
	_base_tariff * ptr = &ramshm_ptr->tariff_data.base_tariff[base_prefix_index];

	strcpy(ptr->bill_id, prefix);
	strcpy(ptr->area, area);
	ptr->call_type = call_type;
	
	return 1;
}

extern int ocs_get_call_type_by_des(const char *prefix);
int ocs_parse_base_prefix(char *data)
{
	const  char	delimiter[] = ",;	";
	char	buf[1024] = {""},*token;
	char	prefix[64], area[128];
	int	index = 0;
	int   call_type = PPS_CSTA_TYPE_BASE;
	
	while(index<3)
	{
		token = strsep((char **)&(data),delimiter);
		if(token == NULL )
		{
			index++;
			continue;
		}

		strcpy(buf,token);

		switch(index)
		{
			case 0x00: //prefix
				strcpy(prefix, buf);
			break;
			case 0x01: //area des
				strcpy(area, buf);
			break;
		}
		index ++;
	}

	call_type = ocs_get_call_type_by_des(prefix) + PPS_CSTA_TYPE_BASE;
	
	ocs_set_crm_base_prefix_record(prefix, area, call_type, base_prefix_index);
	base_prefix_index ++;
	
	return 1;

}

extern void ocs_get_crm_prefix_definition();
extern char *ocs_get_crm_prefix_filename(char *ptr);
int ocs_read_crm_base_prefix_file()
{

	FILE *fp = NULL;
    	char file_name[128] = {""};
	char buf[1024];

	ocs_get_crm_prefix_definition();
	
	ocs_get_crm_prefix_filename(file_name);	
	fp = fopen(file_name,"rb");
	if(fp == NULL)
	{
		printf("can't open file %s\r\n", file_name);
		return 0;
	}

	base_prefix_index = 0;
	while(fgets(buf,1023,fp) !=(char *)0)
	{
		if( (int *)strchr(buf,'#') !=NULL) continue;
		if( !strlen(buf) ) continue;  
		ocs_parse_base_prefix(buf);
	}
	
	fclose(fp);

	return 1;
}

int ppsBackupRamDataToFile()
{
  static int   backupState = 0;
  int		   retval = 0;
  static int   backupCounter = 0;

	PutLogFunID("ppsBackupRamDataToFile");

  switch(backupState){
    case 0:
    	pps_real_update_file_close();
      SaveTariffPlan();
	  backupState = 1;
	break;
	case 1:
		SaveRechargeCard();
	  	backupState = 2;
    break;
	case 2:
	  SaveSubsData();
	  backupState = 3;
	break;
	case 3:
	  //SaveTariffData();
	  //mnpf_exit(1);
	  pps_real_update_file_init();
	  backupState = 4;
	break;
	case 4:
	  if(backupCounter++>(5*CYCLE_STATE_INTERVAL))
	  {
		backupCounter = 0;
		backupState = 0;
		retval = 1;
	  }
	break;
	default:
	  retval = 1;
	break;
  }
  return retval;
}


/*------------------------------------------------*/

int tftpReadRequest(u_short portno, char *filename)
{
   int   retval=1,filename_len;
   char	 readmode[BUFSIZE]="octetoblksizeo1024";
   _msg_list ipmsg;

	PutLogFunID("tftpReadRequest");

   filename_len = strlen(filename);

    ipmsg.msgSrcPort = portno;
//    ipmsg.msgSrcIP   = LOCAL_IP;
	tftp_port = 69;
	tftp_ip = primary_data_server;//
    ipmsg.msgDstPort = tftp_port; //TFTP_PORT;
    ipmsg.msgDstIP   = tftp_ip;
    ipmsg.msgBroadcast  = 0x00;

	ipmsg.msgContent[0] = 0;
	ipmsg.msgContent[1] = 1; //read request
	memcpy(ipmsg.msgContent + 2,filename,filename_len);
	memcpy(ipmsg.msgContent + filename_len + 3,readmode,18);
	ipmsg.msgContent[filename_len + 2]=0;
	ipmsg.msgContent[filename_len + 8]=0;
	ipmsg.msgContent[filename_len + 16]=0;
	ipmsg.msgContent[filename_len + 21]=0;
	ipmsg.msgLength = filename_len + 22; 
    iptrPutMessage(ipmsg);
    return retval;
}

int tftpReadData(u_short portno, u_char *databuf,int flag)
{
   static int readblocknum=0;
   static int proc_len = 0;
   int    ackblocknum;
   int    retval=0;
   _msg_list ipmsg,ipack;

	PutLogFunID("tftpReadData");

   if(flag)
   {
	 ipack.msgLength = 4;
	 ipack.msgContent[0]=0x00;
	 ipack.msgContent[1]=0x04;
	 ipack.msgContent[2]=readblocknum>>8;
	 ipack.msgContent[3]=readblocknum;
//		 ipack.msgSrcIP = LOCAL_IP;
	 ipack.msgSrcPort = PPS_SERVICE_PORT;
	 tftp_port = ipmsg.msgSrcPort;
	 tftp_ip = ipmsg.msgSrcIP;
	 ipack.msgDstPort = tftp_port;
	 ipack.msgDstIP = tftp_ip;
	 iptrPutMessage(ipack);
     return 0;
   }

   if(iptrGetMessage(&ipmsg,PPS_SERVICE_PORT))
   {
      if(ipmsg.msgContent[1]==3)
	  {
		 ackblocknum = ipmsg.msgContent[2]*256+ipmsg.msgContent[3];
		 proc_len +=ipmsg.msgLength-4;
		 if(ackblocknum == readblocknum+1){
		    readblocknum = ackblocknum;
		 }else if(ackblocknum==0x0000){
		   if(readblocknum==0xffff){
		      readblocknum = ackblocknum;
		   }
		 }
		 //if(ipmsg.msgLength<4+RAMDATA_PACK_SIZE){//last packet
		 //}
		 memcpy(databuf,ipmsg.msgContent,ipmsg.msgLength); //length
		 
		 retval = ipmsg.msgLength;
		 ipack.msgLength = 4;
		 ipack.msgContent[0]=0x00;
		 ipack.msgContent[1]=0x04;
		 ipack.msgContent[2]=ackblocknum>>8;
		 ipack.msgContent[3]=ackblocknum;
//		 ipack.msgSrcIP = LOCAL_IP;
		 ipack.msgSrcPort = PPS_SERVICE_PORT;
		 tftp_port = ipmsg.msgSrcPort;
		 tftp_ip = ipmsg.msgSrcIP;
		 ipack.msgDstPort = tftp_port;
		 ipack.msgDstIP = tftp_ip;
		 iptrPutMessage(ipack);
      } 
	  else if(ipmsg.msgContent[1]==5)
	  { 
		   //printf("Error!\n");
	  }
	  if(ipmsg.msgContent[1] ==6){
		 proc_len = 0;
		 readblocknum=0;

		 ipack.msgLength = 4;
		 ipack.msgContent[0]=0x00;
		 ipack.msgContent[1]=0x04;
		 ipack.msgContent[2]=readblocknum>>8;
		 ipack.msgContent[3]=readblocknum;
//		 ipack.msgSrcIP = LOCAL_IP;
		 ipack.msgSrcPort = PPS_SERVICE_PORT;
		 ipack.msgDstPort = tftp_port;
		 ipack.msgDstIP = tftp_ip;
		 iptrPutMessage(ipack);
	  }
	}   
    return retval;
}

int ReadDataFromOMCServer()
{
   static int tftpState = 0;
   u_char     databuf[1024];
   int        retval=0;
   static int trytimes=0,retrytimes=0;
   u_short    blocknum,length;
   char       filename[BUFSIZE]="pps_backup.dat";
   void       *ptr = (void *)ramshm_ptr;
   int		  i;

	PutLogFunID("ReadDataFromOMCServer");

   switch(tftpState)
   {
      case 0:
	    sprintf(filename,"pps_backup%02d.dat",(time_now[6]+7-1)%7);
	    if(tftpReadRequest(PPS_SERVICE_PORT,filename))
		  tftpState = 1;
	  break;
	  case 1:
	    for(i=0;i<1;i++)
		{
	      length = tftpReadData(PPS_SERVICE_PORT,databuf,0);
		  if(length>=4){
		     blocknum = databuf[2] * 256 + databuf[3];
//			 if(blocknum>=RAMDATA_PACK_NUM) continue;
	         debugmib.display.dataSrc=_SRC_OMC_HD;
		     debugmib.display.initProgress = (blocknum)*100/RAMDATA_PACK_NUM;
             memcpy(ptr+(blocknum-1)*RAMDATA_PACK_SIZE,
			        &databuf[4],
					length-4);  //length is variable
					
		     trytimes=0;
			 retrytimes = 0;
		     if(blocknum>=RAMDATA_PACK_NUM)
		     {
			   retval = 1;
		     }
		  }else if(trytimes++>MAX_RAM_INIT_RETRY){
		     trytimes = 0;
	         tftpReadData(PPS_SERVICE_PORT,databuf,1);
			 if(retrytimes++>MAX_RAM_INIT_RETRY)
			 {
			   retrytimes = 0;
		       retval = -1;
			 }
		  }
		}
	  break;
	  default:
	  break;
   }
   return retval;
}

int tftpWriteRequest(int portno,char *filename)
{
    int       retval=1,filename_len;
    char	  writemode[BUFSIZE]="octetoblksizeo1024";
    _msg_list ipmsg;

   	PutLogFunID("tftpWriteRequest");
	
	filename_len = strlen(filename);
    ipmsg.msgSrcPort = portno;
//    ipmsg.msgSrcIP   = LOCAL_IP;
    tftp_port = 69;
	tftp_ip = primary_data_server;
    ipmsg.msgDstPort = tftp_port;
    ipmsg.msgDstIP   = tftp_ip;
    ipmsg.msgBroadcast  = 0x00;

	ipmsg.msgContent[0] = 0;
	ipmsg.msgContent[1] = 2; //write request
	memcpy(&ipmsg.msgContent[2],filename,filename_len);
	memcpy(&ipmsg.msgContent[ filename_len + 3],writemode,18);
	ipmsg.msgContent[filename_len + 2]=0;
	ipmsg.msgContent[filename_len + 8]=0;
	ipmsg.msgContent[filename_len + 16]=0;
	ipmsg.msgContent[filename_len + 21]=0;
	ipmsg.msgLength = filename_len + 22; 
    iptrPutMessage(ipmsg);

    return retval;
}

int tftpWriteData()
{
    int retval = 0;
	static int blocknum=1,ackblocknum=0;
	static int trytimes=0;
	static int reSendTimes=0;
	_msg_list ipmsg,ipsend;
    void *ptr = (void *)ramshm_ptr;

	PutLogFunID("tftpWriteData");

    if(iptrGetMessage(&ipmsg,PPS_SERVICE_PORT))
	{
	   if(ipmsg.msgContent[1] == 4){
	     ackblocknum = ipmsg.msgContent[2]*256+ipmsg.msgContent[3];
		 if(ackblocknum == blocknum){
		   if(blocknum++>=RAMDATA_PACK_NUM){
	          blocknum=0;
	          ackblocknum=0;
	          trytimes=0;	  
			  reSendTimes = 0;
		      return 1;
		   }
		 }
	   }else if(ipmsg.msgContent[1] == 6)
	   {
	     blocknum = 1;
	   }
//	   ipsend.msgSrcIP = LOCAL_IP;
	   tftp_port = ipmsg.msgSrcPort;
	   tftp_ip = ipmsg.msgSrcIP;
	   ipsend.msgSrcPort = PPS_SERVICE_PORT;
	   ipsend.msgDstPort = tftp_port;
	   ipsend.msgDstIP = tftp_ip;
	   ipsend.msgLength = 4 + 1024;
	   ipsend.msgContent[0] = 0x00;
	   ipsend.msgContent[1] = 0x03;
       ipsend.msgContent[2] = blocknum>>8;
	   ipsend.msgContent[3] = blocknum;
	   memcpy(&ipsend.msgContent[4],
			  ptr+(blocknum-1)*RAMDATA_PACK_SIZE,
			  RAMDATA_PACK_SIZE);
       iptrPutMessage(ipsend);
	   reSendTimes = 0;
	}else if(trytimes++>MAX_RAM_INIT_RETRY)
	{
	   trytimes=0;	
	   if(reSendTimes++>=MAX_RAM_INIT_RETRY){
	      reSendTimes = 0;
	      blocknum=0;
	      ackblocknum=0;
	      retval = 1;	     
	   }else{
//	      ipsend.msgSrcIP = LOCAL_IP;
	      ipsend.msgSrcPort = PPS_SERVICE_PORT;
	      ipsend.msgDstPort = tftp_port;
	      ipsend.msgDstIP = tftp_ip;
	      ipsend.msgLength = 4 + 1024;
	      ipsend.msgContent[0] = 0x00;
	      ipsend.msgContent[1] = 0x03;
          ipsend.msgContent[2] = blocknum>>8;
	      ipsend.msgContent[3] = blocknum;
	      memcpy(&ipsend.msgContent[4],
		  	     ptr+(blocknum-1)*RAMDATA_PACK_SIZE,
			     RAMDATA_PACK_SIZE);
                 iptrPutMessage(ipsend);
	   }
	}
	return retval;
}

int ppsBackupRamDataToOMCServer()
{
   int retval = 0;
   static int backupState = 0;
   char   filename[32];

	PutLogFunID("ppsBackupRamDataToOMCServer");

   sprintf(filename,"pps_backup%02d.dat",time_now[6]);
   switch(backupState){
     case 0:
	   if(tftpWriteRequest(PPS_SERVICE_PORT,filename)){
	     backupState = 1;
	   }
	 break;
	 case 1:
	   if(tftpWriteData()){
	     backupState = 0;
	     retval = 1;
       }
	 break;
	 default:
	 break;
   }
   return retval;
}

/* --- pps subscriber index management routines -------*/
u_long ppsBinSearchIndex(int low, int high, long long key)
//make sure that the value of low and high is valid before invoke this function. 
{
	int 			mid;
	long long		midvalue;
  

	if(low > high)		//bug occured
	{
		printf("BinSearchIndex ERR,low=%d,high=%d,key=%lld",low,high,key);
		return low;
	}
   
	if(high == low + 1 )
	{
		if(key <= ramshm_ptr->index_data.index_table.prim_index[low].key)
			return low;
		else if(key <= ramshm_ptr->index_data.index_table.prim_index[high].key)
			return high;
		else
			return high + 1;
	}
  
	if(low == high)
	{
		//if(low == 0)
		//	return 0;
		if(key <= ramshm_ptr->index_data.index_table.prim_index[low].key)
			return low;
		else 
			return low + 1;
	}
  
	mid = (low + high)/2;
	midvalue = ramshm_ptr->index_data.index_table.prim_index[mid].key;

	if(key == midvalue)
	{
		return mid;
	}
	else if(key < midvalue)
	{
		return ppsBinSearchIndex(low, mid, key);
	}
	else
	{
		return ppsBinSearchIndex(mid, high, key);
	}
}

int AssignPPSStoreIndex()
{
	int index;
	int	pWriteSub;
	
	pWriteSub = ramshm_ptr->index_data.free_index.pWriteSub;
	
	
	if(pWriteSub<=0)
	{
		if(debugmib.measurement.usernumber != MAX_SUBS_RECORD)
		{
			printf("Store index error!, no free space while exist subs.= %ld\n",
				debugmib.measurement.usernumber);
		}
		return -1;
	}

	index = ramshm_ptr->index_data.free_index.free_memory[pWriteSub-1];
	pWriteSub -- ;
	if(pWriteSub<0) pWriteSub = 0;
	ramshm_ptr->index_data.free_index.pWriteSub = pWriteSub;
	
	if(ramshm_ptr->index_data.free_index.status[index] == 1)
	{
		return AssignPPSStoreIndex();
	}

	debugmib.measurement.free_index =  
			ramshm_ptr->index_data.free_index.pWriteSub;
	
	return index;
}

int FreePPSStoreIndex(int store_index)
{
	int				pWriteSub;
	_pps_index_db	*shmp;

	if(store_index<0 || store_index>=MAX_SUBS_RECORD) 
		return 0;
	
	shmp = &ramshm_ptr->index_data;
	pWriteSub = shmp->free_index.pWriteSub;
	
	if(pWriteSub>=MAX_SUBS_RECORD)
	{
		printf("Store index error!, all space are free while %ld subs. exist\n",
				debugmib.measurement.usernumber);
		return 0;
	}
	shmp->free_index.status[store_index] = 0;
	shmp->free_index.free_memory[pWriteSub] = store_index;

	pWriteSub ++ ;
	pWriteSub %= (MAX_SUBS_RECORD+1);
	shmp->free_index.pWriteSub = pWriteSub;
	

	debugmib.measurement.free_index = shmp->free_index.pWriteSub;
	return 1;
}

/*------------------------------*/
int AddPPSTableIndex(long long key, int store_index)
{
	int					index;
	_pps_index_db		*shmp;

	shmp = &ramshm_ptr->index_data;

	if(debugmib.measurement.usernumber == 0)
	{
		index = 0;
		shmp->index_table.prim_index[index].store_index = store_index;
		shmp->index_table.prim_index[index].key = key;
		return 1;
	}

	index = ppsBinSearchIndex(0,debugmib.measurement.usernumber-1,key);

	if(index>=MAX_SUBS_RECORD) 
	{
		DebugMsg(debugmib.display.asciiOut,"Space is full with total %ld subs!\n",debugmib.measurement.usernumber);
		return 0;
	}

	if(shmp->index_table.prim_index[index].key == key)
	{
		//DebugMsg(debugmib.display.asciiOut,"index: %lld existing at: %d\n",key,index);
		return 0;
	}
	
	//DebugMsg(debugmib.display.asciiOut,"index: %lld  at: %d\n",key,index);
	
	if(index>=debugmib.measurement.usernumber )
	{
		shmp->index_table.prim_index[index].store_index = store_index;
		shmp->index_table.prim_index[index].key = key;
	}
	else 
	{
		/*
		memmove(&tmpIndexTable,
				&shmp->index_table.prim_index[index],
				(debugmib.measurement.usernumber-index)*sizeof(_pps_index_node));
		memmove(&shmp->index_table.prim_index[index+1],
				&tmpIndexTable,
				(debugmib.measurement.usernumber-index)*sizeof(_pps_index_node));
		*/
		memmove(&shmp->index_table.prim_index[index+1],
				&shmp->index_table.prim_index[index],
				(debugmib.measurement.usernumber-index)*sizeof(_pps_index_node));

		shmp->index_table.prim_index[index].store_index = store_index;
		shmp->index_table.prim_index[index].key = key;
	}
	return 1;
}


int DeletePPSTableIndex(int index, int store_index)
{
	
	_pps_index_db		*shmp;

	FreePPSStoreIndex(store_index);

	shmp = &ramshm_ptr->index_data;
	shmp->index_table.prim_index[index].key = 0;
	shmp->index_table.prim_index[index].store_index  = 0;
	if(index ==  debugmib.measurement.usernumber-1)
	{
		return 1;
	}

	memmove(&shmp->index_table.prim_index[index],
			&shmp->index_table.prim_index[index+1],
			//(MAX_SUBS_RECORD-index-1)*sizeof(_pps_index_node));
			(debugmib.measurement.usernumber-index-1)*sizeof(_pps_index_node));

	return 1;
}

int FindPPSTableIndex(long long key)
{	
	int	index;

	if(debugmib.measurement.usernumber == 0)
		return -1;
	index = ppsBinSearchIndex(0,debugmib.measurement.usernumber-1,key);

	if(index>=MAX_SUBS_RECORD) 
		return -1;

	if(ramshm_ptr->index_data.index_table.prim_index[index].key != key)
	{
		return -1;
	}

	return index;
}

int FindPPSSubsStoreIndex(long long key)
{
	int	index;
	int	store_index = 0;

#ifdef OCS_WITH_CRM
	store_index = ocs_get_ue_index(key);
	if(store_index == INVALID_UE_INDEX)
		store_index = -1;
	return store_index;
#endif
	index = FindPPSTableIndex(key);
	
	
	if(index<0) 
	{
		return index;
	}
	//DebugMsg(debugmib.display.asciiOut,"find store index: %lld -%d\n",key,index);
	store_index = 
		ramshm_ptr->index_data.index_table.prim_index[index].store_index;
	if(store_index<0 || store_index>= MAX_SUBS_RECORD)
	{
		return -1;
	}		
		
	return store_index;
}


int GetAccountInfoBySortIndex(int index, char *msisdn)
{
	int	retval = 0;
	
	if(index<0 || index>=debugmib.measurement.usernumber) 
		return retval;
	if(debugmib.measurement.usernumber == 0)
		return retval;
	if(msisdn == NULL)
		return retval;
		
	retval = 1;
#ifdef OCS_WITH_CRM
	//if(OCS_with_external_CRM())
	{
		long long llmsisdn = ocs_get_ue_by_index(index);
		sprintf(msisdn,"%lld",llmsisdn);
	}
	//else
#else
	{
		sprintf(msisdn,"%lld",ramshm_ptr->index_data.index_table.prim_index[index].key);
	}
#endif

	return retval;
}


int	GetPPSSubsRecord(char *msisdn, _prepaid_info *shmp)
{
	// msisdn in what format? NAI+NUMBER OR NUMBER ?

	int store_index, len;
	int	head,tail;

	len = strlen(msisdn);

	if(len<MIN_MSISDN_ALEN  || len>MAX_MSISDN_ALEN) return -1;

	store_index = FindPPSSubsStoreIndex(atoll(msisdn));

	if(store_index<0) return -1;
	head = store_index /UNIT_STORE_ACCOUNT;
	tail = store_index % UNIT_STORE_ACCOUNT;

	memcpy(shmp,
		&ramshm_ptr->prepaid_data.prepaid_info[head][tail],
		sizeof(_prepaid_info));
	return store_index;
}

/*-----------------subs management ----------------*/
extern int ocs_add_ue_record(long long msisdn, int store_index);
int CreatePPSSubsIndexTable()
{
	int				loop,len,head,tail,l;
	int				user_counter = 0;
	char				buf[BUFSIZE],msisdn[32];
	_prepaid_info	*shmp;

	memset(&ramshm_ptr->index_data.free_index,
			0,
			sizeof(_pps_free_index)); /* clear flag table */
	memset(&ramshm_ptr->index_data.index_table,
			0,
			sizeof(_pps_index_table)); /* clear index table */

	ramshm_ptr->index_data.free_index.user_counter = 0;
	ramshm_ptr->index_data.free_index.pWriteSub = 0;
	debugmib.measurement.usernumber = 0;	

	for(loop=MAX_SUBS_RECORD;loop>=0;loop--)
	{
	       if(loop%200==0)
   	           ReadSyncMessageForInit();
	       
		head = loop / UNIT_STORE_ACCOUNT;
		tail = loop % UNIT_STORE_ACCOUNT;
		
		if(head>=MSISDN_HEAD_NUM) continue;
		shmp = &ramshm_ptr->prepaid_data.prepaid_info[head][tail];
		len = shmp->msisdn[MAX_MSISDN_BLEN-1];

		if(len<MIN_MSISDN_ALEN || len>MAX_MSISDN_ALEN)
		{
			memset(shmp,0,sizeof(_prepaid_info));
			FreePPSStoreIndex(loop);
			continue;
		}
		BcdToAscii(msisdn,shmp->msisdn,(MAX_MSISDN_BLEN-1)*2);
		msisdn[len] = 0;
		if(!ValidateAsciiMSISDN(msisdn,len))
		{
			memset(shmp,0,sizeof(_prepaid_info));
			FreePPSStoreIndex(loop);
			continue;
		}

		 shmp->favorite_numbers = 0;
		 for(l=0;l<MAX_FAVORITE_NUMBERS;l++)
		 {
		 	len = shmp->favorite_number[l][MAX_MSISDN_BLEN-1];
			if(len>=3 && 	len<=MAX_MSISDN_ALEN)
			{
				BcdToAscii(buf,shmp->favorite_number[l],(MAX_MSISDN_BLEN-1)*2);
				buf[len] = 0;
				if(!ValidateAsciiMSISDN(msisdn,len))
				{
					memset(shmp->favorite_number[l],0,MAX_MSISDN_BLEN);
				}
				else
				{
					shmp->favorite_numbers ++;
				}
			}
			else
				memset(shmp->favorite_number[l],0,MAX_MSISDN_BLEN);
		 }
		 
		 shmp->latch_flag = 0;
#ifdef OCS_WITH_CRM
		if(ocs_add_ue_record(atoll(msisdn), loop)==0)
		{
 			DebugMsg(debugmib.display.asciiOut,
				"msisdn %s is duplicated, delete!", msisdn);
			memset(shmp,0,sizeof(_prepaid_info));
			FreePPSStoreIndex(loop);
		}
#else
		if(!AddPPSTableIndex(atoll(msisdn), loop))
		{
    			DebugMsg(debugmib.display.asciiOut,
				"msisdn %s is duplicated, delete!", msisdn);
			memset(shmp,0,sizeof(_prepaid_info));
			FreePPSStoreIndex(loop);
			continue;
		}
#endif		
		user_counter++;
		UserNumberIncrement();

	}
	
#if DEBUG
    DebugMsg(debugmib.display.asciiOut,"total user: %d",user_counter);
    DebugMsg(debugmib.display.asciiOut,"free index: %d", 
		ramshm_ptr->index_data.free_index.pWriteSub);

#endif
	ramshm_ptr->index_data.free_index.user_counter = user_counter;
	return 1;
}

extern int pps_real_update_user_file(int head, int tail);
extern int ocs_delete_ue_record(long long msisdn);
int AddPPSSubsData(_prepaid_info *shmp)
{
	int		store_index,head,tail;
	int		len=0;
	char	msisdn[32];
	long	long	lmsisdn;
	_prepaid_data	*pdata_shmp;

	len = shmp->msisdn[MAX_MSISDN_BLEN-1];

	if(len<MIN_MSISDN_ALEN || len>MAX_MSISDN_ALEN)
		return -1;

	BcdToAscii(msisdn,shmp->msisdn,9*2);
	msisdn[len] = 0;
	lmsisdn = atoll(msisdn);
	pdata_shmp = &ramshm_ptr->prepaid_data;

	if(debugmib.measurement.usernumber>0)
	{
		store_index = FindPPSSubsStoreIndex(lmsisdn);
		if(store_index>=0 && store_index<MAX_SUBS_RECORD)
		{
			head = store_index / UNIT_STORE_ACCOUNT;
			tail = store_index % UNIT_STORE_ACCOUNT;

			memcpy(&pdata_shmp->prepaid_info[head][tail],
						shmp,
						sizeof(_prepaid_info));
			DebugMsg(debugmib.display.asciiOut,"Subs. %s exist @%d, replace it!\n",
					msisdn,store_index);
			return store_index;
		}
	}

	if(debugmib.measurement.usernumber>=MAX_SUBS_RECORD)
	{
		DebugMsg(debugmib.display.asciiOut,"Space is full,cann't store subs. data any more!\n");
		return -1;
	}

	store_index = AssignPPSStoreIndex();
	if(store_index<0 || store_index>=MAX_SUBS_RECORD)
	{
		return -1;
	}
	//DebugMsg(debugmib.display.asciiOut,"Subs. %s does not exist,stored at: %d!\n",msisdn,store_index);
#ifdef OCS_WITH_CRM
	if(ocs_add_ue_record(lmsisdn, store_index) == 0)
	{
		return -1;
	}
#else

	if(!AddPPSTableIndex(lmsisdn,store_index))
	{
		
		return -1;
	}
#endif

	head = store_index / UNIT_STORE_ACCOUNT;
	tail = store_index % UNIT_STORE_ACCOUNT;
	memcpy(&pdata_shmp->prepaid_info[head][tail],
			shmp,
			sizeof(_prepaid_info));

	UserNumberIncrement();

       pps_real_update_user_file(head, tail);

	return store_index;
}

int ModifyPPSSubsData(_prepaid_info *shmp)
{
	int		store_index,len;
	int		head, tail;
	char	msisdn[32];
	long	long	lmsisdn;
	_prepaid_data	*pdata_shmp;

	len = shmp->msisdn[MAX_MSISDN_BLEN-1];

	if(len<MIN_MSISDN_ALEN || len>MAX_MSISDN_ALEN)
		return 0;

	BcdToAscii(msisdn,shmp->msisdn,9*2);
	msisdn[len] = 0;
	lmsisdn = atoll(msisdn);
	
#ifdef OCS_WITH_CRM
	store_index = ocs_get_ue_index(lmsisdn);

#else
	store_index = FindPPSSubsStoreIndex(lmsisdn);
#endif

	if(store_index==-1 || store_index == INVALID_UE_INDEX)
	{
		//AddPPSSubsData(shmp);
		return 0;
	}
	pdata_shmp = &ramshm_ptr->prepaid_data;
	
	head = store_index / UNIT_STORE_ACCOUNT;
	tail = store_index % UNIT_STORE_ACCOUNT;
	memcpy(&pdata_shmp->prepaid_info[head][tail],
			shmp,
			sizeof(_prepaid_info));

       pps_real_update_user_file(head, tail);

	return 1;
}

int DeletePPSSubsData(_prepaid_info *shmp)
{
	int		store_index;
	int		head, tail;

	int		len=0;
	char	msisdn[32];
	long	long	lmsisdn;
	_prepaid_data	*pdata_shmp;

	len = shmp->msisdn[MAX_MSISDN_BLEN-1];

	if(len<MIN_MSISDN_ALEN || len>MAX_MSISDN_ALEN)
	{
		debugmib.watch_dog[49]++;
		return 0;
	}
	BcdToAscii(msisdn,shmp->msisdn,9*2);
	msisdn[len] = 0;
	lmsisdn = atoll(msisdn);

#ifdef OCS_WITH_CRM
	store_index = ocs_get_ue_index(lmsisdn);
	if(store_index == INVALID_UE_INDEX)
	{
		DebugMsg(debugmib.display.asciiOut,"Subs. %s doesn't exist, cann't delete it!\n",msisdn);
		return 0;
	}
	ocs_delete_ue_record(lmsisdn);

	DebugMsg(debugmib.display.asciiOut,"Delete subs %s ,stored at: %d!\n",msisdn, store_index);
	
#else
	int index = FindPPSTableIndex(lmsisdn);
	if(index==-1)
	{
		debugmib.watch_dog[50]++;
		return 0;
	}

	store_index = ramshm_ptr->index_data.index_table.prim_index[index].store_index;

	if(store_index==-1)/* never set to -1? , 10-12 */
	{
		debugmib.watch_dog[51]++;
		DebugMsg(debugmib.display.asciiOut,"Subs. %s doesn't exist, cann't delete it!\n",msisdn);
		return 0;
	}
	
	DeletePPSTableIndex(index,store_index);
	{
		DebugMsg(debugmib.display.asciiOut,"Delete subs %s ,stored at: %d.%d!\n",msisdn,index,store_index);
	}
#endif

	pdata_shmp = &ramshm_ptr->prepaid_data;

	head = store_index / UNIT_STORE_ACCOUNT;
	tail = store_index % UNIT_STORE_ACCOUNT;

	memset(&pdata_shmp->prepaid_info[head][tail],
				0,
				sizeof(_prepaid_info));

	UserNumberDecrement();

       pps_real_update_user_file(head, tail);

	return 1;
}


/* ---- test functins ----- */
void ppsListAllIndexByOrder()
{
	int	i;
	FILE	*fp=NULL;

	fp = fopen("/usr/local/subsManage/pps_index.txt","w");
	if(fp==NULL)
		return;

	if(debugmib.measurement.usernumber == 0)
	{
		fprintf(fp,"No subs exists!\n");				
	}
	else
	{
		fprintf(fp,"#	msisdn		index\n");
		for(i=0;i<debugmib.measurement.usernumber;i++)
		{
			fprintf(fp,"%04d	%lld	%d\n",
				i,
				ramshm_ptr->index_data.index_table.prim_index[i].key,
				ramshm_ptr->index_data.index_table.prim_index[i].store_index);
		}
	}
	fclose(fp);
}

void ppsListAllSubsNumber()
{
	int		i,len;
	int		head,tail,store_index;
	FILE	*fp=NULL;
	_prepaid_info *shmp;
	char	msisdn[32];
	
	fp = fopen("/usr/local/subsManage/pps_subs.txt","w");
	if(fp==NULL)
		return;

	if(debugmib.measurement.usernumber == 0)
	{
		fprintf(fp,"No subs exists!\n");				
	}
	else
	{
		fprintf(fp,"#	msisdn\n");
		for(i=0;i<debugmib.measurement.usernumber;i++)
		{
			store_index =
			   ramshm_ptr->index_data.index_table.prim_index[i].store_index;
			if(store_index<0 || store_index>=MAX_SUBS_RECORD) continue;
			head = store_index / UNIT_STORE_ACCOUNT;
			tail =  store_index % UNIT_STORE_ACCOUNT;
			shmp = &ramshm_ptr->prepaid_data.prepaid_info[head][tail];
			len = shmp->msisdn[MAX_MSISDN_BLEN-1]%17;
			ppsBcdToAsciiR(msisdn,shmp->msisdn,18);
			msisdn[len] = 0;
			fprintf(fp,"%05d	%s\n",
				store_index,msisdn);
		}
	}
	fclose(fp);
}

void ppsListAllSubsMSISDN()
{
	int		len;
	int		head,tail,loop;
	FILE	*fp=NULL;
	_prepaid_info *shmp;
	char	msisdn[32];
	char timebuf[128];
	
	fp = fopen("/usr/local/subsManage/pps_msisdn.txt","w");
	if(fp==NULL)
		return;

	fprintf(fp,"#		msisdn\n");
	for(loop=0;loop<MAX_SUBS_RECORD;loop++)
	{
		head = loop / UNIT_STORE_ACCOUNT;
		tail = loop % UNIT_STORE_ACCOUNT;
		
		if(head>=MSISDN_HEAD_NUM) continue;
		shmp = &ramshm_ptr->prepaid_data.prepaid_info[head][tail];
		len = shmp->msisdn[MAX_MSISDN_BLEN-1];

		if(len<1)
		{
			continue;
		}
		BcdToAscii(msisdn,shmp->msisdn,(MAX_MSISDN_BLEN-1)*2);
		msisdn[len] = 0;
		AsciiTime(timebuf,shmp->mo_expiration_date);
		fprintf(fp,"%05d	%s-%d-%s-%.02f\n", loop,msisdn, shmp->status, timebuf, shmp->balance);
	}
	fclose(fp);
}

void ppsAddBalanceToAll(int balance)
{
	int		len;
	int		head,tail,loop;

	_prepaid_info *shmp;
	//char	msisdn[32];
	
	for(loop=0;loop<MAX_SUBS_RECORD;loop++)
	{
		head = loop / UNIT_STORE_ACCOUNT;
		tail = loop % UNIT_STORE_ACCOUNT;
		
		if(head>=MSISDN_HEAD_NUM) continue;
		shmp = &ramshm_ptr->prepaid_data.prepaid_info[head][tail];
		len = shmp->msisdn[MAX_MSISDN_BLEN-1];

		if(len<2)
		{
			continue;
		}

		shmp->balance += balance;

	}
}


/*--------- real time write user/card data functions -------*/
/*--------- definitions -------------------------------*/
typedef struct real_file_type
{
	FILE    *fp;
	char	   file_name[128];
	int      open_time;
	int      last_update_time;
	int      last_update_index;
}_real_file_type;

_real_file_type   pps_user_file, pps_card_file;

/*---------- routines ------------------------------*/
int pps_real_update_file_init()
{
    FILE *fp=NULL;

    fp = fopen(PPS_USER_BACKUP_NAME,"r+b");
    if(fp == NULL)
    {
        fp = fopen(PPS_USER_BACKUP_NAME,"a+b");
        if(fp == NULL)        	
            return 0;
    }

    if(pps_user_file.fp)
    	fclose(pps_user_file.fp);
    
    pps_user_file.fp = fp;
    strcpy(pps_user_file.file_name, PPS_USER_BACKUP_NAME);
    pps_user_file.open_time = tvnow.tv_sec;

    fp = fopen(PPS_RECHARGE_CARD_BACKUP_NAME,"r+b");
    if(fp == NULL)
    {
        fp = fopen(PPS_RECHARGE_CARD_BACKUP_NAME,"a+b");
        if(fp == NULL)
            return 0;
    }

    if(pps_card_file.fp)
    	fclose(pps_card_file.fp);
    
    pps_card_file.fp = fp;
    strcpy(pps_card_file.file_name, PPS_RECHARGE_CARD_BACKUP_NAME);
    pps_card_file.open_time = tvnow.tv_sec;

    return 1;
}


int pps_real_update_file_close()
{
    if(pps_user_file.fp)
    {
        fclose(pps_user_file.fp);
        pps_user_file.fp = NULL;
    }
    
    if(pps_card_file.fp)
    {
        fclose(pps_card_file.fp);
        pps_card_file.fp = NULL;
    }
    
    return 1;
}

int pps_real_update_user_file(int head, int tail)
{
    long base_size = sizeof(long long) * MSISDN_HEAD_NUM;
    long offset_size;
    
    if( pps_user_file.fp == NULL)
    {
       pps_real_update_file_init();
    	return 0;
    }
    if(head>=MSISDN_HEAD_NUM || tail>=UNIT_STORE_ACCOUNT)
    	return 0;
    
    offset_size = (head*UNIT_STORE_ACCOUNT+tail)*sizeof(_prepaid_info);

    fseek(pps_user_file.fp, base_size+offset_size, SEEK_SET);

    fwrite((void *)&ramshm_ptr->prepaid_data.prepaid_info[head][tail], sizeof(_prepaid_info),1,pps_user_file.fp);

    fflush(pps_user_file.fp);
	
    pps_user_file.last_update_time = tvnow.tv_sec;
    pps_user_file.last_update_index = head * UNIT_STORE_ACCOUNT + tail ;

    return 1;
}

	
int pps_real_update_card_file(int head, int tail)
{
    long base_size = sizeof(long) * MAX_VALUE_TYPE +
    				 sizeof(u_char) * MAX_CARD_SEGMENT +
    				 sizeof(long long)*MAX_CARD_SEGMENT;
     
    long offset_size;
    
    if( pps_card_file.fp == NULL)
    {
       pps_real_update_file_init();
    	return 0;
    }
    if(head>=MAX_CARD_SEGMENT || tail>=MAX_CARD_NUM_PSEG)
    	return 0;
    
    offset_size = (head*MAX_CARD_NUM_PSEG+tail)*sizeof(_recharge_card_info);

    fseek(pps_card_file.fp, base_size+offset_size, SEEK_SET);

    fwrite((void *)&ramshm_ptr->card_data.prepaid_card[head][tail], sizeof(_recharge_card_info),1,pps_card_file.fp);

    pps_card_file.last_update_time = tvnow.tv_sec;
    pps_card_file.last_update_index = head * MAX_CARD_NUM_PSEG + tail ;

    return 1;
}
