/******************************************************************************//** * @file CTsdbSaveSrv.cpp * @brief 时序库存库服务,,服务框架 * @author yikenan * @version 1.0 * @date **********************************************************************************/ #include "boost/program_options.hpp" #include "boost/algorithm/string/predicate.hpp" #include "pub_logger_api/logger.h" #include "pub_utility_api/SingleProcInstance.h" #include "net_msg_bus_api/MsgBusApi.h" #include "tsdb_api/TsdbApi.h" #include "CNodeMng.h" #include "CTsdbSaveSrv.h" #define TSDB_LOCAL_SAVE_SRV_PROC_NAME "tsdb_local_save" using namespace std; using namespace iot_public; namespace iot_dbms { CTsdbSaveSrv::CTsdbSaveSrv() { m_enRunModel = RM_NORMAL; } CTsdbSaveSrv::~CTsdbSaveSrv() { stop(); iot_public::StopLogSystem(); } //< @param int & nStatus 错误码 bool CTsdbSaveSrv::start(int argc, char *argv[], int& /*nStatus*/) { assert(!m_ptrRedunSw); //< NULL string strAppName; string strStartArgs; //< 参数解析 if (!parseCommandLine(argc, argv, strAppName,strStartArgs)) { std::cerr << "参数解析失败" << std::endl; return false; } //< 启动日志 iot_public::StartLogSystem(strAppName.c_str(), TSDB_LOCAL_SAVE_SRV_PROC_NAME); if(!getSysAppInfo(strAppName)) { LOGERROR("获取应用信息失败"); return false; } //< 判断是否已启动 if (isAlreadyRunning(strStartArgs)) { LOGFATAL(TSDB_LOCAL_SAVE_SRV_PROC_NAME" 已启动,不可重复启动,本实例退出!"); return false; } //< 消息总线 if (!iot_net::initMsgBus(TSDB_LOCAL_SAVE_SRV_PROC_NAME, "", true)) { LOGFATAL("初始化消息总线失败,程序启动失败!"); return false; } //< 时序库接口库 if (!initTsdbApi()) { LOGFATAL("初始化时序库接口库失败,程序启动失败!"); return false; } //< 初始化 CNodeMng 加载配置等 if (!CNodeMng::getInstance().init(m_stRunAppInfo)) { LOGFATAL("CNodeMng 初始化失败,程序启动失败!"); return false; } //< CFrontThread 由 m_ptrRedunSw 管理 //< 初始化 m_ptrRedunSw m_ptrRedunSw.reset(new CTsdbSaveRedunSw(this,m_stRunAppInfo)); if(m_ptrRedunSw == NULL || m_ptrRedunSw->initialize() != iotSuccess) { LOGFATAL("CNodeMng 初始化失败,程序启动失败!"); return false; } switch (m_enRunModel) { case RM_NORMAL: { //< 进程管理 { iot_sys::SProcessInfoKey objProcInfo; objProcInfo.nAppId = m_stRunAppInfo.nAppId; objProcInfo.nDomainId = CNodeMng::getInstance().getLocalDomainID(); objProcInfo.strNodeName = CNodeMng::getInstance().getLocalNodeName(); objProcInfo.strProcName = TSDB_LOCAL_SAVE_SRV_PROC_NAME; objProcInfo.strProcParam = strStartArgs; m_ptrProcMng = iot_sys::getProcMngInstance(objProcInfo); if (!m_ptrProcMng) { LOGFATAL("getProcMngInstance return NULL"); return false; } m_ptrProcMng->setCallback(this); } //< 冗余管理 { m_ptrRedundantMng = iot_sys::getRedundantMngInstance(CNodeMng::getInstance().getLocalDomainID(), m_stRunAppInfo.nAppId, CNodeMng::getInstance().getLocalNodeName()); 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 (iotSuccess != m_ptrRedunSw->redundantSwitch(true, false)) { LOGFATAL("以主机模式启动失败!"); return false; } } break; case RM_NO_PROC_MNG_SLAVE: { if (iotSuccess != m_ptrRedunSw->redundantSwitch(false, true)) { LOGFATAL("以备机模式启动失败!"); return false; } } break; default: { LOGFATAL("非预期的启动模式,程序启动失败!"); return false; } break; } LOGINFO(TSDB_LOCAL_SAVE_SRV_PROC_NAME" is now running ..."); return true; } bool CTsdbSaveSrv::stop() { LOGINFO(TSDB_LOCAL_SAVE_SRV_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 (m_ptrProcMng) //{ // m_ptrProcMng->unsetCallback(); //} //< 清理业务线程 if (CNodeMng::haveInstance()) { //LOGDEBUG("Release CNodeMng ..."); //< CFrontThread 由 m_ptrRedunSw 管理 CNodeMng::getInstance().release(); //LOGDEBUG("Release CNodeMng complete !"); } //< 更新进程管理状态 if (m_ptrProcMng) { //LOGDEBUG("Release m_ptrProcMng ..."); updateProcInfo(false, false, false); m_ptrProcMng.reset(); //LOGDEBUG("Release m_ptrProcMng complete !"); } //< 释放时序库接口库 releaseTsdbApi(); //< 停止消息总线 iot_net::releaseMsgBus(); //< 停止日志系统 //< 移到析构函数中,防止日志库停止后,又写日志,从而使log4cplus提示找不到logger //iot_public::StopLogSystem(); return true; } int CTsdbSaveSrv::toQuit() { shutdown(); return iotSuccess; } int CTsdbSaveSrv::updateProcInfo(bool bActive, bool bMaster, bool bSlave) { if (m_ptrProcMng) { return m_ptrProcMng->updateProcessInfo(bActive, bMaster, bSlave); } return iotFailed; } bool CTsdbSaveSrv::isAlreadyRunning(const std::string &strStartArgs ) { std::string strUniqueName = TSDB_LOCAL_SAVE_SRV_PROC_NAME; strUniqueName += strStartArgs; return iot_public::CSingleProcInstance::hasInstanceRunning( strUniqueName ); } bool CTsdbSaveSrv::parseCommandLine(int argc, char *argv[],std::string &strAppName, std::string &strStartArgs) { //< 拼接启动参数,用于向进程管理注册 for ( int i = 1; i < argc; ++i ) { if ( i != 1 ) { strStartArgs += " "; } strStartArgs += argv[i]; } 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, can only ran as PUBLIC") ("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")) { std::cout << "Must set app !" << std::endl; return false; } else { strAppName = vm["app"].as(); } if (vm.count("no_proc_mng_master")) { m_enRunModel = RM_NO_PROC_MNG_MASTER; } else if (vm.count("no_proc_mng_slave")) { m_enRunModel = RM_NO_PROC_MNG_SLAVE; } else { m_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; } bool CTsdbSaveSrv::getSysAppInfo(const std::string &strAppName) { CSysInfoInterfacePtr sysInfoPtr; if(createSysInfoInstance(sysInfoPtr) == false) { LOGERROR("AppName=%s ,createSysInfoInstance fail!\n", strAppName.c_str()); return false; } if(sysInfoPtr == NULL) { LOGERROR("AppName=%s ,Get System Info fail!\n", strAppName.c_str()); return false; } if(iotSuccess != sysInfoPtr->getLocalRunAppInfoByName(strAppName,m_stRunAppInfo)) { LOGERROR("getLocalRunAppInfoByName fail"); return false; } return true; } } //< namespace iot_dbms