/***************************************************************************
                   Config Class (DaemonConfigs.cpp)
                -----------------------------------------

	begin      : 2015/04/28
	copyright  : (C) 2013 Solbox Inc.
	author     : Development Team
	email      : storage.sd@solbox.com
	version    : 3.5

	CopyRight(C) 2005 Solbox Inc. All Rights reserved.
	Redistribution and use in source and binary forms, with or with out
	modification, are not permitted in outside of Solbox Inc.
***************************************************************************/
#include "DaemonConfigs.h"
#include <cstdlib>
#include <iostream>
#include "Config.h"

CDeamonConfig *CDeamonConfig::m_pInstance = NULL;

CCommonConfig::CCommonConfig( string szFilename, string szProgramName )
	: m_szConfigFile(szFilename), m_szProgramName(szProgramName)
{
	m_nAliveCheckPort = 0;
}

CCommonConfig::~CCommonConfig()
{
}

bool CCommonConfig::LoadConf()
{
#ifdef _DEBUG
	cout << "CCommonConfig::LoadConf() =>" << endl;
#endif // _DEBUG
	string szValue;

	// Config 처리를 위한 객체 생성
	Config conf;

	// Config File open
	if( conf.Open( m_szConfigFile ) == false )
	{
		m_szErrMessage = "Config file open failed.[" + m_szConfigFile + "]";
		return false;
	}

	// log path
	if( conf.GetConfig( "COMMON", "DEFAULT_LOG_DIR", szValue ) )
	{
		m_szAppLogRoot = szValue;
	}

	// log level
	if( conf.GetConfig( "COMMON", "LOG_LEVEL", szValue ) )
	{
		m_nLogLevel = atoi( szValue.c_str() );
	}

	// RCDB Access Information
	if( conf.GetConfig( "COMMON", "RCDB_IP", szValue ) )
	{
		m_cDatabaseInfo.m_szRcdbIp = szValue;
	}
	if( conf.GetConfig( "COMMON", "RCDB_PORT", szValue ) )
	{
		m_cDatabaseInfo.m_nRcdbPort = atoi( szValue.c_str() );
	}
	if( conf.GetConfig( "COMMON", "RCDB_DB_NAME", szValue ) )
	{
		m_cDatabaseInfo.m_szRcdbName = szValue;
	}
	if( conf.GetConfig( "COMMON", "RCDB_ACCT", szValue ) )
	{
		m_cDatabaseInfo.m_szRcdbAcct = szValue;
	}
	if( conf.GetConfig( "COMMON", "RCDB_ACCT_PW", szValue ) )
	{
		m_cDatabaseInfo.m_szRcdbAcctPw = szValue;
	}

	// RC ID
	if (conf.GetConfig("COMMON", "RCID", szValue))
	{
		m_szRcid = szValue;
	}

	// RCTS SERVER
	if (conf.GetConfig("COMMON", "RCTS_SERVER", szValue))
	{
		m_szRctsServer = szValue;
	}
	
	// FHS fimngd alive check port
	if (conf.GetConfig("COMMON", "FHS_PORT_MNGCHECK", szValue))
	{
		m_nAliveCheckPort = atoi(szValue.c_str());
	}

	// File save directory path
	if (conf.GetConfig("COMMON", "FILE_STORAGE_ROOT", szValue))
	{
		m_szFileStorageRoot = szValue;
	}

	// Internal communication NIC name
	if (conf.GetConfig("COMMON", "INTERNAL_NIC_NAME", szValue))
	{
		m_szInternalNicName = szValue;
	}

#ifdef _DEBUG
	PrintValue();
#endif // _DEBUG

	return true;
}

