#include "ModeMaster.h"
#include "SourceData.h"
#include "Logger.h"
#include "SyncList.h"
#include "MasterJobThread.h"

// class CServiceMode : Service Master Mode class
CMasterMode::CMasterMode(CProcessSocketControl * pclient)
	: CServiceMode(pclient)
{
}

CMasterMode::~CMasterMode()
{
}

bool CMasterMode::CreateSyncList(CReqMasterData &d)
{
	return m_synclist.CreateList(d);
}

void CMasterMode::Execute()
{
	std::string message = "";
	list<CMasterJobThread*> listThread;
	list<CWorkResult*> listWorkResult;
	bool bResult = true;

	if (IsEmpytSycnList())
	{
		LOG(LERR, "Empty Master Mode Sync Data");
		message = "Empty Master Mode Sync Data";	
		// return 처리전에  꼭 client 에 결과 전송처리할 것
		// 결과 전송하지 않으면.. 무한 대기함.
		m_pclient->SendResultSyncToClient( true, message );

		return;
	}
	
	CMasterJobThread *pMasterJobThread = NULL;
	while( IsEmpytSycnList() == false )
	{
		// Master job work thread 수행 결과를 받기 위한 변수
		CWorkResult* pResult = new CWorkResult;

		CSyncInfo objSyncInfo = m_synclist.Pop();
		LOG( LDBG, "Master[%s] Slave[%s] RCTS [%s]", objSyncInfo.sync_master.c_str() , objSyncInfo.sync_slave.c_str(), objSyncInfo.sync_rcts.c_str());
		
		pMasterJobThread = new CMasterJobThread(objSyncInfo, pResult);
		listWorkResult.push_back(pResult);
		// thread 구동.....
		if( pMasterJobThread->Start() == true )
		{
			listThread.push_back(pMasterJobThread);
			LOG(LDBG, "MasterJobThread start ok.");
		}
		else
		{
			LOG(LINF, "MasterJobThread start failed.");
			
			// 다른 sync 작업은 성공적으로 쓰레드 생성 될 수 있므로 해당 sync item만 에러 설정함
			//message = "MasterJobThread create start failed.";
			//m_pclient->SendResultSyncToClient( bResult, message );
			pResult->bSuccess = false;
			pResult->strMasterID = objSyncInfo.sync_master;
			pResult->strMessage = "MasterJob Thread create start failed.";
			if( pMasterJobThread != NULL )
			{
				delete pMasterJobThread;
			}			
		}
	}
	
	// 전체 쓰레드가 종료될때까지 대기 하기 위해서 thread join 처리
	while (!listThread.empty())
	{
		list<CMasterJobThread *>::iterator list_iter = listThread.begin();

		CMasterJobThread * pthread = *list_iter;
		pthread_t handle = pthread->GetThreadHandle();
		LOG(LDBG, "Thread Join [%lu]", (unsigned long)handle);
		pthread_join(handle, NULL);
		LOG(LDBG, "Thread Join realese [%lu]", (unsigned long)handle);
		listThread.erase(list_iter);
		delete pthread;
	}

	// 성공 실패 여부를 확인 하는 작업 필요.
	while (!listWorkResult.empty())
	{
		list<CWorkResult*>::iterator iter = listWorkResult.begin();
		CWorkResult* pResult = *iter;
		// 최종 성공 여부 전달 판단
		if( pResult->bSuccess == false)
		{
			bResult = false;
		}

		// " MasterTranid;메세지|MasterTranid;메세지|MasterTranid;메세지|MasterTranid;메세지"
		// return message 제작
		if( message.size() != 0 )
		{
			message += "|";
		}
		message += pResult->strMasterID;
		message += ";";
		message += pResult->bSuccess ? "T":"F";
		message += ";";
		message += pResult->strRcts;
		message += ";";
		message += pResult->strMessage;
		if(pResult->strSyncFileName.size() != 0)
		{
			message += ";";
			message += pResult->strSyncFileName;
		}

		listWorkResult.erase(iter);
		delete pResult;
	}

	// 연결된 client로 수행 작업 결과들 리턴
	m_pclient->SendResultSyncToClient( bResult, message );

	LOG(LINF, "Result : %s", message.c_str());
	return;
}


