#include "AliveFhsCacheThread.h"

#include "Logger.h"

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


// alive fhs 정보의 cache 갱신 주기 ( sec )
#define ALIVE_FHS_CACHE_INTERVAL      1


// 공유메모리 FHS 정보가 기동초기 완전하지 않아...
// 지정된 시간(sec) 동안 skip 처리 하기 위한 define.
#define ALIVE_FHS_SKIP_TIME           6


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

	// vector 객체에 대한 포인터 초기화.
	m_vecAliveFhs1.clear();
	m_vecAliveFhs2.clear();
	m_pCurrent = &( m_vecAliveFhs1 );
	m_pOld     = &( m_vecAliveFhs2 );

	// Skip flag 는 기동 초기 설정 처리.
	m_bResultSkip = true;
}

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

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

		return false;
	}

	return true;
}

// Thread 함수
void * CAliveFhsCacheThread::threadFunc( void * arg )
{
	CAliveFhsCacheThread * pObject = reinterpret_cast<CAliveFhsCacheThread *>( arg );
	pthread_detach( pthread_self() );
	
	// SKIP 상태 해지를 판단하기 위한 변수.
	int nSkipCount = 0;
	
	// 주기적으로 alive FHS cache 갱신 처리.
	while( 1 )
	{
		pthread_testcancel();
		pObject->Execute();
		pthread_testcancel();

		// 지정된 횟수를 초과하면 Skip 처리를 해제한다.
		if( pObject->m_bResultSkip == true )
		{
			if( nSkipCount > ALIVE_FHS_SKIP_TIME )
			{
				pObject->m_bResultSkip = false;

				_LOG( LINF, "AliveFhsCacheThread: alive FHS SKIP mode end. ");
			}
			else
			{
				++nSkipCount;
				//_LOG( LDBG, "AliveFhsCacheThread: Alive FHS SKIP..." );
			}
		}

		// 지정된 주기마다 cache 갱신.
		sleep( ALIVE_FHS_CACHE_INTERVAL );
	}
	
	// Thread 종료시 Handle 초기화
	pObject->m_threadHandle = 0;

	return NULL;
}


// 실제 cache 처리를 담당하는 함수.
void CAliveFhsCacheThread::Execute()
{
	// 이전 정보를 저장한 vector 초기화.
	m_pOld->clear();

	// 공유메모리로부터 Alive FHS 정보 저장 처리
	m_pShmManager->GetAliveFhsList( *m_pOld );
	
	// 최신 Alive FHS 정보를 사용하도록 포인터 정보 변경 처리.
	m_pTemp    = m_pCurrent;
	m_pCurrent = m_pOld;
	m_pOld     = m_pTemp;
	
	// SKIP 모드가 아닌 상태에서 Alive FHS 정보가 유효하지 않은 경우만 로깅 처리.
	if( m_pCurrent->size() == 0 && m_bResultSkip == false )
	{
		_LOG( LWAR, "AliveFhsCacheThread: Alive FHS not exist. [%zu]", m_pCurrent->size());
	}

	return;
}

// Alive FHS 목록 제공을 위한 interface 함수.
// param   vecResult [out] alive fhs 결과 정보를 저장하기 위한 변수.
// return  -1   : FHS 정보가 아직 불안전하니 SKIP 처리하라는 의미
//        그 외 : alive fhs 갯수.
int CAliveFhsCacheThread::GetAliveFhs( std::vector<struct FhsServiceStatInfo> & vecResult )
{
	// skip flag 가 설정된 경우...
	if( m_bResultSkip == true )
		return -1;
	else
	{
		// 정상 상황인 경우...
		vecResult = *( m_pCurrent );

		return m_pCurrent->size();
	}
}