bool CCommonConfig::CheckValue()
{
	if(m_szAppLogRoot.empty())
	{
		m_szErrMessage  = "Config info get failed. [" + m_szProgramName + " or COMMON]->DEFAULT_LOG_DIR";
		return false;
	}

	if( m_nLogLevel <= 0)
	{
		m_szErrMessage  = "Config info get failed. [" + m_szProgramName + " or COMMON]->LOG_LEVEL";
		return false;
	}

	if(m_cDatabaseInfo.m_szRcdbIp.empty())
	{
		m_szErrMessage  = "Config info get failed. [" + m_szProgramName + " or COMMON]->RCDB_IP";
		return false;
	}

	if( m_cDatabaseInfo.m_nRcdbPort <= 0)
	{
		m_szErrMessage  = "Config info get failed. [" + m_szProgramName + " or COMMON]->RCDB_PORT";
		return false;
	}

	if(m_cDatabaseInfo.m_szRcdbName.empty())
	{
		m_szErrMessage  = "Config info get failed. [" + m_szProgramName + " or COMMON]->RCDB_DB_NAME";
		return false;
	}

	if(m_cDatabaseInfo.m_szRcdbAcct.empty())
	{
		m_szErrMessage  = "Config info get failed. [" + m_szProgramName + " or COMMON]->RCDB_ACCT";
		return false;
	}

	if(m_cDatabaseInfo.m_szRcdbAcctPw.empty())
	{
		m_szErrMessage  = "Config info get failed. [" + m_szProgramName + " or COMMON]->RCDB_ACCT_PW";
		return false;
	}

	if (m_szRcid.empty())
	{
		m_szErrMessage = "Config info get failed. [" + m_szProgramName + " or COMMON]->RCID";
		return false;
	}

	if (m_szRctsServer.empty())
	{
		m_szErrMessage = "Config info get failed. [" + m_szProgramName + " or COMMON]->RCTS_SERVERR";
		return false;
	}

	if (m_nAliveCheckPort <= 0)
	{
		m_szErrMessage = "Config info get failed. [" + m_szProgramName + " or COMMON]->FHS_PORT_MNGCHECK";
		return false;
	}
	
	if (m_szFileStorageRoot.empty())
	{
		m_szErrMessage = "Config info get failed. [" + m_szProgramName + " or COMMON]->FILE_STORAGE_ROOT";
		return false;
	}

	if (m_szInternalNicName.empty())
	{
		m_szErrMessage = "Config info get failed. [" + m_szProgramName + " or COMMON]->FILE_STORAGE_ROOT";
		return false;
	}

	return true;	
}

void CCommonConfig::PrintValue()
{
	cout << "Log   Value : " << m_szAppLogRoot << "," << m_nLogLevel << endl;
	cout << "RC    Value : " << m_szRcid <<  endl;
	cout << "RCTS  Value : " << m_szRctsServer <<  endl;
	cout << "FHS   Value : " << m_szInternalNicName << "," << m_szFileStorageRoot << endl;
	cout << "RCDB  Value : " << m_cDatabaseInfo.m_szRcdbIp << "," 
		<< m_cDatabaseInfo.m_nRcdbPort << "," << m_cDatabaseInfo.m_szRcdbName 
		<< "," << m_cDatabaseInfo.m_szRcdbAcct << "," << m_cDatabaseInfo.m_szRcdbAcctPw << endl;
}

CDeamonConfig::CDeamonConfig(string szFilename, string szProgramName)
	: CCommonConfig(szFilename, szProgramName)
{
	m_nHotContentPort = 0;
	m_nTransferStatPort = 0;
	m_nFhsInfoPort = 0;
	m_nMaxFhs = 0;
	m_nMaxAccount = 0;
	m_nMaxAnonyMous = 0;
	m_nQueueCount = 0;
	m_nMaxIPCQueueSize = 0;
}

CDeamonConfig::~CDeamonConfig()
{
}

