/* Title:	bsscomm.c
 * Description:	IMP Interface
 * Author:	XChen
 * Date:	2006-09-20
 */
#include "bsscomm.h"
#include "includes.h"

#include "bss_hb.h"
/*
 * Variables that are initialized when process is started 
 *
 */
int timerCounter = 0;
int no_of_bss_per_pacs;
int no_of_bts_per_bss;
#define MAX_ALARMEVENT_SIZE 10000;
unsigned long networkevent_size=0L;
unsigned long omcr_command_size=0L;
unsigned long btsmeasurements_size=0L;

unsigned long glbevtnum=1L;
unsigned long alarmevent_row_no;
unsigned long btsmeas_row_no;
unsigned long networkevent_row_no;
unsigned long class_count;
unsigned long contid_count;
unsigned long alarmevent_init=0L;
unsigned long networkevent_init=0L;
unsigned long btsmeasurements_init=0L;
/*
 * Variable to store the alarmevent/networkevents
 */
char   response[SQLSTRING_LEN];
char   strValue[100];
u16    intValue;
u16    lenOfArray;
s32    ValArray[MAX_ARRAY_LENGTH];
tARs32 s32Array[MAX_ARRAY_LENGTH];

tOid TheOid = OID_INIT;
char *pTempOidSymCont = NULL;
int  Eid = 0;
int  EvCid = 0;
/*
 * Variable to store the Send/Recv messages
 */
static u8 MsgRecvBuffer[IMP_MAX_HDR_LENGTH + MSG_BODY_SIZE];
static u8 MsgSendBuffer[IMP_MAX_HDR_LENGTH + MSG_BODY_SIZE];
static u8 MsgSendBody[MSG_BODY_SIZE];
static u8 *pSendBody = MsgSendBody;
bool MsgError = FALSE;

/////////////////////////////////////////////////////////
int nbsplus=0;
int nbsplus_down=0;
int monitoring=0;
int stat_interval;
int wait_interval;

int ret;
time_t last_round=0L;      // avoid the select() to use up all resources
time_t this_round=0L;
time_t last_heartbeat=0L;  // Keep sending heartbeat within HEARTBEAT_INTERVAL
time_t this_heartbeat=0L;
int width_change=1;
int width=0;
    
/*
  init IMP Connnection
*/
void initImpConn(tImpConn * pBssConn)
{
    pBssConn->bssid         = -1;
    strcpy(pBssConn->ip, "0.0.0.0");
    pBssConn->bssname[0]    = '\0';
    pBssConn->port          = -1;
    pBssConn->sockfd        = -1;
    pBssConn->SeqNum        = (u32) 0;
    OidCtor(&(pBssConn->TheOid));    // TheOid = OID_INIT
    pBssConn->TheCid        = NM_CLASS_UNDEFINED;
    pBssConn->pCmdQ         = (struct queue *) 0;
    pBssConn->pCmdQEnd      = (struct queue *) 0;
    pBssConn->uploaded      = 0;
    pBssConn->connected     = 0;
    pBssConn->download_in_progress = 0;
    pBssConn->upload_in_progress = 0;
    memset(pBssConn->lastMsgRecvBuffer,0xF,IMP_MAX_HDR_LENGTH + MSG_BODY_SIZE);
    pBssConn->last_Total    = 0;
    pBssConn->bootupTime    = 0L;
    pBssConn->last_TransId  = 0L;
    pBssConn->this_connected_abnormal= 0L;
    pBssConn->last_connected_abnormal= 0L;
}

/*
bsType:
0==BSC+BTS
1==BS+
*/
int checkBsType(int bssid){
	char tmpStr[64];
	
	sprintf(tmpStr,"SELECT BsPlus FROM BssOmcDb.OMCR_BssFunc WHERE bssid='%d'",bssid);
	mysql_query(mysql_sock, tmpStr);
	if (mysql_errno(&mysql))
		return (0);

	result = mysql_use_result(&mysql);
	row = mysql_fetch_row(result);
	if(row == 0){
		mysql_free_result(result);
		return (0);
	}else{
		
		if(atoi(row[0])==0){
			mysql_free_result(result);
			return (0);
		}else{
			mysql_free_result(result);
			return (1);
		}
	}
}
/*
  init IMP Event
*/
void initImpEvent(tImpEvent *pBssEvent)
{
    int i;
    pBssEvent->eventname[0]  = '\0';
    pBssEvent->objectid[0]   = '\0';
    pBssEvent->classname[0]  = '\0';
    pBssEvent->eventtime[0]  = '\0';
    pBssEvent->globaleventnumber = 0L;
    pBssEvent->alarmlevel[0] = '\0';
    for (i=0; i<EVENTINFO_ARRAY_SIZE; i++)
        pBssEvent->eventinfo[i][0] = '\0';
    pBssEvent->eventinfosize = 0;
    pBssEvent->eventtype  = 0;
    pBssEvent->severity   = SV_CEASED;
}
//Add Imp Connection
void AddImpConn(int bssid, char *ipaddr, char *bssname, int uploaded)
{
    tImpConn *pBssConn;
    pBssConn = BssConn + bssid;
    pBssConn->bssid = bssid;
    strcpy(pBssConn->ip, ipaddr);
    strcpy(pBssConn->bssname, bssname);
    pBssConn->port = NMIPORT;
    bsplus_down[nbsplus_down++] = pBssConn;
    pBssConn->uploaded = uploaded;
}

bool SetOidStr(int Oid,char *pTempOid)
{
	int retval;
	sprintf(sqlstring,"SELECT ObjectName FROM OMCR_ObjectId WHERE Oid=%d",Oid);
	mysql_query(mysql_sock,sqlstring);
        retval=mysql_errno(&mysql);
        if (retval) {
            return FALSE;
        }
        result = mysql_use_result(&mysql);
        row = mysql_fetch_row(result);
		if(row==0){
			mysql_free_result(result);
			return FALSE;
		}
		else{
			strcpy(pTempOid,row[0]);
			mysql_free_result(result);
			return TRUE;
		}
}
int GetOid(char *pTempOid)
{
	int retval;
	int Oid = -1;
	sprintf(sqlstring,"SELECT Oid FROM OMCR_ObjectId WHERE ObjectName='%s'",pTempOid);
	mysql_query(mysql_sock,sqlstring);
        retval=mysql_errno(&mysql);
        if (retval) {
            return -1;
        }
        result = mysql_use_result(&mysql);
        row = mysql_fetch_row(result);
		if(row==0){
			mysql_free_result(result);
			return -1;
		}
		else{
			Oid = atol(row[0]);
			mysql_free_result(result);
			return Oid;
		}
}
bool SetCidStr(int Cid,char *pTempCid)
{
	int retval;
	sprintf(sqlstring,"SELECT ClassName FROM OMCR_ClassId WHERE Cid=%d",Cid);
	mysql_query(mysql_sock,sqlstring);
        retval=mysql_errno(&mysql);
        if (retval) {
            return FALSE;
        }
        result = mysql_use_result(&mysql);
        row = mysql_fetch_row(result);
		if(row==0){
			mysql_free_result(result);
			return FALSE;
		}
		else{
			strcpy(pTempCid,row[0]);
			mysql_free_result(result);
			return TRUE;
		}
}
int GetCid(char *pTempCid)
{
	int retval;
	int Cid = -1;
	sprintf(sqlstring,"SELECT Cid FROM OMCR_ClassId WHERE ClassName='%s'",pTempCid);
	mysql_query(mysql_sock,sqlstring);
        retval=mysql_errno(&mysql);
        if (retval) {
            return -1;
        }
        result = mysql_use_result(&mysql);
        row = mysql_fetch_row(result);
		if(row==0){
			mysql_free_result(result);
			return -1;
		}
		else{
			Cid = atol(row[0]);
			mysql_free_result(result);
			return Cid;
		}
}
bool GetEventName(int Cid,int Eid,char *pTempEid,char *pTempAlarmLevel)
{
	int retval;
	if((Cid==22)&&(Eid==0))
	{
		strcpy(pTempEid,"BtsMeasurements");
		strcpy(pTempAlarmLevel,"0");
		return TRUE;
	}
/*	else if((Cid==23)&&(Eid==0))
	{
		strcpy(pTempEid,"BscMeasurements");
		strcpy(pTempAlarmLevel,"0");
		return TRUE;
	}*/
	sprintf(sqlstring,"SELECT EventName,Alarmlevel FROM OMCR_EventInfo WHERE ClassId=%d AND EventId=%d",Cid,Eid);
	mysql_query(mysql_sock,sqlstring);
        retval=mysql_errno(&mysql);
        if (retval) {
            return FALSE;
        }
        result = mysql_use_result(&mysql);
        row = mysql_fetch_row(result);
		if(row==0){
			mysql_free_result(result);
			return FALSE;
		}
		else{
			strcpy(pTempEid,row[0]);
			strcpy(pTempAlarmLevel,row[1]);
			mysql_free_result(result);
			return TRUE;
		}
}
bool GetEvPara(int Cid,int Eid,int num,char *pTempPara)
{
	int retval;
	sprintf(sqlstring,"SELECT Para_%d FROM OMCR_EventInfo WHERE ClassId=%d AND EventId=%d",num,Cid,Eid);
	mysql_query(mysql_sock,sqlstring);
        retval=mysql_errno(&mysql);
        if (retval) {
            return FALSE;
        }
        result = mysql_use_result(&mysql);
        row = mysql_fetch_row(result);
		if(row==0){
			mysql_free_result(result);
			return FALSE;
		}
		else{
			strcpy(pTempPara,row[0]);
			mysql_free_result(result);
			return TRUE;
		}
}
/*
 * Return 0 means no error, other values are mysql error code
 */
unsigned int execute_sql(char *sqlbuffer, unsigned long *no_affected_row)
{
    unsigned int retval;

    mysql_query(mysql_sock,sqlbuffer);
    retval=mysql_errno(&mysql);
    if (retval)
        return (retval);

    if (!strncasecmp(sqlbuffer,"select",6))
    {
        result = mysql_store_result(&mysql);
        if (no_affected_row != 0)
        {
            *no_affected_row=mysql_affected_rows(mysql_sock);
        }
        mysql_free_result(result);
    }
    else
    {
        // For UPDATE,DELETE,INSERT
        if (no_affected_row != 0)
        {
            *no_affected_row=mysql_affected_rows(mysql_sock);
        }
    }
    return (retval);
}

int execute_sql_query(char *sqlstatment)
{
    int value;
    
	mysql_query(mysql_sock, sqlstatment);
	if (mysql_errno(&mysql))
        return(0);

    result = mysql_use_result(&mysql);
	if (result == NULL) {			
		return (0);
	}

	if(!(row = mysql_fetch_row(result))){
		mysql_free_result(result);
		return(0);
	}else
		value = atoi(row[0]);
	
    mysql_free_result(result);
    return(value);
}

void environ_var(char *env_name,int value,int *variable)
{
    if ( getenv(env_name) == (char *) 0)
        *variable=value;
    else
        *variable=atoi(getenv(env_name));
}

//  connect MySQL Database
void connectDB()
{
    mysql_init(&mysql);
    mysql_sock=mysql_real_connect(&mysql,NULL,USERNAME,PASSWD,DB,0,NULL,0);
    if (mysql_sock == 0)
        exit(6);
}
// clean up DB
static void cleanUp()
{
    int i;
    tImpConn *pBssConn;

    sprintf(sqlstring, "UPDATE OMCR_BSSTABLE SET connected=0");
    execute_sql(sqlstring,0);

    clearBssStatus();//bss_hb.c

    mysql_close(mysql_sock);
    //close Bss connection sockfd
    for (i=0; i<nbsplus; i++) {
        pBssConn = bsplus[i];
        close(pBssConn->sockfd);
    }
    //free mysql database
    for (i=0;i<num_of_mysql_table;i++) {
        free(*(mysql_tables+i));
    }
    free(mysql_tables);

    // clear the ip list before exit, unreliable!!
    if (monitor_fd != -1)
        write(monitor_fd, "03rst", 5);
    close(monitor_fd);
    exit(0);
}
// init OMCR_COMMAND table
void initOMCR_COMMANDTable()
{
    sprintf(sqlstring,"%s%s",
        "UPDATE OMCR_COMMAND set bssid=0,nmicommand='',",
        "seqNum=null,status=0,resultcode=0,result='',responsecode=0,response=''");
    execute_sql(sqlstring,0);
}
/*
  get all tablename from MySQL Database
*/
void GetAllTableName()
{
    int i=0;
    
    mysql_tables = (char **) malloc(sizeof(char *) * MAX_NUM_OF_SQL_TABLE);
	result = mysql_list_tables(mysql_sock, "OMCR_%");
    while ((row = mysql_fetch_row(result)))
    {
        *(mysql_tables+i) = (char *) malloc(sizeof(char) * (strlen(row[0])+1));
        strcpy(*(mysql_tables+i), row[0]);
        i++;
        if (i >= MAX_NUM_OF_SQL_TABLE)
            return; 
    }
    num_of_mysql_table = (unsigned int) mysql_num_rows(result);
	
    if (mysql_errno(&mysql))
        exit(1);
    mysql_free_result(result);
}
// get max config from DB
void GetBssMaxConfigFromDB()
{
    omcr_command_size=execute_sql_query("SELECT count(*) FROM OMCR_COMMAND");
	class_count=execute_sql_query("SELECT count(*) FROM OMCR_ClassId");
	contid_count=execute_sql_query("SELECT count(*) FROM OMCR_ObjectId");
    btsmeasurements_size=execute_sql_query("SELECT count(*) FROM OMCR_BtsMeasurements");
   
    networkevent_size=execute_sql_query("SELECT count(*) FROM OMCR_NETWORKEVENT");
    no_of_bss_per_pacs=execute_sql_query("SELECT count(*) FROM OMCR_BSSTABLE");
    no_of_bts_per_bss=execute_sql_query(
		"SELECT count(*) FROM OMCR_BSSTREE WHERE bssid=1 AND ObjectId REGEXP 'Bts\\.'");
    networkevent_init=execute_sql_query(
       "SELECT row_no FROM OMCR_NETWORKEVENT ORDER BY GlobalEventNumber ASC LIMIT 1");    
    alarmevent_init=execute_sql_query(
       "SELECT row_no FROM OMCR_ALARMEVENT ORDER BY GlobalEventNumber ASC LIMIT 1");
    btsmeasurements_init=execute_sql_query(
       "SELECT row_no FROM OMCR_BtsMeasurements ORDER BY StartTime ASC LIMIT 1");
}
/*
 * Put the value in Cdate and Ctime
 */
void currentTime(char *Cdate, char *Ctime, time_t tloc)
{
    strftime(Ctime,TIME_LEN,"%T",gmtime(&tloc));
    strftime(Cdate,TIME_LEN,"%D",gmtime(&tloc));
}

void syncBssTimeWithOMC(tImpConn *pBssConn, time_t tloc)
{
    #define TIME_STRING_MAX 9
    char Cdate[TIME_STRING_MAX];
    char Ctime[TIME_STRING_MAX];
    char buffer[2 * TIME_STRING_MAX + 33];

    currentTime(Cdate,Ctime,tloc);
//    sprintf(buffer,"set DateDisp=0 Cdate=\"%s\" Ctime=\"%s\"",Cdate, Ctime);
	sprintf(buffer,"set 53:0=0 53:4=\"%s\" 53:5=\"%s\"",Cdate, Ctime);
    ProcessUserCommand(pBssConn,"oid Clockobj.0",(u32) 0);//cid=53,oid=3
    ProcessUserCommand(pBssConn,buffer,(u32) 0);
    sleep(1);
}
// sync BssTree Alarm
void syncBssTreeAlarm()
{
    unsigned long i, nptr=0L,alarmevent_size;
    struct tSyncAlarm
    {
        int s_bssid;
        char s_objectid[MAX_OBJECTID_LEN];
        int s_severity;
    };
    struct tSyncAlarm *ptr;
    struct tSyncAlarm *baseptr;
    alarmevent_size = execute_sql_query("SELECT count(*) FROM OMCR_ALARMEVENT");

    baseptr = (struct tSyncAlarm *) malloc(sizeof(struct tSyncAlarm) * alarmevent_size);
    /*
     * Synchronize the OMCR_BSSTREE.MaxSeverity with OMCR_ALARMEVENT at startup
     */
    sprintf(sqlstring,"UPDATE OMCR_BSSTREE set MaxSeverity=0");
    if (mysql_query(mysql_sock, sqlstring))
          return;
    sprintf(sqlstring, "%s%s", "SELECT DISTINCTROW bssid,ObjectId,Severity from OMCR_ALARMEVENT ",
                       "WHERE Severity>0");
    if (mysql_query(mysql_sock, sqlstring))
          return;
    result = mysql_use_result(mysql_sock);
    ptr = baseptr;
    while ((row = mysql_fetch_row(result)))
    {
        ptr->s_bssid = atoi(row[0]);
        strcpy(ptr->s_objectid, row[1]);
        ptr->s_severity = atoi(row[2]);
        ptr++;
        nptr++;
    }
    mysql_free_result(result);

    ptr = baseptr;
    for (i=0L; i<nptr; i++)
    {
        sprintf(sqlstring, "%s%d%s%d%s'%s'",
            "UPDATE OMCR_BSSTREE set MaxSeverity=", ptr->s_severity,
            " WHERE bssid=",                        ptr->s_bssid,
            " AND objectid=",                       ptr->s_objectid
        );
        if (mysql_query(mysql_sock, sqlstring)) {
              return;
        }
        ptr++;
    }
    free (baseptr);
}
// MemorAllocation:BssConn,bsplus,bsplus_down
void MemoryAllocation()
{
    BssConn     = (tImpConn *)  malloc(sizeof(tImpConn) * no_of_bss_per_pacs);
    bsplus      = (tImpConn **) malloc(sizeof(tImpConn) * no_of_bss_per_pacs);
    bsplus_down = (tImpConn **) malloc(sizeof(tImpConn) * no_of_bss_per_pacs);
}

