#include "Client_cfd.h" #include "pub_sysinfo_api/SysInfoApi.h" #include "pub_utility_api/SingleProcInstance.h" #include "boost/program_options.hpp" namespace cfd_Server{ client_cfd::client_cfd() { p_manger = NULL; } client_cfd::~client_cfd() { stop(); kbd_public::StopLogSystem(); } bool client_cfd::start(int argc, char *argv[], int &nStatus) { assert( !m_ptrRedunSw ); //< NULL kbd_public::CSysInfoInterfacePtr ptrSysInfo; EnRunModel enRunModel = RM_NORMAL; std::string strAppName = CN_AppName_COMAPP; //< 启动日志 kbd_public::StartLogSystem( strAppName.c_str(), EZ_NYGK_PROC_NAME ); if ( kbd_public::createSysInfoInstance(ptrSysInfo) == false ) { LOGFATAL( "createSysInfoInstance() return false !" ); return false; } //< 获取运行参数 if ( kbdSuccess != ptrSysInfo->getLocalRunAppInfoByName(strAppName,m_stRunAppInfo)) { LOGFATAL( "getLocalRunAppInfoByName() failed !" ); return false; } //< 参数解析 if ( !parseCommandLine( argc, argv, enRunModel, strAppName )) { // help返回的也是false,输出失败不合适 //std::cerr << "参数解析失败" << std::endl; return false; } //< 判断是否已启动 if ( isAlreadyRunning()) { LOGFATAL( EZ_NYGK_PROC_NAME" 已启动,不可重复启动,本实例退出!" ); return false; } //< 消息总线 if ( !kbd_net::initMsgBus( EZ_NYGK_PROC_NAME, "", true )) { LOGFATAL( "消息总线初始化失败,程序启动失败!" ); return false; } //业务初始化 p_manger = new client_MsgManger; p_manger->resume(); m_ptrRedunSw = boost::make_shared( this ); switch ( enRunModel ) { case RM_NORMAL: { //< 进程管理 { std::string strStartArgs; for ( int i = 1; i < argc; ++i ) { if ( i != 1 ) { strStartArgs += " "; } strStartArgs += argv[i]; } kbd_sys::SProcessInfoKey objProcInfo; objProcInfo.nAppId = m_stRunAppInfo.nAppId; objProcInfo.nDomainId = m_stRunAppInfo.nDomainId; objProcInfo.strNodeName = m_stRunAppInfo.strLocalNodeName; objProcInfo.strProcName = EZ_NYGK_PROC_NAME; objProcInfo.strProcParam = strStartArgs; m_ptrProcMng = kbd_sys::getProcMngInstance( objProcInfo ); if ( !m_ptrProcMng ) { LOGFATAL( "getProcMngInstance return NULL" ); return false; } m_ptrProcMng->setCallback( this ); } //< 冗余管理 { m_ptrRedundantMng = kbd_sys::getRedundantMngInstance( m_stRunAppInfo.nDomainId, m_stRunAppInfo.nAppId, m_stRunAppInfo.strLocalNodeName ); if ( !m_ptrRedundantMng ) { LOGERROR( "getRedundantMngInstance return NULL" ); return false; } m_ptrRedundantMng->setCallback( m_ptrRedunSw ); } //< 更新进程管理状态 updateProcInfo( true, false, false ); } break; case RM_NO_PROC_MNG_MASTER: { if ( kbdSuccess != m_ptrRedunSw->redundantSwitch( true, false )) { LOGFATAL( "以主机模式启动失败!" ); return false; } } break; case RM_NO_PROC_MNG_SLAVE: { if ( kbdSuccess != m_ptrRedunSw->redundantSwitch( false, true )) { LOGFATAL( "以备机模式启动失败!" ); return false; } } break; default: { LOGFATAL( "非预期的启动模式,程序启动失败!" ); return false; } break; } LOGINFO( EZ_NYGK_PROC_NAME" is now running ..." ); return true; } bool client_cfd::stop() { LOGINFO( EZ_NYGK_PROC_NAME" is now exiting ..." ); //< 取消冗余切换,防止正在退出时发生冗余切换 if ( m_ptrRedundantMng ) { LOGDEBUG("Release m_ptrRedundantMng ..."); m_ptrRedundantMng->unsetCallback(); m_ptrRedundantMng.reset(); LOGDEBUG("Release m_ptrRedundantMng complete !"); } //< 释放 m_ptrRedunSw if ( m_ptrRedunSw ) { LOGDEBUG("Release m_ptrRedunSw ..."); m_ptrRedunSw.reset(); LOGDEBUG("Release m_ptrRedunSw complete !"); } //< 清理业务线程 if(p_manger != NULL){ p_manger->quit(); delete p_manger; p_manger = NULL; } //< 更新进程管理状态 if ( m_ptrProcMng ) { LOGDEBUG("Release m_ptrProcMng ..."); updateProcInfo( false, false, false ); m_ptrProcMng.reset(); LOGDEBUG("Release m_ptrProcMng complete !"); } //< 停止消息总线 kbd_net::releaseMsgBus(); //< 停止日志系统 //移到析构函数中,防止日志库停止后,又写日志,从而使log4cplus提示找不到logger //kbd_public::StopLogSystem(); return true; } int client_cfd::toQuit() { shutdown(); return kbdSuccess; } int client_cfd::updateProcInfo(bool bActive, bool bMaster, bool bSlave) { if ( m_ptrProcMng ) { return m_ptrProcMng->updateProcessInfo( bActive, bMaster, bSlave ); } return kbdFailed; } bool client_cfd::isAlreadyRunning() { return kbd_public::CSingleProcInstance::hasInstanceRunning( EZ_NYGK_PROC_NAME ); } bool client_cfd::parseCommandLine( int argc, char *argv[], EnRunModel &enRunModel, std::string &strAppName ) { namespace po = boost::program_options; po::options_description desc( "usage" ); po::variables_map vm; try { desc.add_options() ( "app"",a", po::value(), "\t""The APP name" ) ( "no_proc_mng_master"",m", "\t""Run as master without ProcMng and RedundantMng" ) ( "no_proc_mng_slave"",s", "\t""Run as slave without ProcMng and RedundantMng" ) ( "help"",h", "\t""Print this info" ); po::store( po::parse_command_line( argc, argv, desc ), vm ); po::notify( vm ); if ( vm.count( "help" )) { std::cout << desc << std::endl; return false; } if ( vm.count( "no_proc_mng_master" ) && vm.count( "no_proc_mng_slave" )) { std::cout << "no_proc_mng_master and no_proc_mng_slave can not use at the same time !" << std::endl; return false; } if ( 0 != vm.count( "app" )) { strAppName = vm["app"].as(); } else { strAppName = CN_AppName_COMAPP; } if ( vm.count( "no_proc_mng_master" )) { enRunModel = RM_NO_PROC_MNG_MASTER; } else if ( vm.count( "no_proc_mng_slave" )) { enRunModel = RM_NO_PROC_MNG_SLAVE; } else { enRunModel = RM_NORMAL; } } catch ( std::exception &ex ) { std::cerr << ex.what() << std::endl; std::cout << desc << std::endl; return false; } catch ( ... ) { std::cerr << "未知错误" << std::endl; std::cout << desc << std::endl; return false; } return true; } }