bool CDeamonConfig::LoadConf()
{
	CCommonConfig::LoadConf();
#ifdef _DEBUG
	cout << "CMyConfig::LoadConf() =>" << endl;
#endif // _DEBUG
	string szValue;

	// Config 처리를 위한 객체 생성
	Config conf;

	// Config File open
	if( conf.Open( m_szConfigFile ) == false )
	{
		m_szErrMessage = "Config file open failed.[" + m_szConfigFile + "]";
		return false;
	}

	// Config File open
	if( conf.GetConfig( m_szProgramName, "DEFAULT_LOG_DIR", szValue ) )
	{
		m_szAppLogRoot = szValue;
	}

	// log level
	if( conf.GetConfig( m_szProgramName, "LOG_LEVEL", szValue ) )
	{
		m_nLogLevel = atoi( szValue.c_str() );
	}

	// RCDB Access Information
	if( conf.GetConfig( m_szProgramName, "RCDB_IP", szValue ) )
	{
		m_cDatabaseInfo.m_szRcdbIp = szValue;
	}
	if( conf.GetConfig( m_szProgramName, "RCDB_PORT", szValue ) )
	{
		m_cDatabaseInfo.m_nRcdbPort = atoi(szValue.c_str()  );
	}
	if( conf.GetConfig( m_szProgramName, "RCDB_DB_NAME", szValue ) )
	{
		m_cDatabaseInfo.m_szRcdbName = szValue;
	}
	if( conf.GetConfig( m_szProgramName, "RCDB_ACCT", szValue ) )
	{
		m_cDatabaseInfo.m_szRcdbAcct = szValue;
	}
	if( conf.GetConfig( m_szProgramName, "RCDB_ACCT_PW", szValue ) )
	{
		m_cDatabaseInfo.m_szRcdbAcctPw = szValue;
	}

	// RC ID
	if (conf.GetConfig(m_szProgramName, "RCID", szValue))
	{
		m_szRcid = szValue;
	}

	// RCTS SERVER
	if (conf.GetConfig(m_szProgramName, "RCTS_SERVER", szValue))
	{
		m_szRctsServer = szValue;
	}

	// FHS fimngd alive check port
	if (conf.GetConfig("COMMON", "FHS_PORT_MNGCHECK", szValue))
	{
		m_nAliveCheckPort = atoi(szValue.c_str());
	}

	// File save directory path
	if (conf.GetConfig(m_szProgramName, "FILE_STORAGE_ROOT", szValue))
	{
		m_szFileStorageRoot = szValue;
	}

	// Internal communication NIC name
	if (conf.GetConfig(m_szProgramName, "INTERNAL_NIC_NAME", szValue))
	{
		m_szInternalNicName = szValue;
	}

	// fimngd 전용 config
	//Hot content request tcp port
	if (conf.GetConfig(m_szProgramName, "HOT_CONTENT_REQUEST_TCP_PORT", szValue))
	{
		m_nHotContentPort = atoi( szValue.c_str() );
	}
	// Transfer status send port
	if (conf.GetConfig(m_szProgramName, "TRANSFER_STAT_SEND_PORT", szValue))
	{
		m_nTransferStatPort = atoi( szValue.c_str() );
	}
	// Fhs info request port
	if (conf.GetConfig(m_szProgramName, "FHS_INFO_REQUEST_PORT", szValue))
	{
		m_nFhsInfoPort = atoi( szValue.c_str() );
	}
	// FHS maximum number within an RC
	if (conf.GetConfig(m_szProgramName, "MAX_FHS", szValue))
	{
		m_nMaxFhs = atoi( szValue.c_str() );
	}
	// The maximum volume within one RC
	if (conf.GetConfig(m_szProgramName, "MAX_ACCOUNT", szValue))
	{
		m_nMaxAccount = atoi( szValue.c_str() );
	}
	// No authentication maximum number of folders
	if (conf.GetConfig(m_szProgramName, "MAX_ANONYMOUS", szValue))
	{
		m_nMaxAnonyMous = atoi( szValue.c_str() );
	}
	// No authentication maximum number of folders
	if (conf.GetConfig(m_szProgramName, "IPC_QUEUE_COUNT", szValue))
	{
		m_nQueueCount = atoi( szValue.c_str() );
	}
	// No authentication maximum number of folders
	if (conf.GetConfig(m_szProgramName, "IPC_QUEUE_MAX_SIZE", szValue))
	{
		m_nMaxIPCQueueSize = atoi( szValue.c_str() );
	}


	// config 파일에 직접 노출 하진 않지만 conf 파일에 설정 가능 하도록 숨김
    // fd count
    szValue.clear();
	if (conf.GetConfig(m_szProgramName, "FD_COUNT", szValue) == false)
    {
        m_nFdCount = FD_COUNT;
    }
    else
    {
        m_nFdCount = atoi( szValue.c_str() );
    }

	szValue.clear();

	// CHG 2020-07-20 huibong internal cache 관련 fd 감시 on/off 관련 기능 개선 (#33112)
	//                - IS_FD_COUNT -> EXTRACT_FD_COUNT 으로 항목명 변경
	//                - default 는 0 (false) 이며.. 그외 정수는 true 로 판단 처리됨.
	if (conf.GetConfig(m_szProgramName, "EXTRACT_FD_COUNT", szValue) == false)
	{
		// CHG 2020-07-20 huibong internal cache 관련 fd 감시 on/off 관련 기능 개선 (#33112)
		//                - queue pop 처리한 content 에 대해 fd count 정보 추출 여부를 판단하는 변수
		//                - true 인 경우 fd count 정보 수집 처리, default false
		//                - 설정값이 존재하지 않는 경우.. true -> false 로 수정 처리
		m_bExtractContentFdCount = false;
	}
	else
	{
		// 0 인 경우에는 false, 그 외에는 true
		m_bExtractContentFdCount = atoi(szValue.c_str()) ? true : false ;
	}
    
	szValue.clear();
	if (conf.GetConfig(m_szProgramName, "FD_COUNT_CMD", szValue) == false)
	{
		m_szFdCntCMD = DEFAULT_CNT_CMD;
	}
	else
	{
		m_szFdCntCMD = szValue;
	}

    // hot content expire time 
    szValue.clear();
	if (conf.GetConfig(m_szProgramName, "CONTENT_EXPIRE_SEC", szValue) == false)
    {
        m_nContentExpireSec = CONTENT_EXPIRE_SEC;
    }
    else
    {
        m_nContentExpireSec = atoi( szValue.c_str() );
    }

	// hot content info max saved count
	szValue.clear();
	if (conf.GetConfig(m_szProgramName, "CONTENT_INFO_MAX", szValue) == false)
	{
		m_nContentInofMax = CONTENT_INFO_MAX;
	}
	else
	{
		m_nContentInofMax = atoi(szValue.c_str());
	}


#ifdef _DEBUG
	PrintValue();
#endif // _DEBUG

	return true;
}