void restoreBssConn(int bssid, char *ip)
{
    int i;
    time_t tloc;
    char presenttime[20]="\0";
    tImpConn *pBssConn;
    /*
     * Try to restore failed connection
     * If reconnect,
     * 1. put the connection in bsplus[]
     * 2. delete it from bsplus_down[] by replacing
     *    the current with last element in bsplus_down[]
     */
    
    for (i=0;i<nbsplus_down;i++)
    {
        pBssConn=bsplus_down[i];
        if ( (pBssConn->bssid != bssid) || (strcmp(pBssConn->ip,ip)) )
            continue;
 
        pBssConn->sockfd = connectIwBox(pBssConn->ip,pBssConn->port);
        if (pBssConn->sockfd != -1)
        {
            pBssConn->last_TransId = 0L;
            pBssConn->download_in_progress = 0; 
            pBssConn->upload_in_progress = 0;
            pBssConn->connected = 1;
            bsplus[nbsplus] = pBssConn;
            nbsplus++;

            width_change=1;

            bsplus_down[i] = bsplus_down[nbsplus_down-1];
            nbsplus_down--;
            /*
             * Remove old command in DB when connection re-established.
             */
            sprintf(sqlstring, "%s%s%s%s%d",
                "UPDATE OMCR_COMMAND SET resultcode=1027,",
                "result='Connection Re-established',",
                "responsecode=-1,response=\"\",",
                "status=0 WHERE status<>0 AND bssid=", pBssConn->bssid
            );
            execute_sql(sqlstring,0);
            /*
             * clear OMC connection broken alarm
             */
            tloc=time((time_t*)0);
            strftime(presenttime, 20, "%Y-%m-%d %T", localtime(&tloc));
            sprintf(sqlstring, "%s%d%s'%s'%s%d%s%d%s'%s'%s%d",
                "UPDATE OMCR_ALARMEVENT SET Severity=", SV_CEASED,
                ",ClearTime=",                          presenttime,
                " WHERE bssid=",                        pBssConn->bssid,
                " AND Severity<>",                      SV_CEASED,
                " AND ObjectId=",                       "BssFunc",
                " AND Cause=",                          65531  //=65531x256
            );
            execute_sql(sqlstring,0);

            sprintf(sqlstring, "%s%d%s%d%s'%s'",
                "UPDATE OMCR_BSSTREE SET MaxSeverity=", SV_CEASED,
                " WHERE bssid=",  pBssConn->bssid,
                " AND ObjectId=", "BssFunc"
            );
            execute_sql(sqlstring,0);
        }
    }   /* End_of_for */
}

void discBssConn(int bssid, char *ip, fd_set *readfds)
{
    tImpConn *pBssConn;
    struct queue *tmpQPtr;
    time_t tloc;
    char presenttime[20]="\0";
    int tmpfd;
    int i;

    for (i=0; i<nbsplus; i++)
    {
        if ( ((bsplus[i])->bssid == bssid) && (!strcmp((bsplus[i])->ip, ip)))
        {
            break;
        }
    }
    if ( i==nbsplus )
        return;

    /* TCP connnection lost 
     * 1. Delete command from OMCR_COMMAND TABLE
     * 2. reset the pCmdQ and pCmdQEnd, clear entry in CmdBuffer
     * 3. Substitute i-th item with the last one of bsplus
     * 4. Move bsplus[i] to bsplus_down[]
     */

    pBssConn = BssConn + bssid;
    /*
     * Send OMC connection broken
     */
    tloc=time((time_t*)0);
    strftime(presenttime, 20, "%Y-%m-%d %T", localtime(&tloc));
    sprintf(sqlstring, "%s%d%s'%s'%s%ld%s'%s'%s'%s'%s%d%s%d%s%d%s'%s'%s%ld",
        "REPLACE OMCR_ALARMEVENT SET bssid=", pBssConn->bssid,
        ",ObjectId=",                   "BssFunc",
        ",GlobalEventNumber=",          glbevtnum,
        ",AlarmLevel=",                 "4",        // 4 -> critical
        ",EventInfo=",                  "BSS and OMC connection broken",
        ",Cause=",                      65531,      // =65531x256
        ",EventType=",                  3,          // =EVT_EQUIPMENT
        ",Severity=",                   SV_CRITICAL,
        ",EventTime=",                  presenttime,
        ",AckTime=null,ClearTime=null,row_no=", alarmevent_row_no
    );
    execute_sql(sqlstring,0);
    sprintf(sqlstring, "%s%d%s%d%s'%s'",
        "UPDATE OMCR_BSSTREE SET MaxSeverity=", SV_CRITICAL,   // 1 -> critical
        " WHERE bssid=",                        pBssConn->bssid,
        " AND ObjectId=",                       "BssFunc"
    );
    execute_sql(sqlstring,0);
    alarmevent_row_no++;
    alarmevent_row_no = alarmevent_row_no % MAX_ALARMEVENT_SIZE;
    /*
     * Remove old command in DB when connection lost.
     */
    sprintf(sqlstring, "%s%s%s%s%d",
        "UPDATE OMCR_COMMAND SET status=0,resultcode=1028,",
        "result='Connection lost',",
        "responsecode=-1,response=\"\"",
        "WHERE status<>0 AND bssid=", pBssConn->bssid
    );
    execute_sql(sqlstring,0);

    /* Empty the command queue */
    while (pBssConn->pCmdQ && pBssConn->pCmdQ->nextcmd)
    {
        tmpQPtr = pBssConn->pCmdQ;
        pBssConn->pCmdQ = tmpQPtr->nextcmd;
        tmpQPtr->nextcmd = (struct queue *) 0;
    }
    pBssConn->pCmdQ = pBssConn->pCmdQEnd = (struct queue *) 0;

    tmpfd = pBssConn->sockfd;
    pBssConn->sockfd=-1;
    FD_CLR(tmpfd, readfds);
    close(tmpfd);

    bsplus_down[nbsplus_down] = pBssConn;//if connection lost, move bsplus[i] to bsplus_down[]
    nbsplus_down++;

    /* last element (nbsplus-1) */
    bsplus[i] = bsplus[nbsplus-1];
    nbsplus--;

    width_change=1;
}

void clearBssConn(tImpConn *pBssConn,fd_set *readfds)
{
    if (pBssConn->connected > 0)
    {
        pBssConn->connected = 0;
        pBssConn->last_Total = 0;
        pBssConn->bootupTime = 0L;
        discBssConn(pBssConn->bssid, pBssConn->ip, readfds);
        update_bsstable_status(pBssConn);
    }
}
/*
 * Connect to IwBox with specific hostname and port number
 */
int connectIwBox(char *target, int port)
{
    int sock=-1;
    int flags,retcode;
    struct sockaddr_in serv_addr;
    struct hostent *hp;

    bzero((char *) &serv_addr, sizeof(serv_addr));

    if ((hp = gethostbyname(target)) == NULL) {
        //host name error
        return(-1);
    }

    bcopy(hp->h_addr, (char *) &serv_addr.sin_addr, hp->h_length);
    /* set family to internet */
    serv_addr.sin_family = AF_INET;
    /* serv_addr.sin_addr.s_addr = inet_addr(target); */
    serv_addr.sin_port = htons(port);

    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        //can't open stream socket
        return (-1);
    }
    
    //get the socket flags
    if ((flags = fcntl(sock, F_GETFL, 0)) < 0) {
        return(-1);
    }

    //set socket non-block
    if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) < 0) {
        return(-1);
    }

    if ((retcode = connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr))) && errno != EINPROGRESS){
        close(sock);	
        return (-1);
    }
    
    if (0 == retcode) {  //connection has been finished
        //recover the socket to block
        if (fcntl(sock, F_SETFL, flags) < 0) {
            return(-1);
        }
    }
  
    return(sock);
}

void stopIwBoxMonitor()
{
    close(monitor_fd);
    monitor_fd=-1;
    monitoring=0;
}

void startIwBoxMonitor(char *hostname, int port)
{
    int len;
    int i;
    tImpConn *pBssConn;

    monitor_fd = connectIwBox(hostname, port);
    if (monitor_fd == -1)
    {
		sprintf(sqlstring, "%s%s%s",
            "UPDATE OMCR_BSSTABLE SET connected='0' ",
            "WHERE ip=", hostname);
        execute_sql(sqlstring,0);
        return;
    }

    len = write(monitor_fd, "03rst", 5);
    if (len == 5)
    {
        //Connect to BSS monitor
        monitoring=1;
		/*
         * Tell monitor program the bsplus ip/bssid list
         */
        for (i=0; i<nbsplus; i++)
        {
            pBssConn = bsplus[i];
            InformIwBoxMonitor(pBssConn,ADD);
        }
        for (i=0; i<nbsplus_down; i++)
        {
            pBssConn = bsplus_down[i];
            InformIwBoxMonitor(pBssConn,ADD);
        }
    }
    else
        stopIwBoxMonitor();
}


void InformIwBoxMonitor(tImpConn *pBssConn, int action)
{
    int len;
    char buffer[24];            // "add 254 192.189.101.111"   = 24
    char mon_buffer[26];        // "23add 254 192.189.101.111" = 26

    if (action == ADD)
        sprintf(buffer,"add %d %s",pBssConn->bssid, pBssConn->ip);
    else if (action == DEL)
        sprintf(buffer,"del %d %s",pBssConn->bssid, pBssConn->ip);
    else if (action == CLR)
        sprintf(buffer,"clr %d %s",pBssConn->bssid, pBssConn->ip);

    sprintf(mon_buffer,"%.2d",strlen(buffer));
    strcat(mon_buffer,buffer);
    len = write(monitor_fd, mon_buffer, strlen(mon_buffer));
}

void GetMonitorResult(char *buffer, fd_set *readfds)
{
    tImpConn *pBssConn;
    char cmd[4];
    char ip[16];
    int bssid;

    strncpy(cmd,buffer,3);
    cmd[3]='\0';

    if( !strncmp(cmd, "die", 3))
        return;

    sscanf(buffer+4,"%d %s", &bssid, ip);
    pBssConn = BssConn + bssid;

    if(!strncmp(cmd, "new", 3))
    {
        if ((pBssConn->connected == 0) && !strcmp(pBssConn->ip,ip))
        {
            restoreBssConn(bssid, ip);
            if (pBssConn->connected != 0)
            {
                update_bsstable_status(pBssConn);
                sleep(2);
                ProcessUserCommand(pBssConn,"oid EventLog.0.0",(u32) 0);
                ProcessUserCommand(pBssConn,"action 64:1",(u32) 0);//tst
            }
        }
    }
    else if( !strncmp(cmd, "clr", 3))
    {
        clearBssConn(pBssConn,readfds);
    }
    //else
    //{
    //    return;
    //}
    
    if(pBssConn->connected<CONNECTED_STATE_MAX&&pBssConn->connected>0){
    	//printf("pBssConn->this_connected_abnormal=%ld\n",pBssConn->this_connected_abnormal);
    	//printf("pBssConn->last_connected_abnormal=%ld\n",pBssConn->last_connected_abnormal);
    	pBssConn->this_connected_abnormal=time((time_t*)0);
    	if(abs(pBssConn->this_connected_abnormal-pBssConn->last_connected_abnormal)>=60&&
    		pBssConn->last_connected_abnormal!=0){
    		pBssConn->this_connected_abnormal=0;
    		pBssConn->last_connected_abnormal=0;
    		clearBssConn(pBssConn,readfds);
    		restoreBssConn(bssid, ip);
    		
            if (pBssConn->connected != 0)
            {
                update_bsstable_status(pBssConn);
                sleep(2);
                ProcessUserCommand(pBssConn,"oid EventLog.0.0",(u32) 0);
                ProcessUserCommand(pBssConn,"action 64:1",(u32) 0);//tst
            }
    	}
    	if(pBssConn->last_connected_abnormal==0)
    		pBssConn->last_connected_abnormal=pBssConn->this_connected_abnormal;
    }else{
    	pBssConn->this_connected_abnormal=0;
    	pBssConn->last_connected_abnormal=0;
    }
    
}
/////////////////////////////////////////////////////////////////////////
/*
 add the nmi command to the command queue
*/
void addCmd2Queue(tImpConn *pBssConn,char *nmicommand,long SeqNum)
{
    struct queue *currPtr;
    /*
     * Update the pBssConn->pCmdQ and pCmdQEnd
     * Insert commands into Cmd queue of diff ImpConn
     * cmdSeqNum is an auto-increment sequence no for commands
     * CmdBufferPtr always points to an available CmdBuffer[] entry
     */
    currPtr = &(CmdBuffer[CmdBufferPtr]);
    if (pBssConn->pCmdQEnd) /* queue is not empty */
    {
        pBssConn->pCmdQEnd->nextcmd = currPtr;
    }
    else  /* is null pointer, queue is empty */
    {
        pBssConn->pCmdQ = currPtr;
    }
    pBssConn->pCmdQEnd = currPtr;
    
    strncpy(currPtr->command, nmicommand, CMD_SIZE);
    currPtr->nextcmd = (struct queue *) 0;
    currPtr->TransId = SeqNum;
    currPtr->available = FALSE;
}
/*
 retrieve command from MySQL
*/
void retrieveCmdFromDatabase()
{
    tImpConn *pBssConn;
    unsigned long cmdSeqNum=0L;
    int not_ready=0;
    char command[CMD_SIZE]="\0";
    int bssid=0;
    unsigned int retval;
    //memset(sqlstring,'\0',sizeof(sqlstring));
    //strcpy(sqlstring,
	#define	 GETCMD "SELECT row_no,bssid,nmicommand,seqNum FROM OMCR_COMMAND WHERE status=255 ORDER BY seqNum ASC"
    mysql_query(mysql_sock, GETCMD);
	
	retval=mysql_errno(&mysql);
   
	if (retval)
    {
		perror("retrieveCmdFromDatabase():SQL command failed\n"); 
        return;
    }
    result = mysql_use_result(&mysql);
    while ((row = mysql_fetch_row(result)))
    {
        /* Bssid < 0 for new Bsplus or delete bsplus command */
        bssid = atoi(row[1]);
        if (bssid < 0)   // For newbsplus and dropbsplus command
        {
            cmdSeqNum = atol(row[3]);
            strncpy(command,row[2],CMD_SIZE);
            // The add/delete command will be done later after while loop
            // so as to sync the operation requirement on database
            // Break the while loop so that the command send immediately
            // ProcessUserCommand((tImpConn *) 0,row[2], cmdSeqNum);
            break;
            /* Break the while loop here */
        }
        else
        {
            pBssConn = BssConn + atoi(row[1]);

            /* if it is not connected, don't put command in queue */
            if (pBssConn->connected == 0)
            {
                 not_ready = 2;
                 cmdSeqNum = atol(row[3]);
                 break;
            }
            else if (pBssConn->connected < CONNECTED_STATE_MAX)
            {
                 not_ready = 1;
                 cmdSeqNum = atol(row[3]);
                 break;
            }
            else  // connected == CONNECTED_STATE_MAX, put command in cmdQ
            {
                cmdSeqNum = atoi(row[3]);
                addCmd2Queue(pBssConn,row[2],cmdSeqNum);
                /*
                 * Break the while loop if no buffer available
                 * leave unprocess cmd in db
                 */
                if (!FindAvailCmdBufferPtr())
                    break;
            }  /* End_of_if */
        }
    }   /* End_of_while ((row */
	if (mysql_errno(&mysql))
    {
        perror("Get command failed!\n");
    }
    mysql_free_result(result);
    // For newbss / dropbss command, as its bssid=-1 when written to OMCR_COMMAND
    if (bssid < 0)
    {
        ProcessUserCommand((tImpConn *)0, command, cmdSeqNum);
    }

    if (not_ready == 1)   /* BSS bootup time < wait_interval */
    {
        sprintf(sqlstring, "%s%s%s%s%s%ld",
            "UPDATE OMCR_COMMAND SET status=0",
            ",resultcode=1025",
            ",result='BSS is not ready to execute command after bootup'",
            ",responsecode=-1,response=\"\"",
            " WHERE status=255 and seqNum=", cmdSeqNum
        );
        execute_sql(sqlstring,0);
    }
    else if (not_ready == 2)   /* BSS is not connected */
    {
        sprintf(sqlstring, "%s%s%s%s%s%ld",
            "UPDATE OMCR_COMMAND SET status=0",
            ",resultcode=1024",
            ",result='OMC and BSS connection broken' ",
            ",responsecode=-1,response=\"\"",
            "WHERE status=255 and seqNum=", cmdSeqNum
        );
        execute_sql(sqlstring,0);
		sprintf(sqlstring, "%s%s%d",
            "UPDATE OMCR_BSSTABLE SET connected='0' ",
            "WHERE bssid=", bssid);
        execute_sql(sqlstring,0);
    }

	if (cmdSeqNum != 0L)  // some rows selected in OMCR_COMMAND 
    {
        sprintf(sqlstring, "%s%d%s%s%s%s%ld",
            "UPDATE OMCR_COMMAND SET status=", CMD_READ_FROM_DB,//254
            ",resultcode=1026",
            ",result='Processing in BssComm'",
            ",responsecode=-1,response=\"\" ",
            "WHERE status=255 and seqNum<=", cmdSeqNum);
        execute_sql(sqlstring,0);
    }
}
/*
 * Find next available CmdBufferPtr
 * return FALSE if not found
 */
bool FindAvailCmdBufferPtr()
{
    struct queue *currPtr;
    int i;
    /*
     * Look for next available buffer
     * or set CmdBufferPtr=CMD_BUFFER_FULL if it is not found
     */

    // According to the flow, at least one entry must be freed after 1 cycle
    // Set CmdBufferPtr to zero and find available space again
    if (CmdBufferPtr == CMD_BUFFER_FULL)
        CmdBufferPtr = 0;
    for (i=0; i<CMD_BUFFER_SIZE; i++)
    {
        if (++CmdBufferPtr == CMD_BUFFER_SIZE)
            CmdBufferPtr=0;

        currPtr = &(CmdBuffer[CmdBufferPtr]);
        if ( currPtr->available )
        {
            return (TRUE);
        }
    }
    CmdBufferPtr = CMD_BUFFER_FULL;
    //Command queue is full, send command in next round
    return (FALSE);
}

/*
 * Send 1 command to each BSS in one cycle if queue is not empty
 */
void DispatchNmiCommand(tImpConn *pBssConn)
{
    struct queue *tmpQPtr;
    int HasSent;
    char buf[16]="\0";
    // Command Queue is not empty &&
    // last transaction got response (last_TransId = 0)
    if ((pBssConn->pCmdQ) && (pBssConn->last_TransId == 0L))
    {
        tmpQPtr = pBssConn->pCmdQ;
        HasSent = ProcessUserCommand(pBssConn,tmpQPtr->command, tmpQPtr->TransId);
        sprintf(buf,"HasSent=%d", HasSent);

        /* Update last processed TransId to ImpConn */
        // switch(HasSent)
        //    UPLOAD: upload request and no need to send to BSS
        //    TRUE:   Command successfully send to BSS
        //    FALSE:  Command syntax error and no need to send to BSS
        //
        if (HasSent == UPLOAD)
            pBssConn->last_TransId = 0L;
        else if (HasSent == TRUE)
            pBssConn->last_TransId = tmpQPtr->TransId;
        else
            pBssConn->last_TransId = 0L;

        /* de-queue 1 command from the command queue */
        pBssConn->pCmdQ = tmpQPtr->nextcmd;
        tmpQPtr->nextcmd = (struct queue *)0;
        tmpQPtr->available = TRUE;

        if (!pBssConn->pCmdQ)   /* Command Queue empty */
        {
            pBssConn->pCmdQEnd = (struct queue *) 0;
        }

        /* Overflow in the last round */
        if (CmdBufferPtr == CMD_BUFFER_FULL)
            FindAvailCmdBufferPtr();
    }
}

