#include	"unp.h"
#include    "unpipc.h"

//pthread_mutex_t vrcd_lock = PTHREAD_MUTEX_INITIALIZER;
char logString[1024];

void vrcd_timeout()
{
	WriteSHLog_safe("------- vrcd func timeout!! -------\n");
	return;
}

void vrcd_thread_make(int i)
{
    void    *vrcd_thread_main(void *);

    /* make tcp listen thread (for Update Share Memory. recieve from vrcd) */
    Pthread_create(&vrcd_tptr[i].thread_tid, NULL, &vrcd_thread_main, (void *)i);
    return;     /* main thread returns */
}

void * vrcd_thread_main(void *arg)
{
    int             res;
    int             vrcd_func(int, int);
    socklen_t       clilen;
    struct sockaddr *cliaddr;
	char			logString[1024];

    cliaddr = Malloc(vrcd_addrlen);

	WriteSHLog_safe("vrcd thread %d starting....\n", (int)arg);

    for ( ; ; ) {
		int connfd;
        clilen = vrcd_addrlen;
        Pthread_mutex_lock(&vrcd_lock);
        connfd = Accept(vrcdfd, cliaddr, &clilen);
        Pthread_mutex_unlock(&vrcd_lock);

		// huibong
		//WriteSHLog_safe("vrcd thread %d, accept OK\n", (int)arg);

		res = -1;
        vrcd_tptr[(int) arg].thread_count++;

        res = vrcd_func(connfd, (int)arg);
	
		// huibong
		//WriteSHLog_safe("vrcd thread %d, vrcd_func return.[%d]\n", (int)arg, res);

#ifdef __DEBUG__
        if (res == 0)
            fprintf(stderr, "\nOne vrcd Job Success!\n");
        else
            fprintf(stderr, "\nOne vrcd Job Fail!!\n");
#endif

//#ifdef	__SETLOG__
#ifdef	__DEBUG__
		if (res != 0)
		{
			WriteSHLog_safe("FAIL! ::vrcd thread number(%d), repeate(%lu)\n", (int)arg, vrcd_tptr[(int) arg].thread_count);
		}
#endif
		if (connfd)
	        Close(connfd);
		SafeProcessRunSpinWait();
    }
}

int vrcd_func(int cfd, int thnum)
{
    struct common_message_header *cheader;
    struct svr_status *recv_serv;

    unsigned long int nread;
    unsigned long int bodylen;
    int svr_num;
	int nBodyRead;
    char header_buf[1024];
    char *vrcd_buf = NULL;
    //char sndResult[32];
	
	// huibong
	//WriteSHLog_safe("vrcd thread: start\n");

    if ((nread = Readn(cfd, header_buf, MaxSizeOfCMH)) == 0)
	{
        return 1;
	}
	// huibong
	//WriteSHLog_safe("vrcd thread: nread [%u]\n",nread);

#if 0
    fprintf(stderr, "Receive Size(header) from rc_vrcd: %lu\n", nread);
#endif
    /* Casting receiving string */
    cheader = (struct common_message_header *)header_buf;

    /* view common message header */
    //view_header_packet(cheader);
    bodylen = ntohl(cheader->ulBodyLength);

	vrcd_buf = (char *)malloc(bodylen+128);
	memset(vrcd_buf, 0, bodylen+128);
	
	// huibong
	//WriteSHLog_safe("vrcd thread: body len [%lu]\n",bodylen);

    if ((nread = Readn(cfd, vrcd_buf, bodylen) == 0))
	{
		free(vrcd_buf);
        return 1;
	}

	// huibong
	//WriteSHLog_safe("vrcd thread: nread 2 [%u]\n",nread);

	Pthread_mutex_lock(&vrcd_lock2);
    if (running_vrcd_thread_count >= 5)
    {
		//WriteSHLog_safe("-------------------------- vrcd thread Passed ---------------------------\n");
        free(vrcd_buf);
		Pthread_mutex_unlock(&vrcd_lock2);
        return 1;
    }
    else {
        running_vrcd_thread_count++;
		Pthread_mutex_unlock(&vrcd_lock2);
    }

#if 0
    fprintf(stderr, "Receive Size(body) : (%lu)\n\n\n", bodylen);
#endif
    /* Casting receiving string */
	nBodyRead = 0;
    svr_num = *((int *)(vrcd_buf + nBodyRead));
	nBodyRead += sizeof(int);
    recv_serv = (struct svr_status *)(vrcd_buf + nBodyRead);
	
	// huibong
	WriteSHLog_safe("rc_statd receive: count[%3d], 0th fhs[%s]\n", svr_num, recv_serv[0].du.domain);

    /* view body packet */
	/*
    int i;
    for (i=0; i < svr_num; i++)
    {
        view_serv_status_packet(recv_serv);
        recv_serv++;
    }
	*/

	Semop(vrcd_semid, &waitop, 1);
    updateShm(recv_serv, svr_num, thnum);
	running_vrcd_thread_count--;
	Semop(vrcd_semid, &postop, 1);
	
#ifdef __DEBUG__
	fprintf(stderr , "vrcd_func@@@@@@@@@@@@@@\n");
#endif
    /* Send Result */
    //sprintf(sndResult, "%d", 1);
    //Writen(cfd, sndResult, 32);

	free(vrcd_buf);
    return 0;
}

