373 lines
9.5 KiB
C++
Raw Normal View History

2025-03-13 10:46:26 +08:00

/******************************************************************************//**
* @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<std::string>(), "\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<std::string>();
}
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