void CheckMarshalStatus(tNMSTAT NmStat)
{
    if (NmStat != NMSTAT_SUCCESS)
    {
        MsgError = TRUE;
    }
}

//Caller: SetCommand,GetCommand
static void MarshalAttribute(tImpConn * pBssConn, char *pChars)
{
      tNMSTAT NmStat;
      int   i=0;
      char *p;
	  char tmp[6];
      tCID Cid = 0;
      u8   AttrNum = 0;
      //test begin
	  if(!strncasecmp(pChars,"Adminstate",10))
      strcpy(pChars,"1:0");
	  if(!strncasecmp(pChars,"DownLoadInProgress",18))
	  strcpy(pChars,"8:4");
	  if(!strncasecmp(pChars,"Label",5))
		  strcpy(pChars,"0:2");
	  //test end
      if(pBssConn->TheCid != (tCID) -1){
	        i = strcspn(pChars,":");
		    strncpy(tmp,pChars,i);
            Cid = atoi(tmp);
            p = strpbrk(pChars,":");
            AttrNum = atol(++p);
	  }
       NmStat = NmMarshalAttrId(&pSendBody,(tCID) Cid,(u8) AttrNum);
       CheckMarshalStatus(NmStat);
}
//Caller: CreateCommand,DeleteCommand
int MarshalClsId(char *pImpCmdContName)
{
    tNMSTAT NmStat;
    tCID Cid;
    Cid = (tCID)GetCid(pImpCmdContName);
    if (*pImpCmdContName != '\0') {
        NmStat = NmMarshalClassId(&pSendBody, (tCID) Cid);
        CheckMarshalStatus(NmStat);
    } else {
        MsgError = TRUE;
    }
    return (TRUE);
}
int MarshalNum(u32 * pImpCmdIndex)
{
    tNMSTAT NmStat;
    NmStat = NmMarshalU32(&pSendBody, (u32) *pImpCmdIndex);
    CheckMarshalStatus(NmStat);
    return (TRUE);
}
/*
  Clear the old sendbody
*/
int MsgReset()
{
    MsgError = FALSE;
    pSendBody = MsgSendBody;
    return (TRUE);
}
/*
   Send IMP Message
*/
static void SendImpMsg(u16 Op, u32 TransId, tImpConn * pBssConn)
{
    bool Status = TRUE;
    tNMSTAT NmStat;
    tIMPHDR Hdr;
    u8 *pBuf;
    int HdrLen;
    int BodyLen;
    int Len;

    NmStat = NmMarshalEndOfMsg(&pSendBody, (u32) 0, FALSE);
    CheckMarshalStatus(NmStat);
    memset((char *) (&Hdr), (char) 0, sizeof(tIMPHDR));
    Hdr.OpCode = Op;
    OidCopy(&Hdr.ObjId, &(pBssConn->TheOid));

    /* reset Sequence no when it reachs max of u32 */
    if ( pBssConn->SeqNum == 0xffffffff ) {
        pBssConn->SeqNum = 0L;
    }
    Hdr.Seq = ++(pBssConn->SeqNum);
    Hdr.TransId1 = TransId;
    Hdr.Link = 0x0101;        /* one of one , no fragmentation */
    BodyLen = (int) (pSendBody - MsgSendBody);
    Hdr.RespBodyLen = (tNMLEN) BodyLen;
    pBuf = MsgSendBuffer;
    NmStat = NmMarshalImpHeader(&pBuf, &Hdr);
    CheckMarshalStatus(NmStat);
    if (!MsgError) {
        HdrLen = (int) (pBuf - MsgSendBuffer);
        Len = HdrLen + BodyLen;
        
        bcopy((char *) MsgSendBody, (char *) pBuf, BodyLen);
        
        if (write(pBssConn->sockfd, (char *) MsgSendBuffer, Len) < Len) {
            
            Status = FALSE;
        }
    }
}

int OidCommand(tImpConn * pBssConn,char *pImpCmdContName, u32 *pImpCmdIndex, ix ImpCmdIndexCount, u32 TransId)
{
    int i;
	tNMSTAT NmStat;
    tOid TempOid = OID_INIT;
    MsgError = FALSE;
    pTempOidSymCont = (char *) 0;

    pTempOidSymCont = pImpCmdContName;//cmd string
    if (pTempOidSymCont == (char *)0)
    {
        MsgError = TRUE;
    }
    else
    {
        for (i = 0; i < ImpCmdIndexCount; i++)
        {
            TempOid.Ix[i] = *(pImpCmdIndex++);
        }
        TempOid.IxCnt = ImpCmdIndexCount;
    	TempOid.ContId = GetOid(pTempOidSymCont);
        if ( TempOid.ContId == NM_CONTID_UNDEFINED )
        {
            MsgError = TRUE;
        }
    }

    if (!MsgError)
    {
        OidCopy(&(pBssConn->TheOid), &TempOid);
        MsgReset();
        NmStat = NmMarshalAttrId(&pSendBody, 0, 0);
        if (NmStat == NMSTAT_SUCCESS) {
        SendImpMsg(IMP_MSG_GET_REQ, TransId, pBssConn);
        } 
        return (TRUE);
    }
    else
    {
        return (FALSE);
    }
}

/*
 * pImpCmd is the pointer to the nmi commandline string
 * Incoming message format must be:
 * get Attribute, Attribute ...
 * e.g.
 *    get Cellallocation Label CellIdentity
 */
int GetCommand(tImpConn * pBssConn, char *pImpCmd, u32 TransId)
{
    int SetState=0;
    int errpos=0;
    int nextstage = 1;
    char StrBuffer[1024];
    char *pStrBuffer;

    MsgReset();
    if (*pImpCmd == '\0')
    {
	nextstage = 0;
    }
    else if (*pImpCmd == ' ')
    {
        pImpCmd++;
        SetState = GET_READ_ATTRIB;
    }
    else
    {
        errpos=10;
        MsgError=1;
	nextstage = 0;
    }

    while (nextstage)
    {
        switch (SetState) {
		case GET_READ_ATTRIB:
            /* Get the Attrib value */
            pStrBuffer = StrBuffer;
            while (isalnum(*pImpCmd) || (*pImpCmd == '_')) {
                *pStrBuffer = *pImpCmd;
                pStrBuffer++;
                pImpCmd++;
            }
            *pStrBuffer = '\0';
            if ((*pImpCmd != ' ') && (*pImpCmd != '\t') && (*pImpCmd != '\0')) {
                errpos = 1;
                MsgError = 1;
                nextstage = 0;
            }
            SetState = GET_ATTRIB_END;
            break;
        case GET_ATTRIB_END:
            MarshalAttribute(pBssConn, StrBuffer);
            if ((*pImpCmd == ' ') || (*pImpCmd == '\t')) {
                pImpCmd++;
                SetState = GET_READ_ATTRIB;
            } else if (*pImpCmd == '\0') {
                nextstage = 0;
            } else {
                errpos = 2;
                MsgError = 1;
                nextstage = 0;
            }
            break;
        default:
            errpos = 3;
            MsgError = 1;
            nextstage = 0;
            break;
	}
    }

    if (!MsgError) {
        SendImpMsg(IMP_MSG_GET_REQ, TransId, pBssConn);
        return (TRUE);
    } else {
        return (FALSE);
    }
}

/*
 * pImpCmd is the pointer to the  command string
 * Incoming message format must be:
 * Attribute = [IntArray|Int] ...
 * e.g.
 *    Cellallocation=[0=1 1=84] Label="BTS1" CellIdentity=24837
 */
int SetCommand(tImpConn * pBssConn, char *pImpCmd, u32 TransId)
{
    tARs32 NumArray[MAX_ARRAY_LENGTH];
    ix NumArrayLength = 0;
    ix NumArrayIx;

    int errpos = 0;
    int SetState = SET_READ_ATTRIB;
    int nextstage = 1;
    char StrBuffer[1024]="\0";
    char *pStrBuffer;
    
    MsgReset();
    do {
        switch (SetState) {
        case SET_READ_ATTRIB:

            /* Get the Attrib value */
            pStrBuffer = StrBuffer;
           while (isalnum(*pImpCmd) || (*pImpCmd == '_') || (*pImpCmd == ':')) {
                *pStrBuffer = *pImpCmd;
                pStrBuffer++;
                pImpCmd++;
            }
            *pStrBuffer = '\0';
            if (*pImpCmd != '=') {
                errpos = 1;
                MsgError = 1;
                nextstage = 0;
            }
            SetState = SET_ATTRIB_END;
            break;
        case SET_ATTRIB_END:

            MarshalAttribute(pBssConn, StrBuffer);//Get AttrId
            ++pImpCmd;
            if (isdigit(*pImpCmd) || (*pImpCmd == '-')) {
                SetState = SET_READ_INT;
                break;
            } else if (*pImpCmd == '[') {
                SetState = SET_READ_INTARRAY;
                pImpCmd++;
                break;
            } else if (*pImpCmd == '"') {
                SetState = SET_READ_STRING;
                pImpCmd++;
                break;
            }
            errpos = 2;
            MsgError = 1;
            nextstage = 0;
            break;
        case SET_READ_INT:

            pStrBuffer = StrBuffer;
            while (isdigit(*pImpCmd) || (*pImpCmd == '-')) {
                *pStrBuffer = *pImpCmd;
                pStrBuffer++;
                pImpCmd++;
            }
            *pStrBuffer = '\0';
            SetState = SET_INT_END;
            break;
        case SET_INT_END:

            CheckMarshalStatus(NmMarshalU32(&pSendBody, atol(StrBuffer)));
            if (*pImpCmd == ' ') {
                SetState = SET_READ_ATTRIB;
                pImpCmd++;
            } else if (*pImpCmd == '\0') {
                nextstage = 0;
            } else {
                errpos = 3;
                MsgError = 1;
                nextstage = 0;
            }
            break;
        case SET_READ_STRING:

            pStrBuffer = StrBuffer;
           while (isprint(*pImpCmd) && (*pImpCmd != '"')) {
                *pStrBuffer = *pImpCmd;
                pStrBuffer++;
                pImpCmd++;
            }
            if (*pImpCmd == '"') {

                *pStrBuffer = '\0';
                SetState = SET_STRING_END;
            } else {
                errpos = 4;
                MsgError = 1;
                nextstage = 0;
            }
            break;
        case SET_STRING_END:

            CheckMarshalStatus(NmMarshalString(&pSendBody, StrBuffer));
            ++pImpCmd;
            if (*pImpCmd == ' ') {
                SetState = SET_READ_ATTRIB;
                pImpCmd++;
            } else if (*pImpCmd == '\0') {
                nextstage = 0;
            } else {
                errpos = 5;
                MsgError = 1;
                nextstage = 0;
            }
            break;
        case SET_READ_INTARRAY:

            bzero((char *) NumArray, sizeof(NumArray));
            NumArrayLength = 0;
            while (*pImpCmd != ']' && *pImpCmd != '\0')
            {
                /* Decoding [0=2 1=23] format */
                pStrBuffer = StrBuffer;
                while (isdigit(*pImpCmd)) {
                    *pStrBuffer = *pImpCmd;
                    pStrBuffer++;
                    pImpCmd++;
                }
                *pStrBuffer = '\0';
                if (*pImpCmd == '=') {
                    pImpCmd++;
                    NumArrayIx = atol(StrBuffer);
                    pStrBuffer = StrBuffer;
                    while (isdigit(*pImpCmd) || (*pImpCmd == '-')) {
                        *pStrBuffer = *pImpCmd;
                        pStrBuffer++;
                        pImpCmd++;
                    }
                    *pStrBuffer = '\0';
                    NumArray[NumArrayLength].Index = NumArrayIx;
                    NumArray[NumArrayLength].Value = atol(StrBuffer);
                    NumArrayLength++;
                    switch (*pImpCmd) {
                        case ']':
                            SetState = SET_INTARRAY_END;
                            break;
                        case ' ':
                            pImpCmd++;
                            break;
                        default:
                            errpos = 6;
                            MsgError = 1;
                            nextstage = 0;
                            break;
                            /* break the while loop */
                    }
                } else {
                    errpos = 7;
                    MsgError = 1;
                    nextstage = 0;
                    break;
                    /* break the while loop */
                }
            }            /* End_of_while( *pImpCmd */
            break;
        case SET_INTARRAY_END:

            CheckMarshalStatus(NmMarshalARs32(&pSendBody, NumArray,
                              (u16) NumArrayLength));
            ++pImpCmd;
            if (*pImpCmd == ' ') {
                SetState = SET_READ_ATTRIB;
                pImpCmd++;
            } else if (*pImpCmd == '\0') {
                nextstage = 0;
            } else {
                errpos = 8;
                MsgError = 1;
                nextstage = 0;
            }
            break;
        default:
            errpos = 9;
            MsgError = 1;
            nextstage = 0;
            break;
        }   /* End_of_switch */
    } while (nextstage);

    if (!MsgError) {
        SendImpMsg(IMP_MSG_SET_REQ, TransId, pBssConn);
        return (TRUE);
    }
    else
    {
        return (FALSE);
    }
}
/*
 * All Commands accept the following arguments
 *    pImpCmdContName   -- the name of container, action, parameters
 *    pImpCmdIndex      -- u16 array of numeric parameters
 *             e.g oid bts.1.0   OR
 *                 set CellAllocation=[0=1 1=124]
 *    pImpCmdIndexCount -- point to the last valid element of pImpCmdIndex[]
 */
int ActionCommand(tImpConn *pBssConn, char *pImpCmdContName, u32 *pImpCmdIndex,ix ImpCmdIndexCount, u32 TransId)
{
    int i;
    int j = 0;
	char tmp[4];
	char *p;
    tNMSTAT NmStat;
    tCID Cid = 0;
    u8   ActionId = 0;
     MsgReset();
   
	 j = strcspn(pImpCmdContName,":");
		 strncpy(tmp,pImpCmdContName,j);
      Cid = atoi(tmp);
      p = strpbrk(pImpCmdContName,":");
      ActionId = (u8)atoi(++p);
    if (pImpCmdContName != NULL) {
        NmStat = NmMarshalActionId(&pSendBody,
            (tCID) Cid,
            (u8) ActionId);
        CheckMarshalStatus(NmStat);
    } else {
        MsgError = TRUE;
    }
    /* Read Action parameters */
    for (i = 0; i < ImpCmdIndexCount; i++)
    {
        //pParm = pAct->GetParm(i);
        NmStat = NmMarshalU32(&pSendBody, (u32) * pImpCmdIndex++);
        CheckMarshalStatus(NmStat);
    }
    if (!MsgError) {
        SendImpMsg(IMP_MSG_ACTION_REQ, TransId, pBssConn);
        return (TRUE);
    }
    else {
        return (FALSE);
    }
}

int CreateCommand(tImpConn * pBssConn, char *pImpCmdContName,u32 * pImpCmdIndex, u32 TransId)
{

    MsgReset();

    MarshalClsId(pImpCmdContName);
    MarshalNum(pImpCmdIndex);
    if (!MsgError) {
        SendImpMsg(IMP_MSG_CREATE_REQ, TransId, pBssConn);
        return (TRUE);
    }
    else
    {
        return (FALSE);
    }
}

int DeleteCommand(tImpConn * pBssConn, char *pImpCmdContName,u32 * pImpCmdIndex, u32 TransId)
{

    MsgReset();

    MarshalClsId(pImpCmdContName);
    MarshalNum(pImpCmdIndex);
    if (!MsgError) {
        SendImpMsg(IMP_MSG_DELETE_REQ, TransId, pBssConn);
        return (TRUE);
    }
    else
    {
        return (FALSE);
    }
}

int ContentsCommand(tImpConn *pBssConn, u32 TransId)
{
    MsgReset();
    if (!MsgError) {
        SendImpMsg(IMP_MSG_CONTENTS_REQ, TransId, pBssConn);
        return (TRUE);
    }
    else
    {
        return (FALSE);
    }
}
/*
 * 1. Check whether the bssid & IP are in use and 
 * 2. Try to connect to the new bsplus
 * 3. ok  -> update bsplus[] and mysql DB
 *        -> set MeasurementReportInterval
 *        -> send action BtsStatus
 *        -> re-calculate the width of select()
 *    nok -> write error to mysql DB OMCR_COMMAND
 */
void NewBsplus(int bssid, char *ip, u32 TransId)
{
    int i;
    int flag=0;
    int sockfd;
    tImpConn *pBssConn;
    
    for (i=0;i<nbsplus;i++) {
        if ((bsplus[i])->bssid == bssid)
           flag = BSSID_EXIST;
        if (!strcmp((bsplus[i])->ip, ip))
           flag = IP_EXIST;
    }
    for (i=0;i<nbsplus_down;i++)
    {
        if ((bsplus_down[i])->bssid == bssid)
           flag = BSSID_EXIST;
        if (!strcmp((bsplus_down[i])->ip, ip))
           flag = IP_EXIST;
    }
    if (bssid >= no_of_bss_per_pacs)
    {
           flag = BSSID_TOO_BIG;
    }

    if (flag == IP_EXIST)
    {
        update_command_status(
            NMERROR_OBJECT_EXISTS, "object already exists",
            1034, "Duplicate IP address", TransId
        );
        return;
    }
    else if (flag == BSSID_EXIST)
    {
        update_command_status(
            NMERROR_OBJECT_EXISTS, "object already exists",
            1030, "Duplicate BSS ID", TransId
        );
        return;
    }
    else if (flag == BSSID_TOO_BIG)
    {
        update_command_status(
            NMERROR_ATTR_REJECTED, "attr value rejected",
            1029, "Bss Id too big", TransId
        );
        return;
    }

    sockfd = connectIwBox(ip,NMIPORT);
    if (sockfd == -1)
    {
        update_command_status(
            NMERROR_OBJ_UNREACHABLE, "object unreachable",
            1031, "The BSS cannot be reached", TransId
        );
        return;
    }
    /* update ImpConn structure */
    pBssConn = BssConn + bssid;
    pBssConn->bssid = bssid;
    strcpy(pBssConn->ip, ip);
    pBssConn->port          = NMIPORT;
    pBssConn->sockfd        = sockfd;
    pBssConn->connected     = 1;
    pBssConn->last_TransId = 0L;

    InformIwBoxMonitor(pBssConn,ADD);
    update_bsstable_status(pBssConn);

    bsplus[nbsplus] = pBssConn;
    nbsplus++;

    width_change=1;
    /*
     * Remove old command in DB when connection re-established.
     */
    sprintf(sqlstring, "%s%s%s%d%s%ld",
        "UPDATE OMCR_COMMAND SET resultcode=1280,result='New BSS Created'",
        ",responsecode=-1,response=\"\"",
        ",status=0 WHERE status<>0 AND bssid=", pBssConn->bssid,
        " AND seqNum<", TransId
    );

    execute_sql(sqlstring,0);

    update_command_status(
        NMSTAT_SUCCESS,"ok",
        1280, "New BSS Created", TransId
    );
    ProcessUserCommand(pBssConn,"oid EventLog.0.0",(u32) 0);
    ProcessUserCommand(pBssConn,"action 64:1",(u32) 0);//tst
}
/*
 * 1. Check whether the bssid & IP is existed
 * 2. yes -> update bsplus[] or bsplus_down depends on whether connected
 *        -> delete the entry from OMCR_BSSTABLE
 *        -> delete its presence in OMCR_BSSTREE
 *        -> cancel its entry in monitoring program
 *        -> re-calculate the width of select()
 *    no  -> write error to mysql DB OMCR_COMMAND
 */