void updateShm(struct svr_status *r_ss, int r_ss_num, int thnum)
{
    servinfo_t *start_ptr, *ii;

    int i, j;
    int retval;
	int shm_size;
    int dflag;
    char *addr = NULL;

	shm_size = get_sizeof_shm();
	start_ptr = get_shm_start_pointer();

    for (i = 0; i < r_ss_num; i++) {
        dflag = 0;
        for (ii = start_ptr; strcmp(ii->m_pszServName, END_OF_SHM); ii++) {
			if (ii->m_pszServName[0] == '\0')
	            break;
#if 0
			/* test : 090707 */
			if (!strcmp(ii->m_pszServName, "GAMPLE_NS_RTS1036") || !strcmp(ii->m_pszServName, "GAMPLE_NS_RTS1046"))
			{
				WriteSHLog_safe("------- check invalidate -------\n");
				WriteSHLog_safe("Domain : %s, TotalDisk : %llu\n", ii->m_pszDomainName, (r_ss + i)->du.total);
			}
#endif			

			if (ii->m_ServType != 2 || ii->m_Status == SERV_DEAD || ii->m_Status == NO_MONITOR)
				continue;
            if (ii->m_pszDomainName != NULL && strcmp(ii->m_pszDomainName, "")) {
                if (!strcmp(ii->m_pszDomainName, (r_ss + i)->du.domain)) {
                    memcpy((char *)&(ii->ss), (char *)(r_ss + i), sizeof(struct svr_status));
                    dflag = 1;
                }
				else if (!strcmp(ii->m_pszDomainName, (r_ss + i)->du.hostname)) {
                    memcpy((char *)&(ii->ss), (char *)(r_ss + i), sizeof(struct svr_status));
                    dflag = 1;
                }
            }
        }

        // Check If IP 
		if (dflag == 0)
		{
			struct in_addr *inp = NULL;
	        if (((retval = inet_aton((r_ss + i)->du.domain, inp)) != 0) && dflag == 0) {
			    for (ii = start_ptr; strcmp(ii->m_pszServName, END_OF_SHM); ii++) {
					if (ii->m_pszServName[0] == '\0')
						break;
					if (ii->m_ServType != 2 || ii->m_Status == SERV_DEAD || ii->m_Status == NO_MONITOR)
						continue;
				    if (!strcmp(ii->m_szIpString, (r_ss + i)->du.domain)) {
					    strncpy(ii->m_pszDomainName, (r_ss + i)->du.domain, MAX_DOMAIN_NAME);
						memcpy((char *)&(ii->ss), (char *)(r_ss + i), sizeof(struct svr_status));
	                    dflag = 1;
		            }
			    }
	        }
		}

        // Check If Domain
		{
			struct hostent *he = NULL;
			if (dflag == 0)
			{
				addr = ((r_ss + i)->du.hostname[0] == '\0') ? (r_ss + i)->du.domain : (r_ss + i)->du.hostname;
		        if (addr != NULL)
			        he = gethostbyname(addr);
				if (he == NULL)
				    continue;
			}

		    if (dflag == 0)
			{
	            for (ii = start_ptr; strcmp(ii->m_pszServName, END_OF_SHM); ii++)
		        {
					if (ii->m_ServType != 2 || ii->m_Status == SERV_DEAD || ii->m_Status == NO_MONITOR)
						continue;
	                for (j = 0; he->h_addr_list[j]; j++)
		            {
			            if (!strncmp(ii->m_szIpString, inet_ntoa(*(struct in_addr *)he->h_addr_list[j]), MAX_IP_STRING))
				        {
#ifdef __DEBUG__
							WriteSHLog_safe("[+++++] ServName : %s , IPADDR : %s(%s) , DomainName : %s\n", ii->m_pszServName, ii->m_szIpString, inet_ntoa(*(struct in_addr *)he->h_addr_list[j]), addr);
#endif
	                        strncpy(ii->m_pszDomainName, addr, MAX_DOMAIN_NAME);
		                    memcpy((char *)&(ii->ss), (char *)(r_ss + i), sizeof(struct svr_status));
							break;
	                    }
		            }
			    }
	        }
	    }
	}
    munmap((void *)start_ptr, shm_size);
}

