#include "GmsSendThread.h"
#include "Logger.h"

#include <unistd.h>
#include <errno.h>
#include <string.h>

// GMS 전송 주기 (sec)
// rc_vrcd  :  8 sec
// rc_statd : 10 sec ( sqlite 의 SQLITE_BUSY 발생 최소화 목적 )
// rc_mond  : 10 sec ( FHS csagentd 로 부터 10 sec 단위로 시스템 정보를 수신하므로.. )
#define GMS_SEND_INTERVAL              10


// 생성자..
CGmsSendThread::CGmsSendThread( CShmManager * pShmManager )
	: m_pShmManager( pShmManager)
{
	// Thread Handle 초기화
	m_threadHandle = 0;

	// 저장 객체 초기화 및 빠른 처리를 위한 예약 처리.
	m_vecSystemInfo.clear();
	
	// 1024 개 까지 저장가능토록... (640 * 1024 = 640 KByte)
	m_vecSystemInfo.reserve( MAX_CLIENT_COUNT );

}

// 소멸자..
CGmsSendThread::~CGmsSendThread()
{
	// Thread 가 동작 중인 경우 Thread 동작 정지 처리.
	if( m_threadHandle != 0 )
		pthread_cancel(m_threadHandle);
}


// Thread 를 생성하여 작업을 시작한다...
bool CGmsSendThread::Start()
{
	int nResult = pthread_create( &m_threadHandle, NULL, CGmsSendThread::threadFunc, this );
	if( nResult != 0 )
	{
		// Thread 생성 실패시...
		int errorNum = errno;
		LOG( LERR, "GmsSendThread: Thread create failed.[%d][%s]", errorNum, strerror(errorNum) );

		return false;
	}

	return true;
}


// Thread 함수...
void * CGmsSendThread::threadFunc( void * arg )
{
	CGmsSendThread * pObject = reinterpret_cast<CGmsSendThread *>(arg);
	pthread_detach( pthread_self() );

	// 초기 기동시...FHS 상태 정보가 아직 수집되지 않은 상태이므로...
	// 잠시 sleep 했다가.. 작업을 시작한다.
	sleep( GMS_SEND_INTERVAL );

	// 주기적으로 GMS 에 전송 처리 
	while( 1 )
	{
		pthread_testcancel();
		pObject->Execute();
		pthread_testcancel();

		sleep( GMS_SEND_INTERVAL );
	}

	// Thread 종료시 Handle 초기화
	pObject->m_threadHandle = 0;

	return NULL;
}


// 실제 GMS 로 RC 상태 정보 전송 작업을 수행한다...
void CGmsSendThread::Execute()
{
	
	// 공유메모리의 RC 정보를 멤버변수 m_vecSystemInfo 에 저장 처리.
	m_vecSystemInfo.clear();
	m_pShmManager->GetGmsSendList( m_vecSystemInfo );
	
	// 멤버 변수 m_vecSystemInfo 에 저장된 RC 정보를 GMS 로 전송 처리.
	// => 전송할 정보가 없을 경우에는 전송하지 않는다.
	// => GMS Web 상에는 이전에 수신된 정보로 표시됨.
	if( m_vecSystemInfo.empty() == false )
	{
		/*
		// Debug 목적..
		for( unsigned int i = 0; i < m_vecSystemInfo.size(); ++i )
		{
			_LOG( LDBG, "GmsSendThread: vector result [%s][%lu] [%d][%lu][%u] "
				  , m_vecSystemInfo[i].domain, m_vecSystemInfo[i].stamp
				  , m_vecSystemInfo[i].manual_disable, m_vecSystemInfo[i].free, m_vecSystemInfo[i].traffic_ob );
		}
		*/

		// GMS 로 전송 처리..
		// 전송 결과는 본 Thread 에서는 중요하지 않으므로.. 반환값 검사 안함.
		unsigned int nSendSize = sizeof( struct PacketDataGms ) * m_vecSystemInfo.size();
		m_socketGms.SendData( m_vecSystemInfo.size(), (char *)( &m_vecSystemInfo[0] ), nSendSize );

		// 로깅
		_LOG( LINF, "GmsSendThread: GMS send data. count [%zu]", m_vecSystemInfo.size() );
	}
	else
	{
		// GMS 로 전송할 Data 가 없는 경우.. 로깅 처리..
		_LOG( LINF, "GmsSendThread: GMS send data empty. not send.." );
	}

	return;
}