void DropBsplus(int bssid, char *ip, u32 TransId)
{
    int i;
    tImpConn **bssArray;
    int *nbssArray;
    tImpConn *pBssConn = BssConn + bssid;

    if (strcmp(pBssConn->ip, ip))
    {
        update_command_status(
            NMERROR_OBJECT, "no such object",
            1032,"The IP address is not found in the system", TransId
        );
        return;
    }

    InformIwBoxMonitor(pBssConn,DEL);

    if (pBssConn->connected > 0)
    {
        bssArray = bsplus;
        nbssArray = &nbsplus;
    }
    else
    {
        bssArray = bsplus_down;
        nbssArray = &nbsplus_down;
    }

    for (i=0;i<*nbssArray;i++)
    {
        if ((bssArray[i])->bssid == bssid)
        {
            bssArray[i] = bssArray[*nbssArray-1];
            (*nbssArray)--;
            break;
        }
    }
    /*
     * Delete the entry into OMCR_BSSTABLE and OMCR_BSSTREE(Presence=0)
     */
    sprintf(sqlstring, "%s%s%d",
        "UPDATE OMCR_BSSTABLE SET ip='',name='',remark='',connected=0,alarmed=0,uploaded=0",
        " WHERE bssid=", pBssConn->bssid
    );
    execute_sql(sqlstring,0);
    sprintf(sqlstring, "%s%s%d",
        "UPDATE OMCR_BSSTREE SET Presence=0,MaxSeverity=0",
        " WHERE bssid=", pBssConn->bssid
    );
    execute_sql(sqlstring,0);

    //
    // clear all relevant alarm
    sprintf(sqlstring, "%s%s%d",
        "UPDATE OMCR_ALARMEVENT SET Severity=0,ClearTime=NOW()",
        " WHERE bssid=", pBssConn->bssid
    );
    execute_sql(sqlstring,0);

    // update OMCR_BSSTABLE for the deletion
    update_command_status(
        0, "0",
        1281,"BSS is deleted", TransId
    );

    initImpConn(pBssConn);
    width_change=1;
}

int AddDropBsplusCommand(char *pImpCmd, int action, u32 TransId)
{
    int i;
    int bssid=0;
    char ip[16]="\0";
    int nextstage=1;
    int State=READ_BSSID;

    MsgError=FALSE;
    do
    {
        switch(State)
        {
            case READ_BSSID://read bssid
                while (isdigit(*pImpCmd))
                {
                    bssid = bssid * 10 + *pImpCmd - '0';
                    pImpCmd++;
                }
                State=READ_BSSID_END;
                break;
            case READ_BSSID_END:
                if ((*pImpCmd != ' ') && (*pImpCmd != '\t'))
                {
                    MsgError = TRUE;
                    nextstage=0;
                }
                while ((*pImpCmd == ' ') || (*pImpCmd == '\t'))
                {
                    pImpCmd++;
                }
                State=READ_IP;
                break;
            case READ_IP://read ip
                for(i=0; i<16; i++)
                {
                    if (isdigit(*pImpCmd) || (*pImpCmd == '.'))
                        ip[i] = *pImpCmd++;
                    else
                        break;
                }
                ip[i] = '\0';
                State=READ_IP_END;
                break;
            case READ_IP_END:
                if (*pImpCmd != '\0')
                    MsgError=TRUE;
                nextstage=0;
                break;
            default:
                break;
        }
    } while (nextstage);

    if (!MsgError)
    {
        if (action == NEWBSS)
            NewBsplus(bssid,ip,TransId);
        else if (action == DROPBSS)
            DropBsplus(bssid,ip,TransId);
        return (TRUE);
    }
    else
    {
        return (FALSE);
    }
}

int CommandType(char *pCmd)
{
    if (!strcasecmp(pCmd, "set")) {
        return (SET);
    }
    if (!strcasecmp(pCmd,"oid")) {
        return (OID);
    }
    if (!strcasecmp(pCmd,"get")) {
        return (GET);
    }
    if (!strcasecmp(pCmd,"contents")) {
        return (CONTENTS);
    }
    if (!strcasecmp(pCmd,"create")) {
        return (CREATE);
    }
    if (!strcasecmp(pCmd,"action")) {
        return (ACTION);
    }
    if (!strcasecmp(pCmd,"delete")) {
        return (DELETE);
    }
    if (!strcasecmp(pCmd, "newbss")) {
        return (NEWBSS);
    }
    if (!strcasecmp(pCmd, "dropbss")) {
        return (DROPBSS);
    }
    if (!strcasecmp(pCmd, "upload")) {
        return (UPLOAD);
    }
    return (BSSERROR);
}

/*
 *  State changes: READ_CMD ------------------------------> READ_END
 *                        `--> READ_OBJECT ---------------> READ_END
 *                                      `--> READ_PARMS --> READ_END
 */
int ProcessCommandString(char *pCommandString,char *pObjName, u32 *pParameter, int *count)
{
    char delimiter=' ';
    char Cmd[]="1234567890";
    int  State=READ_CMD;
    char *pStr=pCommandString;
    char *pCmd=Cmd;
    char *pObj=pObjName;
    u32  *pParam=pParameter;
    char Num[]="1234567890";
    char *pNum=NULL;
    int  op=BSSERROR;

    *count=0;
    *pObj='\0';

    while (State != READ_END)
    {
        switch (State) {
        case READ_CMD:
            while ( isalpha(*pStr) )  /* valid cmd: oid,set,contents,get ...*/
            {
                *pCmd = tolower(*pStr);
                pStr++;
                pCmd++;
            }
            *pCmd='\0';
            op=CommandType(Cmd);
            switch (op)
            {
                case SET:
                case NEWBSS:
                case DROPBSS:
                case UPLOAD:
                    if (*pStr++ != ' ') return (BSSERROR-1);
                    if (!isalnum(*pStr)) return (BSSERROR-2);
                    return (op);
                    break;
                case GET:
                    if ((*pStr != '\0') && (*pStr != ' ') && (*pStr != '\t')) return (BSSERROR-3);
                    return (op);
                    break;
                case CONTENTS:
                    if (*pStr != '\0') return (BSSERROR-3);
                    return (op);
                    break;
                case OID:
                    delimiter = '.';
                case ACTION:
                case CREATE:
                case DELETE:
                    if (*pStr != ' ') return (BSSERROR-4);
                    State=READ_OBJECT;
                    break;
                default:
                    return (BSSERROR-5);
                    break;
            }
            pStr++;
            break;
        case READ_OBJECT:
            while ( isalnum(*pStr) || (*pStr == '_') || (*pStr == ':')) {
                *pObj = *pStr;
                pStr++;
                pObj++;
            }
            *pObj='\0';
    
            if (*pStr == delimiter) {
                State=READ_PARMS;
            } else if (*pStr == '\0') {
                State=READ_END;
            } else {
                return (BSSERROR-6);
            }
            pStr++;
            break;
        case READ_PARMS:
            pNum=Num;
            while( isdigit(*pStr) || (*pStr == '-')) {
                *pNum = *pStr;
                pNum++;
                pStr++;
            }
            if (*pStr == '\0') {
                State=READ_END;
            } else if (*pStr != delimiter ) {
                return (BSSERROR-7);
            }
            *pNum='\0';

            *pParam=atol(Num);
    
            pStr++;
            pParam++;
            ++(*count);
            break;
        default:
            return (BSSERROR-8);
            break;
        } /* End_of_switch (State */
    }     /* End_of_while (State */
    return (op);
}

/*
 * If the input command is not in correct format, update database with error
 * Support:
 *   1. standard imp command -- oid,get,set,create,delete,action
 *   2. newbss/dropbss <bssid> <ipaddress>
 *   3. upload
 */
int ProcessUserCommand(tImpConn *pBssConn, char *pCommandString, u32 TransId)
{
    int action;
    int cnt;
    int NoError;
    char pObjName[80]="";
    u32 Parameter[] = {
        (u32)0, (u32)0, (u32)0, (u32)0, (u32)0, (u32)0, (u32)0, (u32)0,
        (u32)0, (u32)0, (u32)0, (u32)0, (u32)0, (u32)0, (u32)0, (u32)0,
        (u32)0, (u32)0, (u32)0, (u32)0, (u32)0, (u32)0, (u32)0, (u32)0,
        (u32)0, (u32)0, (u32)0, (u32)0, (u32)0, (u32)0, (u32)0, (u32)0
    };

    action = ProcessCommandString(pCommandString,
                pObjName,Parameter,&cnt);

    switch(action)
    {
        case SET:
            NoError=SetCommand(pBssConn, pCommandString + 4, TransId);
            break;
        case GET:
            NoError=GetCommand(pBssConn, pCommandString + 3, TransId);
            break;
        case CONTENTS:
            NoError=ContentsCommand(pBssConn, TransId);
            break;
        case OID:
            NoError=OidCommand(pBssConn, pObjName, Parameter, cnt, TransId);
            break;
        case ACTION:
            NoError=ActionCommand(pBssConn,pObjName,Parameter,cnt, TransId);
            break;
        case CREATE:
            NoError=CreateCommand(pBssConn,pObjName,Parameter, TransId);
            break;
        case DELETE:
            NoError=DeleteCommand(pBssConn,pObjName,Parameter, TransId);
            break;
        case NEWBSS:
            NoError=AddDropBsplusCommand(pCommandString + 7, action, TransId);
            return(NoError);
            break;
        case DROPBSS:
            NoError=AddDropBsplusCommand(pCommandString + 8, action, TransId);
            return(NoError);
            break;
        case UPLOAD:
            NoError=requestBssCfg(pBssConn);
            pBssConn->upload_TransId=TransId;
            /*if (NoError)
            {
                update_command_status(
                    NMSTAT_SUCCESS,"ok",
                    1282,"Upload command is sent", TransId
                );
            }
            else*/
            if (!NoError)
            {
                update_command_status(
                    1283, "failure w/o error",
                    1283,"Upload command is failed", TransId
                );
            }
            syncBssTreeAlarm();
            return(UPLOAD);        
            break;
        default:
            NoError=FALSE;
            break;
    } /* End_of_switch */

    if (!NoError && TransId>0)
    {
        sprintf(response,"Command Syntax error:%s", pCommandString);
        update_command_status(
            NMERROR_BAD_MESSAGE, "unreadable message",
            1033,response, TransId
        );
    }
    return(NoError);
}
/*
 * This routine does:
 * 1. Wait for BSS started for 120 sec 
 * 2. Get Bss Object Tree
 * 3. Sync Clock
 * 4. Get missing Events by "Action GetEvents"
 */