bool CDeamonConfig::CheckValue()
{
	if (CCommonConfig::CheckValue() == false)
		return false;

	if( m_nHotContentPort <= 0)
	{
		m_szErrMessage  = "Config info get failed. [" + m_szProgramName + " or COMMON]->HOT_CONTENT_REQUEST_TCP_PORT";
		return false;
	}
	if( m_nTransferStatPort <= 0)
	{
		m_szErrMessage  = "Config info get failed. [" + m_szProgramName + " or COMMON]->TRANSFER_STAT_SEND_PORT ";
		return false;
	}
	if( m_nFhsInfoPort <= 0)
	{
		m_szErrMessage  = "Config info get failed. [" + m_szProgramName + " or COMMON]->FHS_INFO_REQUEST_PORT ";
		return false;
	}
	if( m_nMaxFhs <= 0)
	{
		m_szErrMessage  = "Config info get failed. [" + m_szProgramName + " or COMMON]->MAX_FHS";
		return false;
	}
	if( m_nMaxAccount <= 0)
	{
		m_szErrMessage  = "Config info get failed. [" + m_szProgramName + " or COMMON]->MAX_ACCOUNT";
		return false;
	}
	if( m_nMaxAnonyMous <= 0)
	{
		m_szErrMessage  = "Config info get failed. [" + m_szProgramName + " or COMMON]->MAX_ANONYMOUS";
		return false;
	}
	if( m_nQueueCount <= 0)
	{
		m_szErrMessage  = "Config info get failed. [" + m_szProgramName + " or COMMON]->IPC_QUEUE_COUNT";
		return false;
	}
	if( m_nMaxIPCQueueSize <= 0)
	{
		m_szErrMessage  = "Config info get failed. [" + m_szProgramName + " or COMMON]->IPC_QUEUE_MAX_SIZE";
		return false;
	}


	// 값들의 최대 최소 설정.
	//  1 < queue count <= 20 
	if( m_nQueueCount > 20 )
	{
		m_nQueueCount = 20;
	}

	// 500 <= queue size <= 5000
	if( m_nMaxIPCQueueSize < 500 )
	{
		m_nMaxIPCQueueSize = 500;
	}
	if( m_nMaxIPCQueueSize > 5000 )
	{
		m_nMaxIPCQueueSize = 5000;
	}
	return true;
}

void CDeamonConfig::PrintValue()
{
	CCommonConfig::PrintValue();	
}

bool CDeamonConfig::Init(string szProgramName, string szFilename)
{
	if (CDeamonConfig::m_pInstance == NULL)
	{
		CDeamonConfig::m_pInstance = new CDeamonConfig(szFilename, szProgramName);
	}

	return true;
}

void CDeamonConfig::Exit()
{
	if (CDeamonConfig::m_pInstance != NULL)
	{
		delete CDeamonConfig::m_pInstance;
		CDeamonConfig::m_pInstance = NULL;
	}
}

CDeamonConfig* CDeamonConfig::GetInstance()
{
	return CDeamonConfig::m_pInstance;
}