void view_header_packet(struct common_message_header *cheader)
{
    /******************************************************************************/
    /**************************** View receive packet(header) *********************/
    /******************************************************************************/
    fprintf(stderr, "Transaction ID -> [ %s ]\n", cheader->szTransactionID);
    fprintf(stderr, "Mode           -> [ 0x%04X ]\n", ntohl(cheader->ulMode));
    fprintf(stderr, "Issuer         -> [ %s ]\n", cheader->szIssuer);
    fprintf(stderr, "Service ID     -> [ %s ]\n", cheader->szServiceID);
    fprintf(stderr, "Result         -> [ 0x%04X ]\n", ntohl(cheader->ulResult));
    fprintf(stderr, "Body Length    -> [ %lu ]\n\n", (unsigned long)ntohl(cheader->ulBodyLength));
    fflush(stderr);
}

void view_serv_status_packet(struct svr_status *recv_serv)
{
    /******************************************************************************/
    /**************************** View receive packet(body) ***********************/
    /******************************************************************************/
    fprintf(stderr, "Time stamp     -> [ %ld ]\n", (long)recv_serv->stamp);
    fprintf(stderr, "Domain         -> [ %s ]\n", recv_serv->du.domain);
    fprintf(stderr, "Total          -> [ %llu ]\n", (recv_serv->du.total));
    fprintf(stderr, "Free           -> [ %llu ]\n", (recv_serv->du.free));
    fprintf(stderr, "Manual y/n     -> [ %d ]\n", (recv_serv->du.manual_disable));
    fprintf(stderr, "upload level   -> [ %d ]\n", (recv_serv->du.upload_level));
    fprintf(stderr, "disk backlog   -> [ %d ]\n", (recv_serv->du.disk_backlog));
    fprintf(stderr, "disk percent   -> [ %d ]\n", (recv_serv->du.disk_percent));
    fprintf(stderr, "conn establish -> [ %d ]\n", (recv_serv->du.connection_established));
    fprintf(stderr, "conn total     -> [ %d ]\n", (recv_serv->du.connection_total));
    fprintf(stderr, "traffic ip     -> [ %lu ]\n", (recv_serv->du.traffic_ip));
    fprintf(stderr, "traffic ib     -> [ %lu ]\n", (recv_serv->du.traffic_ib));
    fprintf(stderr, "traffic op     -> [ %lu ]\n", (recv_serv->du.traffic_op));
    fprintf(stderr, "traffic ob     -> [ %lu ]\n", (recv_serv->du.traffic_ob));
    fprintf(stderr, "Hostname       -> [ %s ]\n\n", recv_serv->du.hostname);
    fflush(stderr);
}