unsigned int imp_response(tImpConn *pBssConn, tIMPHDR *pHeader,char *response)
{
    unsigned int retval=0;
    u16 Op = pHeader->OpCode;
	int Cid = -1;
    char ObjectName[MAX_OBJECTID_LEN]="\0";
    char id[3]="\0";
    int i;
    /*
     * connected=1
     *   - just connected and do "action BtsStatus" under EventLog.0.0
     *   - Retrieve the time from BtsStatus
     *   - syncBssTime()
     *   - Wait "wait_interval" seconds and requestBssCfg
     *   - set connected = CONNECTED_STATE_MAX
     */
    switch (pBssConn->connected)
    {
        case 1: /* 1 = just connected */
                break;
        case CONNECTED_STATE_MAX:
                /* Download Parameter */
                if (Op == IMP_MSG_SET_RESP)
                {
                    if (pBssConn->TheCid == (tCID) 8)//BssFunc
      			    {
                        if (!strncmp(response,"8:4=0",20))
                        {
                            pBssConn->download_in_progress = 0;
                        }
                        else if (!strncmp(response,"8:4=1",20))//DownLoadInProgress
                        {
                            pBssConn->download_in_progress = 1;
                        }
                        ///* return because we don't have OMCR_BssFunc Table */
                        //return (retval);
                    }
                }
                /* During downloading, do not update OMC database */
                if (pBssConn->download_in_progress == 1)
                        return (retval);

                if ((Op==IMP_MSG_GET_RESP) || (Op==IMP_MSG_SET_RESP))
                {
                    /* Oid response is also GET_RESP */
                    updateBssCfg(pBssConn,pHeader,response);//write the responsed data to MySQL
                }
                else if ((Op==IMP_MSG_CREATE_RESP) || (Op==IMP_MSG_DELETE_RESP))//create delete
                {
                    sscanf(response,"%s %s",ObjectName,id);//read response
					Cid = atoi(ObjectName);
					if(SetCidStr(Cid,ObjectName)){
						if (!strncmp(ObjectName, "BtsMgr", 6))//BtsMgr
							pBssConn->current_upload_level=0;
						else
							pBssConn->current_upload_level=1;
						for(i=0;i<(pHeader->ObjId).IxCnt;i++){
			                sprintf(ObjectName,"%s.%d",ObjectName,(pHeader->ObjId).Ix[i]);
			                pBssConn->current_upload_level++;
			            }
			            
			            sprintf(ObjectName,"%s.%s",ObjectName,id);
			            pBssConn->current_upload_level++;
                        
                         requestObjCfg(pBssConn, ObjectName,0);
                         requestChildCfg(pBssConn,ObjectName);
					}
                }
                break;
        default:
                break;
    }
    return (retval);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void ProcessCreateDeleteBody(u8** ppBuf,char *strValue, u16 *intValue)
{
    tNMSTAT NmStat;
    tCID    Cid;
    u16     Index;

    if ((NmStat = NmUnMarshalClassId(ppBuf, &Cid)) != NMSTAT_SUCCESS)
    {
		perror("class id error!\n");
    }
    else if ((NmStat = NmUnMarshalU16(ppBuf, &Index)) != NMSTAT_SUCCESS)
    {
		perror("index error!\n");
    }
    else 
    {
        *intValue=Index;
        sprintf(strValue,"%d",Cid);
    }
}

static tNMSTAT ProcessNullType(u8** ppBuf, char *strValue)
{
    tNMSTAT    NmStat;

    if ((NmStat = NmUnMarshalNull(ppBuf)) == NMSTAT_SUCCESS)
    {
		strcpy(strValue,"*NULL*");
    }
    return (NmStat);
}

static tNMSTAT ProcessIntType(u8** ppBuf, tCID Cid, u8 AttrNum,char *strValue)
{
    tNMSTAT    NmStat;
    s32        Val;

    if ((NmStat = NmUnMarshalS32(ppBuf, &Val)) == NMSTAT_SUCCESS)
    {
		if((Cid !=(tCID)(-1))&&(AttrNum !=(u8)(-1)))
                 sprintf(strValue,"%ld",Val);
    }
    return (NmStat);
}


static tNMSTAT ProcessIntArrayType(u8** ppBuf)
{
    tNMSTAT  NmStat;
    u16      ArrayLen;

    if ((NmStat = NmUnMarshalArrayS32(ppBuf, ValArray, &ArrayLen,
        MAX_ARRAY_LENGTH)) == NMSTAT_SUCCESS)
    {
            lenOfArray = ArrayLen;
    }
    return (NmStat);
}

static tNMSTAT ProcessIntArIxType(u8** ppBuf)
{
    tNMSTAT NmStat;
    u16     ArrayLen;

    if ((NmStat = NmUnMarshalARs32(ppBuf, s32Array, &ArrayLen,
        MAX_ARRAY_LENGTH)) == NMSTAT_SUCCESS)
    {
            lenOfArray = ArrayLen;
    }
    return (NmStat);
}

static tNMSTAT ProcessStringType(u8** ppBuf, char *strValue)
{
    tNMSTAT    NmStat;
    char*    pChars = (char*)0;

    if ((NmStat = NmUnMarshalString(ppBuf, &pChars)) == NMSTAT_SUCCESS)
    {
        sprintf(strValue,"\"%s\"",pChars);
    }
    if (pChars != (char*)0)
    {
        free(pChars);
    }
    return (NmStat);
}

static tNMSTAT ProcessOidType(u8** ppBuf, char *strValue)
{
    tNMSTAT NmStat;
    tOid    OidVal;
     num    ContId;
     u16    Index;
     u16    EndIx;
    if ((NmStat = NmUnMarshalObjectId(ppBuf, &OidVal)) == NMSTAT_SUCCESS)
    {
      ContId = (num)OidVal.ContId;
      EndIx = OidVal.IxCnt;
      sprintf(strValue,"%d",ContId);
      strValue+=strlen(strValue);
      for(Index=0;Index<EndIx;Index++)
      {  sprintf(strValue,".%d",OidVal.Ix[Index]);
	    strValue+=strlen(strValue);  
      }
    }
    return (NmStat);
}

static tNMSTAT ProcessCidType(u8** ppBuf, bool IsClassId,char *strValue, tImpConn *pBssConn)
{
    tNMSTAT NmStat;
    tCID    CidVal;

    if ((NmStat = NmUnMarshalClassId(ppBuf, &CidVal)) == NMSTAT_SUCCESS)
    {
        sprintf(strValue,"%d",CidVal);
        if (IsClassId)
        {
            pBssConn->TheCid = CidVal;
        }
    }
    return (NmStat);
}

static void ProcessUnknownType(u8** ppBuf)
{
    u8    Tag;
    Tag = **ppBuf;
    NmSkipImpField(ppBuf);
}

static void ProcessContentsBody(u8** ppBuf, char *response)
{
    tNMSTAT    NmStat;
    tCID       Cid;
    char       comma[2]="";

    if ((NmStat = NmUnMarshalClassId(ppBuf, &Cid)) != NMSTAT_SUCCESS)
    {
        if ((**ppBuf & IMP_TYPE_MASK) != IMP_TYPE_END_OF_MSG)
        {;
        }
    }
    else
    {
        response[0]='\0';
        while ((**ppBuf & IMP_TYPE_MASK) == IMP_TYPE_CLASS_ID)
        {
            ProcessCreateDeleteBody(ppBuf, strValue, &intValue);//get classid and index
            sprintf(response,"%s%s%s %d", response, comma, strValue, intValue);
            comma[0]=',';
            comma[1]='\0';
        }
    }
}

static void ProcessSetGetBody(tImpConn *pBssConn, u8** ppBuf, char *response,u16 *responsecode, bool HasStatus)
{
    bool    Processing = TRUE;
    tNMSTAT NmStat;
    tCID    Cid;
    u8      AttrNum;
    u8      Tag;
    tNMSTAT VarStat;
    char    comma[2]="";
    int     i;

    response[0] = '\0';
    while (Processing && ((**ppBuf & IMP_TYPE_MASK) == IMP_TYPE_ATTR_ID))
    {
        if ((NmStat = NmUnMarshalAttrId(ppBuf, &Cid, &AttrNum)) !=
            NMSTAT_SUCCESS)
        {
            break;
        }
        sprintf(response,"%s%s%d:%d",response, comma, Cid, AttrNum);
        
        Tag = **ppBuf;
        switch (Tag & IMP_ARRAY_TYPE_MASK)
        {
          case IMP_TYPE_NULL:
            if (ProcessNullType(ppBuf, strValue) != NMSTAT_SUCCESS)
            {
                Processing = FALSE;
            }
            else
            {
                sprintf(response,"%s=%s",response,strValue);
            }
            break;
          case IMP_TYPE_UINT:
          case IMP_TYPE_SINT:
            if (ProcessIntType(ppBuf, Cid, AttrNum, strValue) !=
                NMSTAT_SUCCESS)
            {
                Processing = FALSE;
            }
            else
            {
                sprintf(response,"%s=%s",response,strValue);
            }
            break;
          case IMP_ARRAY_UINT:
          case IMP_ARRAY_SINT:
            if (ProcessIntArrayType(ppBuf) != NMSTAT_SUCCESS)
            {
                Processing = FALSE;
            }
            else
            {
                sprintf(response,"%s_0=%ld",response,ValArray[0]);
                for (i=1; i<lenOfArray; i++)
                    sprintf(response,"%s,%d:%d_%d=%ld",
                        response,Cid,AttrNum,i,ValArray[i]);
            }
            break;
          case IMP_ARRAY_IX_UINT:
          case IMP_ARRAY_IX_SINT:
            if (ProcessIntArIxType(ppBuf)
                != NMSTAT_SUCCESS)
            {
                Processing = FALSE;
            }
            else
            {
                sprintf(response,"%s_%d=%ld",
                    response,(int)s32Array[0].Index, s32Array[0].Value);
                for (i=1; i<lenOfArray; i++)
                    sprintf(response,"%s,%d:%d_%d=%ld", response, Cid,AttrNum,
                        (int)s32Array[i].Index, s32Array[i].Value);
            }
            break;
          case IMP_ARRAY_CHAR_STRING:
            if (ProcessStringType(ppBuf, strValue) != NMSTAT_SUCCESS)
            {
                Processing = FALSE;
            }
            else
            {
                sprintf(response,"%s=%s",response,strValue);
            }
            break;
          case IMP_ARRAY_OBJECT_ID:
            if (ProcessOidType(ppBuf, strValue) != NMSTAT_SUCCESS)
            {
                Processing = FALSE;
            }
            else
            {
                sprintf(response,"%s=%s",response,strValue);
            }
            break;
          case IMP_TYPE_CLASS_ID:
            if (ProcessCidType(ppBuf, ((Cid == 0) && (AttrNum == 0)),
                strValue, pBssConn) != NMSTAT_SUCCESS)
            {
                Processing = FALSE;
            }
            else
            {
                sprintf(response,"%s=%s",response,strValue);
            }
            break;
          case IMP_TYPE_ATTR_ID:
          case IMP_TYPE_END_OF_MSG:
            // Must be a get request that failed to return values.
            //
            continue;
          default:
            ProcessUnknownType(ppBuf);
            break;
        }
        if (HasStatus && Processing &&
            ((**ppBuf & IMP_TYPE_MASK) == IMP_TYPE_STATUS_CODE))
        {
            if ((NmStat=NmUnMarshalStatusCode(ppBuf,&VarStat))!=NMSTAT_SUCCESS)//StatueCode
            {
                break;
            }
            if (VarStat != NMSTAT_SUCCESS)
            {
                sprintf(response,"%d",VarStat);
                if (responsecode != NULL)
                    *responsecode=VarStat;
            }
        }   /* End_of_switch (Tag */

        comma[0] = ',';
        comma[1] = '\0';
    } /* End_of_while (Proc */
}

static void ProcessActionParms(tImpConn *pBssConn, u8** ppBuf, char *response)
{
    bool    Processing = TRUE;
    tNMSTAT NmStat;
   
    char    ParmNum[]="ParaNum";
    u8      Tag;
    tNMSTAT VarStat;
    int     i;

    while (Processing && ((**ppBuf & IMP_TYPE_MASK) != IMP_TYPE_END_OF_MSG))
    {
		
        sprintf(response,"%s,%s", response, ParmNum);
        
        Tag = **ppBuf;
        switch (Tag & IMP_ARRAY_TYPE_MASK)
        {
          case IMP_TYPE_NULL:
            if (ProcessNullType(ppBuf, strValue) != NMSTAT_SUCCESS)
            {
                Processing = FALSE;
            }
            else
            {
                sprintf(response,"%s=%s",response,strValue);
            }
            break;
          case IMP_TYPE_UINT:
          case IMP_TYPE_SINT:
            if (ProcessIntType(ppBuf, 0, 0, strValue) !=
                NMSTAT_SUCCESS)
            {
                Processing = FALSE;
            }
            else
            {
                sprintf(response,"%s=%s",response,strValue);
            }
            break;
          case IMP_ARRAY_UINT:
          case IMP_ARRAY_SINT:
            if (ProcessIntArrayType(ppBuf)
                != NMSTAT_SUCCESS)
            {
                Processing = FALSE;
            }
            else
            {
                sprintf(response,"%s_0=%ld",response,ValArray[0]);
                for (i=1; i<lenOfArray; i++)
                    sprintf(response,"%s,%s_%d=%ld",
                        response,ParmNum,i,ValArray[i]);
            }
            break;
          case IMP_ARRAY_IX_UINT:
          case IMP_ARRAY_IX_SINT:
            if (ProcessIntArIxType(ppBuf)
                != NMSTAT_SUCCESS)
            {
                Processing = FALSE;
            }
            else
            {
                sprintf(response,"%s_%d=%ld",
                    response,(int)s32Array[0].Index, s32Array[0].Value);
                for (i=1; i<lenOfArray; i++)
                    sprintf(response,"%s,%s_%d=%ld", response, ParmNum,
                        (int)s32Array[i].Index, s32Array[i].Value);
            }
            break;
          case IMP_ARRAY_CHAR_STRING:
            if (ProcessStringType(ppBuf,strValue) != NMSTAT_SUCCESS)
            {
                Processing = FALSE;
            }
            else
            {
                sprintf(response,"%s=%s",response,strValue);
            }
            break;
          case IMP_ARRAY_OBJECT_ID:
            if (ProcessOidType(ppBuf,strValue) != NMSTAT_SUCCESS)
            {
                Processing = FALSE;
            }
            else
            {
                sprintf(response,"%s=%s",response,strValue);
            }
            break;
          case IMP_TYPE_CLASS_ID:
            if (ProcessCidType(ppBuf, 0,
                strValue, pBssConn) != NMSTAT_SUCCESS)
            {
                Processing = FALSE;
            }
            else
            {
                sprintf(response,"%s=%s",response,strValue);
            }
            break;
          case IMP_TYPE_END_OF_MSG:
            Processing = FALSE;
            break;
          default:
            ProcessUnknownType(ppBuf);
            break;
        }

        if (Processing && ((**ppBuf & IMP_TYPE_MASK) == IMP_TYPE_STATUS_CODE))
        {
            if ((NmStat = NmUnMarshalStatusCode(ppBuf, &VarStat)) !=
                NMSTAT_SUCCESS)
            {    
                break;
            }
            
        }//end if
        
    }
}
static void ProcessActionBody(tImpConn *pBssConn, u8** ppBuf,char *response)
{
    tNMSTAT   NmStat;
    tCID      ClassId;
    u8        ActionId;

    response[0] = '\0';
    if ((**ppBuf & IMP_TYPE_MASK) == IMP_TYPE_ACTION_ID)
    {
        NmStat = NmUnMarshalActionId(ppBuf, &ClassId, &ActionId);
        if (NmStat == NMSTAT_SUCCESS)
        {
           
            if (pBssConn->TheCid != (tCID)-1)
            {   
                    sprintf(response,"action %d.%d",ClassId,ActionId);
            }
        }
		// Now process the parameter values and their statuses.
        //
        ProcessActionParms(pBssConn, ppBuf, response);
    }
}

static void ProcessEventBody(tImpConn *pBssConn, u8** ppBuf,tImpEvent *pBssEvent)
{
      int  i,num=0;
      int  Cid=0;
	  
      u8    Tag = 208;
      u8    AttrNum=0;
	  
      char  attributename[64]="\0";
      bool  ReadingValues = FALSE;
      
    int   size = pBssEvent->eventinfosize;
//	Cid = (int)pBssConn->TheCid;

    ReadingValues = TRUE;
    
    while (ReadingValues == TRUE)
    {
		if (!strcasecmp(pBssEvent->eventname,"BtsMeasurements"))
		{
			if(GetMeasPara(EvCid,Eid,num,attributename))
                num++;
		}
        else
        {
			if(GetEvPara(EvCid,Eid,num,attributename))
				num++;
		}
	    Tag = **ppBuf;
        
        if (ReadingValues)
        {
            switch (Tag & IMP_ARRAY_TYPE_MASK)
            {
              case IMP_TYPE_NULL:
                if (ProcessNullType(ppBuf, strValue) != NMSTAT_SUCCESS)
                {
                    ReadingValues = FALSE;
                }
                else
                {
                    sprintf(pBssEvent->eventinfo[size++], "%s=%s",attributename, strValue);
                }
                break;
              case IMP_TYPE_UINT:
              case IMP_TYPE_SINT:
                if (ProcessIntType(ppBuf, Cid, AttrNum, strValue)!= NMSTAT_SUCCESS)
                {
                    ReadingValues = FALSE;
                }
                else
                {
                    sprintf(pBssEvent->eventinfo[size++], "%s=%s",attributename, strValue);
                }
                break;
              case IMP_ARRAY_UINT:
              case IMP_ARRAY_SINT:
                if (ProcessIntArrayType(ppBuf) != NMSTAT_SUCCESS)
                {
                    ReadingValues = FALSE;
                }
                else
                {
                    for (i=0; i<lenOfArray; i++)
                    {
                        sprintf(pBssEvent->eventinfo[size++],"%s_%d=%ld",attributename,i,ValArray[i]);
                    }
                }
                break;
              case IMP_ARRAY_CHAR_STRING:
                if (ProcessStringType(ppBuf, strValue) != NMSTAT_SUCCESS)
                {
                    ReadingValues = FALSE;
                }
                else
                {
                    sprintf(pBssEvent->eventinfo[size++], "%s=%s",attributename, strValue);
                }
                break;
              case IMP_ARRAY_OBJECT_ID:
                if (ProcessOidType(ppBuf, strValue) != NMSTAT_SUCCESS)
                {
                    ReadingValues = FALSE;
                }
                else
                {
                    sprintf(pBssEvent->eventinfo[size++], "%s=%s",attributename, strValue);
                }
                break;
              case IMP_TYPE_CLASS_ID:
                if (ProcessCidType(ppBuf, FALSE, strValue, pBssConn)!= NMSTAT_SUCCESS)
                {
                    ReadingValues = FALSE;
                }
                else
                {
                    sprintf(pBssEvent->eventinfo[size++], "%s=%s",attributename, strValue);
                }
                break;
			  case IMP_TYPE_END_OF_MSG:
				  ReadingValues = FALSE;
			    break;
              default:
                ProcessUnknownType(ppBuf);
                break;
            }
			 
        }	
    }
    pBssEvent->eventinfosize = size;
}

bool ProcessEventMsg(tImpConn *pBssConn, u8* pMsg, tImpEvent *pBssEvent)
{
    tNMSTAT    NmStat;
    tEVHDR     EvHdr;
    u8*        pBuf = (u8*)0;
    u32        When;
    char*      pWhen = (char*)0;
    char	   pTempClassName[32]="\0";
	char       pTempEventName[32]="tst";
	char	   pTempAlarmLevel[10]="0";
	char       pTempStr[16]="\0";

	int	       Cid = 0;
	int		   Oid = 0;
//	int		   Eid;
    num        EventCode;
    bool       Status=FALSE;
    int        i,p=0;
    initImpEvent(pBssEvent);
    pBuf = pMsg;
    NmStat = NmUnMarshalEventHeader(&pBuf, &EvHdr);//Get EventHeader
    if (NmStat == NMSTAT_SUCCESS)
    {
   
        if (EvHdr.EvCls != (tCID)(-1))
        {
			Cid = (int)EvHdr.EvCls;
			if(SetCidStr(Cid,pTempClassName)){
            sprintf(pBssEvent->classname,"%s",pTempClassName);
            }
			Eid = (int)(EvHdr.EvNum);
            if (GetEventName(Cid,Eid,pTempEventName,pTempAlarmLevel))
            {
                sprintf(pBssEvent->eventname,"%s",pTempEventName);
				strcpy(pBssEvent->alarmlevel,pTempAlarmLevel);
            }
            else
            {
                strcpy(pBssEvent->eventname,"unknown event number");
            }
        }
        else
        {
            return(FALSE);
        }
        EventCode = (num)EvHdr.EvCode;
        if (EventCode == IMP_EVENT_REPLY)
        {
            if (EvHdr.ActCls == (u16) 64)//eventlog:action tst()
            {   
                if (EvHdr.ActNum == (u8) 1)
                {
					strcpy(pBssEvent->eventname,"tstComplete");
                }
            }
        }

        Oid = (int)EvHdr.ObjId.ContId;
        if(SetOidStr(Oid,pTempStr))
			while(pTempStr[p++]!='\0');
         p=p-1;
        for(i=0;i<EvHdr.ObjId.IxCnt;i++)
        {  
			sprintf(&pTempStr[p],".%d",EvHdr.ObjId.Ix[i]);
	        p+=2;  
        }
	    sprintf(pBssEvent->objectid,"%s",pTempStr);
        strftime(pBssEvent->eventtime, 20, "%Y-%m-%d %T",localtime((time_t*) &(EvHdr.Time)));
        
		pBssEvent->eventsecond = EvHdr.Time;
        pBssEvent->globaleventnumber = EvHdr.GlEvNum;
        glbevtnum = pBssEvent->globaleventnumber+1;

        When = EvHdr.Time;
        if (When > 799000000) /* Somewhere around May 1, 1995 */
        {
            pWhen = ctime((time_t*)&When);
        }

        When = EvHdr.GlEvNum;
        EvCid = EvHdr.EvCls;    
         
        // Event stores only values, need to look up attrs from event.
        // "FailureReport" will call ProcessEventBody()
		
		if (GetEventName(Cid,Eid,pTempEventName,pTempAlarmLevel))
		{
            ProcessEventBody(pBssConn, &pBuf, pBssEvent);
		}
            Status=TRUE;
    }
    return (Status);
}

bool ProcessMessage(tImpConn *pBssConn, u8* pMsg, tIMPHDR *pHeader, fd_set *readfds)
{
    tNMSTAT    NmStat;
    u8*        pBuf;
    u16        Op;
    tNMSTAT    MsgStat;
    bool       Status=FALSE;
    int        i;
    tImpEvent  *pBssEvent=&BssEvent;
    char       tablename[100]="\0";
    long       cellid;
    u16        responsecode;

    NmStat = NmReadImpOpCode(pMsg, &Op);
    if (NmStat == NMSTAT_SUCCESS)
    {
        if (Op == IMP_MSG_EVENT_IND) /* Decode Event Message */
         {
            Status = ProcessEventMsg(pBssConn, pMsg, pBssEvent);
            if (Status)
            {
                if (!strcmp(pBssEvent->eventname,"FailureReport"))
                {
                    update_alarmevent_table(sqlstring,pBssConn,pBssEvent,readfds);
                }
                else if (!strcmp(pBssEvent->eventname,"BtsMeasurements"))
		        {
                    update_BtsMeas_table(sqlstring,pBssConn,pBssEvent,&cellid);
				    btsmeas_row_no++;
					//if(btsmeasurements_size!=0L)
                    //btsmeas_row_no %= btsmeasurements_size;
                }
                else if (!strcmp(pBssEvent->eventname,"BscMeasurements"))
		        {
                    ;
                }
                else if (!strcmp(pBssEvent->eventname,"tstComplete"))
		        {
                    update_bootup_time(pBssConn,pBssEvent);
                }
                else if (!strcmp(pBssEvent->eventname,"Cser") ||
                         !strcmp(pBssEvent->eventname,"ACN"))
                {
                    sprintf(tablename,"OMCR_%s", pBssEvent->classname);
                    update_networkevent_table(sqlstring,pBssConn,pBssEvent);
                    for (i=0;i<num_of_mysql_table;i++) {
                        if (!strcmp(*(mysql_tables+i), tablename)) {
                            update_acn_cser_event(sqlstring,pBssConn,pBssEvent);
                        }
                    }
                }
                else
		        {   /* NE */
                    if (!strcmp(pBssEvent->eventname,"CardCreated"))
		            {
                        update_cardcreated_event(pBssConn,pBssEvent);
                    }
                    else if (!strcmp(pBssEvent->eventname,"TrxCreated")||
								!strcmp(pBssEvent->eventname,"TrxDeleted"))//bts.nm Eid=8
		            {
                        update_trxcreated_event(pBssConn,pBssEvent);
                    }
                    update_networkevent_table(sqlstring,pBssConn,pBssEvent);
               }
            }
        }
        else  /* Decode IMP Response Message */
        {
            pBuf = pMsg;
            NmStat = NmUnMarshalImpHeader(&pBuf, pHeader);
            if (NmStat == NMSTAT_SUCCESS)
            {
                Op = pHeader->OpCode;
                MsgStat = pHeader->StatCode;

                Status = TRUE;
                switch(Op)
                {
                    case IMP_MSG_CREATE_RESP:
                    case IMP_MSG_DELETE_RESP:
                        ProcessCreateDeleteBody(&pBuf, strValue, &intValue);
                        sprintf(response,"%s %d",strValue, intValue);
                        break;
                    case IMP_MSG_CONTENTS_RESP:
                        ProcessContentsBody(&pBuf, response);
                        break;
                    case IMP_MSG_SET_RESP:
                    case IMP_MSG_GET_RESP:
                        ProcessSetGetBody(pBssConn,&pBuf,response,&responsecode,TRUE);
                        break;
                    case IMP_MSG_ACTION_RESP:
                        ProcessActionBody(pBssConn,&pBuf,response);
                        break;
                }

                if ((pHeader->TransId1 == (u32) 0) && (Op == IMP_MSG_GET_RESP))
                {
                    /*
                     * Trans ID=0 and Get Response
                     * --> for object existent check using "oid"
                     * --> for retrieving object parameters using "get"
                     */
                    imp_response(pBssConn, pHeader, response);
                }
                else if (pBssConn->last_TransId == pHeader->TransId1)
                {
                    /*
                     * Trans ID > 0
                     * --> for handling command sent from MySQL database
                     */
                    imp_response(pBssConn, pHeader, response);
                    if (pHeader->TransId1 != 0L) {
						if(MsgStat == (tNMSTAT)0){
                        update_command_status(
                            MsgStat, "ok",
                            responsecode ,response, pHeader->TransId1);
						}else
							update_command_status(
                            MsgStat, "error",
                            responsecode ,response, pHeader->TransId1);
                    }
                    pBssConn->last_TransId = (u32)0;
                }
              
            }
              /* End_of_if (NmStat*/
        }       /* End_of_if (Op == */
    }
    
    return (Status);
}

bool CheckForMessages(tImpConn *pBssConn, tIMPHDR *pHeader, fd_set *readfds, time_t last_heartbeat_time)
{
    bool           Status = TRUE;
    bool           finish_read_whole_msg;
    u8*            pBuf;
    tNMLEN         MsgLen;
    tNMSTAT        NmStat;
    int            Total;
    int            Len=0;
    struct timeval WaitTime;
    fd_set         ReadFds;
    int            RetVal;
    int            width;
	int			   i;

    width = pBssConn->sockfd + 1;
    do
    {
        finish_read_whole_msg = false;

        if (pBssConn->last_Total < 0)
        {
            pBssConn->last_Total = 0;
        }

        /* Wait for anymore message */
        WaitTime.tv_sec=0;
        WaitTime.tv_usec=0;

        FD_ZERO(&ReadFds);
        FD_SET(pBssConn->sockfd, &ReadFds);
        RetVal = select(width, &ReadFds, (fd_set*)0, (fd_set*)0, &WaitTime);
        if (RetVal>0 && FD_ISSET(pBssConn->sockfd, &ReadFds) && pBssConn->sockfd>0)
        {
            /* Part 0: Copy previous buffer content into present buffer */
            for (i=0; i<pBssConn->last_Total; i++)
            {
                MsgRecvBuffer[i] = pBssConn->lastMsgRecvBuffer[i];
            }
			
            /* Part I: Read IMP Length Header */
            if (pBssConn->last_Total < IMP_TYPE_LENGTH_MBYTES)
            {
                /* Recover if last round data has not completely arrived */
                Total = read(pBssConn->sockfd,
                    (char*)MsgRecvBuffer + pBssConn->last_Total,
                    IMP_TYPE_LENGTH_MBYTES - pBssConn->last_Total);
                if ((Total == -1) || (Total>IMP_TYPE_LENGTH_MBYTES - pBssConn->last_Total))
                {
                    Status = FALSE;
                    clearBssConn(pBssConn,readfds);
                    InformIwBoxMonitor(pBssConn,CLR);
                    break;
                }
                pBssConn->last_Total += Total;
            }

            /* Part II: Read the remaining IMP message */
            if (pBssConn->last_Total >= IMP_TYPE_LENGTH_MBYTES)
            {
                pBuf = MsgRecvBuffer;

                NmStat = NmUnMarshalLength(&pBuf, &MsgLen); //get the message length

                if (NmStat == NMSTAT_SUCCESS)
                {
                    Len = (int) MsgLen;

                    FD_ZERO(&ReadFds);
                    FD_SET(pBssConn->sockfd, &ReadFds);
                    RetVal = select(width, &ReadFds, (fd_set*)0, (fd_set*)0, &WaitTime);
                    if (RetVal>0 && FD_ISSET(pBssConn->sockfd, &ReadFds))
                    {
                        Total = read(pBssConn->sockfd,
                            (char*)(MsgRecvBuffer+pBssConn->last_Total),
                            Len - pBssConn->last_Total);
                        if ((Total == -1) || (Total > Len-pBssConn->last_Total))
                        {
                            Status = FALSE;
                            clearBssConn(pBssConn,readfds);
                            InformIwBoxMonitor(pBssConn,CLR);
                            break;
                        }
                        pBssConn->last_Total += Total;

                        if (pBssConn->last_Total == Len)
                            finish_read_whole_msg = true;
                    }
                    else if (RetVal < 0)
                    {
                        Status = FALSE;
                    }
                }
                else
                {
		         /* shift read input tcp stream to locate the IMP message header */
		         pBssConn->last_Total=2;
		         MsgRecvBuffer[0]=MsgRecvBuffer[1];
		         MsgRecvBuffer[1]=MsgRecvBuffer[2];

                    Status = FALSE;
                }       /* End_of_if (NmStat == */
            }


            /* Part III: Whole message has been read */
            if (finish_read_whole_msg == true)
            {
                /* Clear last_Total when the whole message is read */
				pBssConn->last_Total=0;

                if (Status)
                {
                    ProcessMessage(pBssConn, MsgRecvBuffer, pHeader, readfds);
                }
            }
            else  /* Only read part of the whole message */
            {
                /*
                 * Data is partially arrived.
                 * As STREAM socket is used, more data can be retrieved in next round
                 * Besides, the contents read so far is dumped for displaying
                 */				
                if (pBssConn->last_Total > 0)
                {
                    for (i=0; i<pBssConn->last_Total; i++)
                    {
                        pBssConn->lastMsgRecvBuffer[i] = MsgRecvBuffer[i];
                    }
                }
            }   /* End_of_if (Total == */
        }
        else if (RetVal < 0)
        {
            Status = FALSE;
        }
        else	/* RetVal == 0 */
        {
            break;
        }   /* End_of_if (RetVal > */

        if ((time((time_t*)0)- last_heartbeat_time) >= HEARTBEAT_INTERVAL)
            break;

    } while (Status && (pBssConn->sockfd>0));
    
    return(Status);
}
//////////////////////////////////////////////////////////////////////////////////////////////////
//Caller: clearBssConn,NewBsplus,GetMonitorResult,ImpConnMultiplexer
unsigned int update_bsstable_status(tImpConn *pBssConn)
{
    sprintf(sqlstring, "UPDATE OMCR_BSSTABLE SET ip='%s', connected=%d WHERE bssid=%d",
        pBssConn->ip, pBssConn->connected, pBssConn->bssid);
    return ( execute_sql(sqlstring,0) );
}
//Caller: ProcessMessage,ProcessUserCommand,NewBsplus,DropBsplus
unsigned int update_command_status(int resultcode, char *result,int responsecode, char *response, u32 TransId)
{
    if (strlen(response) >= SQLSTRING_LEN )
    {
        exit(2);
    }

    sprintf(sqlstring, "%s%d%s%d%s%s%s%d%s%s%s%ld",
        "UPDATE OMCR_COMMAND SET status=", CMD_END,
        ",resultcode=",                    resultcode,
        ",result='",                       result,
        "',responsecode=",                 responsecode,
        ",response='",                     response,
        "' WHERE seqNum=",                 TransId
    );
    return ( execute_sql(sqlstring,0) );
}

unsigned int update_BtsMeas_table(char *buffer, tImpConn *pBssConn,tImpEvent *pBssEvent, long *cellid)
{
    int i;
    unsigned int retval;

//	struct timeval tv;
//	struct timezone tz;
//	gettimeofday(&tv,&tz);
//	printf("begin time is %ld.%ld\n\n",tv.tv_sec,tv.tv_usec);
    sprintf(buffer,
        "REPLACE INTO OMCR_BtsMeasurements SET new=1,bssid=%d,EndTime=%ld,row_no=%ld,updateTime=CURRENT_TIMESTAMP",
        pBssConn->bssid, pBssEvent->eventsecond,btsmeas_row_no);
    
    for (i=0; i<pBssEvent->eventinfosize; i++)
    {
        strcat(buffer,",");
        strcat(buffer,pBssEvent->eventinfo[i]);
        if (!strncmp(pBssEvent->eventinfo[i],"CellIdentity=",13))
            *cellid=atol((pBssEvent->eventinfo[i])+13);
    }
    //rintf(buffer, "%s WHERE row_no=%ld", buffer, btsmeas_row_no);
	//printf("row_no=%d\n",btsmeas_row_no);
	//printf("sql>%s\n\n",buffer);

    retval=execute_sql(buffer,0);
//	printf("end time is %d.%d\n\n",tv.tv_sec,tv.tv_usec);
    return (0);
}
/*
 * Return 0 = OK, otherwise error number
 */
unsigned int getLedStatus(void)
{
    int bssid,btsid,signal_element;
    int unit_id;        // identify the hardware or logical unit in BSC/BTS
    int max_severity;
    int index;
    int led_no;
	int	i,j;
    unsigned int retval=0;
    
    char *tmpStr,*onePart;

	int btsAlvailStatus[NO_OF_BSS*NO_OF_BTSMgr];
	int bscAlvailStatus[NO_OF_BSS];

	for(i=0;i<NO_OF_BSS*NO_OF_BTSMgr;i++)
		btsAlvailStatus[i]=7; //7=not installed

	sprintf(sqlstring, "SELECT AvailStatus,ObjectId,bssid FROM OMCR_Bts WHERE AvailStatus !=7 ORDER BY bssid ASC,ObjectId ASC");
    
	mysql_query(mysql_sock,sqlstring);
    retval = mysql_errno(&mysql);
    if (retval)
    {
        return (retval);
    }
    result = mysql_use_result(&mysql);
	
    while ((row = mysql_fetch_row(result)))
    {
    	tmpStr=row[1];
    	if(strsep(&tmpStr,"."))
			onePart=strsep(&tmpStr,".");
			
		if(onePart!=NULL)
			i=atoi(row[2])*NO_OF_BTSMgr+atoi(onePart);  
		else
			continue;  	
		
		if(atoi(row[0])!=4)
			btsAlvailStatus[i]=atoi(row[0]);
		else{
			if(btsAlvailStatus[i]==7)
				btsAlvailStatus[i]=atoi(row[0]);
		}
	}
    mysql_free_result(result);
    
    //for(i=0;i<NO_OF_BSS*NO_OF_BTSMgr;i++)
	//	printf("btsAlvailStatus[%d]=%d",i,btsAlvailStatus[i]);

    for (i=NO_OF_BSS*NO_OF_BTSMgr-1; i>=0 ;i--)
    {
        (bts_led[i]).alarmcode = 0;
        (bts_led[i]).alarmlevel = 0;
        (bts_led[i]).component_id = 0;
        (bts_led[i]).presence = false; 
        for ( j=HB_LED_CONTROL_LEN*2-1; j>=0; j--)
            (bts_led[i]).led[j] = 0xf;        // Not install
    }

	for(i=0;i<NO_OF_BSS;i++)
		bscAlvailStatus[i]=7; //7=not installed

	sprintf(sqlstring, "SELECT AvailStatus FROM OMCR_Bsc ORDER BY bssid ASC,ObjectId ASC");
    
	mysql_query(mysql_sock,sqlstring);
    retval = mysql_errno(&mysql);
    if (retval)
    {
        return (retval);
    }
    result = mysql_use_result(&mysql);
	i=0;
    while ((row = mysql_fetch_row(result)))
    {
		bscAlvailStatus[i++]=atoi(row[0]);
	}
    mysql_free_result(result);

    for (i=NO_OF_BSS-1; i>=0 ;i--)
    {
        (bsc_led[i]).alarmcode = 0;
        (bsc_led[i]).alarmlevel = 0;
        (bsc_led[i]).component_id = 0;
        (bsc_led[i]).presence = false; 
        for ( j=HB_LED_CONTROL_LEN*2-1; j>=0; j--)
            (bsc_led[i]).led[j] = 0xf;        // Not install
    }

    sprintf(sqlstring, "%s%s",
        "SELECT DISTINCT BssId,Signal_Element,MaxSeverity FROM OMCR_BSSTREE ",
        "WHERE Presence=1 AND Signal_Element<>'0' ORDER BY MaxSeverity ASC");
    
	mysql_query(mysql_sock,sqlstring);
    retval = mysql_errno(&mysql);
    if (retval)
    {
        return (retval);
    }
    result = mysql_use_result(&mysql);
    while ((row = mysql_fetch_row(result)))
    {
        bssid = atoi(row[0]);
        signal_element=atoi(row[1]);
        btsid = signal_element / 1000;
        unit_id = signal_element % 1000;
        max_severity = atoi(row[2]);
        
  		if(btsid!=99){//bts
	        index = bssid*NO_OF_BTSMgr+btsid;
	        led_no = object2LedId(btsid,unit_id);
	        if (led_no == -1)
	        {
	            continue;
	        }
	
	        (bts_led[index]).presence = true;
	        if (max_severity == 1)
	        {
	            (bts_led[index]).led[led_no] = LED_RED;
	        }
	        else if (max_severity == 2)
	        {
	            (bts_led[index]).led[led_no] = LED_YELLOW;
	        }
	        else         // NORMAL
	        {
	            (bts_led[index]).led[led_no] = LED_GREEN;
	        }
	
			//printf("btsAlvailStatus[%d]=%d\n",index,btsAlvailStatus[index]);
			if(btsAlvailStatus[index]!=4)
				(bts_led[index]).led[led_no] = LED_RED;
		}else{
	        led_no = object2LedId(btsid,unit_id);
	        if (led_no == -1)
	        {
	            continue;
	        }
	        
	        (bsc_led[bssid]).presence = true;
	        if (max_severity == 1)
	        {
	            (bsc_led[bssid]).led[led_no] = LED_RED;
	        }
	        else if (max_severity == 2)
	        {
	            (bsc_led[bssid]).led[led_no] = LED_YELLOW;
	        }
	        else         // NORMAL
	        {
	            (bsc_led[bssid]).led[led_no] = LED_GREEN;
	        }
			
			if(bscAlvailStatus[bssid]!=4)
				(bsc_led[bssid]).led[led_no] = LED_RED;
		}
			
    }
    mysql_free_result(result);

    return (retval);
}
/*
 * Find the count of alarms
 * Return -1 if error
 */
int checkForAlarmStatus(tImpConn *pBssConn)
{
    int no_of_alarm=1;
    char buffer[100]="\0";
    /*
     * find out whether the system has critical alarms or not
     */
    sprintf(buffer, "%s%d%s%d%s%d",
        "SELECT count(*) FROM OMCR_ALARMEVENT WHERE bssid=", pBssConn->bssid,
        " AND Severity>", SV_CEASED,
        " AND Severity<=", SV_CRITICAL
    );
    mysql_query(mysql_sock,buffer);
    if (mysql_errno(&mysql))
    {
        return (-1);
    }
    result = mysql_use_result(&mysql);
    row = mysql_fetch_row(result);
    no_of_alarm=atoi(row[0]);
    mysql_free_result(result);

    return(no_of_alarm);
}
/*
 * "Severity = 0" means alarm clear (SV_CEASED)
 * enum{SV_CEASED,SV_CRITICAL,SV_MAJOR,SV_MINOR,SV_WARNING}
 * MAXSEVERITY defines which alarm to be stored and display
 *
 * Return 0=OK, otherwise failed
 */
unsigned int update_alarmevent_table(char *buffer, tImpConn *pBssConn, tImpEvent *pBssEvent, fd_set *readfds)
{
    int i,j;
    int stage;
    int how_many;
    int maxseverity;
    unsigned int retval=0;
    char info[SQLSTRING_LEN]="\0";
    unsigned long no_affected_row=0L;

	int bsType=0;

    pBssEvent->eventcause = 1;
	/*
	 * pBssEvent->eventname is "FailureReport"
	 * event parameter is (Cause, Info,  EventType, Severity, Problem)
			label("Failure Event Report")
			alarm(NM_ALARM_MINOR);
	   1. Cause[3] is " The Cause field of Failure Event Report Msg ";
	   2. Info is " The Text field of Failure Event Report Msg ";
	   3. EventType is " The type of the event ";
	   4. Severity defines the alarm;
	 */
    for (i=0, stage=0; i<pBssEvent->eventinfosize; i++, stage++)
    {
        switch(stage)
        {
            case 0:
                if (!strncmp(pBssEvent->eventinfo[i], "Cause_0", 7))
                {
                    pBssEvent->eventcause = 256 * atoi((pBssEvent->eventinfo[i])+8);
                }
                break;
            case 1:
                if (!strncmp(pBssEvent->eventinfo[i], "Cause_1", 7))
                {
                    pBssEvent->eventcause += atoi((pBssEvent->eventinfo[i])+8);
                }
                break;
            case 2:
              if (!strncmp(pBssEvent->eventinfo[i], "Cause_2", 7))
                {
                    pBssEvent->eventcause += atoi((pBssEvent->eventinfo[i])+8);
                }
                break;
            case 3:
                if (!strncmp(pBssEvent->eventinfo[i], "Info", 4))
                {
                    strcpy(info,(pBssEvent->eventinfo[i])+5);
                }
                break;
            case 4:
                if (!strncmp(pBssEvent->eventinfo[i], "EventType", 9))
                    pBssEvent->eventtype = atoi(pBssEvent->eventinfo[i]+10);
                break;
            case 5:
                if (!strncmp(pBssEvent->eventinfo[i], "Severity", 8))
                    pBssEvent->severity = atoi(pBssEvent->eventinfo[i]+9);
                break;
            default:
                break;
        }
    }
	/*
	 * According the severity
	 */
    if (pBssEvent->severity == SV_CEASED) /* SV_CEASED */
    {
        /*
         * Clear the alarm in OMCR_ALARMEVENT table
         * If eventcause is divisible by 256, whole block of alarms(cause,cause+256)is clear
         */
        if ((pBssEvent->eventcause & 0xff) == 0) // Block alarm clear
        {
            sprintf(buffer, "%s%d%s'%s'%s%d%s%d%s'%s'%s%d%s%d",
                "UPDATE OMCR_ALARMEVENT SET Severity=", pBssEvent->severity,
                ",ClearTime=",                          pBssEvent->eventtime,
                " WHERE bssid=",                        pBssConn->bssid,
                " AND Severity<>",                      SV_CEASED,
                " AND ObjectId=",                       pBssEvent->objectid,
                " AND Cause>=",                         pBssEvent->eventcause,
                " AND Cause<",                          pBssEvent->eventcause+256);
        }
        else // Specific clear -- e.g. ALink is down (SV_CEASED)
        {
            sprintf(buffer, "%s%d%s'%s'%s%d%s%d%s'%s'%s%d",
                "UPDATE OMCR_ALARMEVENT SET Severity=", pBssEvent->severity,
                ",ClearTime=",                          pBssEvent->eventtime,
                " WHERE bssid=",                        pBssConn->bssid,
                " AND Severity<>",                      SV_CEASED,
                " AND ObjectId=",                       pBssEvent->objectid,
                " AND Cause=",                          pBssEvent->eventcause
            );
        }
        retval=execute_sql(buffer,&no_affected_row);
        /*
         * update OMCR_BSSTREE table for MaxSeverity field (Clear Alarm)
         */
        if (no_affected_row > 0)
        {
            sprintf(buffer, "%s%d%s'%s'%s%d%s%d",
                "SELECT MIN(Severity) FROM OMCR_ALARMEVENT WHERE bssid=", pBssConn->bssid,
                " AND ObjectId=",  pBssEvent->objectid,
                " AND Severity>",  SV_CEASED,
                " AND Severity<=", MAXSEVERITY
            );
            mysql_query(mysql_sock,buffer);
            retval=mysql_errno(&mysql);
            if (retval)
            {
                exit(3);
            }
            result = mysql_use_result(&mysql);
            row = mysql_fetch_row(result);
            if ( row[0] == NULL )
                maxseverity=0;
            else
                maxseverity=atoi(row[0]);
    
            mysql_free_result(result);
            sprintf(buffer, "%s%d%s%d%s'%s'",
                "UPDATE OMCR_BSSTREE SET MaxSeverity=", maxseverity,
                " WHERE bssid=",  pBssConn->bssid,
                " AND ObjectId=", pBssEvent->objectid
            );
            retval=execute_sql(buffer,0);

            how_many=checkForAlarmStatus(pBssConn);
        }
        return(retval);
    }
    else if (pBssEvent->severity <= MAXSEVERITY)
    {
        /*
         * Check whether the alarm is associated with an object appeared in
         * table OMCR_BSSTREE
         */
        sprintf(buffer, "%s%d%s'%s'",
            "SELECT ObjectId FROM OMCR_BSSTREE WHERE bssid=", pBssConn->bssid,
            " AND ObjectId="                                , pBssEvent->objectid
        );
        retval=execute_sql(buffer,&no_affected_row);
        /*
         * Add the alarm in OMCR_ALARMEVENT table
         * Condition: the object id must be defined in OMCR_BSSTREE
         */
        if (no_affected_row > 0)
        {
            sprintf(buffer, "%s%d%s'%s'%s%ld%s'%s'%s%s%s%d%s%d%s%d%s'%s'%s%ld",
                "REPLACE OMCR_ALARMEVENT SET bssid=", pBssConn->bssid,
                ",ObjectId=",                        pBssEvent->objectid,
                ",GlobalEventNumber=",               pBssEvent->globaleventnumber,
                ",AlarmLevel=",                      pBssEvent->alarmlevel,
                ",EventInfo=",                       info,
                ",Cause=",                           pBssEvent->eventcause,
                ",EventType=",                       pBssEvent->eventtype,
                ",Severity=",                        pBssEvent->severity,
                ",EventTime=",                       pBssEvent->eventtime,
                ",AckTime=null,ClearTime=null,row_no=", alarmevent_row_no
            );
            //printf("buffer=%s\n",buffer);
            retval=execute_sql(buffer,0);
            alarmevent_row_no++;
            alarmevent_row_no = alarmevent_row_no % MAX_ALARMEVENT_SIZE;
            /*
             * update OMCR_BSSTREE table for "alarmed" field (Add Alarm)
             */
            sprintf(buffer, "%s%d%s%d%s'%s'%s%d%s%d%s",
                "UPDATE OMCR_BSSTREE SET MaxSeverity=", pBssEvent->severity,
                " WHERE bssid=",                        pBssConn->bssid,
                " AND ObjectId=",                       pBssEvent->objectid,
                " AND (MaxSeverity>",                   pBssEvent->severity,
                " OR MaxSeverity=" ,                    SV_CEASED, ")"
            );
            retval=execute_sql(buffer,&no_affected_row);
        }
        //else "Not in OMCR_BSSTREE, alarm is not insert in AE" 
        
        getLedStatus();
        //
        // Send alarm heartbeat if Critical or major alarm
        //
        if ((no_affected_row > 0) && ((pBssEvent->severity == SV_CRITICAL)||(pBssEvent->severity == SV_MAJOR)))
        {
            
            int btsmgr_number=0;
            int system_id;
            for (i=0;i<MAX_OBJECTID_LEN;i++)
            {
                if (pBssEvent->objectid[i] == '.')
                {
                    for (j=1;j<=2;j++)        // Max 2 digits for BtsMgr ID
                        if (pBssEvent->objectid[i+j] != '.')
                            btsmgr_number = btsmgr_number * 10 + (pBssEvent->objectid[i+j]-'0');
                    break;
                }
            }
            // system_id = BSSID * NO_OF_BTSMgr + BTSMGR_ID
            system_id=pBssConn->bssid * NO_OF_BTSMgr + btsmgr_number;

            if (pBssEvent->severity > 2)
                maxseverity = 0;        // Normal
            else
                maxseverity = pBssEvent->severity;
			
			bsType=checkBsType(system_id/NO_OF_BTSMgr);
            send_heartbeat(system_id,&(bsc_led[pBssConn->bssid]),&(bts_led[system_id]),
                           (pBssEvent->eventcause & 0xff00)>>8,pBssEvent->eventcause & 0xff,
                           maxseverity,bsType);
        }
        if ( pBssEvent->eventcause == 3075 )      // Bsc Reboot due to action RebootBsc by Operator
            clearBssConn(pBssConn,readfds);
    }
    else  // SV_INDETERMINATE
    {
        ; // do nothing
    }
    return(retval);
}
/*
 * ACN: Attribute Changed Notification
 * Cser: Change operational State Event Report
 */
unsigned int update_acn_cser_event(char *buffer, tImpConn *pBssConn,tImpEvent *pBssEvent)
{
    int i;
    unsigned int retval=0;
    char info[SQLSTRING_LEN]="";

    if (pBssEvent->eventinfosize)
        strcpy(info,pBssEvent->eventinfo[0]);
    for (i=1; i<pBssEvent->eventinfosize; i++)
    {
		strcat(info,",");
        strcat(info,pBssEvent->eventinfo[i]);
    }

    sprintf(buffer, "%s%s%s%s%s%d%s'%s'",
        "UPDATE OMCR_",   pBssEvent->classname,
        " SET ",          info,
        " WHERE bssid=",  pBssConn->bssid,
        " AND ObjectId=", pBssEvent->objectid
    );
    retval=execute_sql(buffer,0);
   	return (retval);
}

unsigned int update_cardcreated_event(tImpConn *pBssConn, tImpEvent *pBssEvent)
{
    #define BSC_SHELF 0
    #define BTS_SHELF 1
    int slotnum;
	int portnum;
    int objlen;
    bool flag;
    char obj[80]="\0";
    char tempNmiCmd[100]="\0";
    if (pBssEvent->eventinfosize < 2)
        return 0;

    objlen = strlen(pBssEvent->objectid);
    strcpy(obj, pBssEvent->objectid+1);
    obj[objlen-2] = '\0';
    if (!strncmp(pBssEvent->eventinfo[1],"SlotNumber=",11))
    {
        slotnum = atoi((pBssEvent->eventinfo[1])+11);
        //objectid must be in the form "BtsMgr_Shelf.x.0.y"
        //                          or "Shelf.0.y"
        if (!strncmp(obj,"BtsMgr_Shelf.",13))
        {
            sprintf(tempNmiCmd,"oid BtsMgr_Shelf_Card.%s.%d",obj+13,slotnum);
            flag = BTS_SHELF;
        }
        else if (!strncmp(obj,"Shelf.",6))
        {
            sprintf(tempNmiCmd,"oid Card.%s.%d",obj+6,slotnum);
            flag = BSC_SHELF;
        }
        else
        {
            return 0;
        }
        addCmd2Queue(pBssConn,tempNmiCmd,(u32) 1);
        if (FindAvailCmdBufferPtr())
        {
            addCmd2Queue(pBssConn,"get",(u32) 1);
        }
        //
        // For E1 card creation, get the port attributes
        //
        if (!strncmp(pBssEvent->eventinfo[0],"CardType=2",10))
        {
            for ( portnum=0;portnum<=1;portnum++)
            {
                if (FindAvailCmdBufferPtr())
                {
                    if (flag == BTS_SHELF)
                    {
                        sprintf(tempNmiCmd,"oid BtsMgr_Shelf_Card_Port.%s.%d.%d",
                            obj+13,slotnum,portnum);
                    }
                    else
                    {
                        sprintf(tempNmiCmd,"oid BtsMgr_Shelf_Card_Port.%s.%d.%d",
                            obj+6,slotnum,portnum);
                    }
                    addCmd2Queue(pBssConn,tempNmiCmd,(u32) 1);
                }
                if (FindAvailCmdBufferPtr())
                {
                    addCmd2Queue(pBssConn,"get",(u32) 1);
                }
            }
        }

        FindAvailCmdBufferPtr();
    }
    
    return 0;
}

unsigned int update_trxcreated_event(tImpConn *pBssConn, tImpEvent *pBssEvent)
{
    int trxnum;
    int objlen;
    char obj[80]="\0";
    char tempNmiCmd[100]="\0";
    if (!pBssEvent->eventinfosize)
        return 0;

    objlen = strlen(pBssEvent->objectid);
    strcpy(obj, pBssEvent->objectid+4);
    obj[objlen-2] = '\0';
    if (!strncmp(pBssEvent->eventinfo[0],"TrxNumber=",10))
    {
        trxnum = atoi((pBssEvent->eventinfo[0])+10);
        //objectid must be in the form "Bts.x.0"
        sprintf(tempNmiCmd,"oid Trx.%s.%d",obj,trxnum);

        addCmd2Queue(pBssConn,tempNmiCmd,(u32) 1);
        if (FindAvailCmdBufferPtr())
        {
            addCmd2Queue(pBssConn,"get",(u32) 1);
        }
        if (FindAvailCmdBufferPtr())
        {
            sprintf(tempNmiCmd,"oid RCarrier.%s.%d",obj,trxnum);
            addCmd2Queue(pBssConn,tempNmiCmd,(u32) 1);
        }
        if (FindAvailCmdBufferPtr())
        {
            addCmd2Queue(pBssConn,"get",(u32) 1);
        }
        FindAvailCmdBufferPtr();
    }
    
    return 0;
}

unsigned int update_networkevent_table(char *buffer, tImpConn *pBssConn,tImpEvent *pBssEvent)
{
    int i;
    //networkevent_init;
    unsigned int retval;
    char info[SQLSTRING_LEN]="\0";

    if (pBssEvent->eventinfosize)
        strcpy(info,pBssEvent->eventinfo[0]);
    for (i=1; i<pBssEvent->eventinfosize; i++)
    {
        strcat(info,",");
        strcat(info,pBssEvent->eventinfo[i]);
    }

    sprintf(buffer, "%s%d%s'%s'%s'%s'%s'%s'%s%ld%s'%s'%s%ld",
        "REPLACE INTO OMCR_NETWORKEVENT SET bssid=", pBssConn->bssid,
        ",EventName=",                    pBssEvent->eventname,
        ",ObjectId=",                     pBssEvent->objectid,
        ",EventTime=",                    pBssEvent->eventtime,
        ",GlobalEventNumber=",            pBssEvent->globaleventnumber,
        ",EventInfo=",                    info,
        ",row_no=",                 networkevent_row_no
    );
    retval = execute_sql(buffer,0);
	//if(networkevent_size!=0L)
    //networkevent_row_no %= networkevent_size;
    networkevent_row_no++;
    return (retval);
}
// Two cases are possible:
// 1. BSS has sync the clock, 2. BSS has not sync the clock
void update_bootup_time(tImpConn *pBssConn, tImpEvent *pBssEvent)
{
    time_t tloc;

    if (pBssConn->bootupTime == 0L)
    {
        time(&tloc);
        if (pBssEvent->eventsecond > 799000000) /* Somewhere around May 1, 1995 */
        {
            pBssConn->bootupTime = tloc - wait_interval;
        }
        else
        {
            pBssConn->bootupTime = tloc - pBssEvent->eventsecond;
        }
        syncBssTimeWithOMC(pBssConn, tloc);
    }
}
/*
 *               / 0 ,if no need to store,
 * StoredInDB = {  1 ,if paremeters need to be stored in DB
 *               \ 2 ,if only Presence need to know 
 */
int requestObjCfg(tImpConn *pBssConn, char *objectid,int objectidLevel)
{
	MYSQL_RES    *tmp_result;
    MYSQL_ROW    tmp_row;
    
    int retval;
    char nmicmd[80]="\0";
    int  no_error=TRUE;
    //int  count=0;
    if (objectid != 0)
    {      
      	sprintf(sqlstring, "%s%d%s%s%s",
            "SELECT ObjectId,StoreInDB,Url FROM OMCR_BSSTREE WHERE bssid=",//Update BSSTREE
            pBssConn->bssid," AND ObjectId REGEXP '", objectid , "'");    
    }else if(objectidLevel!=0){
        sprintf(sqlstring, "%s%d%s%d%s",
            "SELECT ObjectId,StoreInDB,Url FROM OMCR_BSSTREE WHERE bssid=",//Update BSSTREE
            pBssConn->bssid," AND Layer= '", objectidLevel , "'");
    }else{
    	return (false);
    }

    mysql_query(mysql_sock, sqlstring);
    retval=mysql_errno(&mysql);
    if (retval)
    {
		perror("Error!\n");
        no_error=FALSE;
        return (no_error);
    }
    tmp_result = mysql_use_result(&mysql);


    while ((tmp_row = mysql_fetch_row(tmp_result)))
    {
        if (atoi(tmp_row[1]))
        {
            sprintf(nmicmd,"oid %s",tmp_row[0]);

            addCmd2Queue(pBssConn,nmicmd,(u32) 1);
            if (!FindAvailCmdBufferPtr())
            {
                no_error=FALSE;
				        break;
            }
            if (atoi(tmp_row[1]) == 1)
            {
                addCmd2Queue(pBssConn,"get",(u32) 1);
				//printf("Object = %s, ",row[0]);
                if (!FindAvailCmdBufferPtr())
                {
                    no_error=FALSE;
                    break;
                }
            }
        }
    }
    if ( no_error==TRUE )
    {
        addCmd2Queue(pBssConn,"oid BssFunc",(u32) 1);
        if (!FindAvailCmdBufferPtr())
            no_error=FALSE;
    }
    mysql_free_result(tmp_result);
    return (no_error);
}

int requestChildCfg(tImpConn *pBssConn,char *objectid){
	MYSQL_RES    *tmp_result;
    MYSQL_ROW    tmp_row;
   
    char tmp_objectid[64];
    char *objectIdPart;
    char tmpStr[64];
    int retval;
    int  no_error=TRUE;
    int i;
    char previous_inherit_relatives[ObjectIdMaxLevel][64];
    
    strcpy(tmp_objectid,objectid);
    if(objectIdPart=strchr(tmp_objectid,'.'));
    	*objectIdPart=0;
            	
    objectIdPart=strchr(objectid,'.');
             	
    sprintf(sqlstring, "%s%d%s%s%s",
            "SELECT * FROM OMCR_Inherit_Relatives  WHERE level_",//Update BSSTREE
             pBssConn->current_upload_level," = '", tmp_objectid , "'");
                

    mysql_query(mysql_sock, sqlstring);
    retval=mysql_errno(&mysql);
    if (retval)
    {
	    perror("Error!\n");
        no_error=FALSE;
        return (no_error);
    }
    tmp_result = mysql_store_result(&mysql);

    while ((tmp_row = mysql_fetch_row(tmp_result))){
        for(i=pBssConn->current_upload_level+1;i<ObjectIdMaxLevel;i++){
            if(!strcmp(tmp_row[i],"null"))
                break;
               
            if(!strcmp(previous_inherit_relatives[i],tmp_row[i]))
                continue;
                                      
            strcpy(previous_inherit_relatives[i],tmp_row[i]);
            sprintf(tmpStr,"%s%s",tmp_row[i] , objectIdPart);

		    sprintf(sqlstring, 
				    "UPDATE OMCR_BSSTREE SET Presence=9 WHERE bssid=%d AND level='%d' AND ObjectdId Like %s",
				    pBssConn->bssid, pBssConn->current_upload_level,tmpStr
				    );

			execute_sql(sqlstring,0);
            requestObjCfg(pBssConn, tmpStr,pBssConn->current_upload_level);     
        }
    }
    mysql_free_result(tmp_result);
}

int requestBssCfg(tImpConn *pBssConn)
{  
    MYSQL_RES    *tmp_result;
    MYSQL_ROW    tmp_row;
    char childObjectId[64];
    char *objectIdPart;
   
    int retval;
    int  no_error=TRUE;
    int i;
    char previous_inherit_relatives[ObjectIdMaxLevel][64];
    
    
	if(pBssConn->upload_in_progress==0){
		pBssConn->upload_in_progress=1;
		//addCmd2Queue(pBssConn,"oid BssFunc",(u32) 1);
		requestObjCfg(pBssConn, "BssFunc", 0);
		pBssConn->current_upload_level=1;
		sprintf(sqlstring, 
				"UPDATE OMCR_BSSTREE SET Presence=9 WHERE bssid=%d AND Layer='1'",
				pBssConn->bssid
		       );
		execute_sql(sqlstring,0); 
		return(requestObjCfg(pBssConn, 0, 1)); 
    }else{
    	sprintf(sqlstring, "%s%d%s%d%s",
            "SELECT count(*) FROM OMCR_BSSTREE WHERE bssid=",//Update BSSTREE
            pBssConn->bssid," AND Layer= '", pBssConn->current_upload_level , "' AND Presence='9'");
        mysql_query(mysql_sock, sqlstring);
   
        retval=mysql_errno(&mysql);
        if (retval)
        {
		    perror("Error!\n");
            no_error=FALSE;
            return (no_error);
        }
        result = mysql_store_result(&mysql);
        row = mysql_fetch_row(result);
        
        if(atoi(row[0])>0){
        	mysql_free_result(result);
        	return (no_error);
        }
        mysql_free_result(result);
        
        	
        sprintf(sqlstring, "%s%d%s%d%s",
            "SELECT ObjectId,Presence FROM OMCR_BSSTREE WHERE bssid=",//Update BSSTREE
            pBssConn->bssid," AND Layer= '", pBssConn->current_upload_level , "'");
        mysql_query(mysql_sock, sqlstring);
   
        retval=mysql_errno(&mysql);
        if (retval)
        {
		    perror("Error!\n");
            no_error=FALSE;
            return (no_error);
        }
        result = mysql_store_result(&mysql);
        while ((row = mysql_fetch_row(result)))
        {
            if (atoi(row[1])==0){
             	strcpy(childObjectId,row[0]);
             	objectIdPart=strchr(childObjectId,'.');
             	*objectIdPart=0;
             	
             	objectIdPart=strchr(row[0],'.');
             	
             	sprintf(sqlstring, "%s%d%s%s%s",
                     "SELECT * FROM OMCR_Inherit_Relatives  WHERE level_",//Update BSSTREE
                     pBssConn->current_upload_level," = '", childObjectId , "'");
            
                 mysql_query(mysql_sock, sqlstring);
                 retval=mysql_errno(&mysql);
                 if (retval)
                 {
		             perror("Error!\n");
                     no_error=FALSE;
                     return (no_error);
                 }
                 tmp_result = mysql_store_result(&mysql);
                 
                 while ((tmp_row = mysql_fetch_row(tmp_result))){
                 	for(i=pBssConn->current_upload_level+1;i<ObjectIdMaxLevel;i++){
                 	    if(!strcmp(tmp_row[i],"null"))
                         	break;
                         if(!strcmp(previous_inherit_relatives[i],tmp_row[i]))
                         	continue;          
                     
                 	    sprintf(sqlstring, "%s%d%s%s%s%s",
                         "UPDATE OMCR_BSSTREE SET Presence=0 WHERE bssid=%d AND ",//Update BSSTREE
                         pBssConn->bssid," AND objectId Like '", tmp_row[i] , objectIdPart , "%'");
                         execute_sql(sqlstring,0);
                     }
                 }
                 		  
                 mysql_free_result(tmp_result);
            }else if (atoi(row[1])==1){
                requestChildCfg(pBssConn,row[0]);  
            }
        }
        mysql_free_result(result);
        pBssConn->current_upload_level++;
        if(pBssConn->current_upload_level==ObjectIdMaxLevel){
            pBssConn->upload_in_progress=0;
            update_command_status(
                    NMSTAT_SUCCESS,"ok",
                    1282,"Finished", pBssConn->upload_TransId
            );
            return (no_error);
        }    	
    }
    return (no_error);
}

int updateBssCfg(tImpConn *pBssConn, tIMPHDR *pHeader, char *response)
{
	char ObjectId[MAX_OBJECTID_LEN]="\0";
	char ClassId[32]="\0";
	char sqlbuffer[64]="\0";
	char field[10240]="\0";
	
	int i,j,m=0;
	int len;
	int Oid,Cid;
	char tablename[100];
	memset(tablename,'\0',sizeof(tablename));
	len = strlen(response);
	
	Oid = (int)(pHeader->ObjId).ContId;
	if(SetOidStr(Oid,ObjectId)){
		for(i=0;i<(pHeader->ObjId).IxCnt;i++)
			sprintf(ObjectId,"%s.%d",ObjectId,(pHeader->ObjId).Ix[i]);
	}
	
	if ( pHeader->StatCode != NMSTAT_SUCCESS ){
		if ((pHeader->OpCode == IMP_MSG_GET_RESP) && (len<=40)){
			sprintf(sqlstring, 
								"UPDATE OMCR_BSSTREE SET Presence=0 WHERE bssid=%d AND ObjectId='%s'",
								pBssConn->bssid, ObjectId
						);
			execute_sql(sqlstring,0);
		}
    return(1);   /* nothing to do */
	}

	if (pHeader->OpCode == IMP_MSG_SET_RESP) /* SET RESPONSE ->put data in Object table */
	{
		int num =0,parent;
		char *oneVar = NULL;
		char *oneName = NULL;
		char Var[24][85];
		
		char *settmp = NULL;
		char setfield[8192]="\0";
		char Valtemp[8192]="\0";
		strcpy(Valtemp,response);
		settmp = response;
		Cid = (int)pBssConn->TheCid;
		if(GetTableName(Cid,ClassId))
			sprintf(tablename,"OMCR_%s",ClassId);
	    
		for (i=0;i<num_of_mysql_table;i++)
    {
			if (!strcmp(*(mysql_tables+i),tablename))
 			{
				while((oneVar = strsep(&(response), ",")) != NULL){
					if ((oneName = strsep(&(oneVar), "=")) != NULL)
					{
						parent = num;
						sprintf(&Var[num++][0],"%s",oneVar);
						sprintf(sqlbuffer,
							 "SELECT Attribute_Name FROM OMCR_Meta_Table WHERE Attribute_Id = '%s'",oneName);
						mysql_query(mysql_sock,sqlbuffer);
						result = mysql_store_result(&mysql);
						if(result == NULL){
							return(1);
						}else if(mysql_num_rows(result) == 0){
							mysql_free_result(result);
						}
						while((row=mysql_fetch_row(result)) > (MYSQL_ROW)0){
							if(parent == 0)
								sprintf(setfield,"%s=%s",row[0],&Var[parent][0]);
							else
								sprintf(setfield,"%s,%s=%s",setfield,row[0],&Var[parent][0]);
						}//end while
					}
				}
				strcpy(settmp,Valtemp);
			}
			sprintf(sqlstring, 
              "UPDATE %s SET %s WHERE bssid=%d AND ObjectId='%s'",
      		     tablename, setfield, pBssConn->bssid, ObjectId);
		}                        
	}
	else if ( len > 40 )  /* GET RESPONSE -> put data in Object table */
	{
		char *oneAttr = NULL;
		char *onePart = NULL;
		char value[220][85];

		char *resptmp = NULL;
		char temp[25600]="\0";

		int attrCount=0;
		strcpy(temp,response);
		resptmp = response;
		if (strncmp(response,"0:0=",4))//ClassId
			return(2);

		for (i=4,j=0; !((response[i]==',')||(response[i]=='\0')); i++,j++){
			ClassId[j] = response[i];
		}
		ClassId[j] = '\0';
		Cid = atoi(ClassId);
	
		if ( len == i )
			return(3);   /* should be an error but nothing to do */

		//If the bss software's  version is higher than bssomc's version,
		//there are some attributes which no in the lower bssomc's version. 
		//So we need judge the response message and remove the unknown attribute.   
	  if(GetTableName(Cid,ClassId)){
			if(strstr(response,"no such attribute") != NULL){
				char setStr[2048]="\0";
				while((oneAttr = strsep(&(response), ",")) != NULL){
					attrCount++;
					if(attrCount == 1)
						continue;
				
					if(strstr(oneAttr,"no such attribute") != NULL){ 
						attrCount--;
						continue;
					}
					if(attrCount != 2)
						strcat(setStr,", ");
					strcat(setStr,oneAttr);
				}//end while
				response = setStr;
			}else{
				response = response+i+1;
			}//end if(strstr...
			
			while((oneAttr = strsep(&(response), ",")) != NULL){
				if ((onePart = strsep(&(oneAttr), "=")) != NULL)
					sprintf(&value[m++][0],"%s",oneAttr);
			}//end while((oneAttr...
			strcpy(resptmp,temp);
			sprintf(sqlbuffer,"show fields from OMCR_%s",ClassId);
			mysql_query(mysql_sock,sqlbuffer);
			result = mysql_store_result(&mysql);
			if(result == NULL){
				return(1);
			}else if(mysql_num_rows(result) == 0){
				mysql_free_result(result);
			}
			m = 1,i = 0;
			while((row=mysql_fetch_row(result)) > (MYSQL_ROW) 0){
				if(i<2){
					i++;
				}else {
					if(m == 1)
						sprintf(field,"%s=%s",row[0],&value[m++][0]);
					else
						sprintf(field,"%s,%s=%s",field,row[0],&value[m++][0]);
				}
			}//end while((row..
			sprintf(sqlstring,"UPDATE OMCR_%s SET %s WHERE bssid=%d AND ObjectId='%s'",
				ClassId, field, pBssConn->bssid, ObjectId);
		}
		execute_sql(sqlstring,0);
		return(0);
	}
	else             /* OID RESPONSE -> update BSSTREE table */
	{
		sprintf(sqlstring, 
            "UPDATE OMCR_BSSTREE SET Presence=1 WHERE bssid=%d AND ObjectId='%s'",
            pBssConn->bssid, ObjectId);
	}
	execute_sql(sqlstring,0);
	return(0); 
}
/*
 * Find the max sockfd from *bsplus[] -> BssConn 
 */
int max(int nbsplus,tImpConn *bsplus[])
{
    int i;
    tImpConn *ptr;
    int maxfd=0;

    for (i=nbsplus-1; i>=0; i--)
    {
        ptr = bsplus[i];
        if (maxfd <= ptr->sockfd) {
            maxfd = ptr->sockfd + 1;
        }
        ptr++;
    }
    return (maxfd);
}
/*
 * Maintain a IMP connection with all the manageable iwbox
 */
void ImpConnMultiplexer()
{
	tIMPHDR header;
	bool Status;
	
	fd_set readfds;
	struct timeval timeout;
    int len;
	char buffer[BUFMAX]="\0";
    int i;
    int acrd_bssid;
    tImpConn *pBssConn = NULL;
    int bsType;
	

    /*
     * bsplus_down[] contains the BSS system stored in MySQL() database
     * InformIwBoxMonitor() will tell monitor program the bsplus ip/bssid list
     *
     * sockfd store the socket fd and width=max(BssConn[].sockfd)+1
     * sockfd is indexed as BssConn[0,1, ...,nbsplus-1].sockfd
     */

//    for (num=0;num<2;num++)
	
    if (width_change)
    {
        width = max(nbsplus,bsplus);
        if (width<monitor_fd+1)
            width=monitor_fd+1;
        width_change=0;
    }
	
	/* if connected == CONNECTED_STATE_MAX */
    for (i=0; i<nbsplus; i++)
    {
        pBssConn = bsplus[i];
        if ( pBssConn->connected == CONNECTED_STATE_MAX )
        {
            DispatchNmiCommand(pBssConn);
        }
     }
    /* send heartbeat */
    this_heartbeat=time((time_t*)0);
    if (abs(this_heartbeat - last_heartbeat) >= HEARTBEAT_INTERVAL)
    {
		int tmpResult;
		tmpResult=getLedStatus();
        if(tmpResult!=0)
		{
			perror("getLedStatus() failed\n");
        }
        for (i=NO_OF_BSS*NO_OF_BTSMgr-1; i>=0; i--)
        {
            acrd_bssid = (int) i / NO_OF_BTSMgr;
            pBssConn = &BssConn[acrd_bssid];
			
            if ((bts_led[i]).presence && (pBssConn!=0) && (pBssConn->connected == CONNECTED_STATE_MAX) )
            {
				bsType=checkBsType(i/NO_OF_BTSMgr);
					
                send_heartbeat(i,&(bsc_led[acrd_bssid]),&(bts_led[i]),0,0,0,bsType);
            }
        }/* End for(i=NO_OF... */
            
        for (i=0; i<nbsplus; i++)
        {
            pBssConn = bsplus[i];
            /*
             * Poll BSC to identify whether it is functioning
             */
            if ( pBssConn->connected == CONNECTED_STATE_MAX )
            {
                // Send a "contents" commands to BSS
                ProcessUserCommand(pBssConn,"contents",(u32) 0);
             }
        }
        last_heartbeat = this_heartbeat;
    }
    FD_ZERO(&readfds);
///////////////////////////////////////////////////
    if (monitor_fd != -1)
        FD_SET(monitor_fd, &readfds);
//////////////////////////////////////////////////
    for (i=0; i<nbsplus; i++)
    {
        pBssConn = bsplus[i];
        FD_SET(pBssConn->sockfd, &readfds);
    }

    this_round = time((time_t*)0);
    if ((this_round - last_round) <= SELECT_INTERVAL)//2L
    {
        timeout.tv_sec = 0;    /* 1 second for now */
        timeout.tv_usec = 500000;
        ret = select(width, &readfds, (fd_set *) 0, (fd_set *) 0, &timeout);
    }
    else
    {
        ret = 0;
    }
	if (ret == -1)
    {
        perror( "select() error\n");
        // Send ALARM to MySQL
    }
    else if (ret == 0)  // BssComm receive no event
    {
        last_round = this_round;
        // Change logfile if date changed
        //changeLogFilename();
        if ( CmdBufferPtr != CMD_BUFFER_FULL) /* Queue is not full */
        {
            retrieveCmdFromDatabase();
        }
/////////////////////////////////////////////////////////////          
        /*  If monitor program die, recover it!!*/
        if (!monitoring)
        {
            startIwBoxMonitor("127.0.0.1", MONITOR_PORT);
            if (width<monitor_fd+1)
                width=monitor_fd+1;
        }
/////////////////////////////////////////////////////////////
        /* Check how long did BSS start */
        for (i=0; i<nbsplus; i++)
        {
            pBssConn = bsplus[i];
            if (pBssConn->connected < CONNECTED_STATE_MAX)
            {
                if ((pBssConn->bootupTime>0L) &&
                    ((time((time_t*)0)-pBssConn->bootupTime) >(unsigned long) wait_interval))
                {
                    pBssConn->connected=CONNECTED_STATE_MAX;
                    update_bsstable_status(pBssConn);
                    if (pBssConn->uploaded == 0) //Never upload before
                    {
                        requestBssCfg(pBssConn);// upload,get all
                        pBssConn->uploaded = 1;
                        sprintf(sqlstring,
                            "UPDATE OMCR_BSSTABLE SET uploaded=1 WHERE bssid=%d",
                            pBssConn->bssid);
                        execute_sql(sqlstring,0);
                    }
                }
            }
         }/* End check how long */
         /* continue because select() return zero */
         return;
    }
    //-- For monitor socket --//
////////////////////////////////////////////////////////////////////////////////////
    if ((monitor_fd!=-1)&&FD_ISSET(monitor_fd, &readfds) && monitoring) {
        buffer[0]=0;
		buffer[1]=0;
        ret--;
        len = read(monitor_fd, buffer, 2);
        if ( (len == 2) && isdigit(buffer[0]) && isdigit(buffer[1]) )
        {
            buffer[2]='\0';
            len = atoi(buffer);
            if ( read(monitor_fd, buffer, len) == len )
            {
                buffer[len]='\0';
                GetMonitorResult(buffer, &readfds);
            }
            else
                stopIwBoxMonitor();
        }
        else
            stopIwBoxMonitor();
    }
//////////////////////////////////////////////////////////////////////////////////    
    for (i=0; i<nbsplus; i++)
    {
        /*
         * All fd has been read (ret==0),
         * furthur check not needed.
         */
        if (ret<=0) {
            break;
        }
        pBssConn = bsplus[i];
        if (FD_ISSET(pBssConn->sockfd, &readfds) && pBssConn->sockfd>0)
        {
            ret--;
            Status = CheckForMessages(pBssConn, &header, &readfds, last_heartbeat);
        }
        
        if(pBssConn->upload_in_progress)
        {
        	requestBssCfg(pBssConn);
        }
    }       /* end_of_for (i= */
            /* end_of_for (;;) */
}           /* end_of_ImpConnMultiplexer( */

void imp_init()
{
    int i;
    tImpConn *pBssConn;
    //char *bssversion;

    // get bssversion
    /*if ( (bssversion=getenv("bssversion")) == (char *) 0)
    {
        bssversion = BSSVERSION;
    }*/
    environ_var("MEAS_PERIOD",MEASUREMENT_INTERVAL,&stat_interval);
    environ_var("WAIT_TIME",WAIT_TIME,&wait_interval);
    // init mysql database
	connectDB();
    initOMCR_COMMANDTable();
    GetBssMaxConfigFromDB();
    alarmevent_row_no = alarmevent_init;
    btsmeas_row_no=btsmeasurements_init;
	networkevent_row_no = networkevent_size;
    GetAllTableName();
    
    MemoryAllocation();

    for (pBssConn=BssConn + no_of_bss_per_pacs-1;pBssConn >= BssConn;pBssConn--)
    {
        initImpConn(pBssConn);
    }
    for (i=0; i<CMD_BUFFER_SIZE; i++)
    {
        (CmdBuffer[i]).available = TRUE;
    }
    /*
     * bsplus is an array of tImpConn points that points to BssConn buffer
     * nbsplus records the number of BSPlus  
     */
    mysql_query(mysql_sock, "SELECT bssid,ip,name,uploaded FROM OMCR_BSSTABLE WHERE ip<>''");
    result = mysql_use_result(&mysql);
  
    // Put ImpConn to bsplus_down[]
    nbsplus = nbsplus_down=0;
    while ((row = mysql_fetch_row(result)))
    {
        if (nbsplus_down >= no_of_bss_per_pacs )
        {
            exit(4);
        }
        if (atoi(row[0]) < no_of_bss_per_pacs)
            AddImpConn(atoi(row[0]), row[1], row[2], atoi(row[3]));
    }
    if (mysql_errno(&mysql))
    {
        exit(5);
    }
    mysql_free_result(result);

    syncBssTreeAlarm();
    initBssStatusTransmitter();//from bss_hb.cpp
}


/*****************main *********************/

static struct itimerval itimer, old_itimer;

void onTimer();
void setTimer();
void setup_daemon(void);


/*************************************************
Function:        // main
Description:     // µ÷ÓÃImpConnMultiplexerÄ£¿é£¬ÊÇÄ£¿éµÄÖ÷º¯Êý
Calls:           // imp_init;
Called By:       // 
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 1:successful; 0:failed;
Others:          // 
*************************************************/
int main(int argc, char *argv[])
{
	char runMode;
	signal(SIGHUP,cleanUp);
    signal(SIGINT,cleanUp);
	imp_init();

	if (argc > 0) {
		runMode = getopt(argc, argv, "d");
		switch (runMode) {
		case 'd':
			setup_daemon();
			break;
		case '?':
			break;
		}
	}
	setTimer();
	while (1) {
		usleep(50);
	}
	cleanUp(0);
	return (1);
}

/*************************************************
Function:        // onTimer
Description:     // ¶¨Ê±Æ÷º¯Êý
Calls:           // ImpConnMultiplexer;
Called By:       // 
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 
Others:          // 
*************************************************/
void onTimer()
{
	ImpConnMultiplexer();
	timerCounter++;
	
	if (timerCounter > 50000) {
		timerCounter = 0;
	}
}

/*************************************************
Function:        // setTimer
Description:     // ÉèÖÃ¶¨Ê±Æ÷º¯Êý
Calls:           // onTimer;
Called By:       // 
Table Accessed:  // 
Table Updated:   // 
Input:           // 
Output:          // 
Return:          // 
Others:          // 
*************************************************/
void setTimer()
{
	struct sigaction act;
	act.sa_handler = onTimer;
	sigemptyset(&act.sa_mask);
	act.sa_flags = 0;
	if (sigaction(SIGALRM, &act, NULL) < 0) {
		perror("Produce Sigaction");
		exit(1);
	}

	itimer.it_interval.tv_sec = 0;
	itimer.it_interval.tv_usec = 20 * 1000;
	itimer.it_value.tv_sec = 0;
	itimer.it_value.tv_usec = 20 * 1000;

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

void setup_daemon(void)
{
	/*
	int i;
	
	for (i = 0; i < 3; ++i) {
		close(i);
	}
	*/
	switch (fork()) {
	case -1:
		perror("setup_daemon(), 1st fork()");
		exit(2);
	default:
		exit(0);
	case 0:
		if (setsid() == -1) {
			perror("setup_daemon(), setsid()");
			exit(3);
		}
		switch (fork()) {
		case -1:
			perror("setup_daemon(), 2nd fork()");
			exit(3);
		default:
			exit(0);
		case 0:
			umask(0);
			/* and return with daemon set up */
			return;
		}
	}
}

