test
/** @file TimerBackup.cpp
* @note HangZhou Hikvision Digital Technology Co., Ltd. All Right Reserved.
* @brief 定时备份
*
* @author gaoyong5
* @guardian hulongsheng
* @date 2015/10/09
* @note 2016/7/8 gaoyong5 根据pro4.0的备份方式修改
*/
#include "stdafx.h"
#include "TimerBackup.h"
#include "tinyxml2/tinyxml2.h"
#include "Maintenance/DatabaseSession/BackupRecordSession.h"
#include "Config/ConfigManager.h"
#include "Log/LogManager.h"
#include "libxml/parser.h"
#include "License/LicenseManager.h"
#include "rsmmodule/RSMModuleInterface.h"
#include "Maintenance/MaintenanceManager.h"
#include "Common/BaseDBConn.h"
#include "vsmplatform/Upgrade/DBUpgrade/NetworkComm/DBUpgradeStatusISAPIComm.h"
#include "Common/PrivateAESEncrypt/PrivateAESEncrypt.h"
#include "NetworkComm/URLManager/URLManager.h"
#include "Maintenance/Compress.h"
//#include "TVWall/TVWallManager.h"
#include "System/SystemManager.h"
// 备份新增
#include "Config/LocalConfigManager.h"
#ifndef __linux__
#include <direct.h>
#else
#include <sys/stat.h>
#include <sys/statfs.h>
#endif
#include "StoragePicture/ConfigPictureManager.h"
#include "Log/LogManager.h"
#include "Log/PublicLogManager.h"
//#include "BeeDistributedManager/BeeDistributedManager.h"
#include "BeeUtil/Common/CommonFun.h"
#include "AllInOne/Common/MultiPlatformCommon.h"
#include "AllInOne/NCG/NCGManager.h"
#include "ControlItem/ControlItemManager.h"
#include "SMSToken/SMSTokenManager.h"
#include "Config/ConfigPathManager.h"
#include "BeeNet/Http/HttpServerData.h"
#include "FTPStorageComm/FTPStorageInterface.h"
#include "libcurl/curl.h"
#define CMD_BUF_LEN 256
namespace VSMPlatform
{
using namespace Bee::Base::StringUtil;
using namespace Bee::Net;
struct FTPTransProgressStruct CTimerBackup::ftp_upload_progress_ = { 0 };
namespace
{
// 配置型数据表
vector<string> vec_backup_conf_table =
{
// 空
};
// 图片数据
vector<string> vec_backup_picture_table =
{
// 空
};
// 事务数据
vector<string> vec_backup_event_table =
{
// 空
};
// 报警数据
vector<string> vec_backup_alarm_table =
{
// 空
};
// 刷卡数据
vector<string> vec_backup_swipcards_table =
{
// 空
};
// 考勤数据
vector<string> vec_backup_attendance_table =
{
// 空
};
// 过车记录数据
vector<string> vec_backup_vehicle_table =
{
// 空
};
// BI数据
vector<string> vec_backup_bi_table =
{
// 空
};
// 日志记录数据
vector<string> vec_backup_log_table =
{
// 空
};
// 人脸记录数据
vector<string> vec_backup_face_table =
{
// 空
};
// 回传记录数据
vector<string> vec_backup_dock_back_table =
{
// 空
};
// 备份还原需要用到的程序
#if (defined(_WIN32) || defined(_WIN32_WCE) || defined(_WIN64))
string PostgreSQL_backup_exe = "/bin/pg_dump.exe";
string PostgreSQL_restore_exe = "/bin/pg_restore.exe";
string PostgreSQL_psql_exe = "/bin/psql.exe";
#elif (defined(__linux__))
string PostgreSQL_backup_exe = "/bin/pg_dump";
string PostgreSQL_restore_exe = "/bin/pg_restore";
string PostgreSQL_psql_exe = "/bin/psql";
#endif
// 备份还原中要用到的配置文件
//string pg_hba_trust = "pg_hba_trust.conf"; // 无权限验证的模式
//string pg_hba_md5 = "pg_hba_md5.conf"; // 有权限验证的模式
#if (defined(_WIN32) || defined(_WIN32_WCE) || defined(_WIN64))
string pg_hba = "/data/pg_hba.conf"; // PostgreSQL目录下的配置文件
#elif (defined(__linux__))
string pg_hba = "/data/pg_hba.conf"; // PostgreSQL目录下的配置文件;
#endif
std::vector<std::string> strSplit(const std::string& str, const std::string& s)
{
/*boost::regex reg(s.c_str());
std::vector<std::string> vec;
boost::sregex_token_iterator it(str.begin(), str.end(), reg, -1);
boost::sregex_token_iterator end;
while (it != end)
{
if (*it != "")
{
vec.push_back(*it++);
}
}
return vec;*/
vector<string> res;
if ("" == str)
return res;
//先将要切割的字符串从string类型转换为char*类型
char * strs = new char[str.length() + 1];
//strcpy(strs, str.c_str());
HPR_STRCPY_S(strs, str.length() + 1, str.c_str());
char * d = new char[s.length() + 1];
//strcpy(d, s.c_str());
HPR_STRCPY_S(d, s.length() + 1, s.c_str());
char *p = strtok(strs, d);
while (p) {
string ss = p; //分割得到的字符串转换为string类型
res.push_back(ss); //存入结果数组
p = strtok(NULL, d);
}
return res;
}
bool MakeFullPathDir(const string& path)
{
if (path.empty())
{
return false;
}
size_t uPos = path.find_first_of("/\\");
while (uPos != string::npos)
{
string dir = path.substr(0, uPos + 1);
boost::system::error_code ec;
boost::filesystem::create_directory(dir, ec);
uPos = path.find_first_of("/\\", uPos + 1);
}
boost::system::error_code ec;
boost::filesystem::create_directory(path, ec);
return true;
}
}
size_t WriteToString(char *buffer, size_t size, size_t nmemb, std::string *userp)
{
if (nullptr != userp)
{
userp->append(buffer, size * nmemb);
}
return size * nmemb;
}
#ifdef __linux__
// 临时设置PG密码,析构后还原
class CSetTmpPGPwd
{
public:
CSetTmpPGPwd(const std::string& pg_pwd)
{
pwd_env_ = "PGPASSWORD=" + pg_pwd;
int ret = putenv((char *)pwd_env_.c_str());
}
~CSetTmpPGPwd()
{
unsetenv("PGPASSWORD");
}
private:
std::string pwd_env_; //putenv使用的是程序的内存,如果使用局部变量,会被销毁掉,使用成员变量才可以
};
#endif
/** @fn CTimerBackup()
* @brief 构造函数
* @param void
* @return void
*/
CTimerBackup::CTimerBackup()
: /*m_dc_ctimer_(nullptr),*/
// has_dump_pic_bak_(false),
is_distributed_(false)
{
}
/** @fn ~CTimerBackup()
* @brief 析构函数
* @param void
* @return void
*/
CTimerBackup::~CTimerBackup()
{
}
/** @fn RunEIT()
* @brief 定时器中执行的备份函数
* @param void
* @return void
*/
void CTimerBackup::ExecDriveClonePlan()
{
// 本地备份
TimingDriveCloneTry();
#ifndef HCL_CODE
// 远端备份
if (CLicenseManager::Instance().IsRSMSystem())
{
map<UINT_T, DriveCloneConf>& map_site_backupinfo = CMaintenanceManager::Instance().GetAllSiteDatabaseBackUpInfo();
for (auto& it : map_site_backupinfo)
{
if (it.second.remote_enable)
{
TrySiteBackup(it.first);
}
}
}
#endif // !HCL_CCODE
}
void CTimerBackup::BeeAngetFunCallBack(int iClientId, std::string strMsg, unsigned int iMsgSize, int iMsgType)
{
string message;
if (iBeeAgentClientId == iClientId)
{
if (iMsgType == Bee::Net::WebSocket::TEXT)
{
if (strMsg.empty())
{
IVMS_LOG_ERROR("platform.Maintenance", "Invaled Data, data_lenth = %d", iMsgSize);
return;
}
message = strMsg;
}
}
if (!message.empty())
{
BeeAgentMsgAnalysis(message);
}
}
bool CTimerBackup::ObtainDiffInstallInfo(std::string &strSavePath)
{
//发送请求异机部署的协议和异机部署的配置路径
if (b_is_diff_machine)
{
strSavePath = strBeeAgentSetPath_;
return true;
}
return false;
}
void CTimerBackup::SendToBeeAgentGetBackuoPath()
{
//请求是不是异机部署
shared_ptr<proto::IProto> parse = make_shared<proto::CRapidJsonProto>();
string strGuid = Bee::Base::GuidUtil::CreateGuid();
parse->set_v("/Guid", strGuid);
parse->set_v("/RequestData/Method", "GetDataBaseDeployMode");
string strReq = parse->get_str();
bool bSend = CBeeAgentClientManager::Instance().SendMsg(iBeeAgentClientId, strReq, Bee::Net::WebSocket::TEXT);
if (bSend)
{
IVMS_LOG_INFO("platform.Maintenance", "CTimerBackup::SendToBeeAgentGetBackuoPath GetDataBaseDeployMode Body %s", strReq.c_str());
}
else
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::SendToBeeAgentGetBackuoPath GetDataBaseDeployMode Error Body %s", strReq.c_str());
}
//配置路径
parse->clear();
strGuid = Bee::Base::GuidUtil::CreateGuid();
parse->set_v("/Guid", strGuid);
parse->set_v("/RequestData/Method", "GetBackupPath");
strReq = parse->get_str();
bSend = CBeeAgentClientManager::Instance().SendMsg(iBeeAgentClientId, strReq, Bee::Net::WebSocket::TEXT);
if (bSend)
{
IVMS_LOG_INFO("platform.Maintenance", "CTimerBackup::SendToBeeAgentGetBackuoPath GetBackupPath Body %s", strReq.c_str());
}
else
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::SendToBeeAgentGetBackuoPath GetBackupPath Error Body %s", strReq.c_str());
}
}
bool CTimerBackup::BeeAgentErrorCallBack()
{
return CBeeAgentClientManager::Instance().CheckAuthencation(iBeeAgentClientId, true);
}
bool CTimerBackup::SendToBeeAgentGetAllBackupFile(const string &strPath, string strGuid)
{
strAllFiles_ = "";
strAllFilesGuid_ = strGuid;
i_recvAllFiles_ = -1;
b_recvAllFiles_ = false;
shared_ptr<proto::IProto> parse = make_shared<proto::CRapidJsonProto>();
string strTempGuid = Bee::Base::GuidUtil::CreateGuid();
parse->set_v("/Guid", strTempGuid);
parse->set_v("/RequestData/Method", "GetAllBackupFiles");
string strPathAndVer = strBeeAgentSetPath_ + ";" + g_soft_version;
parse->set_v("/RequestData/Data/BakFilePath", strPathAndVer);
string strReq = parse->get_str();
bool bSend = CBeeAgentClientManager::Instance().SendMsg(iBeeAgentClientId, strReq, Bee::Net::WebSocket::TEXT);
if (bSend)
{
IVMS_LOG_INFO("platform.Maintenance", "CTimerBackup::SendToBeeAgentGetAllBackupFile Body %s", strReq.c_str());
}
else
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::SendToBeeAgentGetAllBackupFile ERROR Body %s", strReq.c_str());
return false;
}
//给10秒的超时时间,没有返回错误码,表示没有出错
time_t startTime;
time_t endTime;
double diffStartEndTime;
time(&startTime);
while (true)
{
if (b_recvAllFiles_)
{
if (0 != i_recvAllFiles_)
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_OBTAIN_RESTORE_FILE_FAIL)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::SendToBeeAgentGetAllBackupFile Diff FAILED Result %d", i_recvAllFiles_);
return false;
}
else
{
b_recvAllFiles_ = false;
if (!strAllFiles_.empty())
{
AllBackupFilesAnalyse(strAllFiles_);
}
else
{
IVMS_LOG_INFO("platform.Maintenance", "CTimerBackup::GetAllBackupFiles Empty!");
}
break;
}
}
time(&endTime);
diffStartEndTime = difftime(endTime, startTime);
if (diffStartEndTime > 15)
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::SendToBeeAgentGetAllBackupFile Diff FAILED,BeeAgent ReBackPackage TimeOut");
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BEEAGENT_TIMEOUT)));
b_recvAllFiles_ = false;
return false;
}
}
//
return true;
}
bool CTimerBackup::BeeAgentMsgAnalysis(const std::string &strMsg)
{
//解析报文信息
IVMS_LOG_DEBUG("platform.Maintenance", "CTimerBackup::BeeAgentMsgAnalysis Msg %s", strMsg.c_str());
shared_ptr<proto::IProto> parse = make_shared<proto::CRapidJsonProto>();
parse->set_str(strMsg);
string strMethod;
strMethod = parse->get_v("/ResponseData/Method");
if (strMethod == "")
{
strMethod = parse->get_v("/RequestData/Method");
}
if (strMethod == "")
{
strMethod = parse->get_v("/RequestData/Data/Method");
}
if (strMethod == "")
{
strMethod = parse->get_v("/ResponseData/Data/Method");
}
if ("SendDataBaseDeployMode" == strMethod) //异机部署
{
string strGuid = parse->get_v("/Guid");
string strMode = parse->get_v("/RequestData/Data/Mode");
if (strMode == "1")
{
b_is_diff_machine = true;
}
else
{
b_is_diff_machine = false;
}
shared_ptr<proto::CRapidJsonProto> pRes = make_shared<proto::CRapidJsonProto>();
pRes->set_v("/Guid", strGuid);
pRes->set_v("/ResponseData/Method", "SendDataBaseDeployMode");
pRes->set_v("/ResponseData/ErrorCode", 0);
string strRes = pRes->get_str();
CBeeAgentClientManager::Instance().SendMsg(iBeeAgentClientId, strRes, Bee::Net::WebSocket::TEXT);
}
if ("GetDataBaseDeployMode" == strMethod)
{
string strMode = parse->get_v("/ResponseData/Data/Mode");
if (strMode == "1")
{
b_is_diff_machine = true;
}
else
{
b_is_diff_machine = false;
}
}
if ("SetBackupPath" == strMethod)//获取看门狗设置的路径
{
string strGuid = parse->get_v("/Guid");
strBeeAgentSetPath_ = parse->get_v("/RequestData/BackupPath");
shared_ptr<proto::CRapidJsonProto> pRes = make_shared<proto::CRapidJsonProto>();
pRes->set_v("/Guid", strGuid);
pRes->set_v("/ResponseData/Method", "SetBackupPath");
pRes->set_v("/ResponseData/ErrorCode", 0);
string strRes = pRes->get_str();
CBeeAgentClientManager::Instance().SendMsg(iBeeAgentClientId, strRes, Bee::Net::WebSocket::TEXT);
}
if ("GetBackupPath" == strMethod)
{
string strGuid = parse->get_v("/Guid");
strBeeAgentSetPath_ = parse->get_v("/ResponseData/Data/BackupPath");
if (strBeeAgentSetPath_ == "")
{
strBeeAgentSetPath_ = parse->get_v("/ResponseData/BackupPath");
}
}
if ("CheckDiskSpace" == strMethod) //检查磁盘空间
{
if (0 == parse->get_int_v("/ResponseData/Data/SpaceIsOK"))
{
b_is_diskSpace_ok = true;
}
else
{
b_is_diskSpace_ok = false;
}
b_recBeeAgent_diskSpace = true;
}
if ("BackupRestoreProgress" == strMethod)//备份还原进度控制
{
iProgressPercent_ = parse->get_int_v("/ResponseData/Data/Percent");
iProgressResult_ = parse->get_int_v("/ResponseData/Data/ProgressResult");
b_recvBeeAgent_progress = true;
}
if ("GetSecretKey" == strMethod)
{
string strGuid = parse->get_v("/Guid");
shared_ptr<proto::CRapidJsonProto> pRes = make_shared<proto::CRapidJsonProto>();
string strSecretKey = CSystemManamger::Instance().GetSecretKey();
string strOut;
CBeeAgentClientManager::Instance().EncryptStringByClient(strOut, iBeeAgentClientId, strSecretKey);
pRes->set_v("/ResponseData/ErrorCode", 0);
pRes->set_v("/Guid", strGuid);
pRes->set_v("/ResponseData/Data/SercretKey", strOut);
string strResKey = pRes->get_str();
bool bSend = CBeeAgentClientManager::Instance().SendMsg(iBeeAgentClientId, strResKey, Bee::Net::WebSocket::TEXT);
if (bSend)
{
IVMS_LOG_INFO("platform.Maintenance", "GetSecretKey MsgBody %s", strResKey.c_str());
}
else
{
IVMS_LOG_ERROR("platform.Maintenance", "GetSecretKey MsgBody Error%s", strResKey.c_str());
}
}
if ("GetToken" == strMethod)
{
string strGuid = parse->get_v("/Guid");
shared_ptr<proto::CRapidJsonProto> pRes = make_shared<proto::CRapidJsonProto>();
pRes->set_v("/Guid", strGuid);
pRes->set_v("/ResponseData/Method", "GetToken");
string str_token;
string str_key_salt;
string str_key_param;
CSMSTokenManager::Instance().GetRegCfgInfo(str_key_salt, str_key_param);
std::shared_ptr<proto::CRapidJsonProto> res = make_shared<proto::CRapidJsonProto>();
res->set_v("/TokenInfo/KeyParam", str_key_param);
res->set_v("/TokenInfo/KeySlat", str_key_salt);
res->set_v("/TokenInfo/HashName", "sha256");
res->set_v("/TokenInfo/RootKeyNum", 2);
str_token = res->get_str();
string strOut;
CBeeAgentClientManager::Instance().EncryptStringByClient(strOut, iBeeAgentClientId, str_token);
pRes->set_v("/ResponseData/ErrorCode", 0);
pRes->set_v("/ResponseData/Data/Token", strOut);
string strResToken = pRes->get_str();
CBeeAgentClientManager::Instance().SendMsg(iBeeAgentClientId, strResToken, Bee::Net::WebSocket::TEXT);
}
if ("ExecuteBackUpOpt" == strMethod)
{
i_recvBackupResult_ = parse->get_int_v("/ResponseData/Data/BackupResult");
b_recvBackupResult_ = true;
if (i_recvBackupResult_ == 0)
{
TypeinBackupPackage(stu_Diff_data_clone_conf, strDiffFilePath_, strDiffCreateTime_);
}
}
if ("ExecuteDataRestoreOpt" == strMethod)
{
i_recvRestoreResult_ = parse->get_int_v("/ResponseData/RestoreResult");
b_recvRestoreResult_ = true;
}
if ("DeleteBackupFiles" == strMethod)
{
i_recvDeleteResult_ = parse->get_int_v("/ResponseData/Data/DeleteResult");
b_recvDeleteBackup_ = true;
}
if ("GetAllBackupFiles" == strMethod)
{
i_recvAllFiles_ = parse->get_int_v("/ResponseData/Data/GetAllResult");
strAllFiles_ = parse->get_v("/ResponseData/Data/AllFiles");
b_recvAllFiles_ = true;
//AllBackupFilesAnalyse(strAllFiles_);
}
if ("CheckFileExist" == strMethod)
{
stru_recvCheckFileExistResult_.error_code = parse->get_int_v("/ResponseData/ErrorCode");
int count = parse->get_cnt("/ResponseData/Data/PathExist");
string url_fmt = "/ResponseData/Data/PathExist[%d]";
for (int i = 0; i < count; ++i)
{
string url = str_fmt(url_fmt.c_str(), i + 1);
stru_recvCheckFileExistResult_.vec_exist.push_back(parse->get_int_v(url));
}
b_recvCheckFileExistResult_ = true;
}
if ("SendServiceEvent" == strMethod)
{
string event_info = parse->get_node_str("/RequestData/Data");
SendServerEvent(event_info);
}
return true;
}
void CTimerBackup::AllBackupFilesAnalyse(std::string strAllFiles)
{
// 对备份路径下的文件进行分析
vector<DriveCloneRecordsInfo> vSysBaks;
vSysBaks.clear();
boost::system::error_code err_c;
if (!strAllFiles.empty())
{
std::vector<std::string> vFileZips;
vFileZips = strSplit(strAllFiles, ";");
for (auto file : vFileZips)
{
if (!file.empty())
{
std::vector<std::string> vFileZip;
vFileZip = strSplit(file, "|");
if (2 != vFileZip.size())
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_OBTAIN_RESTORE_FILE_FAIL)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::SendToBeeAgentGetAllBackupFile Diff FAILED");
return;
}
string strBackUpFileDir = vFileZip.at(0);
string strBackUpFileName = vFileZip.at(1);
size_t p_index = strBackUpFileName.find_last_of(".");
if (p_index == string::npos)
{
continue;
}
size_t t_index = strBackUpFileName.find_last_of("-");
if (t_index == string::npos)
{
continue;
}
string strFileType = strBackUpFileName.substr(p_index + 1, strBackUpFileName.size() - p_index);
strFileType = CVSMCommonFun::tolower(strFileType);
if ((strFileType == "zip") && strBackUpFileName.find("VSM_" + g_soft_version + "_BAK") != string::npos)
{
// 0K的文件过滤掉
if (boost::filesystem::file_size(strBackUpFileName, err_c) != 0)
{
DriveCloneRecordsInfo s_bak_record;
string str_data_type = strBackUpFileName.substr(t_index + 1, strBackUpFileName.size() - t_index - 5);
string res_str = "_";
string rep_str = ",";
string::size_type pos = 0;
string::size_type res_len = res_str.size();
string::size_type rep_len = rep_str.size();
while ((pos = str_data_type.find(res_str, pos)) != string::npos)
{
str_data_type.replace(pos, res_len, rep_str);
pos += rep_len;
}
// 转换为统一的分隔符
s_bak_record.bak_file_path = StringReplace(strBackUpFileDir, "\\", "/");
s_bak_record.backup_time = -1;
size_t time_pos = strBackUpFileDir.find_last_of("_");
if (time_pos != std::string::npos)
{
string curr_element_path_str = strBackUpFileDir.substr(0, time_pos - 1);
time_pos = (curr_element_path_str).find_last_of("_");
if (time_pos != std::string::npos)
{
string bak_time = (curr_element_path_str).substr(time_pos + 1, (curr_element_path_str).length());
string bak_time_fmt = bak_time.substr(0, 4) + "-" + bak_time.substr(4, 2) + "-" + bak_time.substr(6, 2) + " " +
bak_time.substr(8, 2) + ":" + bak_time.substr(10, 2) + ":" + bak_time.substr(12, 2);
s_bak_record.backup_time = Bee::Base::TimeUtil::StrDatetime2TimeT(bak_time_fmt);
}
}
if (s_bak_record.backup_time == -1)
{
s_bak_record.backup_time = boost::filesystem::last_write_time(strBackUpFileDir, err_c);
}
s_bak_record.id_site = 0;
s_bak_record.site_guid = strAllFilesGuid_;
s_bak_record.bak_form = str_data_type;
IVMS_LOG_DEBUG("platform.Maintenance", "SearchLocalDriveCloneFile[3] BACKUP FILE %s.", s_bak_record.bak_file_path.c_str());
// 加入SYS备份列表
vSysBaks.push_back(s_bak_record);
}
}
}
}
}
for (auto sys_it : vSysBaks)
{
IVMS_LOG_DEBUG("platform.Maintenance", "SendToBeeAgentGetAllBackupFile Insert DB FILE %s.", sys_it.bak_file_path.c_str());
if (!BackupRecordSession::InsertLocalBackupRecord(sys_it, g_soft_version))
{
IVMS_LOG_DEBUG("platform.Maintenance", "SendToBeeAgentGetAllBackupFile BACKUP FILE already existed.");
}
}
}
bool CTimerBackup::QueryBackupSchemaAndVersion(map<string, int> backup_schema, map<string, string>& ver_schema)
{
shared_ptr<db_layer::CConnect> ptr_connect = nullptr;
ptr_connect = CVsmPlatformDBConn::Instance().ApplyConn();
if (ptr_connect == nullptr)
{
IVMS_LOG_ERROR("platform.Maintenance", "Conn Failed.");
return false;
}
db_layer::CConnect& rs = *ptr_connect;
string query_sql;
for (auto it : backup_schema)
{
if (it.first == "platform")
{
query_sql = "SELECT version_no FROM platform.module_version_status WHERE module_identity = 'platform';";
}
else if (it.first == "aihub")
{
query_sql = "SELECT version_no FROM platform.module_version_status WHERE module_identity = 'aihub';";
}
else if (it.first == "sia")
{
query_sql = "SELECT version_no FROM platform.module_version_status WHERE module_identity = 'siadevice.d';";
}
else
{
query_sql = str_fmt("SELECT version_no FROM platform.module_version_status WHERE module_identity LIKE '%s", it.first.c_str()) + "__';";
}
if (!rs.ExecuteQuery(query_sql))
{
IVMS_LOG_ERROR("platform.Maintenance", "Query Failed, sql is %s", query_sql.c_str());
return false;
}
string version = rs.GetString("version_no");
if (it.first == "sia")
{
ver_schema.insert(pair<string, string>("siadevice", version));
continue;
}
ver_schema.insert(pair<string, string>(it.first, version));
}
return true;
}
bool CTimerBackup::QueryBackupSchemaAndVersionForSQLite(map<string, string> backup_db, map<string, string>& ver_schema)
{
string plugin_name, descript_file_path;
for (auto db_name : backup_db)
{
plugin_name = db_name.first;
if (plugin_name == "platform")
{
descript_file_path = Bee::Base::FileUtil::GetCurExeDirUtf8() + "META_INFO\\" + "Platform.xml";
}
else
{
descript_file_path = Bee::Base::FileUtil::GetCurExeDirUtf8() + "META_INFO\\" + plugin_name + "\\" + plugin_name + ".xml";
}
if (plugin_name == "public")
{
continue;
}
string plugin_ver = GetPluginVer(descript_file_path, plugin_name);
if (plugin_ver.empty())
{
IVMS_LOG_ERROR("platform.Maintenance", "Query %s's version fail, path %s", plugin_name.c_str(), descript_file_path.c_str());
return false;
}
ver_schema.insert(make_pair(plugin_name, plugin_ver));
}
return true;
}
bool CTimerBackup::RecordBackupTableInfo(map<string, string> ver_schema)
{
boost::system::error_code ec;
// 首先查看是否安装addon
string beeaddons_xml = Bee::Base::FileUtil::GetCurExeDirUtf8() + "BeeAddons/InstalledProducts.xml";
map<string, string> addon_info;
if (boost::filesystem::exists(beeaddons_xml,ec))
{
string beeaddons_buf;
if (!CFileBak::ReadFile(beeaddons_buf, beeaddons_xml))
{
IVMS_LOG_ERROR("platform.Maintenance", "Read InstalledProducts.xml fail, path = %s", beeaddons_xml.c_str());
return false;
}
shared_ptr<proto::IProto> ptr_info(new proto::CXmlProto());
ptr_info->set_str(beeaddons_buf);
int node_count = ptr_info->get_cnt("/InstalledProductsDescription/Addons");
string addon_id, addon_version, str_addon_node;
for (int i = 1; i <= node_count; i++)
{
str_addon_node = StringUtil::str_fmt("/InstalledProductsDescription/Addons/Addon[%d]", i);
addon_id = ptr_info->get_a(str_addon_node, "ID"); // e.g: addon_dahua
addon_version = ptr_info->get_a(str_addon_node, "Version"); // e.g: 1.1.0
addon_info.insert(make_pair(addon_id, addon_version));
}
}
string backup_info_xml = CConfigPathManager::Instance().GetBackupInfoPath();
if (!boost::filesystem::exists(backup_info_xml,ec))
{
IVMS_LOG_ERROR("platform.Maintenance", "BackupInfo.xml not exist, path : %s", backup_info_xml.c_str());
return false;
}
// 首先对加密内容进行解密
string encrypt_buf;
if (!CFileBak::ReadFile(encrypt_buf, backup_info_xml))
{
IVMS_LOG_ERROR("platform.Maintenance", "Read encrypt BackupInfo.xml fail, path = %s", backup_info_xml.c_str());
return false;
}
// 解密后的内容进行保存
string decrypt_buf;
if (!PrivateEncrypt::PrivateAESDecryptDBSetup(decrypt_buf, encrypt_buf))
{
IVMS_LOG_ERROR("platform.Maintenance", "Decryption BackupInfo.xml failed");
return false;
}
if (!CFileBak::WriteFile(backup_info_xml, decrypt_buf))
{
IVMS_LOG_FATAL("platform.Maintenance", "Write Decryption BackupInfo.xml File error");
return false;
}
Sleep(500);
tinyxml2::XMLDocument doc;
doc.LoadFile(backup_info_xml.c_str());
tinyxml2::XMLElement *ptr_root = doc.RootElement();
if (ptr_root != nullptr)
{
tinyxml2::XMLElement *ptr_schema = ptr_root->FirstChildElement("SchemaInfo");
if (ptr_schema != nullptr)
{
// 记录之前先清空文件中的内容
ptr_schema->DeleteChildren();
// 开始向文件中插入备份文件中的数据模式及版本
for (auto it : ver_schema)
{
tinyxml2::XMLElement *ptr_element = doc.NewElement("Table");
//元素的属性 id,属性值为1
ptr_element->SetAttribute("Schema", it.first.c_str());
ptr_element->SetAttribute("Version", it.second.c_str());
ptr_schema->InsertEndChild(ptr_element);
}
}
if (!addon_info.empty())
{
// 记录表名称
tinyxml2::XMLElement *ptr_table_name = ptr_root->LastChildElement("TableInfo");
if (ptr_table_name != nullptr)
{
ptr_table_name->DeleteChildren();
for (auto it : addon_info)
{
tinyxml2::XMLElement *ptr_element = doc.NewElement("Tables");
//元素的属性 id,属性值为1
ptr_element->SetAttribute("AddonID", it.first.c_str());
ptr_element->SetAttribute("Version", it.second.c_str());
ptr_table_name->InsertEndChild(ptr_element);
}
}
}
}
doc.SaveFile(backup_info_xml.c_str());
// 对写好的明文内容进行加密
if (!CFileBak::ReadFile(decrypt_buf, backup_info_xml))
{
IVMS_LOG_ERROR("platform.Maintenance", "Read encrypt BackupInfo.xml fail, path = %s", backup_info_xml.c_str());
return false;
}
if (!PrivateEncrypt::PrivateAESEncryptDBSetup(encrypt_buf, decrypt_buf))
{
IVMS_LOG_ERROR("platform.Maintenance", " BackupInfo.xml Encryption failed");
return false;
}
if (!CFileBak::WriteFile(backup_info_xml, encrypt_buf))
{
IVMS_LOG_FATAL("platform.Maintenance", "Write Encrypt BackupInfo.xml File error");
return false;
}
Sleep(500);
return true;
}
bool CTimerBackup::RecordBackupTableInfo(map<string, string> ver_schema, multimap<string, string> full_table_name)
{
string backup_info_xml = CConfigPathManager::Instance().GetBackupInfoPath();
if (!boost::filesystem::exists(backup_info_xml))
{
IVMS_LOG_ERROR("platform.Maintenance", "BackupInfo.xml not exist, path : %s", backup_info_xml.c_str());
return false;
}
// 首先对加密内容进行解密
string encrypt_buf;
if (!CFileBak::ReadFile(encrypt_buf, backup_info_xml))
{
IVMS_LOG_ERROR("platform.Maintenance", "Read encrypt BackupInfo.xml fail, path = %s", backup_info_xml.c_str());
return false;
}
// 解密后的内容进行保存
string decrypt_buf;
if (!PrivateEncrypt::PrivateAESDecryptDBSetup(decrypt_buf, encrypt_buf))
{
IVMS_LOG_ERROR("platform.Maintenance", "Decryption BackupInfo.xml failed");
return false;
}
if (!CFileBak::WriteFile(backup_info_xml, decrypt_buf))
{
IVMS_LOG_FATAL("platform.Maintenance", "Write Decryption BackupInfo.xml File error");
return false;
}
Sleep(500);
tinyxml2::XMLDocument doc;
doc.LoadFile(backup_info_xml.c_str());
tinyxml2::XMLElement *ptr_root = doc.RootElement();
if (ptr_root != nullptr)
{
tinyxml2::XMLElement *ptr_schema = ptr_root->FirstChildElement("SchemaInfo");
if (ptr_schema != nullptr)
{
// 记录之前先清空文件中的内容
ptr_schema->DeleteChildren();
// 开始向文件中插入备份文件中的数据模式及版本
for (auto it : ver_schema)
{
tinyxml2::XMLElement *ptr_element = doc.NewElement("Table");
//元素的属性 id,属性值为1
ptr_element->SetAttribute("Schema", it.first.c_str());
ptr_element->SetAttribute("Version", it.second.c_str());
ptr_schema->InsertEndChild(ptr_element);
}
}
// 记录表名称
tinyxml2::XMLElement *ptr_table_name = ptr_root->LastChildElement("TableInfo");
if (ptr_table_name != nullptr)
{
ptr_table_name->DeleteChildren();
for (auto it : full_table_name)
{
tinyxml2::XMLElement *ptr_element = doc.NewElement("Tables");
//元素的属性 id,属性值为1
ptr_element->SetAttribute("Schema", it.first.c_str());
ptr_element->SetAttribute("Name", it.second.c_str());
ptr_table_name->InsertEndChild(ptr_element);
}
}
}
doc.SaveFile(backup_info_xml.c_str());
// 对写好的明文内容进行加密
if (!CFileBak::ReadFile(decrypt_buf, backup_info_xml))
{
IVMS_LOG_ERROR("platform.Maintenance", "Read encrypt BackupInfo.xml fail, path = %s", backup_info_xml.c_str());
return false;
}
if (!PrivateEncrypt::PrivateAESEncryptDBSetup(encrypt_buf, decrypt_buf))
{
IVMS_LOG_ERROR("platform.Maintenance", " BackupInfo.xml Encryption failed");
return false;
}
if (!CFileBak::WriteFile(backup_info_xml, encrypt_buf))
{
IVMS_LOG_FATAL("platform.Maintenance", "Write Encrypt BackupInfo.xml File error");
return false;
}
Sleep(500);
return true;
}
bool CTimerBackup::RecordBackupTableInfo(map<string, string> ver_schema, multimap<string, string> full_table_name, vector<BackupCategoryInfo::table_info> vec_main_table)
{
string backup_info_xml = CConfigPathManager::Instance().GetBackupInfoPath();
if (!boost::filesystem::exists(backup_info_xml))
{
IVMS_LOG_ERROR("platform.Maintenance", "BackupInfo.xml not exist, path : %s", backup_info_xml.c_str());
return false;
}
// 首先对加密内容进行解密
string encrypt_buf;
if (!CFileBak::ReadFile(encrypt_buf, backup_info_xml))
{
IVMS_LOG_ERROR("platform.Maintenance", "Read encrypt BackupInfo.xml fail, path = %s", backup_info_xml.c_str());
return false;
}
// 解密后的内容进行保存
string decrypt_buf;
if (!PrivateEncrypt::PrivateAESDecryptDBSetup(decrypt_buf, encrypt_buf))
{
IVMS_LOG_ERROR("platform.Maintenance", "Decryption BackupInfo.xml failed");
return false;
}
if (!CFileBak::WriteFile(backup_info_xml, decrypt_buf))
{
IVMS_LOG_FATAL("platform.Maintenance", "Write Decryption BackupInfo.xml File error");
return false;
}
Sleep(500);
tinyxml2::XMLDocument doc;
doc.LoadFile(backup_info_xml.c_str());
tinyxml2::XMLElement *ptr_root = doc.RootElement();
if (ptr_root != nullptr)
{
tinyxml2::XMLElement *ptr_schema = ptr_root->FirstChildElement("SchemaInfo");
if (ptr_schema != nullptr)
{
// 记录之前先清空文件中的内容
ptr_schema->DeleteChildren();
// 开始向文件中插入备份文件中的数据模式及版本
for (auto it : ver_schema)
{
tinyxml2::XMLElement *ptr_element = doc.NewElement("Table");
//元素的属性 id,属性值为1
ptr_element->SetAttribute("Schema", it.first.c_str());
ptr_element->SetAttribute("Version", it.second.c_str());
ptr_schema->InsertEndChild(ptr_element);
}
}
// 记录表名称
tinyxml2::XMLElement *ptr_table_name = ptr_root->LastChildElement("TableInfo");
if (ptr_table_name != nullptr)
{
ptr_table_name->DeleteChildren();
for (auto it : full_table_name)
{
tinyxml2::XMLElement *ptr_element = doc.NewElement("Tables");
//元素的属性 id,属性值为1
ptr_element->SetAttribute("Schema", it.first.c_str());
ptr_element->SetAttribute("Name", it.second.c_str());
ptr_table_name->InsertEndChild(ptr_element);
}
}
// 记录主表名称
tinyxml2::XMLElement *ptr_main_table = ptr_root->FirstChildElement("MainTable");
if (ptr_main_table != nullptr)
{
ptr_main_table->DeleteChildren();
for (const auto& it_main : vec_main_table)
{
tinyxml2::XMLElement *ptr_element = doc.NewElement("Table");
ptr_element->SetAttribute("Schema", it_main.schema_name.c_str());
ptr_element->SetAttribute("Name", it_main.table_name.c_str());
ptr_main_table->InsertEndChild(ptr_element);
}
}
}
doc.SaveFile(backup_info_xml.c_str());
// 对写好的明文内容进行加密
if (!CFileBak::ReadFile(decrypt_buf, backup_info_xml))
{
IVMS_LOG_ERROR("platform.Maintenance", "Read encrypt BackupInfo.xml fail, path = %s", backup_info_xml.c_str());
return false;
}
if (!PrivateEncrypt::PrivateAESEncryptDBSetup(encrypt_buf, decrypt_buf))
{
IVMS_LOG_ERROR("platform.Maintenance", " BackupInfo.xml Encryption failed");
return false;
}
if (!CFileBak::WriteFile(backup_info_xml, encrypt_buf))
{
IVMS_LOG_FATAL("platform.Maintenance", "Write Encrypt BackupInfo.xml File error");
return false;
}
Sleep(500);
return true;
}
// bool CTimerBackup::BackupStatus(int status)
// {
// IVMS_LOG_ERROR("platform.Maintenance", "START RECORD RUN BACKUP.");
// string backup_info_xml = CConfigPathManager::Instance().GetBackupInfoPath();
// string backup_info_buf;
// if (!CFileBak::ReadFile(backup_info_buf, backup_info_xml))
// {
// IVMS_LOG_ERROR("platform.Maintenance", "Read BackupInfo.xml fail, path = %s", backup_info_xml.c_str());
// return false;
// }
//
// shared_ptr<proto::IProto> ptr_status(new proto::CXmlProto());
//
// ptr_status->set_str(backup_info_buf);
// ptr_status->set_v("/BackupInfo/IsBackupRestore", status);
//
// string str_status = ptr_status->get_str(1);
// CFileBak::WriteFile(backup_info_xml, str_status);
// // 确保XML写完
// Sleep(500);
//
// return true;
// }
PORT_T CTimerBackup::GetPortFromDBInfo()
{
boost::system::error_code ec;
string dbinfo_xml = CConfigPathManager::Instance().GetDBInfoPath();
if (!boost::filesystem::exists(dbinfo_xml, ec))
{
IVMS_LOG_ERROR("platform.Maintenance", "The DBInfo.xml is not exist, path = %s", dbinfo_xml.c_str());
return false;
}
string dbinfo_buf;
if (!CFileBak::ReadFile(dbinfo_buf, dbinfo_xml))
{
IVMS_LOG_ERROR("platform.Maintenance", "Read DBInfo.xml fail, path = %s", dbinfo_xml.c_str());
return false;
}
shared_ptr<proto::IProto> ptr_port(new proto::CXmlProto());
ptr_port->set_str(dbinfo_buf);
PORT_T port = static_cast<PORT_T>(ptr_port->get_int_v("/DBInfo/DBPort", 5432));
IVMS_LOG_INFO("platform.Maintenance", "Port is: = %d", port);
return port;
}
void CTimerBackup::GetUpgradeInfoForBee()
{
int record_upgrade_progress = 0;
int tips = 0;
int upgrade_status = 0;
int upgrade_record_status = -1;
CDBUpgradeStatusISAPIComm::Instance().GetUpgradeProgressForBee(iBeeAgentClientId, record_upgrade_progress, tips, upgrade_status, upgrade_record_status);
if ((record_upgrade_progress == 100 && upgrade_status == 1) || tips == 0 || upgrade_status == 0 || upgrade_status == 3 || upgrade_record_status == 2)
{
if (process_task_id_ != 0)
{
CTimedTaskManager::Instance().DeleteTask(process_task_id_);
}
}
}
/*
iClientId 客户端id
strMsg 消息内容
iMsgSize 消息大小
iMsgType 消息类型 0-文本,1-二进制
*/
auto beeAgentMsgCallBack = [](int iClientId, std::string strMsg, unsigned int iMsgSize, int iMsgType)
{
CTimerBackup::Instance().BeeAngetFunCallBack(iClientId, strMsg, iMsgSize, iMsgType);
};
/*
iClient_id 客户端id
iError_type 错误类型 0-连接成功,1-连接断开
*/
auto beeAgentErrorMsgCallBack = [](int iClient_id, int iError_type)
{
if (0 == iError_type)
{
CTimerBackup::Instance().BeeAgentErrorCallBack();
}
};
/** @fn InitialMgr()
* @brief 初始化,启动一个定时器
* @param void
* @return void
*/
void CTimerBackup::InitialMgr()
{
i_sys_dump_percent_ = 100;
i_dump_sum_ = 100;
// i_sys_pic_bak_percent_ = 100;
b_is_dump_running_ = false;
b_is_site_dump_running_ = false;
b_is_site_dump_percent_ = 100;
i_sys_restore_percent_ = 100;
i_restore_sum_ = 100;
// i_sys_pic_res_percent_ = 100;
b_is_restore_running_ = false;
b_recvBeeAgent_progress = false;
b_recBeeAgent_diskSpace = false;
b_recvBackupResult_ = false;
b_recvRestoreResult_ = false;
b_is_diff_machine = false;
b_is_diskSpace_ok = false;
iProgressResult_ = -1;
iProgressPercent_ = 0;
b_recvDeleteBackup_ = false;
i_recvDeleteResult_ = -1;
b_recvAllFiles_ = false;
i_recvAllFiles_ = -1;
strAllFiles_ = "";
strAllFilesGuid_ = "";
b_is_site_backup_finished_ = false;
// 获取当前数据库版本号
CMaintenanceManager::Instance().GetCurrentVersionInfo(vsm_db_version_);
m_bak_error_ = 0;
m_res_error_ = 0;
m_site_bak_error_ = 0;
// has_dump_pic_bak_ = false;
#ifndef HCL_CODE
if (VSMPlatform::Config::GetPlatformRunType() == VSMPlatform::Config::OutPlatformRunType::StandAlone)
{
PostgreSQL_path_ = CConfigManager::Instance().GetPostgerSQLPath();
}
else
{
PostgreSQL_path_ = CBackupConfigManager::Instance().GetClusterPostgreSQLPath();
}
#if (defined(_WIN32) || defined(_WIN32_WCE) || defined(_WIN64))
PostgreSQL_Data_path_ = CConfigManager::Instance().GetPostgerSQLDataPath();
#elif defined(__linux__)
PostgreSQL_path_ = CMPAManager::Instance().GetCurProgramDir() + "../postgresql/";
#endif
postgre_port_ = GetPortFromDBInfo();
#endif
//auto timer_func = bind(&CTimerBackup::ExecDriveClonePlan, this);
// m_dc_ctimer_ = unique_ptr<CTimer>(new CTimer(timer_func));
// // 间隔一分钟执行
// m_dc_ctimer_->start(60 * 1000 - 1, false);
// 如果不是单机部署,创建一份基础备份
if (VSMPlatform::Config::GetPlatformRunType() == VSMPlatform::Config::OutPlatformRunType::ClusterMaster)
{
// 如果不存在,说明未进行过基础备份,为第一次安装,非重启
// 通知DCC进行基础备份
// UpdateBaseBackup(dc_bak_conf_Plan_.str_save_file_path, PostgreSQL_path_)
string save_file_path = Bee::Base::StringUtil::StringReplace(dc_bak_conf_Plan_.str_save_file_path.c_str(), "\\", "/");
CBackupConfigManager::DistributeBackupInfo backup_info;
backup_info.https_url = "/ISAPI/Bumblebee/DCC/V0/IsNeedExecuteBaseBackup";
backup_info.https_bodys = Bee::Base::StringUtil::str_fmt(R"({"DatabaseBackupRestore":{"SavePath":"%s"}})", save_file_path.c_str());
IVMS_LOG_INFO("platform.Maintenance", "https_url[%s], https_bodys[%s]", backup_info.https_url.c_str(), backup_info.https_bodys.c_str());
if (!CBackupConfigManager::Instance().IncreBackupRestore(backup_info))
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::InitialMgr IncreBackupRestore failed, https[%s]", backup_info.https_url.c_str());
}
}
// 每分钟检查一次备份计划
timed_task_id_ = CTimedTaskManager::Instance().PostTask(string(__FUNCTION__) + "[ExecDriveClonePlan]",
std::bind(&CTimerBackup::ExecDriveClonePlan, this), 60 * 1000, false);
// 如果是集群部署开启定时任务,每小时主动执行归档
if (VSMPlatform::Config::GetPlatformRunType() == VSMPlatform::Config::OutPlatformRunType::ClusterMaster)
{
timed_task_id_active_ = CTimedTaskManager::Instance().PostTask(string(__FUNCTION__) + "[ActiveArchive]",
std::bind(&CTimerBackup::ActiveArchive, this), 6 * 60 * 60 * 1000, false);
timed_task_id_check_ = CTimedTaskManager::Instance().PostTask(string(__FUNCTION__) + "[Timing_RefreshBaseBack]",
std::bind(&CTimerBackup::Timing_RefreshBaseBack, this), 5 * 60 * 1000);
}
// 判断当前是否为分布式
#ifndef HCL_CODE
is_distributed_ = CLicenseManager::Instance().haveDistributedSupport() ? true : false;
//初始化和看门狗的连接
//memset(&BeeAgentInfo, 0, sizeof(AgentClientInfo));
BeeAgentInfo.url = "";
//BeeAgentInfo.port = 8208;
BeeAgentInfo.port = VSMPlatform::CConfigManager::Instance().GetVSMPort().beagent_manager_ssl_port;
BeeAgentInfo.agent_ip = "127.0.0.1";
BeeAgentInfo.module_name = BeeAgentInfo.agent_ip + ":BackupRestore";
BeeAgentInfo.recv_callback = beeAgentMsgCallBack;
BeeAgentInfo.error_callback = beeAgentErrorMsgCallBack;
strBeeAgentSetPath_ = "";
// notes:与看门狗创建连接
CBeeAgentClientManager::Instance().CreateAgentClient(iBeeAgentClientId, BeeAgentInfo);
CBeeAgentClientManager::Instance().CheckAuthencation(iBeeAgentClientId, true);
// CThreadManager::Instance().PostTask(string(__FUNCTION__) + "[GetUpgradeProgressForBee]",
// std::bind(&CDBUpgradeStatusISAPIComm::GetUpgradeProgressForBee, this, iBeeAgentClientId));
string product_type;
if (!QueryUpgradeProduct(product_type))
{
IVMS_LOG_ERROR("platform.UpgradeProgress", "QueryUpgradeProduct FAILED!");
// 如果查询失败,默认为HCP,报错提个醒
product_type = "HCP";
}
// notes:开启线程向看门狗发送升级信息
if (product_type == "HCP")
{
process_task_id_ = CTimedTaskManager::Instance().PostTask(string(__FUNCTION__) + "[GetUpgradeInfoForBee]",
std::bind(&CTimerBackup::GetUpgradeInfoForBee, this), 3 * 1000, false);
if (process_task_id_ == 0)
{
IVMS_LOG_ERROR("platform.UpgradeProgress", "open timer refresh duration failed!");
}
}
//请求是不是异机部署
shared_ptr<proto::IProto> parse = make_shared<proto::CRapidJsonProto>();
string strGuid = Bee::Base::GuidUtil::CreateGuid();
parse->set_v("/Guid", strGuid);
parse->set_v("/RequestData/Method", "GetDataBaseDeployMode");
string strReq = parse->get_str();
bool bSend = CBeeAgentClientManager::Instance().SendMsg(iBeeAgentClientId, strReq, Bee::Net::WebSocket::TEXT);
if (bSend)
{
IVMS_LOG_INFO("platform.Maintenance", "CTimerBackup::InitialMgr GetDataBaseDeployMode Body %s", strReq.c_str());
}
else
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::InitialMgr GetDataBaseDeployMode Error Body %s", strReq.c_str());
}
//配置路径
parse->clear();
strGuid = Bee::Base::GuidUtil::CreateGuid();
parse->set_v("/Guid", strGuid);
parse->set_v("/RequestData/Method", "GetBackupPath");
strReq = parse->get_str();
bSend = CBeeAgentClientManager::Instance().SendMsg(iBeeAgentClientId, strReq, Bee::Net::WebSocket::TEXT);
if (bSend)
{
IVMS_LOG_INFO("platform.Maintenance", "CTimerBackup::InitialMgr GetBackupPath Body %s", strReq.c_str());
}
else
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::InitialMgr GetBackupPath Error Body %s", strReq.c_str());
}
#else
is_distributed_ = false;
#endif
}
/** @fn UnintialMgr()
* @brief 反初始化
* @param void
* @return void
*/
void CTimerBackup::UnintialMgr()
{
CTimedTaskManager::Instance().DeleteTask(timed_task_id_);
if (VSMPlatform::Config::GetPlatformRunType() == VSMPlatform::Config::OutPlatformRunType::ClusterMaster)
{
CTimedTaskManager::Instance().DeleteTask(timed_task_id_active_);
}
#ifdef HCL_CODE
if (check_task_id_ != 0)
{
CTimedTaskManager::Instance().DeleteTask(check_task_id_);
}
#endif // HCL_CODE
}
/** @fn LaunchBackupProcess(const string& backup_file_path)
* @brief 执行备份进程
* @param string& backup_file_path 备份文件全路径
* @return bool
*/
bool CTimerBackup::RemoteDriveClone(const string& backup_file_path)
{
if (b_is_dump_running_ || b_is_restore_running_ || b_is_site_dump_running_)
{
// 日志打印
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_IS_BACKUPING_RESTORING)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::RemoteDriveClone Is Backuping or Restroing Now, Repeat CMDs");
return false;
}
b_is_dump_running_ = true;
b_is_site_dump_running_ = true;
b_is_site_dump_percent_ = 0;
i_sys_dump_percent_ = 0;
i_dump_sum_ = 0;
UINT_T ret = 0;
if (VSMPlatform::Config::GetPlatformRunType() != VSMPlatform::Config::OutPlatformRunType::StandAlone)
{
ret = RSM_ExecPGDumpProgress(backup_file_path);
}
else
{
ret = RSM_ExecPGDumpProgress(backup_file_path, vec_backup_conf_table);
}
i_sys_dump_percent_ = 100;
i_dump_sum_ = 100;
b_is_dump_running_ = false;
b_is_site_dump_running_ = false;
b_is_site_dump_percent_ = 100;
cs_backup_fail_flag_ = false;
if (ret != 0)
{
IVMS_LOG_ERROR("platform.Maintenance", "RemoteDriveClone FAILED");
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_BACKUP_FAIL)));
return false;
}
return true;
}
// 获取备份状态
void CTimerBackup::GetBackupStatus(bool& backup_fail_flag, UINT_T& eror_code, string& backup_path)
{
backup_fail_flag = cs_backup_fail_flag_;
eror_code = static_cast<UINT_T>(error_type_);
backup_path = dc_bak_conf_Plan_.str_save_file_path;
}
bool CTimerBackup::CheckDiskSpace(string& disk_name, UINT_T nfreeSpace)
{
#if (defined(_WIN32) || defined(_WIN32_WCE) || defined(_WIN64))
ULARGE_INTEGER FreeBytesAvailable;
ULARGE_INTEGER TotalNumberOfBytes;
ULARGE_INTEGER TotalNumberOfFreeBytes;
if (!GetDiskFreeSpaceExA(disk_name.c_str(), &FreeBytesAvailable, &TotalNumberOfBytes, &TotalNumberOfFreeBytes))
{
IVMS_LOG_ERROR("platform.Maintenance", "Get Disk Free Space Fail, error code = %d", GetLastError());
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUP_DISK_FULL))); // 具体原因不返回出去
return false;
}
ULONGLONG FreeDisk = TotalNumberOfFreeBytes.QuadPart / 1024 / 1024;
if (FreeDisk < nfreeSpace)// 单位到MB
{
IVMS_LOG_ERROR("platform.Maintenance", "Disk Full , Free Disk = %d", static_cast<UINT_T>(FreeDisk));
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUP_DISK_FULL))); // 具体原因不返回出去
error_type_ = BackupFileError::ErrorType::DiskFull;
return false;
}
return true;
#else
//检查目录是否存在,不存在则创建
if (!boost::filesystem::exists(disk_name))
{
boost::filesystem::create_directory(disk_name);
IVMS_LOG_INFO("platform.Maintenance", "Disk not exist, create : %s", disk_name.c_str());
}
struct statfs statbuf = { 0 };
ULONGLONG free_space_Byte = 0;
if (statfs(disk_name.c_str(), &statbuf) >= 0)
{
free_space_Byte = (unsigned long long)((unsigned long long)statbuf.f_bavail * (unsigned long long)statbuf.f_bsize);
}
else
{
Error::SetLastError(Error::ErrorCode(CMS_MODULE_CMS, CMS_UNKOWN_ERROR));
IVMS_LOG_ERROR("platform.VSM", "Get Disk Free Space Fail in statfs");
return false;
}
ULONGLONG free_space_MB = free_space_Byte / 1024 / 1024; // 单位到k->mb
cout << "free_space_MB:" << free_space_MB << endl;
if (free_space_MB < nfreeSpace)// 单位到MB
{
IVMS_LOG_ERROR("platform.Maintenance", "Disk Full , Free Disk = %d", static_cast<UINT_T>(free_space_MB));
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUP_DISK_FULL))); // 具体原因不返回出去
error_type_ = BackupFileError::ErrorType::DiskFull;
return false;
}
return true;
#endif
}
void CTimerBackup::TimingDriveCloneTry()
{
#ifdef HCL_CODE
if (!MaintenanceSession::QueryDriveCloneTime())
{
return;
}
#endif
vector<int> vec_time;
StringUtil::String2Array(vec_time, dc_bak_conf_Plan_.str_clone_time, ':');
if (vec_time.size() != 2)
{
assert(0);
IVMS_LOG_WARN("platform.Maintenance", "Backup Time Invalied Time = %s", dc_bak_conf_Plan_.str_clone_time.c_str());
return;
}
time_t tm_time = time(0);
tm tm_current_time = *localtime(&tm_time);
if (vec_time[0] == tm_current_time.tm_hour && vec_time[1] == tm_current_time.tm_min)
{
UINT_T result = DRIVE_CLONE_RESTORE_SUCC;
bool do_back_up = false;
// 根据备份频率执行
switch (dc_bak_conf_Plan_.em_clone_freq)
{
case DriveCloneConf::DriveCloneFrequency::Daliy:
{
do_back_up = true;
result = DriveCloneRightAway(dc_bak_conf_Plan_);
}
break;
case DriveCloneConf::DriveCloneFrequency::Weekly:
if ((dc_bak_conf_Plan_.i_clone_day == (UINT_T)tm_current_time.tm_wday) ||
(dc_bak_conf_Plan_.i_clone_day == 7 && (UINT_T)tm_current_time.tm_wday == 0))
{
do_back_up = true;
if (VSMPlatform::Config::GetPlatformRunType() == VSMPlatform::Config::OutPlatformRunType::ClusterMaster)
{
if (b_is_dump_running_ || b_is_restore_running_)
{
// 日志打印
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_IS_BACKUPING_RESTORING)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::DriveCloneRightAway Is Backuping or Restroing Now, Repeat CMDs");
return;
}
b_is_dump_running_ = true;
i_sys_dump_percent_ = 0;
string save_file_path = Bee::Base::StringUtil::StringReplace(dc_bak_conf_Plan_.str_save_file_path.c_str(), "\\", "/");
CBackupConfigManager::DistributeBackupInfo backup_info;
backup_info.https_url = "/ISAPI/Bumblebee/DCC/V0/UpdateBaseBackup";
backup_info.https_bodys = Bee::Base::StringUtil::str_fmt(R"({"DatabaseRestore":{"SavePath":"%s"}})",
save_file_path.c_str());
IVMS_LOG_INFO("platform.Maintenance", "https_url[%s], https_bodys[%s]", backup_info.https_url.c_str(), backup_info.https_bodys.c_str());
if (!CBackupConfigManager::Instance().IncreBackupRestore(backup_info))
{
IVMS_LOG_ERROR("platform.Maintenance", "IncreBackupRestore failed, https[%s]", backup_info.https_url.c_str());
result = DRIVE_CLONE_RESTORE_FAIL;
}
else
{
result = DRIVE_CLONE_RESTORE_SUCC;
}
b_is_dump_running_ = false;
i_sys_dump_percent_ = 100;
}
else
{
result = DriveCloneRightAway(dc_bak_conf_Plan_);
}
}
break;
case DriveCloneConf::DriveCloneFrequency::Monthly:
{
// 天数少月份处理
if (tm_current_time.tm_mon == 1 && dc_bak_conf_Plan_.i_clone_day > 28)
{
time_t tm_day = time(0) + 3600 * 24;
tm tm_interval;
localtime_s(&tm_interval, &tm_day);
if (tm_interval.tm_mon != tm_current_time.tm_mon)
{
do_back_up = true;
result = DriveCloneRightAway(dc_bak_conf_Plan_);
}
}
else if ((tm_current_time.tm_mon == 3 ||
tm_current_time.tm_mon == 5 ||
tm_current_time.tm_mon == 8 ||
tm_current_time.tm_mon == 10) && dc_bak_conf_Plan_.i_clone_day > 30)
{
time_t tm_day = time(0) + 3600 * 24;
tm tm_interval;
localtime_s(&tm_interval, &tm_day);
if (tm_interval.tm_mon != tm_current_time.tm_mon)
{
do_back_up = true;
result = DriveCloneRightAway(dc_bak_conf_Plan_);
}
}
else
{
if (dc_bak_conf_Plan_.i_clone_day == (UINT_T)tm_current_time.tm_mday)
{
do_back_up = true;
result = DriveCloneRightAway(dc_bak_conf_Plan_);
break;
}
}
}
default:
break;
}
if (do_back_up)
{
//如果进行了定时备份就记录日志,虽然备份时异步进行的,不处理异步里面失败的问题
int error = 0;
if (result != DRIVE_CLONE_RESTORE_SUCC)
{
Error::ErrorCode error_code = Error::GetLastError();
error = error_code.iFirstCode;
}
WriteOperationLog::WriteSystemLog(static_cast<ID>(OperationLog::LogType::DataBackUpPlan), "", true, CMS_MODULE_CMS, error);
}
}
}
void CTimerBackup::TrySiteBackup(const UINT_T id_site)
{
rsmmodule::RemoteSiteExtendData remotesite;
if (!rsmmodule::RSMModule_FindRemoteSiteByID(remotesite, id_site))
{
return;
}
DriveCloneConf backupInfo;
CMaintenanceManager::Instance().GetSiteDatabaseBackUpInfo(backupInfo, id_site, remotesite.guid);
if (!backupInfo.remote_enable)
{
return;
}
vector<int> vecTime;
StringUtil::String2Array(vecTime, backupInfo.str_clone_time, ':');
if (vecTime.size() != 2)
{
assert(0);
IVMS_LOG_WARN("platform.Maintenance", "Backup Time Invalied time = %s", backupInfo.str_clone_time.c_str());
return;
}
time_t tmTime = time(0);
tm tmCurrentTime = *localtime(&tmTime);
if (vecTime[0] == tmCurrentTime.tm_hour && vecTime[1] == tmCurrentTime.tm_min)//时间匹配
{
switch (backupInfo.em_clone_freq)
{
case DriveCloneConf::DriveCloneFrequency::Daliy:
RSM_InvokeDriveClone(id_site);
break;
case DriveCloneConf::DriveCloneFrequency::Weekly:
IVMS_LOG_WARN("Maintenance", "Backup Time i_clone_day time = %d %d", backupInfo.i_clone_day, (UINT_T)tmCurrentTime.tm_wday);
if ((backupInfo.i_clone_day % 7) == (UINT_T)tmCurrentTime.tm_wday)
{
RSM_InvokeDriveClone(id_site);
}
break;
case DriveCloneConf::DriveCloneFrequency::Monthly:
{
IVMS_LOG_WARN("Maintenance", "Backup Time tm_mon time = %d %d %d", tmCurrentTime.tm_mon, backupInfo.i_clone_day, tmCurrentTime.tm_mday);
// 天数少月份处理
if (tmCurrentTime.tm_mon == 1 && backupInfo.i_clone_day > 28)
{
time_t tm_day = time(0) + 3600 * 24;
tm tm_interval;
localtime_s(&tm_interval, &tm_day);
if (tm_interval.tm_mon != tmCurrentTime.tm_mon)
{
RSM_InvokeDriveClone(id_site);
}
}
else if ((tmCurrentTime.tm_mon == 3 ||
tmCurrentTime.tm_mon == 5 ||
tmCurrentTime.tm_mon == 8 ||
tmCurrentTime.tm_mon == 10) && backupInfo.i_clone_day > 30)
{
time_t tm_day = time(0) + 3600 * 24;
tm tm_interval;
localtime_s(&tm_interval, &tm_day);
if (tm_interval.tm_mon != tmCurrentTime.tm_mon)
{
RSM_InvokeDriveClone(id_site);
}
}
else
{
if (backupInfo.i_clone_day == (UINT_T)tmCurrentTime.tm_mday)
{
RSM_InvokeDriveClone(id_site);
break;
}
}
}
default:
break;
}
}
}
//输入存储路径,输出存储文件全名路径
bool CTimerBackup::MakeRemoteFilePath(string &file_path, const string &save_path)
{
// 如果目录不存在,要创建出来,并检测目录是否可写
if (!MakeFullPathDir(save_path))
{
IVMS_LOG_ERROR("platform.Maintenance", "Make Dir fail %s", save_path.c_str());
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_CREATE_PATH_FAIL))); // 具体原因不返回出去
error_type_ = BackupFileError::ErrorType::CreatePathFail;
return false;
}
// 检测磁盘空间,小于100MB认为磁盘空间不足,不进行备份
auto index = save_path.find(":");
string disk_name = save_path.substr(0, index + 2);
if (!CheckDiskSpace(disk_name, 100))
{
IVMS_LOG_ERROR("platform.Maintenance", "CheckDiskspace Failed %s", disk_name.c_str());
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUP_DISK_FULL)));
error_type_ = BackupFileError::ErrorType::DiskFull;
return false;
}
// 与本地备份文件名保持一致
file_path = save_path + "VSM_DB-Config.bak";
return true;
}
int CTimerBackup::GetBeeAgentClientId()
{
return iBeeAgentClientId;
}
bool CTimerBackup::RSM_InvokeDriveClone(UINT_T id_site)
{
if (b_is_site_dump_running_ || b_is_site_restore_running_)
{
// 日志打印
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_IS_BACKUPING_RESTORING)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::RSM_InvokeDriveClone Is Backuping or Restroing Now, Repeat CMDs");
return false;
}
if (!CLicenseManager::Instance().IsRSMSystem()) //在执行之前再查询一次license,避免失效问题
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_LICENSE_FOUNCTION_LIMIT)));
b_is_site_dump_running_ = false;
m_site_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
return false;
}
b_is_site_dump_percent_ = 0;
b_is_site_dump_running_ = true;
m_site_bak_error_ = DRIVE_CLONE_RESTORE_SUCC;
rsmmodule::RemoteSiteExtendData remotesite;
if (!rsmmodule::RSMModule_FindRemoteSiteByID(remotesite, id_site))
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_REMOTESITE_IS_NOT_EXIST)));
b_is_site_dump_running_ = false;
b_is_site_dump_percent_ = 100;
m_site_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
return false;
}
CThreadManager::Instance().PostTask(string(__FUNCTION__) + "[Thread_ExecSiteBackupProgress_DB]",
std::bind(&CTimerBackup::Thread_ExecSiteBackupProgress_DB, this, id_site,remotesite.guid));
return true;
}
void CTimerBackup::Thread_DriveCloneRightAway_DBSQLite(const string & root_db_path, const map<string,string> &v_backup_db, const string & new_file_name, const string & str_create_time)
{
// 执行备份
// notes:初始化备份数量计数变量
backup_vec_table_num_ = 0;
// 如果存在运行时数据备份
if (v_backup_db.size() > 0)
{
string back_up_file = root_db_path + "/" + new_file_name;
if (ExecSQLiteDumpProgress(UTF82Local(back_up_file), v_backup_db, DEF_BACKUP_CONFIG) != 0)
{
// 日志打印
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_BACKUP_FAIL)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::Thread_DriveCloneRightAway_DB ExecPGDumpProgress CONFIG FAILED");
m_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
b_is_dump_running_ = false;
}
}
// notes:HCL 存在运行时的保护需要考虑
// else
// {
// if (ExecPGDumpProgress(str_whole_config_file_path, v_config_tables, DEF_BACKUP_ONLY_CONFIG) != 0)
// {
// // 日志打印
// Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_BACKUP_FAIL)));
// IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::Thread_DriveCloneRightAway_DB ExecPGDumpProgress ONLY CONFIG FAILED");
// m_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
// }
// }
//生成压缩文件
string str_zip_file_path = UTF82Local(root_db_path) + "/" + new_file_name + "/VSM_" + g_soft_version + "_BAK-SQLite.zip";
vector<string> file_list;
// 备份的zip文件所在路径
string full_path = UTF82Local(root_db_path) + "/" + new_file_name;
if (boost::filesystem::exists(full_path))
{
boost::filesystem::directory_iterator item_begin(full_path);
boost::filesystem::directory_iterator item_end;
for (; item_begin != item_end; item_begin++)
{
if (boost::filesystem::is_directory(*item_begin))
{
}
else
{
file_list.push_back(item_begin->path().string());
}
}
}
HPR_Sleep(3);
string str_compress_src = full_path + "/*";
if (NoError != Compress::CompressFiles(str_zip_file_path, str_compress_src))
{
IVMS_LOG_ERROR("platform.Maintenance", "CompressFolder FAILED");
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_BACKUP_FAIL)));
m_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
}
// 拷贝组件版本记录文件
IVMS_LOG_INFO("platform.Maintenance", "Start copy BackupInfo.xml");
boost::system::error_code err_c;
namespace ns_fs = boost::filesystem;
string src_backup_info = CConfigPathManager::Instance().GetBackupInfoPath();
string target_backup_info = full_path + "\\BackupInfo.xml";
if (ns_fs::exists(src_backup_info))
{
boost::filesystem::copy_file(src_backup_info, target_backup_info, boost::filesystem::copy_option::overwrite_if_exists, err_c);
if (err_c.value() != 0)
{
IVMS_LOG_ERROR("platform.Maintenance", "copy BackupInfo.xml file failed! The source file is %s, the target file is %s", src_backup_info.c_str(), target_backup_info.c_str());
return;
}
IVMS_LOG_INFO("platform.Maintenance", "copy BackupInfo.xml file SUCC, path is %s", target_backup_info.c_str());
}
// 删除备份源文件
boost::system::error_code ec;
for (auto file_path : file_list)
{
boost::filesystem::remove(file_path, ec);
}
i_sys_dump_percent_ = 100;
i_dump_sum_ = 100;
std::lock_guard<mutex> lock(mtx_finished_);
if (b_is_dump_running_ && i_sys_dump_percent_ == 100)
{
if (m_bak_error_ != DRIVE_CLONE_RESTORE_SUCC)
{
// 出现任意失败,均删除备份文件
FileUtil::DeleteDir((UTF82Local(root_db_path) + "/" + new_file_name).c_str());
}
b_is_dump_running_ = false;
}
}
void CTimerBackup::Thread_ExecSiteBackupProgress_DB(UINT_T id_site, const string &strGuid)
{
b_is_site_backup_finished_ = false;
DriveCloneConf site_backup_Info;
CMaintenanceManager::Instance().GetSiteDatabaseBackUpInfo(site_backup_Info,id_site,strGuid);
/*shared_ptr<proto::IProto> pro_req(new proto::CXmlProto());
pro_req->set_v("/DatabaseBackUp/BackUpNow/SavePath", backupInfo.str_save_file_path);
pro_req->set_v("/DatabaseBackUp/BackUpNow/ContainTypes", 0);*/
string str_response;
rsmmodule::RSMModule_HttpSendForBigRsp(str_response, id_site, "GET", "/ISAPI/Bumblebee/Platform/V0/Maintenance/BackupNow", "", 300 * 1000);
//rsmmodule::RSMModule_HttpSend(str_response, id_site, "GET", "/ISAPI/Bumblebee/Platform/V0/Maintenance/BackupNow", "", 300 * 1000);
//网络超时
if (str_response.empty())
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_VSMSITE), ERROR_CODE(CMS_NETWORK_TIMEOUT)));
b_is_site_dump_percent_ = 100;
b_is_site_dump_running_ = false;
m_site_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
return;
}
//站点备份失败,返回错误码
if (str_response.find("ErrorCode") != string::npos)
{
shared_ptr<proto::IProto> pro_resp(new proto::CRapidJsonProto());
pro_resp->set_str(str_response);
UINT_T iMainCode = pro_resp->get_int_v("/ResponseStatus/ErrorModule");
UINT_T iSubCode = pro_resp->get_int_v("/ResponseStatus/ErrorCode");
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_VSMSITE), ERROR_CODE(CMS_CASCADING_ERROR), Error::MakeCascadingErrorStr(iMainCode, iSubCode)));
b_is_site_dump_percent_ = 100;
b_is_site_dump_running_ = false;
m_site_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
return;
}
struct tm tmm;
time_t time_now = time(0);
localtime_s(&tmm, &time_now);
char szTime[20] = { 0 };
strftime(szTime, 20, "%Y%m%d%H%M%S", &tmm);
char szCreateTime[20] = { 0 };
strftime(szCreateTime, 20, "%Y-%m-%d %H:%M:%S", &tmm);
// 数据写入磁盘
// 生成路径,检查磁盘空间
//string backup_file_path = site_backup_Info.str_save_file_path + "VSM_" + vsm_db_version_ + "_BACKUP_" + szTime + "_" + GuidUtil::CreateGuid() + "/";
string backup_file_path = site_backup_Info.str_save_file_path + "VSM_" + g_soft_version + "_BACKUP_" + szTime + "_" + GuidUtil::CreateGuid() + "/";
// 创建临时文件路径
//string tmp_file_path = backup_file_path + "tmp_file";
string des_backup_xml = backup_file_path + "BackupInfo.xml";
boost::system::error_code ec;
// if (!boost::filesystem::exists(tmp_file_path, ec))
// {
// boost::filesystem::create_directories(tmp_file_path, ec);
// }
// VacuumPath(tmp_file_path);
// 如果目录不存在,要创建出来,并检测目录是否可写
if (!MakeFullPathDir(backup_file_path))
{
b_is_site_dump_running_ = false;
IVMS_LOG_ERROR("platform.Maintenance", "Make Dir fail %s", backup_file_path.c_str());
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_CREATE_PATH_FAIL))); // 具体原因不返回出去
error_type_ = BackupFileError::ErrorType::CreatePathFail;
return;
}
// 检测磁盘空间,小于100MB认为磁盘空间不足,不进行备份
auto index = backup_file_path.find(":");
string disk_name = backup_file_path.substr(0, index + 2);
if (!CheckDiskSpace(disk_name, 100))
{
IVMS_LOG_ERROR("platform.Maintenance", "CheckDiskspace Failed %s", disk_name.c_str());
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUP_DISK_FULL)));
error_type_ = BackupFileError::ErrorType::DiskFull;
b_is_site_dump_percent_ = 100;
b_is_site_dump_running_ = false;
m_site_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
return;
}
// 还原时,解压到zip文件名目录下
backup_file_path = backup_file_path + "VSM_" + g_soft_version + "_BAK-0.zip";
//将数据写到文件
fstream f;
f.open(backup_file_path.c_str(), ios::out | ios::binary);
if (!f.is_open())
{
b_is_site_dump_percent_ = 100;
b_is_site_dump_running_ = false;
m_site_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
return;
}
else
{
f.write(str_response.c_str(), str_response.length());
f.close();
}
// 解压备份文件,释放BackupInfo.xml文件
// if (CompressExecuteFail == Compress::UnCompress(backup_file_path, tmp_file_path))
// {
// b_is_site_dump_running_ = false;
// IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecuteDataRestoreOpt UnCompress() FAILED");
// //删除临时文件Upload
// boost::filesystem::remove_all(tmp_file_path, ec);
// return;
// }
// string tmp_backup_xml = tmp_file_path + "//BackupInfo.xml";
// if (!boost::filesystem::exists(tmp_backup_xml, ec))
// {
// b_is_site_dump_running_ = false;
// IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecuteDataRestoreOpt Compress File No BackupInfo.xml");
// boost::filesystem::remove_all(tmp_file_path, ec);
// return;
// }
// // 拷贝BackupInfo.xml到压缩包同级目录,删除解压文件中的BackupInfo.xml
// boost::filesystem::copy_file(tmp_backup_xml, des_backup_xml, boost::filesystem::copy_option::overwrite_if_exists, ec);
// if (ec.value() != 0)
// {
// b_is_site_dump_running_ = false;
// IVMS_LOG_ERROR("platform.Maintenance", "copy BackupInfo.xml file failed! The source file is %s, the target file is %s", tmp_backup_xml.c_str(), des_backup_xml.c_str());
// return;
// }
// IVMS_LOG_INFO("platform.Maintenance", "copy BackupInfo.xml file SUCC, path is %s", des_backup_xml.c_str());
//
// if (boost::filesystem::exists(tmp_file_path, ec))
// {
// boost::filesystem::remove_all(tmp_file_path, ec);
// }
vector<BackupCategoryInfo::table_info> v_bak_tables;
CBackupConfigManager::Instance().GetCategoryContainTables(v_bak_tables, 0);
map<string, int> backup_schema; //备份文件中的数据模式
map<string, string> backup_vername; //备份文件中的数据模式名称及版本
multimap<string, string> full_table_name; //备份文件中的表 <模式名,表名>
for (auto it : v_bak_tables)
{
backup_schema.insert(pair<string, int>(it.schema_name, index));
// 将表名进行记录
full_table_name.insert(pair<string, string>(it.schema_name, it.table_name));
index++;
}
if (backup_schema.empty())
{
b_is_site_dump_percent_ = 100;
b_is_site_dump_running_ = false;
m_site_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
IVMS_LOG_ERROR("platform.Maintenance", "Database schema is Empty!");
return;
}
// 获取备份文件中的数据模式和版本
if (!QueryBackupSchemaAndVersion(backup_schema, backup_vername))
{
b_is_site_dump_percent_ = 100;
b_is_site_dump_running_ = false;
m_site_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
IVMS_LOG_ERROR("platform.Maintenance", "Failed to Get schema and version in backup file");
return;
}
if (backup_vername.empty())
{
b_is_site_dump_percent_ = 100;
b_is_site_dump_running_ = false;
m_site_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
IVMS_LOG_ERROR("platform.Maintenance", "FAILED obtain schema version");
return;
}
// // 存在分表的主表名
vector<BackupCategoryInfo::table_info> v_main_table;
CBackupConfigManager::Instance().SendMainTableInfo(v_main_table);
// 将备份文件中的数据模式和版本记录在BackupInfo.xml中
if (!RecordBackupTableInfo(backup_vername, full_table_name, v_main_table))
{
b_is_site_dump_percent_ = 100;
b_is_site_dump_running_ = false;
m_site_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
IVMS_LOG_ERROR("platform.Maintenance", "Failed to write to BackupInfo.xml");
return;
}
string tmp_backup_xml = CConfigPathManager::Instance().GetBackupInfoPath();
boost::filesystem::copy_file(tmp_backup_xml, des_backup_xml, boost::filesystem::copy_option::overwrite_if_exists, ec);
if (ec.value() != 0)
{
b_is_site_dump_percent_ = 100;
b_is_site_dump_running_ = false;
m_site_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
IVMS_LOG_ERROR("platform.Maintenance", "copy BackupInfo.xml file failed! The source file is %s, the target file is %s", tmp_backup_xml.c_str(), des_backup_xml.c_str());
return;
}
//写入备份信息到DB
DriveCloneRecordsInfo backup_info;
backup_info.id_site = id_site;
backup_info.bak_file_path = backup_file_path;
backup_info.site_guid = strGuid;
// UINT_T i_no = 0;
if (!BackupRecordSession::InsertBackupRecord(backup_info, szCreateTime))
{
assert(0);
b_is_site_dump_percent_ = 100;
b_is_site_dump_running_ = false;
m_site_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
IVMS_LOG_ERROR("platform.Maintenance", "RSM_InvokeDriveClone::InsertBackupRecord Failed");
return;
}
// 数量限制
Site_EnsureMaxRecordCount(site_backup_Info.i_clone_file_limit, strGuid);
b_is_site_dump_percent_ = 100;
b_is_site_dump_running_ = false;
b_is_site_backup_finished_ = true;
}
bool CTimerBackup::Site_EnsureMaxRecordCount(UINT_T nMaxCount, const string& site_guid)
{
vector<DriveCloneRecordsInfo> vec_backup_record_info;
if (BackupRecordSession::QueryNOTLocalBackupRecordsInfo(vec_backup_record_info, site_guid))
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::Site_EnsureMaxRecordCount Faild!");
}
if (vec_backup_record_info.size() > nMaxCount)
{
sort(vec_backup_record_info.begin(), vec_backup_record_info.end(), [](const DriveCloneRecordsInfo& b1, const DriveCloneRecordsInfo& b2) {if (b1.bak_id < b2.bak_id) { return true; } return false; });
vector<DriveCloneRecordsInfo> useless_record;
for (auto it : vec_backup_record_info)
{
// 如果文件不存在的话,删掉记录
boost::system::error_code ec;
if (!boost::filesystem::exists(UTF82Local(it.bak_file_path), ec))
{
if (BackupRecordSession::DeleteBackupRecord(it.bak_id))
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::Site_EnsureMaxRecordCount::DeleteBackupRecord[1] Failed.");
}
}
else
{
useless_record.push_back(it);
}
}
// 如果文件存在的话,删掉文件
UINT_T record_count = (UINT_T)useless_record.size();
if (record_count > nMaxCount)
{
useless_record.resize(record_count - nMaxCount);
for (auto it_delete : useless_record)
{
boost::system::error_code ec;
// 删除目录
string str_up_file = UTF82Local(it_delete.bak_file_path);
size_t str_idx = str_up_file.find_last_of("/\\");
str_up_file = str_up_file.substr(0, str_idx);
// 删除本地对应备份文件
boost::filesystem::remove_all(str_up_file, ec);
//删掉数据库
if (BackupRecordSession::DeleteBackupRecord(it_delete.bak_id))
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::Site_EnsureMaxRecordCount::DeleteBackupRecord[2] Failed.");
}
}
}
}
return true;
}
bool CTimerBackup::EnsureMaxRecordCount(UINT_T nMaxCount, const string& site_guid)
{
// 删除多余备份文件
vector<DriveCloneRecordsInfo> vec_backup_record_info;
if (BackupRecordSession::QueryNOTLocalBackupRecordsInfo(vec_backup_record_info, site_guid))
{
IVMS_LOG_WARN("platform.Maintenance", "CTimerBackup::EnsureMaxRecordCount[1] Faild!");
}
if (vec_backup_record_info.size() > nMaxCount)
{
sort(vec_backup_record_info.begin(), vec_backup_record_info.end(), [](const DriveCloneRecordsInfo& b1, const DriveCloneRecordsInfo& b2) {if (b1.bak_id < b2.bak_id) { return true; } return false; });
vector<DriveCloneRecordsInfo> useless_record;
for (auto it : vec_backup_record_info)
{
// 如果文件不存在的话,删掉记录
boost::system::error_code ec;
if (is_distributed_)
{
// 判断ADS本地对应备份文件是否存在
/*if (!boost::filesystem::exists(UTF82Local(it.bak_file_path), ec) || !Bee::DistributedManager::ADS_IsBakFileExisted(it.ads_bak_file_path))
{
BackupRecordSession::DeleteBackupRecord(it.bak_id);
}
else
{
useless_record.push_back(it);
}*/
}
else
{
if (!b_is_diff_machine)
{
if (!boost::filesystem::exists(UTF82Local(it.bak_file_path), ec))
{
if (BackupRecordSession::DeleteBackupRecord(it.bak_id))
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::EnsureMaxRecordCount::DeleteBackupRecord[1] Faild!");
}
}
else
{
useless_record.push_back(it);
}
}
else
{
useless_record.push_back(it);
std::string strCreateTime = Bee::Base::TimeUtil::TimeT2StrDatetime(it.backup_time);
IVMS_LOG_INFO("platform.Maintenance", "CTimerBackup::EnsureMaxRecordCount Delete filePath %s,Time %s", it.bak_file_path.c_str(), strCreateTime.c_str());
}
}
}
// 如果文件存在的话,删掉文件
UINT_T record_count = (UINT_T)useless_record.size();
if (record_count > nMaxCount)
{
useless_record.resize(record_count - nMaxCount);
if (b_is_diff_machine)
{
b_recvDeleteBackup_ = false;
i_recvDeleteResult_ = -1;
string strBackupFilePaths;
for (auto it_delete : useless_record)
{
string str_up_file = UTF82Local(it_delete.bak_file_path);
strBackupFilePaths += str_up_file + ";";
}
shared_ptr<proto::IProto> parse = make_shared<proto::CRapidJsonProto>();
string strGuid = Bee::Base::GuidUtil::CreateGuid();
parse->set_v("/Guid", strGuid);
parse->set_v("/RequestData/Method", "DeleteBackupFiles");
parse->set_v("/RequestData/Data/BakFilePaths", strBackupFilePaths);
string strReq = parse->get_str();
CBeeAgentClientManager::Instance().SendMsg(iBeeAgentClientId, strReq, Bee::Net::WebSocket::TEXT);
//给10秒的超时时间,没有返回错误码,表示没有出错,正在备份
time_t startTime;
time_t endTime;
double diffStartEndTime;
time(&startTime);
while (true)
{
if (b_recvDeleteBackup_)
{
if (0 != i_recvDeleteResult_)
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(i_recvDeleteResult_)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::EnsureMaxRecordCount[2] FAILED,Result %d", i_recvDeleteResult_);
b_recvDeleteBackup_ = false;
return false;
}
else
{
for (auto it_delete : useless_record)
{
//删掉数据库
if (BackupRecordSession::DeleteBackupRecord(it_delete.bak_id))
{
IVMS_LOG_INFO("platform.Maintenance", "CTimerBackup::EnsureMaxRecordCount DeleteBackupRecord Success %s", it_delete.bak_file_path.c_str());
}
else
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::EnsureMaxRecordCount DeleteBackupRecord FAILED %s", it_delete.bak_file_path.c_str());
}
}
b_recvDeleteBackup_ = false;
return true;
}
}
time(&endTime);
diffStartEndTime = difftime(endTime, startTime);
if (diffStartEndTime > 10)
{
b_recvDeleteBackup_ = false;
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BEEAGENT_TIMEOUT)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::EnsureMaxRecordCount timeout!");
return false;
}
}
}
else
{
for (auto it_delete : useless_record)
{
boost::system::error_code ec;
// 删除目录
string str_up_file = UTF82Local(it_delete.bak_file_path);
/*size_t str_idx = str_up_file.rfind("\\");
str_up_file = str_up_file.substr(0, str_idx);*/
// 删除SYS本地对应备份文件
boost::filesystem::remove_all(str_up_file, ec);
if (is_distributed_)
{
// 删除ADS本地对应备份文件
/*string str_ads_file = UTF82Local(it_delete.ads_bak_file_path);
size_t str_idx = str_ads_file.rfind("\\");
str_ads_file = str_ads_file.substr(0, str_idx);*/
/*if (!Bee::DistributedManager::ADS_RemoveBakFile(it_delete.ads_bak_file_path))
{
IVMS_LOG_ERROR("platform.Maintenance", "EnsureMaxRecordCount ADS_RemoveBakFile Failed");
}*/
}
//删掉数据库
if (BackupRecordSession::DeleteBackupRecord(it_delete.bak_id))
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::EnsureMaxRecordCount::DeleteBackupRecord[2] Faild!");
}
}
}
}
}
return true;
}
void CTimerBackup::ActiveArchive()
{
time_t timeCurrent = time(0);
//tm tmCurrent = *localtime(&timeCurrent + 2);
tm tmCurrent = *localtime(&timeCurrent);
string str_create_time = Bee::Base::StringUtil::str_fmt("%d-%d-%d %d:%d:%d",
tmCurrent.tm_year + 1900, 1 + tmCurrent.tm_mon, tmCurrent.tm_mday, tmCurrent.tm_hour, tmCurrent.tm_min, tmCurrent.tm_sec);
shared_ptr<db_layer::CConnect> ptr_connect = nullptr;
ptr_connect = CVsmPlatformDBConn::Instance().ApplyConn();
if (ptr_connect == nullptr)
{
IVMS_LOG_ERROR("platform.Maintenance", "Conn Failed.");
return;
}
db_layer::CConnect& rs = *ptr_connect;
// string sql = str_fmt("INSERT INTO platform.backup_record(file_path, create_time, is_local, is_deleted) values('%s', '%s', 0, 0);",
// dc_bak_conf_Plan_.str_save_file_path.c_str(), str_create_time.c_str());
// if (!rs.Execute(sql))
// {
// string err_info;
// UINT_T err_code = rs.GetLastErrorCode(err_info);
// IVMS_LOG_ERROR("platform.Maintenance", "Failed sql [%s], errorcode:%d, errorinfo:%s", sql.c_str(), err_code, err_info.c_str());
// return;
// }
string sql = "SELECT pg_switch_wal();";
if (!rs.ExecuteQuery(sql))
{
string err_info;
UINT_T err_code = rs.GetLastErrorCode(err_info);
IVMS_LOG_ERROR("platform.Maintenance", "Query Failed, sql is %s, errorcode:%d, errorinfo:%s", sql.c_str(), err_code, err_info.c_str());
return;
}
if (rs.Begin())
{
sql = str_fmt("INSERT INTO platform.backup_record(file_path, create_time, is_local, is_deleted) values('%s', '%s', 0, 0);",
dc_bak_conf_Plan_.str_save_file_path.c_str(), str_create_time.c_str());
if (!rs.Execute(sql))
{
string err_info;
UINT_T err_code = rs.GetLastErrorCode(err_info);
rs.Rollback();
IVMS_LOG_ERROR("platform.Maintenance", "Failed sql [%s], errorcode:%d, errorinfo:%s", sql.c_str(), err_code, err_info.c_str());
return;
}
}
else
{
string err_info;
UINT_T err_code = rs.GetLastErrorCode(err_info);
IVMS_LOG_ERROR("platform.Maintenance", "Failed to BEGIN, errorcode:%d, errorinfo:%s", err_code, err_info.c_str());
return;
}
rs.Commit();
}
void CTimerBackup::Timing_RefreshBaseBack()
{
if (b_is_dump_running_)
{
IVMS_LOG_WARN("platform.Maintenance", "CTimerBackup::ExecuteDataRestoreOpt Is Backuping, can not Timing_RefreshBaseBack");
return;
}
// 获取当前时间
time_t tm_time = time(0); // 当前系统的UTC时间
tm tm_current_time = *localtime(&tm_time); // 转换为本地时间(包含时区和夏令时处理)
tm tm_over_time = tm_current_time; // 用来计算一年前时间
int c_day = tm_current_time.tm_mday; // 日
// 计算6分钟前的时间,定时器每隔5分钟检测一次,为去除两个定时器间隔带来的影响,这里计算6分钟前的时间
// 问题:两个定时器之间是有偏差的,例如第一个定时器在3月31号 23:59:59结束。下一个定时器偏差1s,4月1号 00:05:00的时候启动,就不会进入删除。
if (tm_current_time.tm_year == 1970)
{
if (tm_current_time.tm_min < 6)
{
IVMS_LOG_WARN("platform.Maintenance", "The current time is epoch time");
return;
}
}
tm_current_time.tm_min = tm_current_time.tm_min - 6;
time_t time_temp = mktime(&tm_current_time); // 时间转换,带时区
tm_current_time = *localtime(&time_temp);
// 日发生更替检查归档是否需要清理
if (c_day == tm_current_time.tm_mday)
{
return;
}
shared_ptr<db_layer::CConnect> ptr_connect = nullptr;
ptr_connect = CVsmPlatformDBConn::Instance().ApplyConn();
if (ptr_connect == nullptr)
{
IVMS_LOG_ERROR("platform.Maintenance", "Conn Failed.");
return;
}
db_layer::CConnect& rs = *ptr_connect;
string query_sql = "SELECT save_path FROM platform.backup_info WHERE is_deleted = 0;";
if (!rs.ExecuteQuery(query_sql))
{
IVMS_LOG_ERROR("platform.Maintenance", "Query Failed, sql is %s", query_sql.c_str());
return;
}
string save_path = rs.GetString("save_path");
if (save_path.empty())
{
IVMS_LOG_ERROR("platform.Maintenance", "save_path is empty at table of platform.backup_info.");
return;
}
if (b_is_dump_running_ || b_is_restore_running_)
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::DriveCloneRightAway Is Backuping or Restroing Now, Repeat CMDs");
return;
}
b_is_dump_running_ = true;
IVMS_LOG_INFO("platform.Maintenance", "Start Update BaseBack, Clear Wal Log.");
save_path = Bee::Base::StringUtil::StringReplace(save_path.c_str(), "\\", "/");
CBackupConfigManager::DistributeBackupInfo updata_base_back;
updata_base_back.https_url = "/ISAPI/Bumblebee/DCC/V0/RefreshBaseBack";
updata_base_back.https_bodys = Bee::Base::StringUtil::str_fmt(R"({"DatabaseBackupRestore":{"SavePath":"%s"}})", save_path.c_str());
IVMS_LOG_INFO("platform.Maintenance", "https_url[%s], https_bodys[%s].", updata_base_back.https_url.c_str(), updata_base_back.https_bodys.c_str());
if (!CBackupConfigManager::Instance().IncreBackupRestore(updata_base_back))
{
IVMS_LOG_ERROR("platform.Maintenance", "Execute Timing_RefreshBaseBack Failed, https[%s]", updata_base_back.https_url.c_str());
}
b_is_dump_running_ = false;
return;
}
void CTimerBackup::Thread_DriveCloneRightAway_DBSQLiteAPI(const string & root_db_path, const map<string, string>& v_backup_db, const string & new_file_name)
{
// 执行备份
// notes:初始化备份数量计数变量
backup_vec_table_num_ = 0;
// 如果存在运行时数据备份
if (v_backup_db.size() > 0)
{
// back_up_file: C:\Program Files (x86)\HikCentral Lite\VSM Servers\SYS\Backup\VSM_V1.0.0.0_BACKUP_20240801141653_75EEA
string back_up_file = root_db_path + "/" + new_file_name;
if (ExecSQLiteDumpProgressAPI(back_up_file, v_backup_db, DEF_BACKUP_CONFIG) != 0)
{
// 日志打印
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_BACKUP_FAIL)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::Thread_DriveCloneRightAway_DB ExecPGDumpProgress CONFIG FAILED");
m_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
b_is_dump_running_ = false;
}
}
// 备份完成,生成压缩文件
string str_zip_file_path = UTF82Local(root_db_path) + "/" + new_file_name + "/VSM_" + g_soft_version + "_BAK-SQLite.zip";
vector<string> file_list;
// 备份的zip文件所在路径
string full_path = UTF82Local(root_db_path) + "/" + new_file_name;
if (boost::filesystem::exists(full_path))
{
boost::filesystem::directory_iterator item_begin(full_path);
boost::filesystem::directory_iterator item_end;
for (; item_begin != item_end; item_begin++)
{
if (boost::filesystem::is_directory(*item_begin))
{
continue;
}
else
{
file_list.push_back(item_begin->path().string());
}
}
}
HPR_Sleep(3);
string str_compress_src = full_path + "/*";
if (NoError != Compress::CompressFiles(str_zip_file_path, str_compress_src))
{
IVMS_LOG_ERROR("platform.Maintenance", "CompressFolder FAILED");
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_BACKUP_FAIL)));
m_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
b_is_dump_running_ = false;
}
// 拷贝组件版本记录文件
IVMS_LOG_INFO("platform.Maintenance", "Start copy BackupInfo.xml");
boost::system::error_code err_c;
namespace ns_fs = boost::filesystem;
string src_backup_info = CConfigPathManager::Instance().GetBackupInfoPath();
string target_backup_info = full_path + "\\BackupInfo.xml";
if (ns_fs::exists(src_backup_info))
{
boost::filesystem::copy_file(src_backup_info, target_backup_info, boost::filesystem::copy_option::overwrite_if_exists, err_c);
if (err_c.value() != 0)
{
b_is_dump_running_ = false;
IVMS_LOG_ERROR("platform.Maintenance", "copy BackupInfo.xml file failed! The source file is %s, the target file is %s", src_backup_info.c_str(), target_backup_info.c_str());
return;
}
IVMS_LOG_INFO("platform.Maintenance", "copy BackupInfo.xml file SUCC, path is %s", target_backup_info.c_str());
}
// 备份完成不删除
i_sys_dump_percent_ = 100;
i_dump_sum_ = 100;
std::lock_guard<mutex> lock(mtx_finished_);
if (b_is_dump_running_ && i_sys_dump_percent_ == 100)
{
if (m_bak_error_ != DRIVE_CLONE_RESTORE_SUCC)
{
// 出现任意失败,均删除备份文件
FileUtil::DeleteDir(full_path.c_str());
}
b_is_dump_running_ = false;
}
check_task_id_ = CThreadManager::Instance().PostTask(string(__FUNCTION__) + "[CheckAndRecordStatue]",
std::bind(&CTimerBackup::CheckAndRecordStatue, this, file_list, target_backup_info));
}
UINT_T CTimerBackup::ExecSQLiteDumpProgressAPI(const string & root_db_path, const map<string, string>& v_bak_db, const UINT_T & conf_run)
{
//root_db_path : C:\Program Files (x86)\HikCentral Lite\VSM Servers\SYS\Backup\VSM_V1.0.0.0_BACKUP_20240801141653_75EEA
// 获取db文件路径 -- eg. C:\Program Files (x86)\HikCentral\VSM Servers\PGData
string storage_xml = CConfigPathManager::Instance().GetStorageXmlPath();
if (!boost::filesystem::exists(storage_xml))
{
IVMS_LOG_ERROR("platform.Maintenance", "Storage.xml not exist, path : %s", storage_xml.c_str());
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUP_CONFIG_ERROR)));
return DRIVE_CLONE_RESTORE_FAIL;
}
string storage_buf;
if (!CFileBak::ReadFile(storage_buf, storage_xml))
{
IVMS_LOG_ERROR("platform.Maintenance", "Read Storage.xml fail, path = %s", storage_xml.c_str());
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUP_CONFIG_ERROR)));
return DRIVE_CLONE_RESTORE_FAIL;
}
unique_ptr<proto::IProto> pro_result(new proto::CXmlProto);
pro_result->set_str(storage_buf);
string db_path = pro_result->get_v("/StoragePath/DatabaseData/SQLiteDataPath"); // 待备份的db路径
if (db_path.empty())
{
IVMS_LOG_ERROR("platform.Maintenance", "/StoragePath/DatabaseData/Path is empty, path = %s", storage_xml.c_str());
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUP_CONFIG_ERROR)));
return DRIVE_CLONE_RESTORE_FAIL;
}
IVMS_LOG_DEBUG("platform.Maintenance", "db path is :%s.", db_path.c_str());
i_percent_vol = 0;
boost::system::error_code ec;
UINT_T i_total_dump_lines = 0;
// 给压缩留一段时间
i_total_dump_lines = (UINT_T)v_bak_db.size() + 2;
// 3.开始执行备份
for (auto single_db : v_bak_db)
{
string src_db_full_path = UTF82Local(db_path + "\\" + single_db.second);
string target_dbfile_path = UTF82Local(root_db_path) + "\\" + single_db.second;
bool is_ready = false;
if (single_db.first != "public")
{
for (int i = 1; i < 3; i++)
{
if (!db_layer::DBLayer_CheckPoint(single_db.first))
{
Sleep(5000);
continue;
}
is_ready = true;
break;
}
}
else
{
is_ready = true;
}
if (!is_ready)
{
IVMS_LOG_ERROR("platform.Maintenance", "db - %s, failed to check_point.", single_db.second.c_str());
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_OPERATION_FAIL)));
return DRIVE_CLONE_RESTORE_FAIL;
}
if (single_db.first != "public")
{
if (!db_layer::DBLayer_LockPool(single_db.first))
{
IVMS_LOG_ERROR("platform.Maintenance", "db - %s, failed to DBLayer_LockPool.", single_db.second.c_str());
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_OPERATION_FAIL)));
return DRIVE_CLONE_RESTORE_FAIL;
}
}
if (!BackupCurDBFile(src_db_full_path, target_dbfile_path))
{
IVMS_LOG_ERROR("platform.Maintenance", "db - %s backup failed.", single_db.second.c_str());
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUP_CONFIG_ERROR)));
if (!db_layer::DBLayer_UnLockPool(single_db.first))
{
IVMS_LOG_ERROR("platform.Maintenance", "db - %s, failed to DBLayer_UnLockPool.", single_db.second.c_str());
}
return DRIVE_CLONE_RESTORE_FAIL;
}
if (single_db.first != "public")
{
if (!db_layer::DBLayer_UnLockPool(single_db.first))
{
IVMS_LOG_ERROR("platform.Maintenance", "db - %s, failed to DBLayer_UnLockPool.", single_db.second.c_str());
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_OPERATION_FAIL)));
return DRIVE_CLONE_RESTORE_FAIL;
}
}
IVMS_LOG_INFO("platform.Maintenance", "SUCC to backup db - %s", single_db.second.c_str());
string str_log_file_path;
backup_vec_table_num_ += 1;
IVMS_LOG_INFO("platform.Maintenance", "backup_db_num_ is : %d", backup_vec_table_num_);
string str_whole_pg_dump_cmd;
IVMS_LOG_INFO("platform.Maintenance", "i_total_dump_lines : %d", i_total_dump_lines);
if (DRIVE_CLONE_RESTORE_SUCC != AcquireCommandStatus(str_log_file_path, str_whole_pg_dump_cmd, i_total_dump_lines, conf_run))//执行命令,需要修改,兼容进度条
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUP_CONFIG_ERROR)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecPGDumpProgress AcquireCommandStatus Failed");
return DRIVE_CLONE_RESTORE_FAIL;
}
}
return DRIVE_CLONE_RESTORE_SUCC;
}
bool CTimerBackup::CheckDiskIsSuport(string backup_file_path, map<string, string> local_db)
{
boost::system::error_code err_c;
namespace ns_fs = boost::filesystem;
// 获取备份路径下的剩余磁盘空间
auto idx_mark = (UTF82Local(backup_file_path)).find(":");
string drive_mark = (UTF82Local(backup_file_path)).substr(0, idx_mark + 2);
ULARGE_INTEGER FreeBytesAvailable;
ULARGE_INTEGER TotalNumberOfBytes;
ULARGE_INTEGER TotalNumberOfFreeBytes;
if (!GetDiskFreeSpaceExA(drive_mark.c_str(), &FreeBytesAvailable, &TotalNumberOfBytes, &TotalNumberOfFreeBytes))
{
IVMS_LOG_ERROR("platform.Maintenance", "Get \"%s\" Disk Free Space Fail", drive_mark.c_str());
return false;
}
ULONGLONG backup_freeDisk = TotalNumberOfFreeBytes.QuadPart / 1024 / 1024;
auto local_data_size = 0;
string local_data_path = CConfigPathManager::Instance().GetSQLiteDataPath();
for (auto db_name : local_db)
{
string db_full_path = UTF82Local(local_data_path) + "\\" + db_name.second;
if (!ns_fs::exists(db_full_path))
{
continue;
}
ns_fs::path whole_db_path(db_full_path, (void*)boost::filesystem::native);
local_data_size += ns_fs::file_size(whole_db_path, err_c) / 1024 / 1024;
}
// 需要大于db文件的两倍(压缩包+备份的db文件)
if (backup_freeDisk < local_data_size * 2)
{
IVMS_LOG_ERROR("platform.Maintenance", "Disk Full, Free Disk = %d, Need Disk = %d", backup_freeDisk, local_data_size * 2);
return false;
}
return true;
}
void CTimerBackup::VacuumPath(const string& path)
{
boost::system::error_code ec;
boost::filesystem::path fullpath(path, (void*)boost::filesystem::native);
if (boost::filesystem::exists(fullpath, ec))
{
boost::filesystem::directory_iterator item_begin(fullpath);
boost::filesystem::directory_iterator item_end;
for (; item_begin != item_end; item_begin++)
{
if (!boost::filesystem::is_regular_file(*item_begin))
{
continue;
}
string file_name = item_begin->path().string();
boost::filesystem::remove(file_name, ec);
}
}
}
// 执行备份操作-数据类型可选择
UINT_T CTimerBackup::DriveCloneRightAway(const DriveCloneConf &data_clone_conf)
{
#ifndef HCL_CODE
// HCL无异机场景
if (b_is_diff_machine) //异机部署
{
IVMS_LOG_INFO("platform.Maintenance", "CTimerBackup::DriveCloneRightAway Diff Start!");
b_recvBackupResult_ = false;
i_recvBackupResult_ = -1;
iProgressPercent_ = 0;
vector<BackupCategoryInfo::table_info> v_config_tables, v_runtime_tables;
// 获取备份表列表
if (CombingDBCloneTables(v_config_tables, v_runtime_tables, data_clone_conf.str_clone_data_type, is_distributed_) != 0)
{
// 日志打印
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_REQUEST_PARAM_ERROR)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::DriveCloneRightAway CombingDBCloneTables FAILED");
// 重置进度
// i_sys_pic_bak_percent_ = 100;
i_sys_dump_percent_ = 100;
i_dump_sum_ = 100;
i_ads_dump_percent_ = 100;
b_is_dump_running_ = false;
return DRIVE_CLONE_RESTORE_FAIL;
}
time_t timeCurrent = time(0);
tm tmCurrent = *localtime(&timeCurrent);
// guid过长,导致备份文件路径字符过多,只保留五位
string backup_guid = GuidUtil::CreateGuid().substr(0, 5);
string str_save_file_name = str_fmt("VSM_%s_BACKUP_%.4d%.2d%.2d%.2d%.2d%.2d_%s", g_soft_version.c_str(),
tmCurrent.tm_year + 1900, 1 + tmCurrent.tm_mon, tmCurrent.tm_mday, tmCurrent.tm_hour, tmCurrent.tm_min, tmCurrent.tm_sec, backup_guid.c_str());
// 统一入库时间与文件夹名称相同,使用本地时间
string str_create_time = str_fmt("%d-%d-%d %d:%d:%d",
tmCurrent.tm_year + 1900, 1 + tmCurrent.tm_mon, tmCurrent.tm_mday, tmCurrent.tm_hour, tmCurrent.tm_min, tmCurrent.tm_sec);
//const DriveCloneConf &data_clone_conf, std::vector<std::string> v_config_tables, std::vector<std::string>v_runtime_tables, const std::string &str_save_file_name, const std::string &str_whole_set_pwd, const std::string &str_pg_dump_exe_path
string str_pg_dump_exe_path = PostgreSQL_path_ + PostgreSQL_backup_exe;
LocalDBInfo curr_db_info;
CLocalConfigManager::Instance().GetLocationDBInfo(curr_db_info);
char* str_set_pwd = "SET PGPASSWORD=%s\n";
string str_whole_set_pwd = str_fmt(str_set_pwd, curr_db_info.db_passwd.c_str());
string str_save_file_path = strBeeAgentSetPath_;
//string str_save_file_path = "C:/back";
string str_clone_data_type = data_clone_conf.str_clone_data_type;
shared_ptr<proto::IProto> ptr_parse = make_shared<proto::CRapidJsonProto>();
string strGuid = Bee::Base::GuidUtil::CreateGuid();
string strPort = Bee::Base::StringUtil::T2String(curr_db_info.db_port);
string strPathNamePwdExe = str_save_file_path + ";" + str_save_file_name + ";" + str_whole_set_pwd + ";" + g_soft_version + ";" + strPort;
ptr_parse->set_v("/Guid", strGuid);
ptr_parse->set_v("/RequestData/Method", "ExecuteBackUpOpt");
ptr_parse->set_v("/RequestData/Data", "");
ptr_parse->set_v("/RequestData/Data/PathNamePwdExe", strPathNamePwdExe);
ptr_parse->set_v("/RequestData/Data/CloneDataType", str_clone_data_type);
void* ptr_data_node = ptr_parse->get_node("/RequestData/Data");
int index = 0;
map<string, int> backup_schema; //备份文件中的数据模式
map<string, string> backup_vername; //备份文件中的数据模式名称及版本
for (auto it : v_config_tables)
{
backup_schema.insert(pair<string, int>(it.schema_name, index));
index++;
}
if (backup_schema.empty())
{
b_is_dump_running_ = false;
IVMS_LOG_ERROR("platform.Maintenance", "Database schema is Empty!");
return DRIVE_CLONE_RESTORE_FAIL;
}
// 获取备份文件中的数据模式和版本
if (!QueryBackupSchemaAndVersion(backup_schema, backup_vername))
{
b_is_dump_running_ = false;
IVMS_LOG_ERROR("platform.Maintenance", "Failed to Get schema and version in backup file");
return DRIVE_CLONE_RESTORE_FAIL;
}
if (backup_vername.empty())
{
b_is_dump_running_ = false;
IVMS_LOG_ERROR("platform.Maintenance", "FAILED obtain schema version");
return DRIVE_CLONE_RESTORE_FAIL;
}
for (auto it_schema : backup_vername)
{
void* ptr_table = ptr_parse->add_list_v(ptr_data_node, "TablesInfo", "");//LCL
ptr_parse->add_v(ptr_table, "Schema", it_schema.first);
ptr_parse->add_v(ptr_table, "Version", it_schema.second);
}
// 备份表列表
vector<BackupCategoryInfo::table_info> v_bak_tmp;
v_bak_tmp.assign(v_config_tables.begin(), v_config_tables.end());
// 打乱顺序,保证大表等待时间分布均匀
random_shuffle(v_bak_tmp.begin(), v_bak_tmp.end());
auto it = v_bak_tmp.begin();
for (it; it != v_bak_tmp.end(); it++)
{
void* ptr_table = ptr_parse->add_list_v(ptr_data_node, "ConfigTables", "");//LCL
ptr_parse->add_v(ptr_table, "Table", it->table_name);
ptr_parse->add_v(ptr_table, "Schema", it->schema_name);
string str_view;
StringUtil::Array2String(str_view, it->vec_view);
ptr_parse->add_v(ptr_table, "RelatedView", str_view);
}
vector<BackupCategoryInfo::table_info> v_bak_run;
v_bak_run.assign(v_runtime_tables.begin(), v_runtime_tables.end());
// 打乱顺序,保证大表等待时间分布均匀
random_shuffle(v_bak_run.begin(), v_bak_run.end());
auto itRun = v_bak_run.begin();
for (itRun; itRun != v_bak_run.end(); itRun++)
{
void* ptr_table = ptr_parse->add_list_v(ptr_data_node, "RuntimeTables", "");//LCL
ptr_parse->add_v(ptr_table, "Table", it->table_name);
string str_view;
StringUtil::Array2String(str_view, it->vec_view);
ptr_parse->add_v(ptr_table, "RelatedView", str_view);
}
string strReq = ptr_parse->get_str();
CBeeAgentClientManager::Instance().SendMsg(iBeeAgentClientId, strReq, Bee::Net::WebSocket::TEXT);
strDiffFilePath_ = str_save_file_name;
strDiffCreateTime_ = str_create_time;
stu_Diff_data_clone_conf = data_clone_conf;
//给10秒的超时时间,没有返回错误码,表示没有出错,正在备份
time_t startTime;
time_t endTime;
double diffStartEndTime;
time(&startTime);
while (true)
{
if (b_recvBackupResult_)
{
if (0 != i_recvBackupResult_)
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(i_recvBackupResult_)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::Thread_DriveCloneRightAway_DB FAILED %d",i_recvBackupResult_);
m_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
b_recvBackupResult_ = false;
return DRIVE_CLONE_RESTORE_FAIL;
}
else
{
b_recvBackupResult_ = false;
return DRIVE_CLONE_RESTORE_SUCC;
}
}
time(&endTime);
diffStartEndTime = difftime(endTime, startTime);
if (diffStartEndTime > 10)
{
b_recvBackupResult_ = false;
return DRIVE_CLONE_RESTORE_SUCC;
}
}
//TypeinBackupPackage(data_clone_conf, new_file_name, str_create_time);
return DRIVE_CLONE_RESTORE_SUCC;
}
// HCL无需对版本进行判断
// 判断本地部署当前插件版本与产品版本是否符合(通过up_status),不符合则不允许进行备份
if (!VSMPlatform::MaintenanceSession::QueryPluginsUpdateState())
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CSM_DATABASE_NOT_FIT)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::DriveCloneRightAway Check current plugins's version FAILED");
return CSM_DATABASE_NOT_FIT;
}
#endif // !HCL_CODE
if (b_is_dump_running_ || b_is_restore_running_)
{
// 日志打印
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_IS_BACKUPING_RESTORING)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::DriveCloneRightAway Is Backuping or Restroing Now, Repeat CMDs");
return CMS_IS_BACKUPING_RESTORING;
}
// 自动备份和手动备份不能同时执行
std::lock_guard<mutex> lock(mutex_pg_dump_);
b_is_dump_running_ = true;
i_sys_dump_percent_ = 0;
i_dump_sum_ = 0;
// i_sys_pic_bak_percent_ = 0;
// v1.4添加ADS备份进度
i_ads_dump_percent_ = 0;
// has_dump_pic_bak_ = false;
#ifndef HCL_CODE
// v2.6备份上传FTP服务器进度
i_ftp_upload_percent_ = 0;
HPR_MEMSET_S(&ftp_upload_progress_, sizeof(ftp_upload_progress_), 0, sizeof(ftp_upload_progress_));
#endif // !HCL_CODE
m_bak_error_ = DRIVE_CLONE_RESTORE_SUCC;
// 备份文件保存路径处理
// 如果目录不存在,则创建,同时检测目录是否可写
if (!MakeFullPathDir(UTF82Local(data_clone_conf.str_save_file_path)))
{
// 日志打印
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUP_PAHT_CANNOT_WRITE)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::DriveCloneRightAway MakeFullPathDir FAILED, DIR is %s",
UTF82Local(data_clone_conf.str_save_file_path).c_str());
// 重置进度
// i_sys_pic_bak_percent_ = 100;
i_sys_dump_percent_ = 100;
i_dump_sum_ = 100;
i_ads_dump_percent_ = 100;
b_is_dump_running_ = false;
return DRIVE_CLONE_RESTORE_FAIL;
}
#ifdef HCL_CODE
// notes:HCL获取数据库db文件
//vector<string> v_backup_db;
map<string, string> v_backup_db;
// 从平台初始化处,获取所有db文件
v_backup_db = CVsmPlatformDBConn::Instance().SendAllDBFile();
// 除了public.db应该存在其他的db文件,否则是有问题的
if (v_backup_db.size() < 2)
{
// 日志打印
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUPFILE_NOT_EXIST)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::DriveCloneRightAway CombingSQLiteDB FAILED");
// 重置进度
// i_sys_pic_bak_percent_ = 100;
i_sys_dump_percent_ = 100;
i_dump_sum_ = 100;
i_ads_dump_percent_ = 100;
b_is_dump_running_ = false;
return DRIVE_CLONE_RESTORE_FAIL;
}
// 检查磁盘剩余空间是否足够
if (!CheckDiskIsSuport(data_clone_conf.str_save_file_path, v_backup_db))
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUP_DISK_FULL)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::DriveCloneRightAway No more space for Backup.");
// 重置进度
// i_sys_pic_bak_percent_ = 100;
i_sys_dump_percent_ = 100;
i_dump_sum_ = 100;
i_ads_dump_percent_ = 100;
b_is_dump_running_ = false;
return DRIVE_CLONE_RESTORE_FAIL;
}
#endif // HCL_CODE
// 获取备份表列表
vector<BackupCategoryInfo::table_info> v_config_tables;
#ifndef HCL_CODE
// HCP获取备份数据列表
vector<BackupCategoryInfo::table_info> v_runtime_tables;
if (CombingDBCloneTables(v_config_tables, v_runtime_tables, data_clone_conf.str_clone_data_type, is_distributed_) != 0)
{
// 日志打印
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_REQUEST_PARAM_ERROR)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::DriveCloneRightAway CombingDBCloneTables FAILED");
// 重置进度
// i_sys_pic_bak_percent_ = 100;
i_sys_dump_percent_ = 100;
i_dump_sum_ = 100;
i_ads_dump_percent_ = 100;
b_is_dump_running_ = false;
return DRIVE_CLONE_RESTORE_FAIL;
}
#endif // HCL_CODE
time_t timeCurrent = time(0);
tm tmCurrent = *localtime(&timeCurrent);
// guid过长,导致备份文件路径字符过多,只保留五位
string backup_guid = GuidUtil::CreateGuid().substr(0, 5);
// notes:HCL备份文件命名g_soft_version需要注意一下
string str_save_file_name = str_fmt("VSM_%s_BACKUP_%.4d%.2d%.2d%.2d%.2d%.2d_%s", g_soft_version.c_str(),
tmCurrent.tm_year + 1900, 1 + tmCurrent.tm_mon, tmCurrent.tm_mday, tmCurrent.tm_hour, tmCurrent.tm_min, tmCurrent.tm_sec, backup_guid.c_str());
// 统一入库时间与文件夹名称相同,使用本地时间
string str_create_time = str_fmt("%d-%d-%d %d:%d:%d",
tmCurrent.tm_year + 1900, 1 + tmCurrent.tm_mon, tmCurrent.tm_mday, tmCurrent.tm_hour, tmCurrent.tm_min, tmCurrent.tm_sec);
// 数据库备份完整路径
#ifndef __linux__
if (_mkdir((UTF82Local(data_clone_conf.str_save_file_path) + "/" + str_save_file_name).c_str()) != 0)
#else
if (mkdir((UTF82Local(data_clone_conf.str_save_file_path) + "/" + str_save_file_name).c_str(), 0777) != 0)
#endif
{
// 日志打印
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUP_PAHT_CANNOT_WRITE)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::DriveCloneRightAway _mkdir FAILED, DIR is %s",
(UTF82Local(data_clone_conf.str_save_file_path) + "/" + str_save_file_name).c_str());
// 重置进度
// i_sys_pic_bak_percent_ = 100;
i_sys_dump_percent_ = 100;
i_dump_sum_ = 100;
i_ads_dump_percent_ = 100;
b_is_dump_running_ = false;
return DRIVE_CLONE_RESTORE_FAIL;
}
map<string, string> backup_vername; //备份文件中的数据模式名称及版本
#ifndef HCL_CODE
// 开启备份线程前,检测该数据库中的备份模式以及版本
int index = 0;
map<string, int> backup_schema; //备份文件中的数据模式
multimap<string, string> full_table_name; //备份文件中的表 <模式名,表名>
for (auto it : v_config_tables)
{
backup_schema.insert(pair<string, int>(it.schema_name, index));
// 将表名进行记录
full_table_name.insert(pair<string, string>(it.schema_name, it.table_name));
index++;
}
if (backup_schema.empty())
{
b_is_dump_running_ = false;
IVMS_LOG_ERROR("platform.Maintenance", "Database schema is Empty!");
return DRIVE_CLONE_RESTORE_FAIL;
}
// 获取备份文件中的数据模式和版本
if (!QueryBackupSchemaAndVersion(backup_schema, backup_vername))
{
b_is_dump_running_ = false;
IVMS_LOG_ERROR("platform.Maintenance", "Failed to Get schema and version in backup file");
return DRIVE_CLONE_RESTORE_FAIL;
}
if (backup_vername.empty())
{
b_is_dump_running_ = false;
IVMS_LOG_ERROR("platform.Maintenance", "FAILED obtain schema version");
return DRIVE_CLONE_RESTORE_FAIL;
}
// 存在分表的主表名
vector<BackupCategoryInfo::table_info> v_main_table;
CBackupConfigManager::Instance().SendMainTableInfo(v_main_table);
// 将备份文件中的数据模式和版本、主表名记录在BackupInfo.xml中
if (!RecordBackupTableInfo(backup_vername, full_table_name, v_main_table))
{
b_is_dump_running_ = false;
IVMS_LOG_ERROR("platform.Maintenance", "Failed to write to BackupInfo.xml");
return DRIVE_CLONE_RESTORE_FAIL;
}
#else
// 获取备份文件中的数据模式和版本
if (!QueryBackupSchemaAndVersionForSQLite(v_backup_db, backup_vername))
{
b_is_dump_running_ = false;
IVMS_LOG_ERROR("platform.Maintenance", "Failed to Get schema and version in backup file");
return DRIVE_CLONE_RESTORE_FAIL;
}
if (!RecordBackupTableInfo(backup_vername))
{
b_is_dump_running_ = false;
IVMS_LOG_ERROR("platform.Maintenance", "Failed to write to BackupInfo.xml");
return DRIVE_CLONE_RESTORE_FAIL;
}
#endif // !HCL_CODE
// notes:HCP2.5.1做升级前的校验用
// if (!BackupStatus(RUN_DRIVE_CLONE))
// {
// b_is_dump_running_ = false;
// IVMS_LOG_ERROR("platform.Maintenance", "Backup Status record failed.");
// return DRIVE_CLONE_RESTORE_FAIL;
// }
//开启数据备份线程
//boost::thread thread_db = boost::thread(bind(&CTimerBackup::Thread_DriveCloneRightAway_DB, this, data_clone_conf, v_config_tables, v_runtime_tables, str_save_file_name, str_create_time));
//thread_db.detach();
#ifndef HCL_CODE
CThreadManager::Instance().PostTask(string(__FUNCTION__) + "[Thread_DriveCloneRightAway_DB]",
std::bind(&CTimerBackup::Thread_DriveCloneRightAway_DB, this, data_clone_conf, v_config_tables, v_runtime_tables, str_save_file_name, str_create_time));
#else
CThreadManager::Instance().PostTask(string(__FUNCTION__) + "[Thread_DriveCloneRightAway_DBSQLiteAPI]",
std::bind(&CTimerBackup::Thread_DriveCloneRightAway_DBSQLiteAPI, this, data_clone_conf.str_save_file_path, v_backup_db, str_save_file_name));
#endif
return DRIVE_CLONE_RESTORE_SUCC;
}
void CTimerBackup::Thread_DriveCloneRightAway_DB(const DriveCloneConf &data_clone_conf,
const vector<BackupCategoryInfo::table_info> &v_config_tables,
const vector<BackupCategoryInfo::table_info> &v_runtime_tables,
const string &new_file_name, const string &str_create_time)
{
// 调用电视墙的备份
std::future <std::string> fut_tvwall;// = std::async(&CTVWallManager::Backup, &CTVWallManager::Instance());
string str_type = data_clone_conf.str_clone_data_type;
string res_str = ",";
string rep_str = "_";
string::size_type pos = 0;
string::size_type res_len = res_str.size();
string::size_type rep_len = rep_str.size();
while ((pos = str_type.find(res_str, pos)) != string::npos)
{
str_type.replace(pos, res_len, rep_str);
pos += rep_len;
}
string str_whole_config_file_path = UTF82Local(data_clone_conf.str_save_file_path) + "/" + new_file_name + "/VSM_DB-Config" + ".bak";
string str_whole_runtime_file_path = UTF82Local(data_clone_conf.str_save_file_path) + "/" + new_file_name + "/VSM_DB-Runtime" + ".bak";
// 执行备份
// notes:初始化备份数量计数变量
backup_vec_table_num_ = 0;
// 如果存在运行时数据备份
if (v_runtime_tables.size() > 0)
{
if (ExecPGDumpProgress(str_whole_config_file_path, v_config_tables, DEF_BACKUP_CONFIG) != 0)
{
// 日志打印
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_BACKUP_FAIL)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::Thread_DriveCloneRightAway_DB ExecPGDumpProgress CONFIG FAILED");
m_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
}
if (ExecPGDumpProgress(str_whole_runtime_file_path, v_runtime_tables, DEF_BACKUP_RUNTIME) != 0)
{
// 日志打印
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_BACKUP_FAIL)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::Thread_DriveCloneRightAway_DB ExecPGDumpProgress RUNTIME FAILED");
m_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
// ncg backup file is not in the VSM backup dir, so create a file 'ncg_bak'
// and write filename to the file. VSM ONLY require to record the name
}
}
else
{
if (ExecPGDumpProgress(str_whole_config_file_path, v_config_tables, DEF_BACKUP_ONLY_CONFIG) != 0)
{
// 日志打印
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_BACKUP_FAIL)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::Thread_DriveCloneRightAway_DB ExecPGDumpProgress ONLY CONFIG FAILED");
m_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
}
}
// 电视墙备份路径
string swms_backup_path;
std::string ncg_backup_path;
//生成压缩文件
string str_zip_file_path = UTF82Local(data_clone_conf.str_save_file_path) + "/" + new_file_name + "/VSM_" + g_soft_version + "_BAK-" + str_type + ".zip";
vector<string> file_list;
// 备份的zip文件所在路径
string full_path = UTF82Local(data_clone_conf.str_save_file_path) + "/" + new_file_name;
if (boost::filesystem::exists(full_path))
{
boost::filesystem::directory_iterator item_begin(full_path);
boost::filesystem::directory_iterator item_end;
for (; item_begin != item_end; item_begin++)
{
if (boost::filesystem::is_directory(*item_begin))
{
}
else
{
file_list.push_back(item_begin->path().string());
}
}
}
file_list.push_back(str_whole_config_file_path);
// 如果存在运行时数据备份
if (v_runtime_tables.size() > 0)
{
file_list.push_back(str_whole_runtime_file_path);
}
file_list.push_back(swms_backup_path);
if (CControlItemManager::Instance().GetControlItemSupportNum("s_platform_system_advance_ncg") == 1)
{
file_list.push_back(ncg_backup_path); // Modified for NCG
// 视频存储一体机的数据库配置目录为/hcpdata/HCPconfig/,现在默认写死,后期提供接口后,需通过接口获取
string pg_data_path = "/hcpdata/HCPconfig/postgresql/data/";
const std::vector<string> pg_config_files_vec{ pg_data_path + "pg_hba.conf", pg_data_path + "pg_ident.conf", pg_data_path + "postgresql.conf", pg_data_path + "postgresql.auto.conf" };
//PG配置文件备份
file_list.insert(file_list.end(), pg_config_files_vec.begin(), pg_config_files_vec.end());
}
HPR_Sleep(3);
string str_compress_src = full_path + "/*";
if (NoError != Compress::CompressFiles(str_zip_file_path, str_compress_src))
{
boost::system::error_code ec;
boost::filesystem::remove(str_whole_config_file_path, ec);
// 如果存在运行时数据备份
if (v_runtime_tables.size() > 0)
{
boost::filesystem::remove(str_whole_runtime_file_path, ec);
}
boost::filesystem::remove(swms_backup_path, ec);
if (CControlItemManager::Instance().GetControlItemSupportNum("s_platform_system_advance_ncg") == 1)
{
boost::filesystem::remove(ncg_backup_path, ec); // Modified for NCG
}
IVMS_LOG_ERROR("platform.Maintenance", "CompressFolder FAILED");
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_BACKUP_FAIL)));
m_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
}
/**************************** 拷贝文件到备份文件下,作为核验addon用***************************/
IVMS_LOG_INFO("platform.Maintenance", "Start copy BackupInfo.xml");
boost::system::error_code err_c;
namespace ns_fs = boost::filesystem;
string src_backup_info = CConfigPathManager::Instance().GetBackupInfoPath();
string target_backup_info = full_path + "\\BackupInfo.xml";
if (ns_fs::exists(src_backup_info))
{
boost::filesystem::copy_file(src_backup_info, target_backup_info, boost::filesystem::copy_option::overwrite_if_exists, err_c);
if (err_c.value() != 0)
{
IVMS_LOG_ERROR("platform.Maintenance", "copy BackupInfo.xml file failed! The source file is %s, the target file is %s", src_backup_info.c_str(), target_backup_info.c_str());
return;
}
IVMS_LOG_INFO("platform.Maintenance", "copy BackupInfo.xml file SUCC, path is %s", target_backup_info.c_str());
}
/*********************************************************************************************************/
//删除原文件
boost::system::error_code ec;
for (auto file_path : file_list)
{
//pg配置文件不能删除
if (file_path.find("/hcpdata/HCPconfig/postgresql/data/") != string::npos)
{
continue;
}
boost::filesystem::remove(file_path, ec);
}
//boost::filesystem::remove(str_whole_config_file_path, ec);
// 如果存在运行时数据备份
if (v_runtime_tables.size() > 0)
{
boost::filesystem::remove(str_whole_runtime_file_path, ec);
}
boost::filesystem::remove(swms_backup_path, ec);
if (CControlItemManager::Instance().GetControlItemSupportNum("s_platform_system_advance_ncg") == 1)
{
boost::filesystem::remove(ncg_backup_path, ec); // Modified for NCG
}
// v2.6 上传到FTP/SFTP服务器
if (data_clone_conf.em_clone_upload_location != DriveCloneConf::DriveCloneUploadLocation::NoneLocation)
{
std::string str_ftp_file_path = data_clone_conf.str_ftp_save_file_path;
std::string str_local_file_path = UTF82Local(data_clone_conf.str_save_file_path) + "\\" + new_file_name;
if (!UploadToFTPOrSFTP(data_clone_conf, str_local_file_path, str_ftp_file_path))
{
IVMS_LOG_ERROR("platform.Maintenance", "UploadToFTPOrSFTP failed!");
m_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
b_is_dump_running_ = false;
return;
}
i_ftp_upload_percent_ = 100;
}
i_sys_dump_percent_ = 100;
i_dump_sum_ = 100;
std::lock_guard<mutex> lock(mtx_finished_);
if (b_is_dump_running_ && i_sys_dump_percent_ == 100)
{
if (m_bak_error_ != DRIVE_CLONE_RESTORE_SUCC ||
data_clone_conf.em_clone_upload_location != DriveCloneConf::DriveCloneUploadLocation::NoneLocation)
{
// 出现任意失败或选择上传至FTP/SFTP服务器,均删除备份文件
FileUtil::DeleteDir((UTF82Local(data_clone_conf.str_save_file_path) + "/" + new_file_name).c_str());
if (is_distributed_)
{
// 删除ADS备份文件
/*if (!Bee::DistributedManager::ADS_RemoveBakFile((data_clone_conf.str_ads_save_file_path + "/" + new_file_name).c_str()))
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::Thread_DriveCloneRightAway_DB ADS_RemoveBakFile FAILED");
}*/
}
if (m_bak_error_ != DRIVE_CLONE_RESTORE_SUCC)
{
IVMS_LOG_ERROR("platform.Maintenance", "DRIVE_CLONE_RESTORE_FAIL, %s", (UTF82Local(data_clone_conf.str_save_file_path) + "/" + new_file_name).c_str());
}
else
{
IVMS_LOG_INFO("platform.Maintenance", "Delete local clone file for upload to ftp/sftp server");
}
}
else
{
// 录入备份记录
TypeinBackupPackage(data_clone_conf, new_file_name, str_create_time);
}
// 图片与数据库均完成备份
b_is_dump_running_ = false;
//i_sys_dump_percent_batch_ = 1;
// notes:HCP2.5.1做升级前的校验用
// if (!CTimerBackup::Instance().BackupStatus(STOP_DRIVE_CLONE))
// {
// IVMS_LOG_ERROR("platform.Maintenance", "Backup STOP Status record failed.");
// return;
// }
}
}
// 整合备份文件
void CTimerBackup::TypeinBackupPackage(const DriveCloneConf &data_clone_conf, const string &new_file_name, const string &str_create_time, ID site_id)
{
// 备份记录结构体赋值
DriveCloneRecordsInfo bak_info;
bak_info.bak_file_path = data_clone_conf.str_save_file_path + "/" + new_file_name;
bak_info.bak_file_path = StringReplace(bak_info.bak_file_path, "\\", "/");
if (is_distributed_)
{
bak_info.ads_bak_file_path = data_clone_conf.str_ads_save_file_path + "/" + new_file_name;
bak_info.ads_bak_file_path = StringReplace(bak_info.ads_bak_file_path, "\\", "/");
}
string guid = CSystemManamger::Instance().GetSystemGuid();
bak_info.id_site = site_id;
bak_info.site_guid = guid;
bak_info.bak_form = data_clone_conf.str_clone_data_type;
IVMS_LOG_INFO("platform.Maintenance", "DRIVE_CLONE_BACKUP_SUCC, %s, %s", UTF82Local(bak_info.bak_file_path).c_str(), UTF82Local(bak_info.ads_bak_file_path).c_str());
// 记录备份文件信息,调整备份数量
RenewalDriveCloneInfo(bak_info, str_create_time);
}
// 判断当前备份或者计划所需磁盘空间大小
bool CTimerBackup::DetermineDiskCloneVolume(const DriveCloneConf &data_clone_conf)
{
UINT_T i_clone_file_size = 0;
vector<string> v_bak_tables;
if (VSMPlatform::Config::GetPlatformRunType() == VSMPlatform::Config::OutPlatformRunType::StandAlone)
{
// 获取备份表列表
if (CombingDBCloneTables(v_bak_tables, data_clone_conf.str_clone_data_type, is_distributed_) != 0)
{
// 日志打印
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_REQUEST_PARAM_ERROR)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::DriveCloneRightAway CombingDBCloneTables FAILED");
return false;
}
}
// 是否包含图片类型
bool has_pic = false;
vector<int> v_types;
String2Array(v_types, data_clone_conf.str_clone_data_type);
vector<int>::iterator it = find(v_types.begin(), v_types.end(), 1);
if (it != v_types.end())
{
has_pic = true;
}
UINT_T i_tables_volume = 0;
int64 i_pic_volume = 0;
switch (data_clone_conf.em_clone_type)
{
case DriveCloneConf::DriveCloneForm::RightAway:
// 立即备份
if (!BackupRecordSession::QueryCloneFileSize(i_tables_volume, v_bak_tables))
{
// 日志打印
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_OPERATION_FAIL)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::DetermineDiskCloneVolume QueryBakSize FAILED");
return false;
}
if (VSMPlatform::Config::GetPlatformRunType() == VSMPlatform::Config::OutPlatformRunType::StandAlone)
{
if (has_pic)
{
// 获取配置图片存储大小,单位B
CConfigPictureManager::Instance().GetFileSize(i_pic_volume);
}
}
i_clone_file_size = (UINT_T)((i_tables_volume + i_pic_volume) / 1024 / 1024);
break;
case DriveCloneConf::DriveCloneForm::Programme:
// 计划备份-不做空间判断
// 集群部署需要在定时备份中做磁盘空间的检测
if (VSMPlatform::Config::GetPlatformRunType() == VSMPlatform::Config::OutPlatformRunType::ClusterMaster)
{
if (!BackupRecordSession::QueryCloneFileSize(i_tables_volume, v_bak_tables))
{
// 日志打印
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_OPERATION_FAIL)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::DetermineDiskCloneVolume QueryBakSize FAILED");
return false;
}
}
i_clone_file_size = (UINT_T)((i_tables_volume + i_pic_volume) / 1024 / 1024);
break;
default:
// 默认设置大小为100M
i_clone_file_size = 100;
break;
}
// 检测磁盘空间
#ifndef __linux__
auto idx_mark = (UTF82Local(data_clone_conf.str_save_file_path)).find(":");
string drive_mark = (UTF82Local(data_clone_conf.str_save_file_path)).substr(0, idx_mark + 2);
#else
string drive_mark = data_clone_conf.str_save_file_path;
#endif
if (VSMPlatform::Config::GetPlatformRunType() == VSMPlatform::Config::OutPlatformRunType::ClusterMaster)
{
// 集群部署,通知DCC去进行磁盘空间检测
// CheckFreeDisk(drive_mark, i_clone_file_size)
drive_mark = StringReplace(drive_mark.c_str(), "\\", "/");
CBackupConfigManager::DistributeBackupInfo backup_info;
backup_info.https_url = "/ISAPI/Bumblebee/DCC/V0/CheckDiskStatus";
backup_info.https_bodys = Bee::Base::StringUtil::str_fmt(R"({"DatabaseRestore":{"DriveMark":"%s", "DatabaseSize":"%s"}})",
drive_mark.c_str(), std::to_string(i_clone_file_size));
IVMS_LOG_INFO("platform.Maintenance", "https_url [%s],https_bodys[%s]", backup_info.https_url.c_str(), backup_info.https_bodys.c_str());
if (!CBackupConfigManager::Instance().IncreBackupRestore(backup_info))
{
IVMS_LOG_ERROR("platform.Maintenance", "CheckDiskspace timeout, the backup file needs %d MB space, https[%s]",i_clone_file_size, backup_info.https_url.c_str());
return false;
}
return true;
}
if (b_is_diff_machine)//如果是异机部署 jiahong
{
b_is_diskSpace_ok = false;
b_recBeeAgent_diskSpace = false;
shared_ptr<proto::IProto> parse = make_shared<proto::CRapidJsonProto>();
string strGuid = Bee::Base::GuidUtil::CreateGuid();
parse->set_v("/Guid", strGuid);
parse->set_v("/RequestData/Method", "CheckDiskSpace");
parse->set_v("/RequestData/Data/DiskName", drive_mark);
// const char* szStr = "%d";
//std::string strSize = str_fmt(szStr,i_clone_file_size);
parse->set_v("/RequestData/Data/DiskSpace", i_clone_file_size);
string strReq = parse->get_str();
CBeeAgentClientManager::Instance().SendMsg(iBeeAgentClientId, strReq, Bee::Net::WebSocket::TEXT);
//测试
//return true;
//等待看门狗检查磁盘空间的回复,超过30s超时
time_t startTime;
time_t endTime;
double diffStartEndTime;
time(&startTime);
while (true)
{
if (b_recBeeAgent_diskSpace)
{
if (b_is_diskSpace_ok)
{
b_recBeeAgent_diskSpace = false;
return true;
}
}
time(&endTime);
diffStartEndTime = difftime(endTime, startTime);
if (diffStartEndTime > 10)
{
IVMS_LOG_ERROR("platform.Maintenance", "CheckDiskspace timeout %s, the backup file needs %d MB space,BeeAgent ReBackPackage TimeOut",
drive_mark.c_str(), i_clone_file_size);
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BEEAGENT_TIMEOUT)));
b_recBeeAgent_diskSpace = false;
return false;
}
}
}
else
{
if (!CheckDiskSpace(drive_mark, i_clone_file_size))
{
IVMS_LOG_ERROR("platform.Maintenance", "CheckDiskspace FAILED %s, the backup file needs %d MB space",
drive_mark.c_str(), i_clone_file_size);
return false;
}
}
if (is_distributed_)
{
// 判断ADS磁盘空间是否充足
/*Bee::DistributedManager::DriveCloneConf dist_data_clone_conf(data_clone_conf.str_clone_data_type, data_clone_conf.str_save_file_path, data_clone_conf.str_ads_save_file_path);
if (!Bee::DistributedManager::ADS_DetermineDiskCloneVolume(dist_data_clone_conf))
{
IVMS_LOG_ERROR("platform.Maintenance", "CheckDiskspace FAILED %s, the backup file needs more ADS space %d MB",
data_clone_conf.str_save_file_path.c_str(), i_clone_file_size);
return false;
}*/
}
return true;
}
bool CTimerBackup::ResetAcsStatus()
{
return BackupRecordSession::ResetAcsStatusDB();
}
bool CTimerBackup::VacuumDirtyTables()
{
return BackupRecordSession::VacuumDirtyTablesDB();
}
bool CTimerBackup::QueryUpgradeProduct(string & product_type)
{
shared_ptr<db_layer::CConnect> ptr_connect = nullptr;
ptr_connect = CVsmPlatformDBConn::Instance().ApplyConn();
if (ptr_connect == nullptr)
{
IVMS_LOG_ERROR("platform.UpgradeProgress", "Conn Failed.");
return false;
}
db_layer::CConnect& rs = *ptr_connect;
string query_sql = "SELECT product_type FROM platform.db_version WHERE id = (SELECT max(id) FROM platform.db_version);";
if (!rs.ExecuteQuery(query_sql))
{
IVMS_LOG_ERROR("platform.UpgradeProgress", "Query Failed, sql is %s", query_sql.c_str());
return false;
}
product_type = rs.GetString("product_type");
if (product_type.empty())
{
IVMS_LOG_ERROR("platform.UpgradeProgress", "product_type is empty at table of platform.db_version.");
return false;
}
return true;
}
bool CTimerBackup::QueryBackupInfoPlan(string & save_path)
{
shared_ptr<db_layer::CConnect> ptr_connect = nullptr;
ptr_connect = CVsmPlatformDBConn::Instance().ApplyConn();
if (ptr_connect == nullptr)
{
IVMS_LOG_ERROR("platform.Maintenance", "Conn Failed.");
return false;
}
db_layer::CConnect& rs = *ptr_connect;
string query_sql = "SELECT save_path FROM platform.backup_info WHERE is_deleted = 0;";
if (!rs.ExecuteQuery(query_sql))
{
IVMS_LOG_ERROR("platform.Maintenance", "Query Failed, sql is %s", query_sql.c_str());
return false;
}
save_path = rs.GetString("save_path");
return true;
}
bool CTimerBackup::ManualExecuteWal(const string & backup_path)
{
if (b_is_dump_running_ || b_is_restore_running_)
{
// 日志打印
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_IS_BACKUPING_RESTORING)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::DriveCloneRightAway Is Backuping or Restroing Now, Repeat CMDs");
return false;
}
// // 自动备份和手动备份不能同时执行
// std::lock_guard<mutex> lock(mutex_pg_dump_);
b_is_dump_running_ = true;
i_sys_dump_percent_ = 0;
m_bak_error_ = DRIVE_CLONE_RESTORE_SUCC;
// 手动备份需要把基础备份和归档日志拷贝走
boost::system::error_code ec;
string save_root_path = Bee::Base::StringUtil::StringReplace(backup_path.c_str(), "\\", "/");
CBackupConfigManager::DistributeBackupInfo backup_info;
backup_info.https_url = "/ISAPI/Bumblebee/DCC/V0/BackupNow";
backup_info.https_bodys = Bee::Base::StringUtil::str_fmt(R"({"DatabaseRestore":{"BackFilePath":"%s"}})",
save_root_path.c_str()/*, str_create_time.c_str()*/);
IVMS_LOG_INFO("platform.Maintenance", "https_url[%s], https_bodys[%s]", backup_info.https_bodys.c_str(), backup_info.https_bodys.c_str());
if (!CBackupConfigManager::Instance().IncreBackupRestore(backup_info))
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_BACKUP_FAIL)));
m_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::DriveCloneRightAway ManualExecuteWal FAILED");
// 重置进度
b_is_dump_running_ = false;
i_sys_dump_percent_ = 100;
return false;
}
CThreadManager::Instance().PostTask(string(__FUNCTION__) + "[GetClusterBackupResoreStatus]",
std::bind(&CTimerBackup::GetClusterBackupResoreStatus, this, DEF_BACKUP_ONLY_CONFIG));
// b_is_dump_running_ = false;
// i_sys_dump_percent_ = 100;
return true;
}
// 整理备份数据表
UINT_T CTimerBackup::CombingDBCloneTables(vector<string> &v_bak_tables,
const string &str_table_types, const bool &is_distributed)
{
if (str_table_types.empty())
{
// 日志打印
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::CombingDBCloneTables str_table_types is NULL");
return DRIVE_CLONE_RESTORE_FAIL;
}
// 便于通过下标获取数据
/*vector<string> data_type_array[10] = { vec_backup_conf_table, vec_backup_picture_table, vec_backup_event_table, vec_backup_alarm_table,
vec_backup_swipcards_table, vec_backup_attendance_table, vec_backup_vehicle_table, vec_backup_bi_table, vec_backup_log_table, vec_backup_face_table };*/
// 获取备份类型列表
vector<UINT_T> v_data_type;
String2Array(v_data_type, str_table_types);
// 检测一下是否包含了所有默认配置数据
map<int32_t, BackupCategoryInfo> m_default_bak;
CMaintenanceManager::Instance().GetValidDefaultBackupCategory(m_default_bak);
for (auto& elem : m_default_bak)
{
vector<UINT_T>::iterator iter = find(v_data_type.begin(), v_data_type.end(), elem.second.backup_category_type);
if (iter == v_data_type.end())
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::CombingDBCloneTables table_types not include defaultbackup type=%d", elem.first);
return DRIVE_CLONE_RESTORE_FAIL;
}
}
v_bak_tables.clear();
UINT_T ctgs_num = CBackupConfigManager::Instance().GetBackupCategoryTotalNum();
std::map<int32_t, BackupCategoryInfo> vec_backup_category;
CBackupConfigManager::Instance().GetAllBackupCategoryInfo(vec_backup_category);
auto max_item = std::max_element(vec_backup_category.begin(), vec_backup_category.end(), [](std::pair<int32_t, BackupCategoryInfo> a, std::pair<int32_t, BackupCategoryInfo> b) {return a.first < b.first; });
ctgs_num = max_item->first;
for (vector<UINT_T>::iterator it = v_data_type.begin(); it != v_data_type.end(); it++)
{
if (*it > ctgs_num)
{
// 日志打印,输入的备份类型ID超过了实际的数量
IVMS_LOG_INFO("platform.Maintenance", "CTimerBackup::ObtainBakTableNames number %d of str_table_types is OUT of limit %d", *it, ctgs_num);
//return DRIVE_CLONE_RESTORE_FAIL;
}
// 列出总的数据表
if (!CBackupConfigManager::Instance().GetCategoryContainTables(v_bak_tables, *it))
//if (!BackupRecordSession::QueryCategoryContainTables(v_bak_tables, *it, is_distributed))
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::QueryCategoryContainTables Failed");
return DRIVE_CLONE_RESTORE_FAIL;
}
}
if (v_bak_tables.empty())
{
// 日志打印
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ObtainBakTableNames return v_bak_tables is empty");
return DRIVE_CLONE_RESTORE_FAIL;
}
return DRIVE_CLONE_RESTORE_SUCC;
}
// 整理备份数据表
UINT_T CTimerBackup::CombingDBCloneTables(vector<string> &v_config_tables, vector<string> &v_runtime_tables,
const string &str_table_types, const bool &is_distributed)
{
//v_config_tables
//v_runtime_tables
//str_table_types
if (str_table_types.empty())
{
// 日志打印
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::CombingDBCloneTables str_table_types is NULL");
return DRIVE_CLONE_RESTORE_FAIL;
}
// 获取备份类型列表
vector<UINT_T> v_data_type;
String2Array(v_data_type, str_table_types);
// 检测一下是否包含了所有默认配置数据
map<int32_t, BackupCategoryInfo> m_default_bak;
CMaintenanceManager::Instance().GetValidDefaultBackupCategory(m_default_bak);
for (auto& elem : m_default_bak)
{
vector<UINT_T>::iterator iter = find(v_data_type.begin(), v_data_type.end(), elem.second.backup_category_type);
if (iter == v_data_type.end())
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::CombingDBCloneTables table_types not include defaultbackup type=%d", elem.first);
return DRIVE_CLONE_RESTORE_FAIL;
}
}
v_config_tables.clear();
v_runtime_tables.clear();
//UINT_T ctgs_num = BackupRecordSession::QueryCategoryNum();
UINT_T ctgs_num = CBackupConfigManager::Instance().GetBackupCategoryTotalNum();
std::map<int32_t, BackupCategoryInfo> vec_backup_category;
CBackupConfigManager::Instance().GetAllBackupCategoryInfo(vec_backup_category);
auto max_item = std::max_element(vec_backup_category.begin(), vec_backup_category.end(), [](std::pair<int32_t, BackupCategoryInfo> a, std::pair<int32_t, BackupCategoryInfo> b) {return a.first < b.first; });
ctgs_num = max_item->first;
for (vector<UINT_T>::iterator it = v_data_type.begin(); it != v_data_type.end(); it++)
{
if (*it > ctgs_num)
{
// 日志打印,输入的备份类型ID超过了实际的数量
IVMS_LOG_INFO("platform.Maintenance", "CTimerBackup::ObtainBakTableNames number %d of str_table_types is OUT of limit %d", *it, ctgs_num);
// return DRIVE_CLONE_RESTORE_FAIL;
}
// 配置型数据
if (*it == 0)
{
//CBackupConfigManager::Instance().GetCategoryContainTables(v_config_tables, 0);
if (!CBackupConfigManager::Instance().GetCategoryContainTables(v_config_tables, 0))
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::QueryCategoryNOTContainTables Public Tables Failed");
return DRIVE_CLONE_RESTORE_FAIL;
}
continue;
}
// if (*it == 13)
// {
// if (!CBackupConfigManager::Instance().GetCategoryContainTables(v_config_tables, 13))
// {
// IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::QueryCategoryNOTContainTables TV Wall Tables Failed");
// return DRIVE_CLONE_RESTORE_FAIL;
// }
//
// continue;
// }
// 图片数据-不增加至config排除列表
else if (*it == 1)
{
if (!CBackupConfigManager::Instance().GetCategoryContainTables(v_config_tables, 1))
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::QueryCategoryContainTables Picture Tables Failed");
return DRIVE_CLONE_RESTORE_FAIL;
}
continue;
}
// BI数据
else if (*it == 7)
{
// 如果当前备份数据类型为bi_data,则使用bi_data.*,防止表数量过多超出cmd长度限制
//v_runtime_tables.push_back("bi.*");
//continue;
}
if (!CBackupConfigManager::Instance().GetCategoryContainTables(v_config_tables, *it))
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::QueryCategoryContainTables Failed");
return DRIVE_CLONE_RESTORE_FAIL;
}
}
if (v_config_tables.empty())
{
// 日志打印
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ObtainBakTableNames return v_config_tables is empty");
return DRIVE_CLONE_RESTORE_FAIL;
}
return DRIVE_CLONE_RESTORE_SUCC;
}
// 整理备份数据表
UINT_T CTimerBackup::CombingDBCloneTables(vector<BackupCategoryInfo::table_info> &v_config_tables,
vector<BackupCategoryInfo::table_info> &v_runtime_tables, const string &str_table_types,
const bool &is_distributed)
{
//v_config_tables
//v_runtime_tables
//str_table_types
if (str_table_types.empty())
{
// 日志打印
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::CombingDBCloneTables str_table_types is NULL");
return DRIVE_CLONE_RESTORE_FAIL;
}
// 获取备份类型列表
vector<UINT_T> v_data_type;
String2Array(v_data_type, str_table_types);
// 检测一下是否包含了所有默认配置数据
map<int32_t, BackupCategoryInfo> m_default_bak;
CMaintenanceManager::Instance().GetValidDefaultBackupCategory(m_default_bak);
for (auto& elem : m_default_bak)
{
vector<UINT_T>::iterator iter = find(v_data_type.begin(), v_data_type.end(), elem.second.backup_category_type);
if (iter == v_data_type.end())
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::CombingDBCloneTables table_types not include defaultbackup type=%d", elem.first);
return DRIVE_CLONE_RESTORE_FAIL;
}
}
v_config_tables.clear();
v_runtime_tables.clear();
//UINT_T ctgs_num = BackupRecordSession::QueryCategoryNum();
UINT_T ctgs_num = CBackupConfigManager::Instance().GetBackupCategoryTotalNum();
std::map<int32_t, BackupCategoryInfo> vec_backup_category;
CBackupConfigManager::Instance().GetAllBackupCategoryInfo(vec_backup_category);
auto max_item = std::max_element(vec_backup_category.begin(), vec_backup_category.end(), [](std::pair<int32_t, BackupCategoryInfo> a, std::pair<int32_t, BackupCategoryInfo> b) {return a.first < b.first; });
ctgs_num = max_item->first;
for (vector<UINT_T>::iterator it = v_data_type.begin(); it != v_data_type.end(); it++)
{
if (*it > ctgs_num)
{
// 日志打印,输入的备份类型ID超过了实际的数量
IVMS_LOG_INFO("platform.Maintenance", "CTimerBackup::ObtainBakTableNames number %d of str_table_types is OUT of limit %d", *it, ctgs_num);
// return DRIVE_CLONE_RESTORE_FAIL;
}
// 配置型数据
if (*it == 0)
{
//CBackupConfigManager::Instance().GetCategoryContainTables(v_config_tables, 0);
if (!CBackupConfigManager::Instance().GetCategoryContainTables(v_config_tables, 0))
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::QueryCategoryNOTContainTables Public Tables Failed");
return DRIVE_CLONE_RESTORE_FAIL;
}
continue;
}
// if (*it == 13)
// {
// if (!CBackupConfigManager::Instance().GetCategoryContainTables(v_config_tables, 13))
// {
// IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::QueryCategoryNOTContainTables TV Wall Tables Failed");
// return DRIVE_CLONE_RESTORE_FAIL;
// }
//
// continue;
// }
// 图片数据-不增加至config排除列表
else if (*it == 1)
{
if (!CBackupConfigManager::Instance().GetCategoryContainTables(v_config_tables, 1))
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::QueryCategoryContainTables Picture Tables Failed");
return DRIVE_CLONE_RESTORE_FAIL;
}
continue;
}
// BI数据
else if (*it == 7)
{
// 如果当前备份数据类型为bi_data,则使用bi_data.*,防止表数量过多超出cmd长度限制
//v_runtime_tables.push_back("bi.*");
//continue;
}
if (!CBackupConfigManager::Instance().GetCategoryContainTables(v_config_tables, *it))
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::QueryCategoryContainTables Failed");
return DRIVE_CLONE_RESTORE_FAIL;
}
}
if (v_config_tables.empty())
{
// 日志打印
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ObtainBakTableNames return v_config_tables is empty");
return DRIVE_CLONE_RESTORE_FAIL;
}
return DRIVE_CLONE_RESTORE_SUCC;
}
// UINT_T CTimerBackup::CombingSQLiteDB(map<string,string>& backup_db)
// {
// backup_db = CVsmPlatformDBConn::Instance().SendAllDBFile();
// if (backup_db.empty())
// {
// IVMS_LOG_ERROR("platform.Maintenance", "Failed get to all db.");
// return DRIVE_CLONE_RESTORE_FAIL;
// }
// string record_xml = CConfigPathManager::Instance().GetDBRecordPath();
//
// boost::system::error_code ec;
// if (!boost::filesystem::exists(record_xml, ec))
// {
// IVMS_LOG_ERROR("platform.Maintenance", "The DBRecord.xml is not exist, path = %s", record_xml.c_str());
// return false;
// }
// string record_buf;
// if (!CFileBak::ReadFile(record_buf, record_xml))
// {
// IVMS_LOG_ERROR("platform.Maintenance", "Read DBRecord.xml fail, path = %s", record_xml.c_str());
// return false;
// }
//
// shared_ptr<proto::IProto> pro_plugin_id(new proto::CXmlProto());
// pro_plugin_id->set_str(record_buf);
// int plugin_num = pro_plugin_id->get_cnt("/DBRecord/Plugin");
//
// int plugin_schema_index = 0;
// std::string str_plugin_node;
// std::string plugin_id;
// for (int i = 1; i <= plugin_num; i++)
// {
// str_plugin_node = StringUtil::str_fmt("/DBRecord/Plugin[%d]", i);
// plugin_id = pro_plugin_id->get_a(str_plugin_node, "DBName"); // e.g: alarm.s
//
// backup_db.push_back(plugin_id);
// }
// return DRIVE_CLONE_RESTORE_SUCC;
// }
UINT_T CTimerBackup::BACKUPRESTORE_CreateProcess_CMD(HANDLE &hChildStdoutWr, HANDLE &hChildStdinRd)
{
//TO DO: linux
#ifndef __linux__
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
// BOOL bFuncRetn = FALSE;
ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION));
ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.hStdError = hChildStdoutWr;
siStartInfo.hStdOutput = hChildStdoutWr;
siStartInfo.hStdInput = hChildStdinRd;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
TCHAR cmdLine[] = TEXT("cmd.exe");
if (!CreateProcess(NULL, cmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &siStartInfo, &piProcInfo))
{
// 日志打印
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::PG_CreateProcess FAILED");
return DRIVE_CLONE_RESTORE_FAIL;
}
else
{
CloseHandle(piProcInfo.hProcess);
CloseHandle(piProcInfo.hThread);
return DRIVE_CLONE_RESTORE_SUCC;
}
#else
return 0;
#endif
}
/*UINT_T CTimerBackup::PG_CreateProcess_BAT(HANDLE &hChildStdoutWr, HANDLE &hChildStdinRd, const string &str_bat_file)
{
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
// BOOL bFuncRetn = FALSE;
ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION));
ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.hStdError = hChildStdoutWr;
siStartInfo.hStdOutput = hChildStdoutWr;
siStartInfo.hStdInput = hChildStdinRd;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
TCHAR cmdLine[256];
MultiByteToWideChar(CP_ACP, 0, (LPCSTR)str_bat_file.c_str(), -1, cmdLine, 256);
if (!CreateProcess(NULL, cmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &siStartInfo, &piProcInfo))
{
// 日志打印
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::PG_CreateProcess FAILED");
return DRIVE_CLONE_RESTORE_FAIL;
}
else
{
CloseHandle(piProcInfo.hProcess);
CloseHandle(piProcInfo.hThread);
return DRIVE_CLONE_RESTORE_SUCC;
}
}*/
UINT_T CTimerBackup::BACKUPRESTORE_WriteToPipe(HANDLE &hChildStdinWrDup, const string &str_cmd_line)
{
//TO DO: linux
#ifndef __linux__
DWORD dwWritten;
if (!WriteFile(hChildStdinWrDup, str_cmd_line.c_str(), (DWORD)str_cmd_line.length(), &dwWritten, NULL))
{
// 日志打印
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::PG_WriteToPipe FAILED");
return DRIVE_CLONE_RESTORE_FAIL;
}
CloseHandle(hChildStdinWrDup);
return DRIVE_CLONE_RESTORE_SUCC;
#else
return DRIVE_CLONE_RESTORE_FAIL;
#endif
}
UINT_T CTimerBackup::PG_DumpRestore_ReadFromPipe(HANDLE &hChildStdoutRdDup, const UINT_T &i_total_lines, const UINT_T &command_type)
{
#ifndef __linux__
IVMS_LOG_INFO("platform.Maintenance", "command_type: %d", command_type);
DWORD dwRead = 0;
char chBuf[CMD_BUF_LEN + 1] = { 0 };
// UINT_T percent_vol = i_percent_vol;
// if (i_percent_vol >= i_total_lines)
// {
// i_percent_vol = 0;
// }
do
{
//bool dest = false;
ReadFile(hChildStdoutRdDup, chBuf, CMD_BUF_LEN, &dwRead, NULL);
//dwRead = fread_s(chBuf, CMD_BUF_LEN + 1, sizeof(char), CMD_BUF_LEN, (FILE *)hChildStdoutRdDup);
if (dwRead == 0)
{
break;
}
// size_t uPreIndex = 0;
// size_t uIndex = 0;
// string strArray = string(chBuf, CMD_BUF_LEN);
// IVMS_LOG_INFO("platform.Backupexcute", "Output Information: %s", strArray.c_str());
} while (dwRead > 0);
IVMS_LOG_INFO("platform.Maintenance", "CTimerBackup::PG_DumpRestore_ReadFromPipe ReadFile FINISHED");
switch (command_type)
{
case DEF_BACKUP_ONLY_CONFIG:
{
std::lock_guard<mutex> lock(backup_progress_);
i_sys_dump_percent_ = (UINT_T)(((double)backup_vec_table_num_ / (double)i_total_lines) * 100);
b_is_site_dump_percent_ = (UINT_T)(((double)backup_vec_table_num_ / (double)i_total_lines) * 100);
IVMS_LOG_INFO("platform.Maintenance", "i_sys_dump_percent_ is : %d", i_sys_dump_percent_.load());
if (!percent_config_)
{
tmp_i_sys_dump_percent_.store(i_sys_dump_percent_.load());
tmp_b_is_site_dump_percent_.store(b_is_site_dump_percent_.load());
percent_config_ = true;
}
else
{
if (tmp_i_sys_dump_percent_ + 10 < i_sys_dump_percent_ || tmp_b_is_site_dump_percent_ + 10 < b_is_site_dump_percent_)
{
i_sys_dump_percent_ += 5;
b_is_site_dump_percent_ += 5;
}
tmp_i_sys_dump_percent_.store(i_sys_dump_percent_.load());
tmp_b_is_site_dump_percent_.store(b_is_site_dump_percent_.load());
}
// 模糊比例,防止超过100
// 剩余5%留给电视墙
if (i_sys_dump_percent_ > 98 || b_is_site_dump_percent_ > 98)
{
i_sys_dump_percent_ = 99;
b_is_site_dump_percent_ = 99;
}
}
break;
case DEF_RSMBAK:
{
std::lock_guard<mutex> lock(backup_progress_);
i_sys_dump_percent_ = (UINT_T)(((double)backup_site_table_num_ / (double)i_total_lines) * 100);
b_is_site_dump_percent_ = (UINT_T)(((double)backup_site_table_num_ / (double)i_total_lines) * 100);
if (!percent_config_)
{
tmp_i_sys_dump_percent_.store(i_sys_dump_percent_.load());
tmp_b_is_site_dump_percent_.store(b_is_site_dump_percent_.load());
percent_config_ = true;
}
else
{
if (tmp_i_sys_dump_percent_ + 10 < i_sys_dump_percent_ || tmp_b_is_site_dump_percent_ + 10 < b_is_site_dump_percent_)
{
i_sys_dump_percent_ += 5;
b_is_site_dump_percent_ += 5;
}
tmp_i_sys_dump_percent_.store(i_sys_dump_percent_.load());
tmp_b_is_site_dump_percent_.store(b_is_site_dump_percent_.load());
}
// 模糊比例,防止超过100
// 剩余5%留给电视墙
if (i_sys_dump_percent_ > 98 || b_is_site_dump_percent_ > 98)
{
i_sys_dump_percent_ = 98;
b_is_site_dump_percent_ = 98;
}
}
break;
// 备份
case DEF_BACKUP_CONFIG:
{
std::lock_guard<mutex> lock(backup_progress_);
i_sys_dump_percent_ = (UINT_T)(((double)backup_vec_table_num_ / (double)i_total_lines) * 100);
b_is_site_dump_percent_ = (UINT_T)(((double)backup_vec_table_num_ / (double)i_total_lines) * 100);
IVMS_LOG_INFO("platform.Maintenance", "i_sys_dump_percent_ is : %d", i_sys_dump_percent_.load());
if (!percent_config_)
{
tmp_i_sys_dump_percent_.store(i_sys_dump_percent_.load());
tmp_b_is_site_dump_percent_.store(b_is_site_dump_percent_.load());
percent_config_ = true;
}
else
{
if (tmp_i_sys_dump_percent_ + 10 < i_sys_dump_percent_ || tmp_b_is_site_dump_percent_ + 10 < b_is_site_dump_percent_)
{
i_sys_dump_percent_ += 5;
b_is_site_dump_percent_ += 5;
}
tmp_i_sys_dump_percent_.store(i_sys_dump_percent_.load());
tmp_b_is_site_dump_percent_.store(b_is_site_dump_percent_.load());
}
// 模糊比例,防止超过100
// 剩余5%留给电视墙
if (i_sys_dump_percent_ > 98 || b_is_site_dump_percent_ > 98)
{
i_sys_dump_percent_ = 99;
b_is_site_dump_percent_ = 99;
}
}
break;
case DEF_BACKUP_RUNTIME:
break;
// 还原
case DEF_RESTORE:
{
std::lock_guard<mutex> lock(backup_progress_);
i_sys_restore_percent_ = (UINT_T)(((double)restore_bak_num_ / (double)i_total_lines) * 100);
//IVMS_LOG_INFO("platform.Maintenance", "i_sys_restore_percent_ is : %d", i_sys_restore_percent_);
// 模糊比例,防止超过100
// 剩余5%留给电视墙
// if (i_sys_restore_percent_ > 95)
// {
// i_sys_restore_percent_ = 95;
// }
if (!percent_config_)
{
tmp_i_sys_restore_percent_.store(i_sys_restore_percent_.load());
percent_config_ = true;
}
else
{
if (tmp_i_sys_restore_percent_ + 10 < i_sys_restore_percent_)
{
i_sys_restore_percent_ += 5;
}
tmp_i_sys_restore_percent_.store(i_sys_restore_percent_.load());
}
// 模糊比例,防止超过100
if (i_sys_restore_percent_ > 98)
{
i_sys_restore_percent_ = 98;
}
}
break;
default:
break;
}
#endif // !__linux__
return DRIVE_CLONE_RESTORE_SUCC;
}
UINT_T CTimerBackup::SQLite_DumpRestore_ReadFromPipe(HANDLE & hChildStdoutRdDup, const UINT_T & i_db_count, const UINT_T & command_type)
{
IVMS_LOG_INFO("platform.Maintenance", "command_type: %d", command_type);
DWORD dwRead = 0;
char chBuf[CMD_BUF_LEN + 1] = { 0 };
do
{
//bool dest = false;
ReadFile(hChildStdoutRdDup, chBuf, CMD_BUF_LEN, &dwRead, NULL);
if (dwRead == 0)
{
break;
}
} while (dwRead > 0);
IVMS_LOG_INFO("platform.Maintenance", "CTimerBackup::SQLite_DumpRestore_ReadFromPipe ReadFile FINISHED");
switch (command_type)
{
case DEF_BACKUP_ONLY_CONFIG:
{
std::lock_guard<mutex> lock(backup_progress_);
i_sys_dump_percent_ = (UINT_T)(((double)backup_vec_table_num_ / (double)i_db_count) * 100);
b_is_site_dump_percent_ = (UINT_T)(((double)backup_vec_table_num_ / (double)i_db_count) * 100);
IVMS_LOG_INFO("platform.Maintenance", "i_sys_dump_percent_ is : %d", i_sys_dump_percent_.load());
if (!percent_config_)
{
tmp_i_sys_dump_percent_.store(i_sys_dump_percent_.load());
tmp_b_is_site_dump_percent_.store(b_is_site_dump_percent_.load());
percent_config_ = true;
}
else
{
if (tmp_i_sys_dump_percent_ + 10 < i_sys_dump_percent_ || tmp_b_is_site_dump_percent_ + 10 < b_is_site_dump_percent_)
{
i_sys_dump_percent_ += 5;
b_is_site_dump_percent_ += 5;
}
tmp_i_sys_dump_percent_.store(i_sys_dump_percent_.load());
tmp_b_is_site_dump_percent_.store(b_is_site_dump_percent_.load());
}
// 模糊比例,防止超过100
// 剩余5%留给电视墙
if (i_sys_dump_percent_ > 98 || b_is_site_dump_percent_ > 98)
{
i_sys_dump_percent_ = 99;
b_is_site_dump_percent_ = 99;
}
}
break;
case DEF_BACKUP_CONFIG:
{
std::lock_guard<mutex> lock(backup_progress_);
i_sys_dump_percent_ = (UINT_T)(((double)backup_vec_table_num_ / (double)i_db_count) * 100);
b_is_site_dump_percent_ = (UINT_T)(((double)backup_vec_table_num_ / (double)i_db_count) * 100);
IVMS_LOG_INFO("platform.Maintenance", "i_sys_dump_percent_ is : %d", i_sys_dump_percent_.load());
if (!percent_config_)
{
tmp_i_sys_dump_percent_.store(i_sys_dump_percent_.load());
tmp_b_is_site_dump_percent_.store(b_is_site_dump_percent_.load());
percent_config_ = true;
}
else
{
if (tmp_i_sys_dump_percent_ + 10 < i_sys_dump_percent_ || tmp_b_is_site_dump_percent_ + 10 < b_is_site_dump_percent_)
{
i_sys_dump_percent_ += 5;
b_is_site_dump_percent_ += 5;
}
tmp_i_sys_dump_percent_.store(i_sys_dump_percent_.load());
tmp_b_is_site_dump_percent_.store(b_is_site_dump_percent_.load());
}
// 模糊比例,防止超过100
// 剩余5%留给电视墙
if (i_sys_dump_percent_ > 98 || b_is_site_dump_percent_ > 98)
{
i_sys_dump_percent_ = 99;
b_is_site_dump_percent_ = 99;
}
}
break;
case DEF_RSMBAK:
{
std::lock_guard<mutex> lock(backup_progress_);
i_sys_dump_percent_ = (UINT_T)(((double)backup_site_table_num_ / (double)i_db_count) * 100);
b_is_site_dump_percent_ = (UINT_T)(((double)backup_site_table_num_ / (double)i_db_count) * 100);
if (!percent_config_)
{
tmp_i_sys_dump_percent_.store(i_sys_dump_percent_.load());
tmp_b_is_site_dump_percent_.store(b_is_site_dump_percent_.load());
percent_config_ = true;
}
else
{
if (tmp_i_sys_dump_percent_ + 10 < i_sys_dump_percent_ || tmp_b_is_site_dump_percent_ + 10 < b_is_site_dump_percent_)
{
i_sys_dump_percent_ += 5;
b_is_site_dump_percent_ += 5;
}
tmp_i_sys_dump_percent_.store(i_sys_dump_percent_.load());
tmp_b_is_site_dump_percent_.store(b_is_site_dump_percent_.load());
}
// 模糊比例,防止超过100
// 剩余5%留给电视墙
if (i_sys_dump_percent_ > 98 || b_is_site_dump_percent_ > 98)
{
i_sys_dump_percent_ = 98;
b_is_site_dump_percent_ = 98;
}
}
break;
// 还原
case DEF_RESTORE:
{
std::lock_guard<mutex> lock(backup_progress_);
i_sys_restore_percent_ = (UINT_T)(((double)restore_bak_num_ / (double)i_db_count) * 100);
if (!percent_config_)
{
tmp_i_sys_restore_percent_.store(i_sys_restore_percent_.load());
percent_config_ = true;
}
else
{
if (tmp_i_sys_restore_percent_ + 10 < i_sys_restore_percent_)
{
i_sys_restore_percent_ += 5;
}
tmp_i_sys_restore_percent_.store(i_sys_restore_percent_.load());
}
// 模糊比例,防止超过100
if (i_sys_restore_percent_ > 98)
{
i_sys_restore_percent_ = 98;
}
}
break;
default:
break;
}
return DRIVE_CLONE_RESTORE_SUCC;
}
UINT_T CTimerBackup::ExecPGDumpProgress(const string &str_whole_file_path1,
const vector<BackupCategoryInfo::table_info> &v_bak_tables, const UINT_T &conf_run)
{
// 拼装pg_dump命令语句
string str_whole_file_path = str_whole_file_path1;
string str_pg_dump_exe_path = PostgreSQL_path_ + PostgreSQL_backup_exe;
boost::system::error_code err_c;
if (!boost::filesystem::exists(str_pg_dump_exe_path, err_c))
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUP_CONFIG_ERROR)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecPGDumpProgress pg_dump.exe did NOT exists");
return DRIVE_CLONE_RESTORE_FAIL;
}
LocalDBInfo curr_db_info;
CLocalConfigManager::Instance().GetLocationDBInfo(curr_db_info);
// 获取数据库连接密码
#if (defined(_WIN32) || defined(_WIN32_WCE) || defined(_WIN64))
char* str_set_pwd = "SET PGPASSWORD=%s\n";
string str_whole_set_pwd = str_fmt(str_set_pwd, curr_db_info.db_passwd.c_str());
#elif (defined(__linux__))
string str_whole_set_pwd;
CSetTmpPGPwd set_pg_pwd(curr_db_info.db_passwd);
#endif
// 备份表列表
string str_backup_table, str_real_backup_table;
vector<BackupCategoryInfo::table_info> v_bak_tmp;
v_bak_tmp.assign(v_bak_tables.begin(), v_bak_tables.end());
// 打乱顺序,保证大表等待时间分布均匀
random_shuffle(v_bak_tmp.begin(), v_bak_tmp.end());
// 备份命令拆分一下,主要为了判断命令总长度,windows命令行长度不能超过4096
string str_dump_cmd_0 = str_fmt("\"%s\" --host 127.0.0.1 --port %d --username postgres --dbname cms ",
str_pg_dump_exe_path.c_str(), (unsigned short)postgre_port_);
vector<BackupCategoryInfo::table_info>::const_iterator it = v_bak_tmp.begin();
int flag = 0;
//i_sys_dump_percent_batch_ = 1;
//i_sys_dump_percent_batch_total_ = (v_bak_tmp.size() % 10) == 0 ? v_bak_tmp.size() /10 : v_bak_tmp.size()/10 +1;
i_percent_vol = 0;
auto ptr_connect = CVsmPlatformDBConn::Instance().ApplyConn();
if (nullptr==ptr_connect)
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecPGDumpProgress apply conn failed");
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUP_CONFIG_ERROR)));
return DRIVE_CLONE_RESTORE_FAIL;
}
if (!ptr_connect->Begin())
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecPGDumpProgress snapshot begin failed");
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUP_CONFIG_ERROR)));
return DRIVE_CLONE_RESTORE_FAIL;
}
string trans_sql = "SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;SELECT pg_export_snapshot();";
if (!ptr_connect->ExecuteQuery(trans_sql))
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecPGDumpProgress sql execute failed");
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUP_CONFIG_ERROR)));
return DRIVE_CLONE_RESTORE_FAIL;
}
string snapshot_num = ptr_connect->GetString("pg_export_snapshot");
while (it != v_bak_tmp.end())
{
// 存储归档名bak1,bak2
flag++;
str_whole_file_path = str_whole_file_path1 + to_string(flag);
string str_dump_cmd_1 = str_fmt(" --format custom --verbose -c -E utf8 --file \"%s\"\n",
str_whole_file_path.c_str());
int n = 0;
str_backup_table = string();
str_real_backup_table = string();
for (; it != v_bak_tmp.end(); it++)
{
// 拼装命令,-t参数增加序列
str_backup_table += " -t " + it->schema_name + "." + it->table_name + "*_seq" + " -t " + it->schema_name + "." + it->table_name;
n++;
if (!(it->vec_view.empty()))
{
for (auto& view : it->vec_view)
{
str_backup_table += " -t " + view;
}
}
// 判断下命令长度
if (str_dump_cmd_0.size() + str_dump_cmd_1.size() + str_backup_table.size() > DEF_WIN_CMD_MAX_LENTH)
{
string log_cmd = str_dump_cmd_0 + str_backup_table + str_dump_cmd_1;
// 假如只加一个表就会超命令行长度,肯定是有问题了,这个时候返回异常
if (str_real_backup_table.empty())
{
IVMS_LOG_ERROR("platform.Maintenance", "cmd lenth error size=%d cmd=%s",
log_cmd.size(), log_cmd.c_str());
return DRIVE_CLONE_RESTORE_FAIL;
}
// 当前的表并没被加进去,所以不需要it++
IVMS_LOG_WARN("platform.Maintenance", "cmd lenth oversize size=%d cmd=%s",
log_cmd.size(), log_cmd.c_str());
break;
}
str_real_backup_table = str_backup_table;
if (n == 10)
{
// 下一轮从下一个表开始
it++;
break;
}
}
// 将命令中表的个数进行记录
backup_vec_table_num_ += n;
IVMS_LOG_INFO("platform.Maintenance", "backup_vec_table_num_ is : %d", backup_vec_table_num_);
string str_dump_cmd = str_dump_cmd_0 + str_real_backup_table + " --snapshot=" + snapshot_num + str_dump_cmd_1 ;
// 添加执行日志
IVMS_LOG_INFO("platform.Maintenance", "CTimerBackup::ExecPGDumpProgress DUMP CMD : %s", str_dump_cmd.c_str());
// 创建BAT文件路径
auto idx = str_whole_file_path.find(".bak");
string str_bat_file_path;
string str_log_file_path;
if (idx != string::npos)
{
str_bat_file_path = str_whole_file_path.substr(0, idx) + ".bat";
str_log_file_path = str_whole_file_path.substr(0, idx) + ".log";
}
//创建并写入文件
HPR_HANDLE hpr_handle = HPR_OpenFile(str_bat_file_path.c_str(), HPR_READ | HPR_WRITE | HPR_CREATE | HPR_APPEND, HPR_ATTR_WRITE);
if (hpr_handle != HPR_INVALID_FILE)
{
HPR_UINT32 write_data_length;
char* pSQL_Buffer = new char[str_dump_cmd.length() + 1];
if (NULL != pSQL_Buffer)
{
// memcpy_s(pSQL_Buffer, str_dump_cmd.length(), str_dump_cmd.c_str(), str_dump_cmd.length());
HPR_MEMCPY_S(pSQL_Buffer, str_dump_cmd.length(), str_dump_cmd.c_str(), str_dump_cmd.length());
if (HPR_ERROR == HPR_WriteFile(hpr_handle, pSQL_Buffer, static_cast<HPR_UINT32>(str_dump_cmd.length()), &write_data_length))
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecPGDumpProgress DUMP Can NOT Write BAT File.");
HPR_CloseFile(hpr_handle);
delete[] pSQL_Buffer;
return DRIVE_CLONE_RESTORE_FAIL;
}
}
delete[] pSQL_Buffer;
HPR_CloseFile(hpr_handle);
}
else
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecPGDumpProgress DUMP Can NOT Write BAT File.");
HPR_CloseFile(hpr_handle);
return DRIVE_CLONE_RESTORE_FAIL;
}
#if (defined(__linux__))
std::string chmod_bat = "chmod 777 " + str_bat_file_path;
std::system(chmod_bat.c_str());
#endif
// 根据输出行数判断备份进程
UINT_T i_total_dump_lines = 0;
// notes:备份配置型数据,更改计数方式,计数由固定输出行数+表数*迷糊行数更改为表的数量
//i_total_dump_lines = DEF_PREPARE_INFO_ROWS + (UINT_T)v_bak_tables.size() * DEF_BAK_INFO_ROWS;
i_total_dump_lines = (UINT_T)v_bak_tables.size();
string str_bat_cmd = "\"" + str_bat_file_path + "\"";
#if (defined(__linux__))
string str_whole_pg_dump_cmd = str_whole_set_pwd + str_bat_cmd + " >> " + str_log_file_path + " 2>&1 \n";
#else
string str_whole_pg_dump_cmd = str_whole_set_pwd + str_bat_cmd + "\n";
#endif
IVMS_LOG_INFO("platform.Maintenance", "i_total_dump_lines : %d", i_total_dump_lines);
if (DRIVE_CLONE_RESTORE_SUCC != AcquireCommandStatus(str_log_file_path, str_whole_pg_dump_cmd, i_total_dump_lines, conf_run))//执行命令,需要修改,兼容进度条
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUP_CONFIG_ERROR)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecPGDumpProgress AcquireCommandStatus Failed");
boost::system::error_code ec;
boost::filesystem::remove(str_bat_file_path, ec);
boost::filesystem::remove(str_log_file_path, ec);
return DRIVE_CLONE_RESTORE_FAIL;
}
// 删除备份命令和还原文件夹,还原正式结束
boost::system::error_code ec;
boost::filesystem::remove(str_bat_file_path, ec);
boost::filesystem::remove(str_log_file_path, ec);
//i_sys_dump_percent_batch_++;
}
if (!ptr_connect->Commit())
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecPGDumpProgress snapshot commit failed");
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUP_CONFIG_ERROR)));
return DRIVE_CLONE_RESTORE_FAIL;
}
return DRIVE_CLONE_RESTORE_SUCC;
}
UINT_T CTimerBackup::ExecSQLiteDumpProgress(const string & root_db_path, const map<string,string>& v_bak_db, const UINT_T & conf_run)
{
// 获取db文件路径 -- eg. C:\Program Files (x86)\HikCentral\VSM Servers\PGData
string storage_xml = CConfigPathManager::Instance().GetStorageXmlPath();
if (!boost::filesystem::exists(storage_xml))
{
IVMS_LOG_ERROR("platform.Maintenance", "Storage.xml not exist, path : %s", storage_xml.c_str());
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUP_CONFIG_ERROR)));
return DRIVE_CLONE_RESTORE_FAIL;
}
string storage_buf;
if (!CFileBak::ReadFile(storage_buf, storage_xml))
{
IVMS_LOG_ERROR("platform.Maintenance", "Read Storage.xml fail, path = %s", storage_xml.c_str());
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUP_CONFIG_ERROR)));
return DRIVE_CLONE_RESTORE_FAIL;
}
unique_ptr<proto::IProto> pro_result(new proto::CXmlProto);
pro_result->set_str(storage_buf);
string db_path = pro_result->get_v("/StoragePath/DatabaseData/SQLiteDataPath"); // 待备份的db路径
if (db_path.empty())
{
IVMS_LOG_ERROR("platform.Maintenance", "/StoragePath/DatabaseData/Path is empty, path = %s", storage_xml.c_str());
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUP_CONFIG_ERROR)));
return DRIVE_CLONE_RESTORE_FAIL;
}
IVMS_LOG_DEBUG("platform.Maintenance", "db path is :%s.", db_path.c_str());
i_percent_vol = 0;
boost::system::error_code ec;
for (auto m_singal_db : v_bak_db)
{
// 重试3次,sleep 5s
if (!db_layer::DBLayer_CheckPoint(m_singal_db.first))
{
IVMS_LOG_ERROR("platform.Maintenance", "db - %s, failed to check_point.", m_singal_db.first.c_str());
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUP_CONFIG_ERROR)));
return DRIVE_CLONE_RESTORE_FAIL;
}
// 存储归档名如 platform.db
string str_dump_cmd = "copy \"" + db_path + "\\" + m_singal_db.second + "\" \"" + root_db_path + "\""; // eg. copy "C:\Program Files (x86)\HikCentral\VSM Servers\PGData\platfrom.db" "C:\Program Files (x86)\HikCentral\VSM Servers\SYS\Backup"
string backup_file = db_path + "\\" + m_singal_db.second;
string restore_file = root_db_path + "\\" + m_singal_db.second;
//string strPathTo = Bee::Base::FileUtil::GetCurExeDirUtf8() + g_config_dir + g_defaulthttpscertfilename;
boost::filesystem::copy_file(backup_file, restore_file, boost::filesystem::copy_option::overwrite_if_exists, ec);
if (ec.value() != 0)
{
IVMS_LOG_ERROR("platform.Maintenance", "copy backup file fail. error message = %s, backup_file : %s, restore_file : %s.", ec.message().c_str(), backup_file.c_str(), restore_file.c_str());
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_FILE_NOPERMISSION)));
//Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUP_CONFIG_ERROR)));
return DRIVE_CLONE_RESTORE_FAIL;
}
// 路径判断一下在备份
// 存储归档名如 platform.db-shm
backup_file = db_path + "\\" + m_singal_db.second + "-shm";
restore_file = root_db_path + "\\" + m_singal_db.second + "-shm";
boost::filesystem::copy_file(backup_file, restore_file, boost::filesystem::copy_option::overwrite_if_exists, ec);
if (ec.value() != 0)
{
IVMS_LOG_WARN("platform.Maintenance", "copy backup file fail. error message = %s, backup_file : %s, restore_file : %s.", ec.message().c_str(), backup_file.c_str(), restore_file.c_str());
}
// 存储归档名如 platform.db-wal
backup_file = db_path + "\\" + m_singal_db.second + "-wal";
restore_file = root_db_path + "\\" + m_singal_db.second + "-wal";
boost::filesystem::copy_file(backup_file, restore_file, boost::filesystem::copy_option::overwrite_if_exists, ec);
if (ec.value() != 0)
{
IVMS_LOG_WARN("platform.Maintenance", "copy backup file fail. error message = %s, backup_file : %s, restore_file : %s.", ec.message().c_str(), backup_file.c_str(), restore_file.c_str());
}
// 添加执行日志
IVMS_LOG_INFO("platform.Maintenance", "CTimerBackup::ExecSQLiteDumpProgress DUMP CMD : %s", str_dump_cmd.c_str());
// 创建BAT文件路径
//string backup_plugin = m_singal_db.second;
// string str_bat_file_path = root_db_path + "\\VSM_DB - Config.bat";
string str_log_file_path/* = root_db_path + "\\VSM_DB - Config.bat.log"*/;
// 将命令中备份次数进行记录
backup_vec_table_num_ += 1;
IVMS_LOG_INFO("platform.Maintenance", "backup_db_num_ is : %d", backup_vec_table_num_);
//创建并写入文件
// HPR_HANDLE hpr_handle = HPR_OpenFile(str_bat_file_path.c_str(), HPR_READ | HPR_WRITE | HPR_CREATE | HPR_APPEND, HPR_ATTR_WRITE);
// if (hpr_handle != HPR_INVALID_FILE)
// {
// HPR_UINT32 write_data_length;
// char* pSQL_Buffer = new char[str_dump_cmd.length() + 1];
// if (NULL != pSQL_Buffer)
// {
// memcpy_s(pSQL_Buffer, str_dump_cmd.length(), str_dump_cmd.c_str(), str_dump_cmd.length());
// if (HPR_ERROR == HPR_WriteFile(hpr_handle, pSQL_Buffer, static_cast<HPR_UINT32>(str_dump_cmd.length()), &write_data_length))
// {
// IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecPGDumpProgress DUMP Can NOT Write BAT File.");
// HPR_CloseFile(hpr_handle);
// delete[] pSQL_Buffer;
//
// return DRIVE_CLONE_RESTORE_FAIL;
// }
// }
//
// delete[] pSQL_Buffer;
// HPR_CloseFile(hpr_handle);
// }
// else
// {
// IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecSQLiteDumpProgress DUMP Can NOT Write BAT File.");
// HPR_CloseFile(hpr_handle);
//
// return DRIVE_CLONE_RESTORE_FAIL;
// }
#if (defined(__linux__))
std::string chmod_bat = "chmod 777 " + str_bat_file_path;
std::system(chmod_bat.c_str());
#endif
// 根据输出行数判断备份进程
UINT_T i_total_dump_lines = 0;
// notes:备份配置型数据,备份的db数量
//i_total_dump_lines = DEF_PREPARE_INFO_ROWS + (UINT_T)v_bak_tables.size() * DEF_BAK_INFO_ROWS;
i_total_dump_lines = (UINT_T)v_bak_db.size();
//string str_bat_cmd = "\"" + str_bat_file_path + "\"";
#if (defined(__linux__))
string str_whole_pg_dump_cmd = str_whole_set_pwd + str_bat_cmd + " >> " + str_log_file_path + " 2>&1 \n";
#else
string str_whole_pg_dump_cmd/* = str_bat_cmd + "\n"*/;
#endif
IVMS_LOG_INFO("platform.Maintenance", "i_total_dump_lines : %d", i_total_dump_lines);
if (DRIVE_CLONE_RESTORE_SUCC != AcquireCommandStatus(str_log_file_path, str_whole_pg_dump_cmd, i_total_dump_lines, conf_run))//执行命令,需要修改,兼容进度条
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUP_CONFIG_ERROR)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecPGDumpProgress AcquireCommandStatus Failed");
// boost::system::error_code ec;
// boost::filesystem::remove(str_bat_file_path, ec);
// boost::filesystem::remove(str_log_file_path, ec);
return DRIVE_CLONE_RESTORE_FAIL;
}
// 删除备份命令和还原文件夹,还原正式结束
// boost::system::error_code ec;
// boost::filesystem::remove(str_bat_file_path, ec);
// boost::filesystem::remove(str_log_file_path, ec);
}
return DRIVE_CLONE_RESTORE_SUCC;
}
UINT_T CTimerBackup::RSM_ExecPGDumpProgress(const string &str_whole_file_path1, const vector<string> &v_bak_tables1)
{
backup_site_table_num_ = 0;
// 拼装pg_dump命令语句
string str_pg_dump_exe_path = PostgreSQL_path_ + PostgreSQL_backup_exe;
boost::system::error_code err_c;
if (!boost::filesystem::exists(str_pg_dump_exe_path, err_c))
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUP_CONFIG_ERROR)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::RSM_ExecPGDumpProgress pg_dump.exe did NOT exists");
return DRIVE_CLONE_RESTORE_FAIL;
}
// 获取数据库连接密码
char* str_set_pwd = "SET PGPASSWORD=%s\n";
LocalDBInfo curr_db_info;
CLocalConfigManager::Instance().GetLocationDBInfo(curr_db_info);
string str_whole_set_pwd = str_fmt(str_set_pwd, curr_db_info.db_passwd.c_str());
// 备份表列表
vector<BackupCategoryInfo::table_info> v_bak_tmp;
vector<BackupCategoryInfo::table_info> v_bak_tables;
//CBackupConfigManager::Instance().GetCategoryContainTables(v_bak_tables, 0);
// 检测一下是否包含了所有默认配置数据
map<int32_t, BackupCategoryInfo> m_default_bak;
CMaintenanceManager::Instance().GetValidDefaultBackupCategory(m_default_bak);
for (auto& elem : m_default_bak)
{
CBackupConfigManager::Instance().GetCategoryContainTables(v_bak_tables, elem.first);
}
v_bak_tmp.assign(v_bak_tables.begin(), v_bak_tables.end());
random_shuffle(v_bak_tmp.begin(), v_bak_tmp.end());
// 站点记录备份数据文件
int index = 0;
map<string, int> backup_schema; //备份文件中的数据模式
map<string, string> backup_vername; //备份文件中的数据模式名称及版本
multimap<string, string> full_table_name; //备份文件中的表 <模式名,表名>
for (auto it : v_bak_tables)
{
backup_schema.insert(pair<string, int>(it.schema_name, index));
// 将表名进行记录
full_table_name.insert(pair<string, string>(it.schema_name, it.table_name));
index++;
}
if (backup_schema.empty())
{
IVMS_LOG_ERROR("platform.Maintenance", "Database schema is Empty!");
return DRIVE_CLONE_RESTORE_FAIL;
}
// 获取备份文件中的数据模式和版本
if (!QueryBackupSchemaAndVersion(backup_schema, backup_vername))
{
IVMS_LOG_ERROR("platform.Maintenance", "Failed to Get schema and version in backup file");
return DRIVE_CLONE_RESTORE_FAIL;
}
if (backup_vername.empty())
{
IVMS_LOG_ERROR("platform.Maintenance", "FAILED obtain schema version");
return DRIVE_CLONE_RESTORE_FAIL;
}
// 存在分表的主表名
vector<BackupCategoryInfo::table_info> v_main_table;
CBackupConfigManager::Instance().SendMainTableInfo(v_main_table);
// 将备份文件中的数据模式和版本记录在BackupInfo.xml中
if (!RecordBackupTableInfo(backup_vername, full_table_name, v_main_table))
{
IVMS_LOG_ERROR("platform.Maintenance", "Failed to write to BackupInfo.xml");
return DRIVE_CLONE_RESTORE_FAIL;
}
// notes:HCP2.5.1做升级前的校验用
// if (!BackupStatus(RUN_DRIVE_CLONE))
// {
// IVMS_LOG_ERROR("platform.Maintenance", "Backup RUN Status record failed.");
// return DRIVE_CLONE_RESTORE_FAIL;
// }
// 将BackupInfo.xml拷贝记录文件中
IVMS_LOG_INFO("platform.Maintenance", "Start copy BackupInfo.xml");
int des_pos = str_whole_file_path1.find("VSM_DB-Config");
string des_path = str_whole_file_path1.substr(0, des_pos);
// boost::system::error_code err_c;
namespace ns_fs = boost::filesystem;
string src_backup_info = CConfigPathManager::Instance().GetBackupInfoPath();
string target_backup_info = des_path + "BackupInfo.xml";
if (ns_fs::exists(src_backup_info))
{
boost::filesystem::copy_file(src_backup_info, target_backup_info, boost::filesystem::copy_option::overwrite_if_exists, err_c);
if (err_c.value() != 0)
{
IVMS_LOG_ERROR("platform.Maintenance", "copy BackupInfo.xml file failed! The source file is %s, the target file is %s", src_backup_info.c_str(), target_backup_info.c_str());
return DRIVE_CLONE_RESTORE_FAIL;
}
IVMS_LOG_INFO("platform.Maintenance", "copy BackupInfo.xml file SUCC, path is %s", target_backup_info.c_str());
}
// 备份命令拆分一下,主要为了判断命令总长度,windows命令行长度不能超过4096
string str_dump_cmd_0 = str_fmt("\"%s\" --host 127.0.0.1 --port %d --username postgres --dbname cms ",
str_pg_dump_exe_path.c_str(), (unsigned short)postgre_port_);
vector<BackupCategoryInfo::table_info>::const_iterator it = v_bak_tmp.begin();
int flag = 0;
//i_sys_dump_percent_batch_ = 1;
//i_sys_dump_percent_batch_total_ = (v_bak_tmp.size() % 10) == 0 ? v_bak_tmp.size() / 10 : v_bak_tmp.size() / 10 + 1;
i_percent_vol = 0;
while (it != v_bak_tmp.end())
{
// 存储归档名bak1,bak2
flag++;
string str_whole_file_path = str_whole_file_path1 + to_string(flag);
string str_dump_cmd_1 = str_fmt(" --format custom --verbose -c -E utf8 --file \"%s\"\n",
str_whole_file_path.c_str());
int n = 0;
string str_backup_table;
string str_real_backup_table;
for (; it != v_bak_tmp.end(); it++)
{
// 拼装命令,-t参数增加序列
str_backup_table += " -t " + it->schema_name + "." + it->table_name + "*_seq" + " -t " + it->schema_name + "." + it->table_name;
n++;
if (!(it->vec_view.empty()))
{
for (auto& view : it->vec_view)
{
str_backup_table += " -t " + view;
}
}
// 判断下命令长度
if (str_dump_cmd_0.size() + str_dump_cmd_1.size() + str_backup_table.size() > DEF_WIN_CMD_MAX_LENTH)
{
string log_cmd = str_dump_cmd_0 + str_backup_table + str_dump_cmd_1;
// 假如只加一个表就会超命令行长度,肯定是有问题了,这个时候返回异常
if (str_real_backup_table.empty())
{
IVMS_LOG_ERROR("platform.Maintenance", "cmd lenth error size=%d cmd=%s",
log_cmd.size(), log_cmd.c_str());
return DRIVE_CLONE_RESTORE_FAIL;
}
// 当前的表并没被加进去,所以不需要it++
IVMS_LOG_WARN("platform.Maintenance", "cmd lenth oversize size=%d cmd=%s",
log_cmd.size(), log_cmd.c_str());
break;
}
str_real_backup_table = str_backup_table;
if (n == 10)
{
it++;
break;
}
}
backup_site_table_num_ += n;
IVMS_LOG_INFO("platform.Maintenance", "backup_site_table_num_ is : %d", backup_site_table_num_);
string str_dump_cmd = str_dump_cmd_0 + str_real_backup_table + str_dump_cmd_1;
string str_whole_pg_dump_cmd = str_whole_set_pwd + str_dump_cmd;
// 添加执行日志
IVMS_LOG_INFO("platform.Maintenance", "CTimerBackup::ExecPGDumpProgress RSM DUMP CMD : %s", str_dump_cmd.c_str());
// 根据输出行数判断备份进程
// notes:修改为表的数量
//UINT_T i_total_dump_lines = DEF_PREPARE_INFO_ROWS + (UINT_T)v_bak_tables.size() * DEF_BAK_INFO_ROWS;
UINT_T i_total_dump_lines = (UINT_T)v_bak_tables.size();
if (DRIVE_CLONE_RESTORE_SUCC != AcquireCommandStatus("", str_whole_pg_dump_cmd, i_total_dump_lines, DEF_RSMBAK))
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUP_CONFIG_ERROR)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::RSM_ExecPGDumpProgress AcquireCommandStatus Failed");
return DRIVE_CLONE_RESTORE_FAIL;
}
//i_sys_dump_percent_batch_++;
}
//i_sys_dump_percent_batch_ = 1;
return DRIVE_CLONE_RESTORE_SUCC;
}
UINT_T CTimerBackup::RSM_ExecPGDumpProgress(const string & str_whole_file_path1)
{
vector<BackupCategoryInfo::table_info> v_bak_tmp;
vector<BackupCategoryInfo::table_info> v_bak_tables;
vector<string> v_http_bodys;
// 检测一下是否包含了所有默认配置数据
map<int32_t, BackupCategoryInfo> m_default_bak;
CMaintenanceManager::Instance().GetValidDefaultBackupCategory(m_default_bak);
for (auto& elem : m_default_bak)
{
CBackupConfigManager::Instance().GetCategoryContainTables(v_bak_tables, elem.first);
}
v_bak_tmp.assign(v_bak_tables.begin(), v_bak_tables.end());
random_shuffle(v_bak_tmp.begin(), v_bak_tmp.end());
namespace ns_fs = boost::filesystem;
ns_fs::path curr_element_path(str_whole_file_path1, (void*)ns_fs::native);
string des_path = curr_element_path.parent_path().string() + "\\";
// 将备份命令组装好,传给DCC执行
vector<BackupCategoryInfo::table_info>::const_iterator it = v_bak_tmp.begin();
int flag = 0;
i_percent_vol = 0;
string bodys;
while (it != v_bak_tmp.end())
{
// 存储归档名bak1,bak2
flag++;
string str_whole_file_path = str_whole_file_path1 + to_string(flag);
string str_dump_cmd_1 = str_fmt(" --format custom --verbose -c -E utf8 --file \"%s\"\n",
str_whole_file_path.c_str());
int n = 0;
string str_backup_table;
string str_real_backup_table;
for (; it != v_bak_tmp.end(); it++)
{
// 拼装命令,-t参数增加序列
str_backup_table += " -t " + it->schema_name + "." + it->table_name + "_*_seq" + " -t " + it->schema_name + "." + it->table_name;
n++;
if (!(it->vec_view.empty()))
{
for (auto& view : it->vec_view)
{
str_backup_table += " -t " + view;
}
}
str_real_backup_table = str_backup_table;
if (n == 9)
{
it++;
break;
}
}
if (!bodys.empty())
{
bodys += Bee::Base::StringUtil::str_fmt(",{\"TabInfo\":\"%s\"}", str_real_backup_table.c_str());
}
else
{
bodys = Bee::Base::StringUtil::str_fmt("{\"TabInfo\":\"%s\"}", str_real_backup_table.c_str());
}
}
b_is_site_dump_percent_ = 1;
CBackupConfigManager::DistributeBackupInfo backup_info;
backup_info.https_url = "/ISAPI/Bumblebee/DCC/V0/RSMBackup";
backup_info.https_bodys = Bee::Base::StringUtil::str_fmt(R"({"DatabaseBackupRestore":{"Assemble":[%s]}})", bodys.c_str());
IVMS_LOG_INFO("platform.Maintenance", "https_url[%s], https_bodys[%s]", backup_info.https_url.c_str(), backup_info.https_bodys.c_str());
IVMS_LOG_INFO("platform.Maintenance", "b_is_site_dump_percent_[%d]", b_is_site_dump_percent_.load());
if (!CBackupConfigManager::Instance().IncreBackupRestore(backup_info))
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::InitialMgr IncreBackupRestore failed");
i_sys_dump_percent_ = 100;
i_dump_sum_ = 100;
b_is_dump_running_ = false;
b_is_site_dump_running_ = false;
b_is_site_dump_percent_ = 100;
cs_backup_fail_flag_ = false;
return DRIVE_CLONE_RESTORE_FAIL;
}
CThreadManager::Instance().PostTask(string(__FUNCTION__) + "[GetClusterBackupResoreStatus]",
std::bind(&CTimerBackup::GetClusterBackupResoreStatus, this, DEF_RSMBAK));
while (1)
{
if (b_is_site_dump_percent_ == 90)
{
break;
}
else if (b_is_site_dump_percent_ > 90)
{
return DRIVE_CLONE_RESTORE_FAIL;
}
Sleep(3000);
}
IVMS_LOG_INFO("platform.Maintenance", "b_is_site_dump_percent_[%d]", b_is_site_dump_percent_.load());
string whole_file_path1 = Bee::Base::StringUtil::StringReplace(str_whole_file_path1.c_str(), "\\", "/");
CBackupConfigManager::DistributeBackupInfo rsm_backup_info;
rsm_backup_info.https_url = "/ISAPI/Bumblebee/DCC/V0/RSMBackupFileUpLoad";
rsm_backup_info.https_bodys = Bee::Base::StringUtil::str_fmt(R"({"DatabaseRestore":{"SavePath":"%s"}})", whole_file_path1.c_str());
IVMS_LOG_INFO("platform.Maintenance", "https_url[%s], https_bodys[%s].", rsm_backup_info.https_url.c_str(), rsm_backup_info.https_bodys.c_str());
if (!CBackupConfigManager::Instance().IncreBackupRestore(rsm_backup_info))
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_RESTORE_FAIL)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecuteDataRestoreOpt Execute Restore Failed.");
i_sys_dump_percent_ = 100;
i_dump_sum_ = 100;
b_is_dump_running_ = false;
b_is_site_dump_running_ = false;
b_is_site_dump_percent_ = 100;
cs_backup_fail_flag_ = false;
return DRIVE_CLONE_RESTORE_FAIL;
}
// C:\Program Files (x86)\HikCentral\VSM Servers\SYS\RSM_Backup//
string str_response = CBackupConfigManager::Instance().GetRsmBackupFileZip();
string host_save_path = des_path + "VSM_" + g_soft_version + "_BAK-0.zip";
//将数据写到文件
ofstream f;
f.open(host_save_path.c_str(), ios::out | ios::binary);
if (!f.is_open())
{
i_sys_dump_percent_ = 100;
i_dump_sum_ = 100;
b_is_dump_running_ = false;
b_is_site_dump_running_ = false;
b_is_site_dump_percent_ = 100;
cs_backup_fail_flag_ = false;
m_site_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
return DRIVE_CLONE_RESTORE_FAIL;
}
else
{
f.write(str_response.c_str(), str_response.length());
f.close();
}
b_is_site_dump_running_ = false;
b_is_site_dump_percent_ = 100;
return DRIVE_CLONE_RESTORE_SUCC;
}
// 数据库备份信息更新
UINT_T CTimerBackup::RenewalDriveCloneInfo(const DriveCloneRecordsInfo &bak_info, const string &str_create_time)
{
if (!BackupRecordSession::InsertBackupRecord(bak_info, str_create_time))
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_OPERATION_FAIL)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::RenewalDriveCloneInfo FAILED");
m_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
return DRIVE_CLONE_RESTORE_FAIL;
}
std::lock_guard<mutex> lock(dc_bak_conf_mutex_);
if (!EnsureMaxRecordCount(dc_bak_conf_Plan_.i_clone_file_limit, bak_info.site_guid))
{
//Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_BACKUP_FAIL)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::EnsureMaxRecordCount[3] FAILED");
m_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
return DRIVE_CLONE_RESTORE_FAIL;
}
//// 记录系统日志
//SystemLogStruct struSystemLog;
//struSystemLog.enumLogType = SystemLogStruct::LogType::DatabaseBackupSucceed;
//struSystemLog.tmOccur = time(0);
//CLogManager::Instance().AddSystemLog(struSystemLog);
return DRIVE_CLONE_RESTORE_SUCC;
}
bool CTimerBackup::UpdataBackupInfo(const DriveCloneRecordsInfo &bak_info)
{
if (!BackupRecordSession::InsertBackupLoadRecord(bak_info, g_soft_version))
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::UpdataBackupInfo already existed %s", bak_info.bak_file_path.c_str());
return false;
}
return true;
}
// 设置备份计划相关信息
void CTimerBackup::SetupDriveClonePlanInfo(const DriveCloneConf &data_clone_conf)
{
std::lock_guard<mutex> lock(dc_bak_conf_mutex_);
dc_bak_conf_Plan_ = data_clone_conf;
}
// HCP单机/异机还原备份文件
UINT_T CTimerBackup::ExecuteDataRestoreOpt(const string& str_whole_file_path, const string& str_ads_whole_file_path, const string &str_data_types, const map<string, string> &plugin_info)
{
string str_uncomp_file_path;
string str_zip_path = "";
if (!is_start_restore_)
{
restore_bak_num_ = 10;
}
map_restore_table_.clear();
if (b_is_diff_machine)
{
IVMS_LOG_INFO("platform.Maintenance", "CTimerBackup::ExecuteDataRestoreOpt Diff Start!");
b_recvRestoreResult_ = false;
i_recvRestoreResult_ = -1;
str_uncomp_file_path = str_whole_file_path;
str_zip_path = "";
//std::string str_whole_file_path = str_uncomp_file_path;
string str_pg_restore_exe_path = PostgreSQL_path_ + PostgreSQL_restore_exe;
LocalDBInfo curr_db_info;
CLocalConfigManager::Instance().GetLocationDBInfo(curr_db_info);
char* str_set_pwd = "set PGPASSWORD=%s\n";
string str_whole_set_pwd = str_fmt(str_set_pwd, curr_db_info.db_passwd.c_str());
string str_restore_cmd_fmt = "\"%s\" --host 127.0.0.1 --port %d --username postgres --format custom --verbose -c --dbname cms \"%s\"\n";
string str_restore_cmd = str_fmt(str_restore_cmd_fmt.c_str(), str_pg_restore_exe_path.c_str(), (unsigned short)curr_db_info.db_port, str_whole_file_path.c_str());
string str_whole_pg_restore_cmd = str_whole_set_pwd + str_restore_cmd;
// 获取备份表列表
vector<string> v_bak_tables;
if (CombingDBCloneTables(v_bak_tables, str_data_types, is_distributed_) != 0)
{
// 日志打印
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_RESTORE_FAIL)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::DetermineDiskCloneVolume CombingDBCloneTables FAILED");
// 失败停止数据库还原,暂不考虑图片还原情况
m_res_error_ = DRIVE_CLONE_RESTORE_FAIL;
i_sys_restore_percent_ = 100;
i_restore_sum_ = 100;
if (i_sys_restore_percent_ == 100) // && i_sys_pic_res_percent_ == 100
{
// 图片与数据库均完成还原
b_is_restore_running_ = false;
}
return DRIVE_CLONE_RESTORE_FAIL;
}
int iBakCountTables = v_bak_tables.size();
string strPort = Bee::Base::StringUtil::T2String<unsigned short>(curr_db_info.db_port);
str_whole_set_pwd = str_whole_set_pwd + ";" + g_soft_version + ";" + strPort;
shared_ptr<proto::IProto> parse = make_shared<proto::CRapidJsonProto>();
string strGuid = Bee::Base::GuidUtil::CreateGuid();
parse->set_v("/Guid", strGuid);
parse->set_v("/RequestData/Method", "ExecuteDataRestoreOpt");
parse->set_v("/RequestData/Data/PgrestoreCmd", str_whole_set_pwd);
parse->set_v("/RequestData/Data/WholeFilePath", str_uncomp_file_path);
parse->set_v("/RequestData/Data/BackTablesCount", iBakCountTables);
// 把本地的module_version_status的信息放在方法里
void* ptr_data_node = parse->get_node("/RequestData/Data");
for (auto it_schema_info : plugin_info)
{
void* ptr_table = parse->add_list_v(ptr_data_node, "RestoreInfo", "");//LCL
parse->add_v(ptr_table, "SchemaName", it_schema_info.first);
parse->add_v(ptr_table, "SchemaVersion", it_schema_info.second);
}
string strReq = parse->get_str();
CBeeAgentClientManager::Instance().SendMsg(iBeeAgentClientId, strReq, Bee::Net::WebSocket::TEXT);
//给10秒的超时时间,没有返回错误码,表示没有出错,正在还原
time_t startTime;
time_t endTime;
double diffStartEndTime;
time(&startTime);
while (true)
{
if (b_recvRestoreResult_)
{
if (0 != i_recvRestoreResult_)
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(i_recvRestoreResult_)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::Thread_ExecRestoreProgress_DB Diff FAILED Result %d", i_recvRestoreResult_);
m_res_error_ = DRIVE_CLONE_RESTORE_FAIL;
b_recvRestoreResult_ = false;
return DRIVE_CLONE_RESTORE_FAIL;
}
else
{
b_recvRestoreResult_ = false;
return DRIVE_CLONE_RESTORE_SUCC;
}
}
time(&endTime);
diffStartEndTime = difftime(endTime, startTime);
if (diffStartEndTime > 10)
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::Thread_ExecRestoreProgress_DB Diff FAILED,BeeAgent ReBackPackage TimeOut");
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BEEAGENT_TIMEOUT)));
b_recvRestoreResult_ = false;
return DRIVE_CLONE_RESTORE_FAIL;
}
}
return DRIVE_CLONE_RESTORE_SUCC;
}
if (!b_is_diff_machine)
{
if (b_is_restore_running_ || b_is_dump_running_)
{
// 日志打印
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_IS_BACKUPING_RESTORING)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecuteDataRestoreOpt Is Backuping or Restoring Now, Repeat CMDs");
return DRIVE_CLONE_RESTORE_FAIL;
}
string fmt_whole_file_path = UTF82Local(str_whole_file_path);
IVMS_LOG_INFO("platform.Maintenance", "CTimerBackup::ExecuteDataRestoreOpt Restore Path is %s", fmt_whole_file_path.c_str());
b_is_restore_running_ = true;
i_sys_restore_percent_ = 0;
i_restore_sum_ = 0;
// i_sys_pic_res_percent_ = 0;
// has_dump_pic_bak_ = false;
m_res_error_ = DRIVE_CLONE_RESTORE_SUCC;
boost::system::error_code err_c;
size_t path_pos = fmt_whole_file_path.find_last_of("/\\");
str_uncomp_file_path = fmt_whole_file_path.substr(0, path_pos) + "/Restore";
// 清空之前存在的解压缩文件
VacuumPath(str_uncomp_file_path);
// 获取zip完整路径
namespace ns_fs = boost::filesystem;
string str_pic_path = "";
ns_fs::path curr_element_path(fmt_whole_file_path, (void*)ns_fs::native);
if (ns_fs::exists(curr_element_path, err_c))
{
ns_fs::directory_iterator it_begin(curr_element_path);
ns_fs::directory_iterator it_end;
for (; it_begin != it_end; it_begin++)
{
// 判断zip包是否存在
if (ns_fs::is_regular_file(*it_begin))
{
string strBackUpFileName = it_begin->path().string();
size_t p_index = strBackUpFileName.find_last_of(".");
if (p_index == string::npos)
{
continue;
}
string strFileType = strBackUpFileName.substr(p_index + 1, strBackUpFileName.size() - p_index);
strFileType = CVSMCommonFun::tolower(strFileType);
// 还原时判断一下是否为zip文件或7z文件
if ((strFileType == "zip" || strFileType == "7z") && strBackUpFileName.find("VSM_" + g_soft_version + "_BAK") != string::npos)
{
IVMS_LOG_INFO("platform.Maintenance", "Backup file type is .%s.", strFileType.c_str());
str_zip_path = strBackUpFileName;
}
}
}
}
if (str_zip_path.empty())
{
// 日志打印
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUPFILE_NOT_EXIST)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecuteDataRestoreOpt Can Not Find Zip or VSM_%s_BAK", g_soft_version.c_str());
b_is_restore_running_ = false;
i_sys_restore_percent_ = 100;
i_restore_sum_ = 100;
// i_sys_pic_res_percent_ = 100;
m_res_error_ = DRIVE_CLONE_RESTORE_FAIL;
return DRIVE_CLONE_RESTORE_FAIL;
}
}
{
//开启数据库还原线程
CThreadManager::Instance().PostTask(string(__FUNCTION__) + "[Thread_ExecRestoreProgress_DB]",
std::bind(&CTimerBackup::Thread_ExecRestoreProgress_DB, this, str_zip_path, str_uncomp_file_path, str_data_types));
}
is_start_restore_ = false;
return DRIVE_CLONE_RESTORE_SUCC;
}
//HCL单机还原
UINT_T CTimerBackup::ExecuteDataRestoreOpt(const string & str_whole_file_path)
{
// 首先检查一下zip是否存在
if (!boost::filesystem::exists(str_whole_file_path))
{
// 日志打印
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUPFILE_NOT_EXIST)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecuteDataRestoreOpt Backup file no exists, path : %s.", str_whole_file_path.c_str());
return DRIVE_CLONE_RESTORE_FAIL;
}
int db_status = -1;
if (!CMaintenanceManager::Instance().CheckFitSupportRestore(str_whole_file_path, db_status))
{
IVMS_LOG_ERROR("platform.Maintenance", "Failed to CheckFitSupportRestore.");
return DRIVE_CLONE_RESTORE_FAIL;
}
if (!is_start_restore_)
{
restore_bak_num_ = 1;
}
if (b_is_restore_running_ || b_is_dump_running_)
{
// 日志打印
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_IS_BACKUPING_RESTORING)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecuteDataRestoreOpt Is Backuping or Restoring Now, Repeat CMDs");
return DRIVE_CLONE_RESTORE_FAIL;
}
string fmt_whole_file_path = UTF82Local(str_whole_file_path);
b_is_restore_running_ = true;
i_sys_restore_percent_ = 0;
i_restore_sum_ = 0;
// i_sys_pic_res_percent_ = 0;
// has_dump_pic_bak_ = false;
m_res_error_ = DRIVE_CLONE_RESTORE_SUCC;
boost::system::error_code err_c;
// size_t path_pos = fmt_whole_file_path.find_last_of("/\\");
// str_uncomp_file_path = fmt_whole_file_path.substr(0, path_pos) + "/Restore";
string data_path = CConfigPathManager::Instance().GetSQLiteDataPath();
if (data_path.empty())
{
IVMS_LOG_ERROR("platform.Maintenance", "SQLiteDataPath is empty");
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_IS_BACKUPING_RESTORING)));
m_res_error_ = DRIVE_CLONE_RESTORE_FAIL;
i_sys_restore_percent_ = 100;
i_restore_sum_ = 100;
if (i_sys_restore_percent_ == 100) // && i_sys_pic_res_percent_ == 100
{
// 图片与数据库均完成还原
b_is_restore_running_ = false;
}
return DRIVE_CLONE_RESTORE_SUCC;
}
// 这里直接解压到SQLiteData的同级目录下
string str_uncomp_file_path = data_path + "_temp";
// 清空之前存在的解压缩文件
VacuumPath(str_uncomp_file_path);
IVMS_LOG_INFO("platform.Maintenance", "Have Vacuum path : %s.", str_uncomp_file_path.c_str());
//开启数据库还原线程
CThreadManager::Instance().PostTask(string(__FUNCTION__) + "[Thread_ExecRestoreProgress_DB]",
std::bind(&CTimerBackup::Thread_ExecRestoreProgress_DBSQLite, this, str_whole_file_path, str_uncomp_file_path, db_status));
is_start_restore_ = false;
return DRIVE_CLONE_RESTORE_SUCC;
}
//HCP集群还原
UINT_T CTimerBackup::ExecuteDataRestoreOpt(const string & restore_time, const int & backup_type)
{
if (b_is_restore_running_ || b_is_dump_running_)
{
// 日志打印
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_IS_BACKUPING_RESTORING)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecuteDataRestoreOpt Is Backuping or Restoring Now, Repeat CMDs");
return DRIVE_CLONE_RESTORE_FAIL;
}
b_is_restore_running_ = true;
i_sys_restore_percent_ = 0;
m_res_error_ = DRIVE_CLONE_RESTORE_SUCC;
// 获取当前备份计划,得到保存的备份文件地址
string backup_root_path, backup_plan_path;
int backup_id = -1;
if (!QueryLocalBackupFilePath(backup_root_path, backup_id, backup_type, restore_time, backup_plan_path))
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_OPERATION_FAIL)));
m_res_error_ = DRIVE_CLONE_RESTORE_FAIL;
IVMS_LOG_ERROR("platform.Maintenance", "QueryLocalBackupFilePath Failed.");
b_is_restore_running_ = false;
return DRIVE_CLONE_RESTORE_FAIL;
}
backup_root_path = Bee::Base::StringUtil::StringReplace(backup_root_path.c_str(), "\\", "/");
backup_plan_path = Bee::Base::StringUtil::StringReplace(backup_plan_path.c_str(), "\\", "/");
string postgresql_path = Bee::Base::StringUtil::StringReplace(PostgreSQL_path_.c_str(), "\\", "/");
// 执行还原前通知DCC对特殊表进行处理
CBackupConfigManager::DistributeBackupInfo backup_info;
backup_info.https_url = "/ISAPI/Bumblebee/DCC/V0/BackupSpecial";
backup_info.https_bodys = Bee::Base::StringUtil::str_fmt(R"({"DatabaseRestore":{"BackupFileType":"%s"}})", std::to_string(backup_type).c_str());
IVMS_LOG_INFO("platform.Maintenance", "https_url[%s], https_bodys[%s]", backup_info.https_url.c_str(), backup_info.https_bodys.c_str());
if (!CBackupConfigManager::Instance().IncreBackupRestore(backup_info))
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_RESTORE_FAIL)));
m_res_error_ = DRIVE_CLONE_RESTORE_FAIL;
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecuteDataRestoreOpt BackupSpecial Failed.");
i_sys_restore_percent_ = 100;
b_is_restore_running_ = false;
return DRIVE_CLONE_RESTORE_FAIL;
}
CThreadManager::Instance().PostTask(string(__FUNCTION__) + "[GetClusterBackupResoreStatus]",
std::bind(&CTimerBackup::GetClusterBackupResoreStatus, this, DEF_RESTORE));
restore_info_.backup_id = backup_id;
restore_info_.backup_path = backup_root_path;
restore_info_.backup_type = backup_type;
restore_info_.restore_time = restore_time;
restore_info_.backup_plan_path = backup_plan_path;
return DRIVE_CLONE_RESTORE_SUCC;
}
UINT_T CTimerBackup::ExecuteBackupDownload(const string& strFilePath, const LONG socket_id)
{
// 获取zip完整路径
vector<string> file_list;
boost::system::error_code err_c;
namespace ns_fs = boost::filesystem;
string str_zip_path = "";
string str_pic_path = "";
string strConfigFile;
ns_fs::path curr_element_path(strFilePath, (void*)ns_fs::native);
if (ns_fs::exists(curr_element_path, err_c))
{
ns_fs::directory_iterator it_begin(curr_element_path);
ns_fs::directory_iterator it_end;
for (; it_begin != it_end; it_begin++)
{
// 判断zip包是否存在
if (ns_fs::is_regular_file(*it_begin))
{
string strBackUpFileName = it_begin->path().string();
string strFileName = it_begin->path().parent_path().filename().string();
size_t p_index = strBackUpFileName.find_last_of(".");
if (p_index == string::npos)
{
continue;
}
if (boost::filesystem::exists(strBackUpFileName, err_c))
{
strConfigFile = UTF82Local(strFilePath) + "/BackupConfig.txt";
HPR_HANDLE hpr_handle = HPR_OpenFile(strConfigFile.c_str(), HPR_READ | HPR_WRITE | HPR_CREATE | HPR_APPEND, HPR_ATTR_WRITE);
if (hpr_handle != HPR_INVALID_FILE)
{
HPR_UINT32 write_data_length;
char* pSQL_Buffer = new char[strFileName.length() + 1];
if (NULL != pSQL_Buffer)
{
//memcpy_s(pSQL_Buffer, strFileName.length(), strFileName.c_str(), strFileName.length());
HPR_MEMCPY_S(pSQL_Buffer, strFileName.length(), strFileName.c_str(), strFileName.length());
if (HPR_ERROR == HPR_WriteFile(hpr_handle, pSQL_Buffer, static_cast<HPR_UINT32>(strFileName.length()), &write_data_length))
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecuteBackupDownload Error.");
HPR_CloseFile(hpr_handle);
delete[] pSQL_Buffer;
return DRIVE_CLONE_RESTORE_FAIL;
}
}
file_list.push_back(strConfigFile);
delete[] pSQL_Buffer;
HPR_CloseFile(hpr_handle);
}
else
{
HPR_CloseFile(hpr_handle);
int iError = HPR_GetSystemLastError();
IVMS_LOG_ERROR("platform.Maintenance", "HPR_OpenFile Error File Path %s! ErrorCode %d", strConfigFile.c_str(),iError);
return DRIVE_CLONE_RESTORE_FAIL;
}
}
string strFileType = strBackUpFileName.substr(p_index + 1, strBackUpFileName.size() - p_index);
if ((strFileType == "zip") && strBackUpFileName.find("VSM_" + g_soft_version + "_BAK") != string::npos)
{
str_zip_path = strBackUpFileName;
file_list.push_back(str_zip_path);
}
}
}
}
if (str_zip_path.empty())
{
// 日志打印
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUPFILE_NOT_EXIST)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecuteDataRestoreOpt Can Not Find Zip or VSM_%s_BAK", g_soft_version.c_str());
return DRIVE_CLONE_RESTORE_FAIL;
}
string strTime;
string str_zip_file_path = strFilePath + "/VSM_DOWNLOAD" + g_soft_version + "_BAK" + ".zip";
if (NoError != Compress::CompressFiles(str_zip_file_path, file_list))
{
boost::system::error_code ec;
boost::filesystem::remove(str_zip_file_path, ec);
IVMS_LOG_ERROR("platform.Maintenance", "CompressFolder FAILED");
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_BACKUP_FAIL)));
}
ifstream read_file(str_zip_file_path.c_str(), ios::binary);
if (read_file.is_open())
{
istream::pos_type current_pos1 = read_file.tellg();//记录下当前位置
read_file.seekg(0, ios_base::end);//移动到文件尾
istream::pos_type file_size1 = read_file.tellg();//取得当前位置的指针长度->即文件长度
read_file.seekg(0, ios_base::beg);//移动到原来的位置
if (file_size1 > 0)
{
char* data1 = new char[file_size1];
//memset(data1, 0, file_size1);
HPR_MEMSET_S(data1, file_size1, 0, file_size1);
read_file.read(data1, file_size1 * sizeof(char));
HttpResponse http_response;
//ServerHttpHead
http_response.content_type = "application/octet-stream";
http_response.send_timeout = 40000;
http_response.file_name = "/VSM_DOWNLOAD" + g_soft_version + "_BAK" + ".zip";
http_response.content_disposition = "attachment";
LONG ret = CHttpServer::HttpServerSyncSend(socket_id, http_response, static_cast<DWORD>(file_size1), data1);
if (0 != ret)
{
IVMS_LOG_ERROR("platform.Maintenance", "[ExportPersonFullInfo] ServerSend error, socket_id = %d,re_value = %d, nReadLen %d",
socket_id, ret, static_cast<int>(file_size1));
}
//删除文件,不然cms中文件会越来越多
read_file.close();
boost::system::error_code ec;
boost::filesystem::remove(str_zip_file_path, ec);
boost::filesystem::remove(strConfigFile, ec);
delete[] data1;
data1 = nullptr;
}
else
{
HttpResponse http_response;
http_response.http_code = ERROR_CODE(CMS_PERSON_DOWNFILE_FAIL);
http_response.send_timeout = 40000;
LONG ret = CHttpServer::HttpServerSyncSend(socket_id, http_response, 0, nullptr);
if (0 != ret)
{
IVMS_LOG_ERROR("platform.PersonCredential", "[ExportPersonFullInfo] ServerSend error, socket_id = %d, error = %d, file[%s]", socket_id, ret, str_zip_path.c_str());
}
}
}
else
{
//返回404错误
HttpResponse http_response;
http_response.http_code = ERROR_CODE(CMS_PERSON_DOWNFILE_FAIL);
http_response.send_timeout = 40000;
LONG ret = CHttpServer::HttpServerSyncSend(socket_id, http_response, 0, nullptr);
if (0 != ret)
{
IVMS_LOG_ERROR("platform.PersonCredential", "[ExportPersonFullInfo] ServerSend error, socketID = %d, strFileName[%s]", socket_id, str_zip_path.c_str());
}
}
return 0;
}
UINT_T CTimerBackup::ExecuteBackupUpload(const string& strFilePath,NetworkCommErrCode& struCode,string strFileName)
{
//解压到restore路径
string strTempPath = dc_bak_conf_Plan_.str_save_file_path + "/Upload";
boost::system::error_code ec;
boost::filesystem::path fullpath(strTempPath, (void*)boost::filesystem::native);
if (!boost::filesystem::exists(fullpath, ec))
{
boost::filesystem::create_directories(fullpath, ec);
}
VacuumPath(strTempPath);
if (CompressExecuteFail == Compress::UnCompress(strFilePath, strTempPath))
{
//解压失败
struCode.iMainCode = ERROR_CODE(CMS_MODULE_CMS);
struCode.iSubCode = ERROR_CODE(CMS_UNCOMPRESS_FILE_FAIL);
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecuteDataRestoreOpt UnCompress() FAILED");
//删除临时文件Upload
boost::filesystem::remove_all(strTempPath, ec);
boost::filesystem::remove_all(strFilePath, ec);
return -1;
}
// 压缩包解压出来的
string strZipFile;
string strConfigFile;
string strZipName;
boost::filesystem::path total_file_path(strTempPath, (void*)boost::filesystem::native);
namespace ns_fs = boost::filesystem;
//boost::system::error_code err_c;
if (ns_fs::exists(total_file_path, ec))
{
boost::filesystem::directory_iterator item_begin(total_file_path);
boost::filesystem::directory_iterator item_end;
for (; item_begin != item_end; item_begin++)
{
if (boost::filesystem::is_regular_file(*item_begin))
{
string bak_file_name = item_begin->path().string();
string strFile = item_begin->path().filename().string();
if (strFile == "BackupConfig.txt")
{
strConfigFile = bak_file_name;
continue;
}
size_t index = bak_file_name.rfind(".");
if (index == string::npos)
{
continue;
}
string file_type = bak_file_name.substr(index + 1, bak_file_name.length() - index);
if ((file_type == "zip") && bak_file_name.find("VSM_" + g_soft_version + "_BAK") != string::npos)
{
strZipFile = bak_file_name;
strZipName = strFile;
}
}
}
}
else
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecuteBackupUpload Error. UpLoad File Format Error!");
struCode.iMainCode = ERROR_CODE(CMS_MODULE_CMS);
struCode.iSubCode = ERROR_CODE(CMS_FILEPATH_NOT_EXIST);
//删除临时文件Upload
boost::filesystem::remove_all(strTempPath, ec);
boost::filesystem::remove_all(strFilePath, ec);
return -1;
}
if (strZipFile.empty() || strZipName.empty() || strConfigFile.empty())
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecuteBackupUpload Error. UpLoad File Format Error!");
struCode.iMainCode = ERROR_CODE(CMS_MODULE_CMS);
struCode.iSubCode = ERROR_CODE(CMS_IMPORT_FILE_FORMAT_ERROR);
//删除临时文件Upload
boost::filesystem::remove_all(strTempPath, ec);
boost::filesystem::remove_all(strFilePath, ec);
return -1;
}
string buff;
if (CFileBak::ReadFile(buff,strConfigFile))
{
string strFullPath = dc_bak_conf_Plan_.str_save_file_path + "/" + buff;
MakeFullPathDir(strFullPath);
//boost::system::error_code ec;
boost::filesystem::copy_file(strZipFile, strFullPath + "/" + strZipName, boost::filesystem::copy_option::overwrite_if_exists, ec);
if (ec.value() != 0)
{
IVMS_LOG_ERROR("platform.Maintenance", "Copy File Fail error message = %s", ec.message().c_str());
}
//删除临时文件Upload
boost::filesystem::remove_all(strTempPath, ec);
boost::filesystem::remove_all(strFilePath, ec);
}
DriveCloneRecordsInfo bak_info;
string strGuid;
size_t time_pos = buff.find_last_of("_");
if (time_pos != std::string::npos)
{
string curr_element_path_str = buff.substr(0, time_pos);
strGuid = buff.substr(time_pos +1, buff.length() - 1);
time_pos = (curr_element_path_str).find_last_of("_");
if (time_pos != std::string::npos)
{
string bak_time = (curr_element_path_str).substr(time_pos + 1, (curr_element_path_str).length());
string bak_time_fmt = bak_time.substr(0, 4) + "-" + bak_time.substr(4, 2) + "-" + bak_time.substr(6, 2) + " " +
bak_time.substr(8, 2) + ":" + bak_time.substr(10, 2) + ":" + bak_time.substr(12, 2);
bak_info.backup_time = Bee::Base::TimeUtil::StrDatetime2TimeT(bak_time_fmt);
}
}
size_t t_index = strZipName.find_last_of("-");
if (t_index == string::npos)
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecuteBackupUpload File Format Error %s!",strZipName.c_str());
struCode.iMainCode = ERROR_CODE(CMS_MODULE_CMS);
struCode.iSubCode = ERROR_CODE(CMS_IMPORT_FILE_FORMAT_ERROR);
return -1;
}
string str_data_type = strZipName.substr(t_index + 1, strZipName.size() - t_index - 5);
string res_str = "_";
string rep_str = ",";
string::size_type pos = 0;
string::size_type res_len = res_str.size();
string::size_type rep_len = rep_str.size();
while ((pos = str_data_type.find(res_str, pos)) != string::npos)
{
str_data_type.replace(pos, res_len, rep_str);
pos += rep_len;
}
bak_info.bak_file_path = dc_bak_conf_Plan_.str_save_file_path + "/" + buff;
bak_info.bak_file_path = StringReplace(bak_info.bak_file_path, "\\", "/");
bak_info.id_site = 0;
bak_info.site_guid = strGuid;
bak_info.bak_form = str_data_type;
bak_info.file_name = strFileName;
UpdataBackupInfo(bak_info);
//if (!UpdataBackupInfo(bak_info))
//{
//IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::UpdataBackupInfo Error!");
//struCode.iMainCode = ERROR_CODE(CMS_MODULE_CMS);
//struCode.iSubCode = ERROR_CODE(CMS_BACKUP_FILEPATH_EXIST);
//return -1;
//}
return 0;
}
void CTimerBackup::Thread_ExecRestoreProgress_DBSQLite(string str_zip_path, string str_uncomp_file_path, int db_status)
{
// str_zip_path:备份的zip路径
// str_uncomp_file_path:解压的路径Restore
boost::system::error_code err_c;
namespace ns_fs = boost::filesystem;
string db_path = CConfigPathManager::Instance().GetSQLiteDataPath();
// 解压到restore路径
IVMS_LOG_INFO("platform.Maintenance", "START UnCompress db_file to %s.", str_zip_path.c_str());
if (CompressExecuteFail == Compress::UnCompress(str_zip_path, str_uncomp_file_path))
{
//解压失败
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::Thread_ExecRestoreProgress_DBSQLite UnCompress() FAILED");
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUPFILE_NOT_EXIST)));
// 失败停止数据库还原,暂不考虑图片还原情况
m_res_error_ = DRIVE_CLONE_RESTORE_FAIL;
i_sys_restore_percent_ = 100;
i_restore_sum_ = 100;
if (i_sys_restore_percent_ == 100) // && i_sys_pic_res_percent_ == 100
{
// 图片与数据库均完成还原
b_is_restore_running_ = false;
}
return;
}
IVMS_LOG_ERROR("platform.Maintenance", "SUCC UnCompress db_file to %s.", str_zip_path.c_str());
i_sys_restore_percent_ = 10;
// 节点不存在,则检查db状态
if (db_status < 0)
{
boost::system::error_code ec;
boost::filesystem::path total_file_path(str_uncomp_file_path, (void*)boost::filesystem::native);
if (ns_fs::exists(total_file_path, err_c))
{
boost::filesystem::directory_iterator item_begin(total_file_path);
boost::filesystem::directory_iterator item_end;
// 遍历restore文件夹下的bak/db文件
for (; item_begin != item_end; item_begin++)
{
if (boost::filesystem::is_regular_file(*item_begin))
{
string bak_file_name = item_begin->path().string(); // C:\Program Files (x86)\HikCentral\VSM Servers\SYS\Backup\Restore\VSM_DB-Config.bak1
IVMS_LOG_INFO("platform.Maintenance", "START check db status, %s.", bak_file_name.c_str());
// 节点不存在,则检查db状态
if (!CheckDBIsNormal(bak_file_name))
{
IVMS_LOG_ERROR("platform.Maintenance", "DB is error, path : %s.", bak_file_name.c_str());
// 增加错误码提示,db文件损坏
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_CONNECT_FAIL)));
m_res_error_ = DRIVE_CLONE_RESTORE_FAIL;
i_sys_restore_percent_ = 100;
i_restore_sum_ = 100;
if (i_sys_restore_percent_ == 100) // && i_sys_pic_res_percent_ == 100
{
// 图片与数据库均完成还原
b_is_restore_running_ = false;
}
return;
}
IVMS_LOG_INFO("platform.Maintenance", "SUCC check db - %s.", bak_file_name.c_str());
}
i_sys_restore_percent_++;
}
}
}
IVMS_LOG_INFO("platform.Maintenance", "START to RemoveDBLayerConn.");
// 还原时不允许操作数据库
if (!CVsmPlatformDBConn::Instance().RemoveDBLayerConn())
{
IVMS_LOG_ERROR("platform.Maintenance", "Failed to RemoveDBLayerConn.");
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_OPERATION_FAIL)));
m_res_error_ = DRIVE_CLONE_RESTORE_FAIL;
i_sys_restore_percent_ = 100;
i_restore_sum_ = 100;
b_is_restore_running_ = false;
return;
}
IVMS_LOG_INFO("platform.Maintenance", "SUCC to RemoveDBLayerConn.");
i_sys_restore_percent_ = 60;
Sleep(3000);
// 尝试将sqlitedata重命名
string db_path_old = db_path + "_old";
bool rename_succ = false;
for (int i = 1; i < 3; i++)
{
boost::filesystem::rename(db_path, db_path_old, err_c);
if (err_c)
{
Sleep(5000);
continue;
}
rename_succ = true;
break;
}
if (!rename_succ)
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DB_FILE_OCCUPY)));
IVMS_LOG_ERROR("platform.Maintenance", "Rename SQLIteData to SQLIteData_old failed. err_info:%s.", err_c.message().c_str());
m_res_error_ = DRIVE_CLONE_RESTORE_FAIL;
i_sys_restore_percent_ = 100;
i_restore_sum_ = 100;
b_is_restore_running_ = false;
return;
}
IVMS_LOG_INFO("platform.Maintenance", "SUCC Rename SQLIteData to SQLIteData_old.");
i_sys_restore_percent_ = 80;
// 将压缩文件直接重命名为sqlitedata
boost::filesystem::rename(str_uncomp_file_path, db_path, err_c);
i_sys_restore_percent_ = 85;
// 返回失败也不影响,只是层处理保护
if (CVsmPlatformDBConn::Instance().SingleConnApply())
{
string sql = "delete from platform.license_active_code_info;";
if (!CVsmPlatformDBConn::Instance().Execute(sql))
{
IVMS_LOG_WARN("platform.Maintenance", "Failed to excute sql : %s.", sql.c_str());
}
else
{
sql = "delete from platform.license_active_info;";
if (!CVsmPlatformDBConn::Instance().Execute(sql))
{
IVMS_LOG_WARN("platform.Maintenance", "Failed to excute sql : %s.", sql.c_str());
}
}
sql = "delete from platform.file_digest;";
if (!CVsmPlatformDBConn::Instance().Execute(sql))
{
IVMS_LOG_WARN("platform.Maintenance", "Failed to excute sql : %s.", sql.c_str());
}
}
else
{
IVMS_LOG_WARN("platform.Maintenance", "Special processing action after data Restore failed");
}
i_sys_restore_percent_ = 90;
// 删除源文件
IVMS_LOG_INFO("platform.Maintenance", "START remove SQLIteData_old.");
boost::filesystem::path remove_old_data(db_path_old);
boost::filesystem::remove_all(remove_old_data, err_c);
i_sys_restore_percent_ = 100;
i_restore_sum_ = 100;
IVMS_LOG_INFO("platform.Maintenance", "TEST Time : Thread_ExecRestoreProgress_DBSQLite Progress 100");
std::lock_guard<mutex> lock(mtx_finished_);
b_is_restore_running_ = false;
}
UINT_T CTimerBackup::AcquireCommandStatus(const string& log_file_path, string str_whole_cmd, UINT_T i_total_ts, const UINT_T &command_type)
{
#if (defined(_WIN32) || defined(_WIN32_WCE) || defined(_WIN64))
HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup, hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup, hStdout;
SECURITY_ATTRIBUTES saAttr;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
if (!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::AcquireCommandStatus CreatePipe FAILED");
return DRIVE_CLONE_RESTORE_FAIL;
}
if (!DuplicateHandle(GetCurrentProcess(), hChildStdoutRd, GetCurrentProcess(), &hChildStdoutRdDup, 0, FALSE, DUPLICATE_SAME_ACCESS))
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::AcquireCommandStatus DuplicateHandle FAILED");
CloseHandle(hChildStdoutRd);
CloseHandle(hChildStdoutWr);
return DRIVE_CLONE_RESTORE_FAIL;
}
CloseHandle(hChildStdoutRd);
if (!CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::AcquireCommandStatus CreatePipe FAILED");
CloseHandle(hChildStdoutWr);
return DRIVE_CLONE_RESTORE_FAIL;
}
if (!DuplicateHandle(GetCurrentProcess(), hChildStdinWr, GetCurrentProcess(), &hChildStdinWrDup, 0, FALSE, DUPLICATE_SAME_ACCESS))
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::AcquireCommandStatus DuplicateHandle FAILED");
CloseHandle(hChildStdoutWr);
CloseHandle(hChildStdinRd);
CloseHandle(hChildStdinWr);
return DRIVE_CLONE_RESTORE_FAIL;
}
CloseHandle(hChildStdinWr);
#ifndef HCL_CODE
// sqlite与pg相同无需重新定义函数
if (BACKUPRESTORE_CreateProcess_CMD(hChildStdoutWr, hChildStdinRd) != 0)
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::AcquireCommandStatus BACKUPRESTORE_CreateProcess_CMD FAILED");
CloseHandle(hChildStdoutWr);
CloseHandle(hChildStdinRd);
return DRIVE_CLONE_RESTORE_FAIL;
}
#endif // !1
if (BACKUPRESTORE_WriteToPipe(hChildStdinWrDup, str_whole_cmd) != 0)
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::AcquireCommandStatus BACKUPRESTORE_WriteToPipe FAILED");
CloseHandle(hChildStdoutWr);
CloseHandle(hChildStdinRd);
return DRIVE_CLONE_RESTORE_FAIL;
}
// 关闭写句柄,否则ReadFile会阻塞
CloseHandle(hChildStdoutWr);
// 根据输出行数判断备份进程
#ifdef HCL_CODE
SQLite_DumpRestore_ReadFromPipe(hChildStdoutRdDup, i_total_ts, command_type);
#else
PG_DumpRestore_ReadFromPipe(hChildStdoutRdDup, i_total_ts, command_type);
#endif // HCL_CODE
HPR_Sleep(1000);
CloseHandle(hChildStdoutRdDup);
CloseHandle(hChildStdinRd);
return DRIVE_CLONE_RESTORE_SUCC;
#elif (defined(__linux__))
pg_dump_restore_finish_ = false;
//std::thread t1 = std::thread(&CTimerBackup::PG_DumpRestore_ReadFromFile, this, log_file_path, i_total_ts, command_type);
//t1.detach();
CThreadManager::Instance().PostTask(string(__FUNCTION__) + "[PG_DumpRestore_ReadFromFile]",
std::bind(&CTimerBackup::PG_DumpRestore_ReadFromFile, this, log_file_path, i_total_ts, command_type));
std::string bash_pg_dmp = str_whole_cmd;
std::system(bash_pg_dmp.c_str());
pg_dump_restore_finish_ = true;
return DRIVE_CLONE_RESTORE_SUCC;
#endif
}
#if (defined(__linux__))
UINT_T CTimerBackup::PG_DumpRestore_ReadFromFile(const std::string& file_name, const UINT_T &i_total_lines, const UINT_T &command_type)
{
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 等待pg_dump开始执行
UINT_T percent_vol = i_percent_vol;
if (i_percent_vol >= i_total_lines)
{
i_percent_vol = 0;
}
do
{
int count = 0;
char flag;
FILE* ptr_file = fopen(file_name.c_str(), "r");
if (ptr_file == NULL)
{
return 0;
}
while (!feof(ptr_file)) {
flag = fgetc(ptr_file);
if (flag == '\n') count++;
}
percent_vol += count;
fseek(ptr_file, 0, SEEK_END);
int file_size = ftell(ptr_file);
fclose(ptr_file);
switch (command_type)
{
// 备份
case DEF_BACKUP_ONLY_CONFIG:
case DEF_BACKUP_CONFIG:
case DEF_BACKUP_RUNTIME:
case DEF_RSMBAK:
//i_sys_dump_percent_ = (file_size * 100) / (150 * 1024);
//if (file_size >= 150 * 1024)
//{
// i_sys_dump_percent_ = 95; // 模糊比例, 剩余5%留给电视墙
// return 0;
//}
i_sys_dump_percent_ = (UINT_T)(((double)percent_vol / (double)i_total_lines) * 100);
b_is_site_dump_percent_ = (UINT_T)(((double)percent_vol / (double)i_total_lines) * 100);
if (i_sys_dump_percent_ > 95 || b_is_site_dump_percent_ > 95)
{
i_sys_dump_percent_ = 95;
b_is_site_dump_percent_ = 95;
return 0;
}
break;
// 还原
case DEF_RESTORE:
i_sys_dump_percent_ = (file_size * 100) / (250 * 1024);
if (file_size >= 250 * 1024)
{
i_sys_dump_percent_ = 95; // 模糊比例, 剩余5%留给电视墙
return 0;
}
break;
default:
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(1500));
} while (!pg_dump_restore_finish_);
i_percent_vol = percent_vol;
IVMS_LOG_INFO("platform.Maintenance", "CTimerBackup::PG_DumpRestore_ReadFromPipe ReadFile FINISHED");
return DRIVE_CLONE_RESTORE_SUCC;
}
#endif
UINT_T CTimerBackup::ExecPGRestoreProgress_DB(const string &str_whole_file_path, const UINT_T &i_total_ts)
{
// 拼装pg_restore命令语句
string str_pg_restore_exe_path = PostgreSQL_path_ + PostgreSQL_restore_exe;
boost::system::error_code err_c;
if (!boost::filesystem::exists(str_pg_restore_exe_path, err_c))
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUP_CONFIG_ERROR)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecPGRestoreProgress_DB pg_restore.exe did NOT exists");
return DRIVE_CLONE_RESTORE_FAIL;
}
LocalDBInfo curr_db_info;
CLocalConfigManager::Instance().GetLocationDBInfo(curr_db_info);
std::string str_log_file_path; // 日志文件路径
// 获取数据库连接密码
#if (defined(_WIN32) || defined(_WIN32_WCE) || defined(_WIN64))
char* str_set_pwd = "set PGPASSWORD=%s\n";
string str_whole_set_pwd = str_fmt(str_set_pwd, curr_db_info.db_passwd.c_str());
string str_restore_cmd_fmt = "\"%s\" --host 127.0.0.1 --port %d --username postgres --format custom --verbose -c --dbname cms \"%s\"\n";
#else (defined(__linux__))
string str_whole_set_pwd;
CSetTmpPGPwd set_pg_pwd(curr_db_info.db_passwd);
auto path_index = str_whole_file_path.find_last_of("\\/");
if (path_index != std::string::npos)
{
str_log_file_path = str_whole_file_path.substr(0, path_index) + "/VSM_Restore.log";
}
else
{
assert(0);
IVMS_LOG_ERROR("platform.Maintenance", "filepath error %s", str_whole_file_path.c_str());
}
string str_restore_cmd_fmt = "\"%s\" --host localhost --port %d --username postgres --format custom --verbose -c --dbname cms \"%s\" >> " + str_log_file_path + " 2>&1 \n";
#endif
string str_restore_cmd = str_fmt(str_restore_cmd_fmt.c_str(), str_pg_restore_exe_path.c_str(), (unsigned short)postgre_port_, str_whole_file_path.c_str());
IVMS_LOG_INFO("platform.Maintenance", "CTimerBackup::ExecPGDumpProgress restore DUMP CMD : %s", str_restore_cmd.c_str());
IVMS_LOG_INFO("Maintenance", "CTimerBackup::ExecPGDumpProgress restore DUMP CMD : %s", str_restore_cmd.c_str());
string str_whole_pg_restore_cmd = str_whole_set_pwd + str_restore_cmd;
//if (DRIVE_CLONE_RESTORE_SUCC != AcquireCommandStatus(str_log_file_path, str_whole_pg_restore_cmd, i_total_ts * DEF_RES_INFO_ROWS, DEF_RESTORE))
if (DRIVE_CLONE_RESTORE_SUCC != AcquireCommandStatus(str_log_file_path, str_whole_pg_restore_cmd, i_total_ts, DEF_RESTORE))
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_RESTORE_FAIL)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecPGRestoreProgress_DB AcquireCommandStatus Failed");
boost::system::error_code ec;
boost::filesystem::remove(str_log_file_path, ec);
return DRIVE_CLONE_RESTORE_FAIL;
}
return DRIVE_CLONE_RESTORE_SUCC;
}
UINT_T CTimerBackup::ExecSQLiteRestoreProgress_DB(const string & str_whole_file_path, const UINT_T & i_total_ts, string restore_db_path, const map<string, string> & local_db)
{
// 拼装pg_restore命令语句
string str_restore_cmd /*= "copy /Y \"" + str_whole_file_path + "\" \"" + restore_db_path + "\""*/; // 文件存在,默认覆盖
boost::filesystem::path total_file_path(str_whole_file_path, (void*)boost::filesystem::native);
string db_name = total_file_path.filename().string();
if (db_name.empty())
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_RESTORE_FAIL)));
IVMS_LOG_ERROR("platform.Maintenance", "No found db, path : %s.", str_whole_file_path.c_str());
return DRIVE_CLONE_RESTORE_FAIL;
}
// db
restore_db_path = restore_db_path + "\\" + db_name;
boost::system::error_code ec;
boost::filesystem::copy_file(str_whole_file_path, restore_db_path, boost::filesystem::copy_option::overwrite_if_exists, ec);
if (ec.value() != 0)
{
IVMS_LOG_ERROR("platform.Maintenance", "copy certificate file fail. error message = %s, file : %s", ec.message().c_str(), str_whole_file_path.c_str());
if (ec.value() == 22 || ec.value() == 13)
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_FILE_NOPERMISSION)));
}
else
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DB_FILE_OCCUPY)));
}
return DRIVE_CLONE_RESTORE_FAIL;
}
// shm
string src_sw_path = str_whole_file_path + "-shm";
string restore_sw_path = restore_db_path + "-shm";
boost::filesystem::copy_file(src_sw_path, restore_sw_path, boost::filesystem::copy_option::overwrite_if_exists, ec);
if (ec.value() != 0)
{
IVMS_LOG_ERROR("platform.Maintenance", "copy certificate file fail. error message = %s, file : %s", ec.message().c_str(), src_sw_path.c_str());
if (ec.value() == 22 || ec.value() == 13)
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_FILE_NOPERMISSION)));
}
else
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DB_FILE_OCCUPY)));
}
return DRIVE_CLONE_RESTORE_FAIL;
}
// wal
src_sw_path = str_whole_file_path + "-wal";
restore_sw_path = restore_db_path + "-wal";
//restore_db_path = restore_db_path + "\\" + db_name;
boost::filesystem::copy_file(src_sw_path, restore_sw_path, boost::filesystem::copy_option::overwrite_if_exists, ec);
if (ec.value() != 0)
{
IVMS_LOG_ERROR("platform.Maintenance", "copy certificate file fail. error message = %s, file : %s", ec.message().c_str(), src_sw_path.c_str());
if (ec.value() == 22 || ec.value() == 13)
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_FILE_NOPERMISSION)));
}
else
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DB_FILE_OCCUPY)));
}
return DRIVE_CLONE_RESTORE_FAIL;
}
std::string str_log_file_path; // 日志文件路径
//if (DRIVE_CLONE_RESTORE_SUCC != AcquireCommandStatus(str_log_file_path, str_whole_pg_restore_cmd, i_total_ts * DEF_RES_INFO_ROWS, DEF_RESTORE))
if (DRIVE_CLONE_RESTORE_SUCC != AcquireCommandStatus(str_log_file_path, str_restore_cmd, i_total_ts, DEF_RESTORE))
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_RESTORE_FAIL)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecPGRestoreProgress_DB AcquireCommandStatus Failed");
//boost::system::error_code ec;
boost::filesystem::remove(str_log_file_path, ec);
if (ec)
{
IVMS_LOG_ERROR("platform.Maintenance", "remove file failed, error code = %d, file path = [%s].", ec.value(), str_log_file_path.c_str());
}
return DRIVE_CLONE_RESTORE_FAIL;
}
return DRIVE_CLONE_RESTORE_SUCC;
}
void CTimerBackup::Thread_ExecRestoreProgress_DB(string str_zip_path, string str_uncomp_file_path, string str_data_types)
{
boost::system::error_code err_c;
namespace ns_fs = boost::filesystem;
// 解压文件前先备份压缩文件,防止解压中途掉电导致文件损坏问题,该备份执行结果不影响原还原流程,所以即使失败也不直接return
#if (defined(_WIN32) || defined(_WIN32_WCE) || defined(_WIN64))
// Windows下暂不做处理
#elif (defined(__linux__))
// 检测压缩文件是否存在
if (HPR_OK == HPR_AccessFile(str_zip_path.c_str(), HPR_F_OK))
{
// 源文件
string str_src_zip_file_final = str_fmt("%s%s%s", "\"", str_zip_path.c_str(), "\"");
// 目标文件名
string str_dst_zip_file = "";
// 提取备份文件日期
string str_date_expression = "[0-9]{14}";
boost::cmatch mat_date;
boost::regex reg_date(str_date_expression);
bool b_search_result = boost::regex_search(str_src_zip_file_final.c_str(), mat_date, reg_date);
if (b_search_result && mat_date[0].matched)
{
// 如果匹配成功,取第一个即可,格式化目标文件名
string target = "VSM_" + g_soft_version + "_BAK-0-";
str_dst_zip_file = str_fmt("%s%s%s", target.c_str(), mat_date[0].str().c_str(), ".zip");
}
else
{
IVMS_LOG_ERROR("platform.Maintenance", "[CTimerBackup::ExecuteDataRestoreOpt] Failed to extract date information from %s", str_src_zip_file_final.c_str());
}
// 备份到/tmp/目录下 /tmp/VSM_1300_BAK-0-20190315160119.zip
string str_dst_file_final = str_fmt("%s%s%s%s", "\"", "/tmp/", str_dst_zip_file.c_str(), "\"");
// rm -f /tmp/VSM_1300_BAK-0* && \cp -f VSM_1300_BAK-0.zip /tmp/VSM_1300_BAK-0-20190315160119.zip 构造命令行,路径需要用引号引起来
string str_bacpup_commond = "rm -f /tmp/VSM_1300_BAK-0* && \\cp -f " + str_src_zip_file_final + " " + str_dst_file_final;
IVMS_LOG_INFO("platform.Maintenance", "[CTimerBackup::ExecuteDataRestoreOpt] Execute Copy. Commond = %s", str_bacpup_commond.c_str());
// 执行删除和备份文件拷贝, 执行失败也不返回
if (!(ProcessUtil::LaunchApp(str_bacpup_commond, true, true, NULL)))
{
IVMS_LOG_ERROR("platform.Maintenance", "[CTimerBackup::ExecuteDataRestoreOpt] Copy Execute Fail. Commond = %s", str_bacpup_commond.c_str());
}
}
else
{
IVMS_LOG_ERROR("platform.Maintenance", "[CTimerBackup::ExecuteDataRestoreOpt] Backup Execute Fail, File Not Exist %s", str_zip_path.c_str());
}
#endif
// 解压到restore路径
if (CompressExecuteFail == Compress::UnCompress(str_zip_path, str_uncomp_file_path))
{
//解压失败
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecuteDataRestoreOpt UnCompress() FAILED");
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUPFILE_NOT_EXIST)));
// 失败停止数据库还原,暂不考虑图片还原情况
m_res_error_ = DRIVE_CLONE_RESTORE_FAIL;
i_sys_restore_percent_ = 100;
i_restore_sum_ = 100;
if (i_sys_restore_percent_ == 100) // && i_sys_pic_res_percent_ == 100
{
// 图片与数据库均完成还原
b_is_restore_running_ = false;
}
return;
}
string vsm_conf_bak_file_path(""), vsm_run_bak_file_path(""), swms_bak_file_path("");
vector<string> vsm_conf_bak_file_path_vec;
vector<string> vsm_run_bak_file_path_vec;
std::string ncg_bak_file; // Modified for NCG by chenguomin
// 压缩包解压出来的
boost::filesystem::path total_file_path(str_uncomp_file_path, (void*)boost::filesystem::native);
if (ns_fs::exists(total_file_path, err_c))
{
boost::filesystem::directory_iterator item_begin(total_file_path);
boost::filesystem::directory_iterator item_end;
for (; item_begin != item_end; item_begin++)
{
if (boost::filesystem::is_regular_file(*item_begin))
{
string bak_file_name = item_begin->path().string();
size_t index = bak_file_name.rfind(".");
if (index == string::npos)
{
continue;
}
string file_type = bak_file_name.substr(index + 1, bak_file_name.length() - index);
//if (file_type == "Backup" && bak_file_name.find("TVWALL") != string::npos)
//{
// // 电视墙的备份文件格式
// swms_bak_file_path = bak_file_name;
//}
if (file_type.find("bak") != string::npos && bak_file_name.find("VSM_DB-Config") != string::npos)
{
vsm_conf_bak_file_path = bak_file_name;
vsm_conf_bak_file_path_vec.push_back(bak_file_name);
}
//if (file_type.find("bak") != string::npos && bak_file_name.find("VSM_DB-Runtime") != string::npos)
//{
// vsm_run_bak_file_path = bak_file_name;
// vsm_run_bak_file_path_vec.push_back(bak_file_name);
//}
if (CControlItemManager::Instance().GetControlItemSupportNum("s_platform_system_advance_ncg") == 1)
{
// Modified for NCG by chenguomin --------------------------------
IVMS_LOG_ERROR("platform.Maintenance", "NCG1 backup file name is %s", bak_file_name.c_str());
if (file_type == "bak" && bak_file_name.find("NCG_DB_BACKUP") != string::npos)
{
// ncg的备份文件格式
ncg_bak_file = bak_file_name;
}
}
}
}
}
// notes:解压出来文件时,才开始
//i_sys_restore_percent_ = 10;
i_sys_restore_percent_ = 0;
i_restore_sum_ = 10;
// 必须包含配置型数据
if (vsm_conf_bak_file_path_vec.empty())
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecuteDataRestoreOpt File Not Exists %s", vsm_conf_bak_file_path.c_str());
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BACKUPFILE_NOT_EXIST)));
// 失败停止数据库还原,暂不考虑图片还原情况
m_res_error_ = DRIVE_CLONE_RESTORE_FAIL;
i_sys_restore_percent_ = 100;
i_restore_sum_ = 100;
if (i_sys_restore_percent_ == 100) // && i_sys_pic_res_percent_ == 100
{
// 图片与数据库均完成还原
b_is_restore_running_ = false;
}
return;
}
else
{
// 获取备份表列表
vector<string> v_bak_tables;
if (CombingDBCloneTables(v_bak_tables, str_data_types, is_distributed_) != 0)
{
// 日志打印
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_RESTORE_FAIL)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::DetermineDiskCloneVolume CombingDBCloneTables FAILED");
// 失败停止数据库还原,暂不考虑图片还原情况
m_res_error_ = DRIVE_CLONE_RESTORE_FAIL;
i_sys_restore_percent_ = 100;
i_restore_sum_ = 100;
if (i_sys_restore_percent_ == 100) // && i_sys_pic_res_percent_ == 100
{
// 图片与数据库均完成还原
b_is_restore_running_ = false;
}
return;
}
i_percent_vol = 0;
// bak的数量
/* UINT_T bak_num = vsm_conf_bak_file_path_vec.size();*/
IVMS_LOG_INFO("platform.Maintenance", "CTimerBackup::DetermineDiskCloneVolume v_bak_tables : %d", (UINT_T)v_bak_tables.size());
// bool is_only = false;
// for (std::size_t i = 0; i < v_bak_tables.size(); ++i) {
// for (std::size_t j = i + 1; j < v_bak_tables.size(); ++j) {
// if (v_bak_tables[i] == v_bak_tables[j]) {
// IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::DetermineDiskCloneVolume v_bak_tables same table : %s", v_bak_tables[i].c_str());
// is_only = true;
// break;
// }
// }
// }
//
// if (is_only)
// {
// return;
// }
for (auto vsm_conf_bak_file_path1 : vsm_conf_bak_file_path_vec)
{
if (ExecPGRestoreProgress_DB(vsm_conf_bak_file_path1, (UINT_T)v_bak_tables.size()) != 0)
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecuteDataRestoreOpt FAILED");
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_RESTORE_FAIL)));
// 失败停止数据库还原,暂不考虑图片还原情况
m_res_error_ = DRIVE_CLONE_RESTORE_FAIL;
i_sys_restore_percent_ = 100;
i_restore_sum_ = 100;
if (i_sys_restore_percent_ == 100) // && i_sys_pic_res_percent_ == 100
{
// 图片与数据库均完成还原
b_is_restore_running_ = false;
}
return;
}
if (!is_start_restore_)
{
is_start_restore_ = true;
}
else
{
restore_bak_num_ += 10;
}
IVMS_LOG_INFO("platform.Maintenance", "restore_bak_num_ is : %d", restore_bak_num_);
}
// 存在运行时数据
for (auto vsm_run_bak_file_path1 : vsm_run_bak_file_path_vec)
{
if (ExecPGRestoreProgress_DB(vsm_run_bak_file_path1, (UINT_T)v_bak_tables.size()) != 0)
{
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecuteDataRestoreOpt FAILED");
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_RESTORE_FAIL)));
// 失败停止数据库还原,暂不考虑图片还原情况
m_res_error_ = DRIVE_CLONE_RESTORE_FAIL;
i_sys_restore_percent_ = 100;
i_restore_sum_ = 100;
if (i_sys_restore_percent_ == 100) // && i_sys_pic_res_percent_ == 100
{
// 图片与数据库均完成还原
b_is_restore_running_ = false;
}
return;
}
// 执行完成一个bak后,表就还原了10个
if (!is_start_restore_)
{
is_start_restore_ = true;
}
else
{
restore_bak_num_ += 10;
}
IVMS_LOG_INFO("platform.Maintenance", "restore_bak_num_ is : %d", restore_bak_num_);
}
if (!swms_bak_file_path.empty())
{
// 还原电视墙数据
//CTVWallManager::Instance().Restore(swms_bak_file_path);
}
if (CControlItemManager::Instance().GetControlItemSupportNum("s_platform_system_advance_ncg") == 1)
{
// Modified for NCG by chenguomin --------------------------------
IVMS_LOG_ERROR("platform.Maintenance", "NCG backup file name is %s", ncg_bak_file.c_str());
if (!ncg_bak_file.empty())
{
CNCGManager::Instance()->RestoreDatabase(ncg_bak_file);
}
// End for NCG----------------------------------------------------
}
// notes:还原完成,删除多余的子表
string backup_info_xml = str_zip_path + "//../BackupInfo.xml";
if (!boost::filesystem::exists(backup_info_xml))
{
// 提个醒
IVMS_LOG_ERROR("platform.Maintenance", "NO found BackupInfo.xml, path : %s.", backup_info_xml.c_str());
}
else
{
if (!DeleteSurplusPartitionTable(backup_info_xml))
{
IVMS_LOG_ERROR("platform.Maintenance", "Multiple partition tables have not been deleted yet %s.", backup_info_xml.c_str());
}
}
// 删除解压文件
boost::filesystem::remove_all(str_uncomp_file_path, err_c);
// notes:HCP2.5.1做升级前的校验用
// if (!CMaintenanceManager::Instance().RecordRestoreStatus(STOP_RESTORE))
// {
// IVMS_LOG_ERROR("platform.Maintenance", "RESTORE STOP Status record failed");
// }
}
//恢复DropCascadeParTable()中被删除的主表规则RULE
VSMPlatform::MaintenanceSession::ResParTableRule();
i_sys_restore_percent_ = 100;
i_restore_sum_ = 100;
IVMS_LOG_INFO("platform.Maintenance", "TEST Time : Thread_ExecRestoreProgress_DB Progress 100");
std::lock_guard<mutex> lock(mtx_finished_);
if (i_sys_restore_percent_ == 100 && /*i_sys_pic_res_percent_ == 100 &&*/ i_ads_restore_percent_ == 100)
{
// 图片与数据库均完成还原
b_is_restore_running_ = false;
}
}
UINT_T CTimerBackup::ObtainBakResProgress(RecoverProgress &bak_res_status)
{
if (b_is_diff_machine)
{
int iType = 0;
b_recvBeeAgent_progress = false;
iProgressResult_ = -1;
iProgressPercent_ = 0;
if (bak_res_status.rec_type == RecoverProgress::RecoverType::Backup)
{
iType = 1;
}
else if (bak_res_status.rec_type == RecoverProgress::RecoverType::Restore)
{
iType = 2;
}
shared_ptr<proto::IProto> parse = make_shared<proto::CRapidJsonProto>();
string strGuid = Bee::Base::GuidUtil::CreateGuid();
parse->set_v("/Guid", strGuid);
parse->set_v("/RequestData/Method", "BackupRestoreProgress");
parse->set_v("/RequestData/Data/RecoverType", iType);
string strReq = parse->get_str();
CBeeAgentClientManager::Instance().SendMsg(iBeeAgentClientId, strReq, Bee::Net::WebSocket::TEXT);
//给20秒的超时时间
time_t startTime;
time_t endTime;
double diffStartEndTime;
time(&startTime);
while (true)
{
if (b_recvBeeAgent_progress)
{
if (0 == iProgressResult_)
{
bak_res_status.sys_percent = iProgressPercent_;
b_recvBeeAgent_progress = false;
return iProgressResult_;
}
}
time(&endTime);
diffStartEndTime = difftime(endTime, startTime);
if (diffStartEndTime > 10)
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BEEAGENT_TIMEOUT)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ObtainBakResProgress Diff FAILED,BeeAgent ReBackPackage TimeOut");
b_recvBeeAgent_progress = false;
bak_res_status.sys_percent = 100;
return -1;
}
}
return 0;
}
//
UINT_T iRet = 0;
// bak_res_status.has_pic = has_dump_pic_bak_;
switch (bak_res_status.rec_type)
{
// 备份
case RecoverProgress::RecoverType::Backup:
if (m_bak_error_ == 0)
{
if (b_is_dump_running_)
{
// v2.6 计算FTP上传进度
if (dc_bak_conf_Plan_.em_clone_upload_location != DriveCloneConf::DriveCloneUploadLocation::NoneLocation)
{
CTimerBackup::GetUploadProgress();
bak_res_status.sys_percent = static_cast<int>(i_sys_dump_percent_ * 0.9) + static_cast<int>(i_ftp_upload_percent_ * 0.1);
//IVMS_LOG_INFO("platform.Maintenance", "ftp_upload_persent: %d,sys_dump_percent: %d", i_ftp_upload_percent_.load(), i_sys_dump_percent_.load());
}
else
{
// 备份进度
bak_res_status.sys_percent = i_sys_dump_percent_;
if (i_sys_dump_percent_ > 100)
{
i_sys_dump_percent_ = 100;
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_BACKUP_FAIL)));
iRet = CMS_DATABASE_BACKUP_FAIL;
}
}
}
else
{
bak_res_status.sys_percent = 100;
bak_res_status.ads_percent = 100;
// bak_res_status.pic_percent = 100;
percent_config_ = false;
}
}
else
{
// 备份失败直接返回错误码
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_BACKUP_FAIL)));
iRet = m_bak_error_;
}
break;
// 还原
case RecoverProgress::RecoverType::Restore:
if (m_res_error_ == 0)
{
if (b_is_restore_running_)
{
// 区分分布式情况,防止直接50%的进度
bak_res_status.sys_percent = i_sys_restore_percent_;
//IVMS_LOG_INFO("platform.Maintenance", "i_sys_restore_percent_: %d", i_sys_restore_percent_.load());
if (i_sys_restore_percent_ > 100)
{
i_sys_restore_percent_ = 100;
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_RESTORE_FAIL)));
iRet = CMS_DATABASE_BACKUP_FAIL;
}
}
else
{
bak_res_status.sys_percent = 100;
bak_res_status.ads_percent = 100;
// bak_res_status.pic_percent = 100;
}
}
else
{
#ifdef HCL_CODE
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DB_FILE_OCCUPY)));
#else
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_RESTORE_FAIL)));
#endif // HCL_CODE
iRet = m_res_error_;
}
break;
case RecoverProgress::RecoverType::BackPlan:
if (m_bak_error_ == 0)
{
if (b_is_backup_plan_)
{
// 备份进度
bak_res_status.backup_plan_status = i_backup_plan_;
}
else
{
bak_res_status.backup_plan_status = 1;
}
}
else
{
// 备份失败直接返回错误码
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_BACKUP_FAIL)));
iRet = m_bak_error_;
}
break;
default:
break;
}
// 保证100%下状态正确
if (bak_res_status.sys_percent >= 100) // && bak_res_status.pic_percent == 100
{
bak_res_status.sys_percent = 100;
b_is_dump_running_ = false;
b_is_restore_running_ = false;
b_is_backup_plan_ = false;
}
return iRet;
}
int CTimerBackup::ObtainSiteBakResProgress(RecoverProgress &bak_res_status)
{
UINT_T iRet = 0;
if (m_site_bak_error_ == 0)
{
if (b_is_site_dump_running_)
{
#if (defined(_WIN32) || defined(_WIN32_WCE) || defined(_WIN64))
bak_res_status.sys_percent = b_is_site_dump_percent_;
#elif (defined(__linux__))
bak_res_status.sys_percent = 50;
#endif
}
else
{
bak_res_status.sys_percent = 100;
}
}
else
{
// 备份失败直接返回错误码
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_BACKUP_FAIL)));
iRet = m_site_bak_error_;
}
// 保证100%下状态正确
if (bak_res_status.sys_percent == 100)
{
b_is_site_dump_running_ = false;
}
return iRet;
}
int CTimerBackup::RSM_ObtainSiteBackupProgress(UINT_T id_site, RecoverProgress &bak_res_status)
{
string str_response;
rsmmodule::RSMModule_HttpSend(str_response, id_site, "POSTGET", "/ISAPI/Bumblebee/Platform/V1/Maintenance/RSM/Sites/BackupRestoreProgress", "", 1000);
IVMS_LOG_DEBUG("platform.Maintenance", "CTimerBackup::RSM_ObtainSiteBackupProgress Recv %s!", str_response.c_str());
//网络超时
if (str_response.empty())
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_VSMSITE), ERROR_CODE(CMS_NETWORK_TIMEOUT)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::RSM_ObtainSiteBackupProgress Timeout!");
bak_res_status.sys_percent = 100;
return -1;
}
shared_ptr<proto::IProto> parse = make_shared<proto::CRapidJsonProto>();
parse->set_str(str_response);
UINT_T iMainCode = parse->get_int_v("/ResponseStatus/ErrorModule");
UINT_T iSubCode = parse->get_int_v("/ResponseStatus/ErrorCode");
//站点备份失败,返回错误码
if (iSubCode == 217)
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_NO_ERROR), Error::MakeCascadingErrorStr(iMainCode, iSubCode)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::RSM_ObtainSiteBackupProgress Error!");
if (b_is_site_backup_finished_)
{
bak_res_status.sys_percent = 100;
}
else
{
bak_res_status.sys_percent = 0;
}
return 0;
}
else if (0 != iSubCode)
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_VSMSITE), ERROR_CODE(CMS_CASCADING_ERROR), Error::MakeCascadingErrorStr(iMainCode, iSubCode)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::RSM_ObtainSiteBackupProgress Error!");
bak_res_status.sys_percent = 100;
return -1;
}
bak_res_status.sys_percent = parse->get_int_v("/ResponseStatus/Data/BackupRestoreProgress/TotalProgress");
return 0;
}
bool CTimerBackup::SendToBeeAgentCheckFileExist(vector<int>& vec_exist, const vector<string>& vec_files)
{
SendToBeeAgentGetBackuoPath();
b_recvCheckFileExistResult_ = false;
stru_recvCheckFileExistResult_.reset();
shared_ptr<proto::IProto> parse = make_shared<proto::CRapidJsonProto>();
string url_fmt = "/RequestData/Data/BakFileList[%d]";
int index = 1;
for (auto& iter = vec_files.begin(); iter != vec_files.end(); ++iter)
{
string url = Bee::Base::StringUtil::str_fmt(url_fmt.c_str(), index);
parse->set_v(url, *iter);
++index;
}
string strGuid = Bee::Base::GuidUtil::CreateGuid();
parse->set_v("/Guid", strGuid);
parse->set_v("/RequestData/Method", "CheckFileExist");
string strReq = parse->get_str();
CBeeAgentClientManager::Instance().SendMsg(iBeeAgentClientId, strReq, Bee::Net::WebSocket::TEXT);
//给10秒的超时时间,没有返回错误码,表示没有出错,正在备份
time_t startTime;
time_t endTime;
double diffStartEndTime;
time(&startTime);
while (true)
{
if (b_recvCheckFileExistResult_)
{
if (0 != stru_recvCheckFileExistResult_.error_code)
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(stru_recvCheckFileExistResult_.error_code)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::CheckFileExistDiffMachine FAILED,Result %d", stru_recvCheckFileExistResult_.error_code);
b_recvCheckFileExistResult_ = false;
return false;
}
else
{
vec_exist = stru_recvCheckFileExistResult_.vec_exist;
b_recvCheckFileExistResult_ = false;
return true;
}
}
time(&endTime);
diffStartEndTime = difftime(endTime, startTime);
if (diffStartEndTime > 10)
{
b_recvDeleteBackup_ = false;
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_BEEAGENT_TIMEOUT)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::CheckFileExistDiffMachine timeout!");
return false;
}
}
return true;
}
bool CTimerBackup::JudgeIsDifferMachine()
{
return b_is_diff_machine;
}
bool CTimerBackup::UploadToSFTP(const DriveCloneConf &data_clone_conf, const string &str_ftp_file_path, const vector<pair<string, string>> &vec_ftp_files)
{
bool ret = true;
if (!InitSFTPConnect(data_clone_conf))
{
IVMS_LOG_ERROR("platform.Maintenance", "SFTP Server init failed");
return false;
}
if (nullptr == ptr_ftp_storage_)
{
IVMS_LOG_ERROR("platform.Maintenance", "SFTP pointer is empty");
return false;
}
std::vector<std::string> vs_failed_file;
std::vector<FTPStorageComm::FileMappingParam> vs_files;
for (auto ftp_file : vec_ftp_files)
{
FTPStorageComm::FileMappingParam file;
file.ftp_file_name = ftp_file.first;
file.local_full_path = ftp_file.second;
vs_files.push_back(file);
}
if (!ptr_ftp_storage_->UploadToSFTP(vs_failed_file, vs_files, str_ftp_file_path))
{
Bee::Base::Error::ErrorCode error_code = this->GetSFTPError();
if (error_code.iSecondCode != NOERROR)
{
std::string failed_file_name = "";
for (auto file_name : vs_failed_file)
{
failed_file_name += file_name + "/";
}
Error::SetLastError(Error::ErrorCode(ERROR_CODE(error_code.iFirstCode), ERROR_CODE(error_code.iSecondCode)));
IVMS_LOG_ERROR("platform.Maintenance", "SFTP UploadFile failed file : %s, error[%d:%d:%s]", failed_file_name.c_str(), error_code.iFirstCode, error_code.iSecondCode, error_code.GetCasadingErrorInfo().c_str());
m_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
ret = false;
}
}
if (!UinitSFTPConnect())
{
IVMS_LOG_ERROR("platform.Maintenance", "SFTP Server uninit failed");
ret = false;
}
return ret;
}
bool CTimerBackup::InitSFTPConnect(const DriveCloneConf &data_clone_conf)
{
ptr_ftp_storage_ = std::make_shared<FTPStorageComm::CFTPStorage>();
if (nullptr == ptr_ftp_storage_)
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_CONNECT_FTP_ERROR)));
return false;
}
FTPStorageComm::SFTPParam storage_param;
storage_param.ftp_path = data_clone_conf.str_ftp_save_file_path;
storage_param.ip = data_clone_conf.str_ftp_clone_address;
storage_param.port = data_clone_conf.i_ftp_clone_port;
storage_param.str_user_name = data_clone_conf.str_ftp_clone_user_name;
storage_param.str_password = data_clone_conf.str_ftp_clone_password;
if (!ptr_ftp_storage_->Init(storage_param))
{
IVMS_LOG_ERROR("platform.Maintenance", "SFTP CloudStorage client init failed");
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_CONNECT_FTP_ERROR)));
m_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
return false;
}
return true;
}
bool CTimerBackup::UinitSFTPConnect()
{
if (nullptr == ptr_ftp_storage_)
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_CONNECT_FTP_ERROR)));
return false;
}
if (!ptr_ftp_storage_->Uninit())
{
ptr_ftp_storage_ = nullptr;
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_CONNECT_FTP_ERROR)));
return false;
}
ptr_ftp_storage_ = nullptr;
return true;
}
Bee::Base::Error::ErrorCode CTimerBackup::GetSFTPError()
{
Bee::Base::Error::ErrorCode err;
std::string message;
ptr_ftp_storage_->GetErrorInfo(err.iFirstCode, err.iSecondCode, message);
err.SetCasadingErrorInfo(message);
return err;
}
bool CTimerBackup::IsFTPOrSFTPFolderExist(const std::string& ftp_url, const std::string& ftp_path, const std::string& ftp_usr_psw)
{
bool ret = true;
do
{
CURL* curl_handle = curl_easy_init();
if (nullptr == curl_handle)
{
IVMS_LOG_ERROR("platform.Maintenance", "Test FTP failed, handle is null.");
ret = false;
break;
}
std::string ftp_url_ex = "";
std::string str_out_data;
if (ftp_path.empty())
{
ftp_url_ex = ftp_url;
}
else
{
ftp_url_ex = (ftp_url + ftp_path + "/");
}
curl_easy_setopt(curl_handle, CURLOPT_URL, ftp_url_ex.c_str());
curl_easy_setopt(curl_handle, CURLOPT_USERPWD, ftp_usr_psw.c_str());
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &str_out_data);
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteToString);
curl_easy_setopt(curl_handle, CURLOPT_CONNECTTIMEOUT, 10L);
curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, 30L);
CURLcode res = curl_easy_perform(curl_handle);
if (res != CURLE_OK)
{
Bee::Base::Error::ErrorCode error_code = GetFTPError(res);
Error::SetLastError(Error::ErrorCode(ERROR_CODE(error_code.iFirstCode), ERROR_CODE(error_code.iSecondCode)));
IVMS_LOG_INFO("platform.Maintenance", "FTP judge floder failed!");
ret = false;
}
curl_easy_cleanup(curl_handle);
curl_handle = nullptr;
} while (false);
return ret;
}
bool CTimerBackup::CreateFTPOrSFTPSingleFloder(const DriveCloneConf::DriveCloneUploadLocation loc_type, const std::string& ftp_url, const std::string& ftp_path, const std::string& ftp_usr_psw)
{
bool ret = false;
do
{
CURL* curl_handle = curl_easy_init();
if (nullptr == curl_handle)
{
IVMS_LOG_ERROR("platform.Maintenance", "Create FTP path failed, handle is null.");
break;
}
struct curl_slist* headerlist = NULL;
std::string str_out_data;
std::string cmd = "";
if (loc_type == DriveCloneConf::DriveCloneUploadLocation::FTP)
{
cmd = str_fmt("MKD %s", ftp_path.c_str());
}
else
{
cmd = str_fmt("mkdir \"%s\"", ftp_path.c_str());
}
headerlist = curl_slist_append(headerlist, cmd.c_str());
curl_easy_setopt(curl_handle, CURLOPT_URL, ftp_url.c_str());
curl_easy_setopt(curl_handle, CURLOPT_USERPWD, ftp_usr_psw.c_str());
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &str_out_data);
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteToString);
curl_easy_setopt(curl_handle, CURLOPT_POSTQUOTE, headerlist);
curl_easy_setopt(curl_handle, CURLOPT_CONNECTTIMEOUT, 10L);
curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, 30L);
CURLcode res = curl_easy_perform(curl_handle);
if (res != CURLE_OK && res != CURLE_REMOTE_FILE_NOT_FOUND)
{
Bee::Base::Error::ErrorCode error_code = GetFTPError(res);
IVMS_LOG_ERROR("platform.Maintenance", "FTP create floder: %s failed!", ftp_path.c_str());
Error::SetLastError(Error::ErrorCode(ERROR_CODE(error_code.iFirstCode), ERROR_CODE(error_code.iSecondCode)));
ret = false;
}
else
{
ret = true;
}
curl_slist_free_all(headerlist);
curl_easy_cleanup(curl_handle);
curl_handle = nullptr;
headerlist = nullptr;
} while (false);
return ret;
}
bool CTimerBackup::CreateFTPOrSFTPFloders(const DriveCloneConf &data_clone_conf, const std::string &file_path)
{
//判断路径格式是否正确
if (!CheckFtpPathFormat(file_path))
{
IVMS_LOG_ERROR("platform.Maintenance", "The FTP path format error, path[%s].", file_path.c_str());
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_ERR_FTP_PATH_FORMAT_ERROR)));
return false;
}
//判断FTP路径是否存在,不存在则创建路径
std::vector<std::string> vec_path;
Bee::Base::StringUtil::String2Array(vec_path, file_path, '/');
std::string full_path;
std::string full_path_escape;
// 首路径首字符为~符号,需要特殊处理,因为libcurl检测目录是否存在有问题,不存在也返回存在
bool flag = false;
//拼接ftp url;
std::string ftp_url = "";
if (!GenFTPOrSFTPURL(ftp_url, data_clone_conf))
{
IVMS_LOG_ERROR("platform.Maintenance","Generate ftp/sftp url failed");
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_REQUEST_PARAM_ERROR)));
return false;
}
//拼接用户名密码
std::string ftp_user_psw = Bee::Base::StringUtil::str_fmt("%s:%s", data_clone_conf.str_ftp_clone_user_name.c_str(),
data_clone_conf.str_ftp_clone_password.c_str());
if (!IsFTPOrSFTPFolderExist(ftp_url, "", ftp_user_psw)) // 根目录判断
{
IVMS_LOG_ERROR("platform.Maintenance", "Check ftp/sftp floder failed.");
return false;
}
for (auto& single_path : vec_path)
{
if (!full_path.empty())
{
full_path += ("/");
full_path_escape += ("/");
}
else
{
if (!single_path.empty()
&& '~' == single_path[0])
{
flag = true;
}
}
full_path += single_path;
full_path_escape += curl_escape_ex(single_path);
if (!IsFTPOrSFTPFolderExist(ftp_url, full_path_escape, ftp_user_psw) || flag) // 不存在创建
{
IVMS_LOG_INFO("platform.Maintenance", "Check ftp/sftp floder: %s not exist.", full_path_escape.c_str());
if (!CreateFTPOrSFTPSingleFloder(data_clone_conf.em_clone_upload_location, ftp_url, full_path, ftp_user_psw))
{
IVMS_LOG_ERROR("platform.Maintenance", "Create ftp/sftp floder failed, ftp/sftp path: %s", full_path.c_str());
return false;
}
}
}
return true;
}
bool CTimerBackup::UploadToFTP(const DriveCloneConf &data_clone_conf, const string &str_ftp_file_path, const vector<pair<string, string>> &vec_ftp_files)
{
std::string ftp_url = "";
if (!GenFTPOrSFTPURL(ftp_url, data_clone_conf))
{
IVMS_LOG_ERROR("platform.Maintenance", "Generate ftp url failed !");
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_REQUEST_PARAM_ERROR)));
return false;
}
std::string ftp_user_psw = Bee::Base::StringUtil::str_fmt("%s:%s", data_clone_conf.str_ftp_clone_user_name.c_str(),
data_clone_conf.str_ftp_clone_password.c_str());
bool ret = true;
do
{
CURL* curl_handle = curl_easy_init();
if (nullptr == curl_handle)
{
IVMS_LOG_ERROR("platform.Maintenance", "Create FTP path failed, handle is null.");
break;
}
for (auto ftp_file : vec_ftp_files)
{
ftp_upload_progress_.up_total_size += boost::filesystem::file_size(ftp_file.second);
}
for (auto ftp_file : vec_ftp_files)
{
FILE *file = nullptr;
if (fopen_s(&file, ftp_file.second.c_str(), "rb") != 0)
{
IVMS_LOG_ERROR("platform.Maintenance", "Local file:%s open failed!", ftp_file.second.c_str());
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_REQUEST_PARAM_ERROR)));
ret = false;
break;
}
std::string ftp_file_name = ftp_url + str_ftp_file_path + "/" + ftp_file.first;
curl_easy_setopt(curl_handle, CURLOPT_UPLOAD, 1L); // 开启上传模式
curl_easy_setopt(curl_handle, CURLOPT_URL, ftp_file_name.c_str()); // 设置FTP服务器上保存的文件名
curl_easy_setopt(curl_handle, CURLOPT_USERPWD, ftp_user_psw.c_str()); // 设置FTP服务器的用户名
curl_easy_setopt(curl_handle, CURLOPT_READDATA, file); // 打开本地文件
curl_easy_setopt(curl_handle, CURLOPT_INFILESIZE_LARGE, (curl_off_t)-1);
curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L); // 打开详细输出模式
curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 0L); // 取消禁止进度显示操作
curl_easy_setopt(curl_handle, CURLOPT_XFERINFOFUNCTION, FTPTransCallBack); // 设置进度回调函数
FTPTransProgressStruct ftp_upload_progress;
curl_easy_setopt(curl_handle, CURLOPT_XFERINFODATA, &ftp_upload_progress); // 设置下载进度参数
CURLcode res = curl_easy_perform(curl_handle);
if (res != CURLE_OK)
{
Bee::Base::Error::ErrorCode error_code = GetFTPError(res);
IVMS_LOG_ERROR("platform.Maintenance", "FTP create floder failed, ftp/sftp path: %s", ftp_file_name.c_str());
Error::SetLastError(Error::ErrorCode(ERROR_CODE(error_code.iFirstCode), ERROR_CODE(error_code.iSecondCode)));
ret = false;
}
if (nullptr != file)
{
std::fclose(file);
file = nullptr;
}
}
curl_easy_cleanup(curl_handle);
curl_handle = nullptr;
} while (false);
return ret;
}
bool CTimerBackup::GenFTPOrSFTPURL(std::string &ftp_url, const DriveCloneConf &data_clone_conf)
{
ftp_url = StringUtil::str_fmt("%s://%s:%d/",
(data_clone_conf.em_clone_upload_location == DriveCloneConf::DriveCloneUploadLocation::SFTP ? "sftp" : "ftp"),
data_clone_conf.str_ftp_clone_address.c_str(),
data_clone_conf.i_ftp_clone_port);
return true;
}
Bee::Base::Error::ErrorCode CTimerBackup::GetFTPError(const CURLcode curl_code)
{
Bee::Base::Error::ErrorCode error_code;
if (curl_code != CURLE_OK && curl_code != CURLE_REMOTE_FILE_NOT_FOUND)
{
IVMS_LOG_ERROR("platform.Maintenance", "curl-code[%d], str-error[%s].", curl_code, curl_easy_strerror(curl_code));
switch (curl_code)
{
case CURLE_COULDNT_CONNECT:
case CURLE_OPERATION_TIMEDOUT:
{
error_code.iFirstCode = CMS_MODULE_CMS;
error_code.iSecondCode = CMS_CONNECT_FTP_ERROR;
}
break;
case CURLE_LOGIN_DENIED:
{
error_code.iFirstCode = CMS_MODULE_CMS;
error_code.iSecondCode = VSM_EVIDENCE_ERR_FTP_USER_PWD_ERROR;
}
break;
case CURLE_REMOTE_ACCESS_DENIED:
case CURLE_SSH:
{
error_code.iFirstCode = CMS_MODULE_CMS;
error_code.iSecondCode = VSM_EVIDENCE_ERR_FTP_REMOTE_ACCESS_DENIED;
}
break;
default:
{
error_code.iFirstCode = CMS_MODULE_CMS;
error_code.iSecondCode = CMS_CONNECT_FTP_ERROR;
}
break;
}
}
return error_code;
}
bool CTimerBackup::QueryLocalBackupFilePath(string & backup_root_path, int & backup_id, int backup_type, string restore_time, string & backup_plan_path)
{
shared_ptr<db_layer::CConnect> ptr_connect = nullptr;
ptr_connect = CVsmPlatformDBConn::Instance().ApplyConn();
if (ptr_connect == nullptr)
{
IVMS_LOG_ERROR("platform.Maintenance", "Conn Failed.");
return false;
}
db_layer::CConnect& rs = *ptr_connect;
string query_sql = str_fmt("SELECT file_path, id FROM platform.backup_record WHERE is_local = %d AND is_deleted = 0 AND create_time = '%s' LIMIT 1;",
backup_type, restore_time.c_str());
if (!rs.ExecuteQuery(query_sql))
{
IVMS_LOG_ERROR("platform.Maintenance", "Query Failed, sql is %s", query_sql.c_str());
return false;
}
backup_root_path = rs.GetString("file_path");
backup_id = rs.GetInt("id");
query_sql = "SELECT save_path FROM platform.backup_info WHERE is_deleted = 0;";
if (!rs.ExecuteQuery(query_sql))
{
IVMS_LOG_ERROR("platform.Maintenance", "Query Failed, sql is %s", query_sql.c_str());
return false;
}
backup_plan_path = rs.GetString("save_path");
if (backup_root_path.empty() || backup_id <= 0 || backup_plan_path.empty())
{
IVMS_LOG_ERROR("platform.Maintenance", "Backup File Not Found or id is error.");
return false;
}
return true;
}
bool CTimerBackup::SendServerEvent(const string& event_data)
{
std::string url = "/ISAPI/Bumblebee/AlarmPlugin/V1/ServiceEventPush";
Method method = Method::Post;
CmdParamEx cmd_param;
if (!CURLManager::Instance().FindCmdParaByUrlAndMethod(cmd_param, url, method))
{
IVMS_LOG_ERROR("platform.Maintenance", "FindCmdParaByUrlAndMethod failed, url: %s.", url.c_str());
return false;
}
std::stringstream oss;
oss << "{\"ServiceEventInfo\":"
<< event_data
<< "}";
string str_req = oss.str();
MsgIn req_data;
req_data.enumMethod = method;
req_data.strUrl = url;
req_data.struBindData.Bind(str_req);
ProtoParam2 param;
param.pro_ = new proto::CRapidJsonProto();
param.pro_req_ = new proto::CRapidJsonProto();
param.result_ = param.pro_req_->set_str(str_req);
param.pro_->set_v("/ResponseStatus/Data", string());
MsgOut rsp_data;
cmd_param.cmd_param_.fun_(req_data, rsp_data, param);
IVMS_LOG_DEBUG("platform.Maintenance", "SendServerEvent, req_data: %s.", oss.str().c_str());
return true;
}
bool CTimerBackup::DeleteSurplusPartitionTable(string backup_info_xml)
{
shared_ptr<db_layer::CConnect> ptr_connect = nullptr;
ptr_connect = CVsmPlatformDBConn::Instance().ApplyConn();
if (ptr_connect == nullptr)
{
IVMS_LOG_ERROR("platform.Maintenance", "Conn Failed.");
return false;
}
db_layer::CConnect& rs = *ptr_connect;
multimap<string, string> map_partition_table;
// 1.首先获取备份文件中的schema和版本,并与本地数据库进行比较
// 对文件内容解密
string encry_backup_buf;
if (!CFileBak::ReadFile(encry_backup_buf, backup_info_xml))
{
IVMS_LOG_ERROR("platform.Maintenance", "Read File BackupInfo.xml Fail");
return false;
}
string backup_info_buf("");
if (!PrivateEncrypt::PrivateAESDecryptDBSetup(backup_info_buf, encry_backup_buf))
{
IVMS_LOG_ERROR("platform.Maintenance", "Decryption failed");
return false;
}
unique_ptr<proto::IProto> pro_result(new proto::CXmlProto);
pro_result->set_str(backup_info_buf);
int main_tables_num = pro_result->get_cnt("/BackupInfo/MainTable/Table");
IVMS_LOG_INFO("platform.Maintenance", "The backup file contains %d main tables.", main_tables_num);
string query_sql;
for (int i = 1; i <= main_tables_num; i++)
{
string table_node = StringUtil::str_fmt("/BackupInfo/MainTable/Table[%d]", i);
string main_schema_name = pro_result->get_a(table_node, "Schema");
string main_table_name = pro_result->get_a(table_node, "Name");
// 查询数据库中主表对应的分表
query_sql = str_fmt("select c.relname as the_tablename from pg_class c join pg_inherits i on i.inhrelid = c.oid join pg_class d on d.oid = i.inhparent JOIN pg_namespace pn ON pn.oid = d.relnamespace where pn.nspname = '%s' AND d.relname = '%s';",
main_schema_name.c_str(), main_table_name.c_str());
if (!rs.ExecuteQuery(query_sql))
{
IVMS_LOG_ERROR("platform.Maintenance", "Fail to exec sql: %s ", query_sql.c_str());
return false;
}
for (; !rs.IsEOF(); rs.Next())
{
// 子表名
string partition_table_name = rs.GetString("the_tablename");
// 在备份记录文件查找子表,若不存在则记录
size_t pos = backup_info_buf.find(partition_table_name);
if (pos == string::npos)
{
map_partition_table.insert(pair<string, string>(main_schema_name, partition_table_name));
}
}
}
// 删除子表
if (!map_partition_table.empty())
{
string del_sql;
for (auto del_table : map_partition_table)
{
del_sql = str_fmt("DROP TABLE %s.%s;", del_table.first.c_str(), del_table.second.c_str());
if (!rs.Execute(del_sql))
{
IVMS_LOG_ERROR("platform.Maintenance", "Fail to exec sql: %s ", del_sql.c_str());
return false;
}
}
}
IVMS_LOG_INFO("platform.Maintenance", "Backup File has been checked support Restore");
return true;
}
void CTimerBackup::DelManualArchlve()
{
boost::system::error_code ec;
shared_ptr<db_layer::CConnect> ptr_connect = nullptr;
ptr_connect = CVsmPlatformDBConn::Instance().ApplyConn();
if (ptr_connect == nullptr)
{
IVMS_LOG_ERROR("platform.Maintenance", "Conn Failed.");
return;
}
db_layer::CConnect& rs = *ptr_connect;
string sql = "SELECT count(id) FROM platform.backup_record WHERE is_local = 1;";
if (!rs.ExecuteQuery(sql))
{
IVMS_LOG_ERROR("platform.Maintenance", "Query Failed, sql is %s", sql.c_str());
return;
}
int record_num = rs.GetInt(0);
if (record_num > 3)
{
// 查看多出来多少,便删除多少
int count = record_num - 3;
sql = str_fmt("SELECT file_path FROM platform.backup_record WHERE is_local = 1 ORDER BY create_time ASC LIMIT %d;", count);
if (!rs.ExecuteQuery(sql))
{
IVMS_LOG_ERROR("platform.Maintenance", "Query Failed, sql is %s", sql.c_str());
return;
}
for (;!rs.IsEOF();rs.Next())
{
string del_file_name = rs.GetString("file_path");
if (!del_file_name.empty())
{
if (!boost::filesystem::remove_all(del_file_name, ec))
{
sql = str_fmt("DELETE FROM platform.backup_record WHERE file_path = %s;", del_file_name.c_str());
if (!CVsmPlatformDBConn::Instance().Execute(sql))
{
IVMS_LOG_ERROR("platform.Maintenance", "Execute [%s] Failed.", sql.c_str());
return;
}
}
else
{
IVMS_LOG_ERROR("platform.Maintenance", "Remove %s Failed.", del_file_name.c_str());
return;
}
}
}
}
return;
}
bool CTimerBackup::SendMsgToDataBaseService(string control_status)
{
CBackupConfigManager::DistributeBackupInfo port_info;
port_info.https_url = "/ISAPI/Bumblebee/DCC/V0/GetS2PConnPort";
//port_info.https_bodys = R"({"DatabaseRestore":{"RestoreTime":"111"}})";
port_info.https_bodys = R"({"DatabaseRestore":{}})";
if (!CBackupConfigManager::Instance().GetBeeAgentPort(port_info))
{
IVMS_LOG_ERROR("platform.Maintenance", "GetBackupStatus failed.");
return false;
}
int port = CBackupConfigManager::Instance().GetClusterBeeAgentPort();
if (port == 0)
{
IVMS_LOG_WARN("platform.Maintenance", "Fail to Get BeeAgent port.");
port = 8208;
}
shared_ptr<proto::IProto> parse = make_shared<proto::CRapidJsonProto>();
string guid = Bee::Base::GuidUtil::CreateGuid();
parse->set_v("/Guid", guid);
parse->set_v("/RequestData/Method", "ControlService");
parse->set_v("/RequestData/ServiceName", "PostgreSQL");
parse->set_v("/RequestData/Command", control_status.c_str());
string strReq = parse->get_str();
IVMS_LOG_INFO("platform.Maintenance", "BeeAgent strReq[%s].", strReq.c_str());
s2b_guid_ = guid;
auto client = std::make_shared<NotifyBeeAgentClient>(CConfigManager::Instance().GetDataBseIP(),
static_cast<PORT_T>(port));
/*VSMPlatform::CConfigManager::Instance().GetVSMPort().beagent_manager_ssl_port*/
if (client->NotifyBeeAgentClient::StartConnect())
{
if (client->NotifyBeeAgentClient::SendMasterBeeAgentService(strReq, guid))
{
IVMS_LOG_INFO("platform.Maintenance", "SUCC to send BeeAgent.");
client->NotifyBeeAgentClient::CloseConnect();
return true;
}
else
{
IVMS_LOG_ERROR("platform.Maintenance", "Fail to StartConnect BeeAgent.");
}
}
client->NotifyBeeAgentClient::CloseConnect();
IVMS_LOG_ERROR("platform.Maintenance", "BeeAgent Failed to deal PG service.");
return false;
}
void CTimerBackup::AutoIncreBackupRestore(CBackupConfigManager::DistributeBackupInfo backup_info)
{
CBackupConfigManager::Instance().IncreBackupRestore(backup_info);
}
string CTimerBackup::GetPluginVer(string file_path, string plugin_name)
{
string plugin_ver;
if (!boost::filesystem::exists(file_path))
{
IVMS_LOG_ERROR("platform.Maintenance", "%s.xml not exist, path : %s", plugin_name.c_str(), file_path.c_str());
return plugin_ver;
}
string file_buf;
if (!CFileBak::ReadFile(file_buf, file_path))
{
IVMS_LOG_ERROR("platform.Maintenance", "Read %s.xml fail", plugin_name.c_str());
return plugin_ver;
}
shared_ptr<proto::IProto> ptr_path(new proto::CXmlProto());
ptr_path->set_str(file_buf);
if (plugin_name == "platform" || plugin_name == "aihub")
{
plugin_ver = ptr_path->get_v("/Platform/Version");
}
else
{
plugin_ver = ptr_path->get_v("/Plugin/Version");
}
return plugin_ver;
}
std::string CTimerBackup::curl_escape_ex(const std::string& name)
{
char* escape_control = curl_escape(name.c_str(), (int)name.size());
string str_encode = name;
if (nullptr != escape_control)
{
str_encode = escape_control;
}
curl_free(escape_control);
return str_encode;
}
bool CTimerBackup::UploadToFTPOrSFTP(const DriveCloneConf &data_clone_conf, const std::string &str_local_file_path, string &str_ftp_file_path)
{
if (boost::filesystem::exists(str_local_file_path))
{
std::vector<std::string> vec_path;
Bee::Base::StringUtil::String2Array(vec_path, str_local_file_path, '\\');
if (!str_ftp_file_path.empty())
{
str_ftp_file_path += "/";
}
str_ftp_file_path += vec_path.back();
if (!CreateFTPOrSFTPFloders(data_clone_conf, str_ftp_file_path))
{
IVMS_LOG_ERROR("platform.Maintenance", "Upload to SFTP server FAILED !");
m_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
return false;
}
vector<pair<string, string>> vec_upload_files;
boost::filesystem::directory_iterator item_begin(str_local_file_path);
boost::filesystem::directory_iterator item_end;
for (; item_begin != item_end; item_begin++)
{
if (boost::filesystem::is_directory(*item_begin))
{
}
else
{
std::vector<std::string> vec_file_path;
Bee::Base::StringUtil::String2Array(vec_file_path, item_begin->path().string(), '\\');
std::string ftp_file_name = vec_file_path.back();
vec_upload_files.push_back(make_pair(ftp_file_name, item_begin->path().string()));
}
}
switch (data_clone_conf.em_clone_upload_location)
{
case DriveCloneConf::DriveCloneUploadLocation::SFTP:
{
if (!CTimerBackup::Instance().UploadToSFTP(data_clone_conf, vec_path.back(), vec_upload_files))
{
IVMS_LOG_ERROR("platform.Maintenance", "Upload to sftp server failed !");
m_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
return false;
}
}
break;
case DriveCloneConf::DriveCloneUploadLocation::FTP:
{
if (!CTimerBackup::Instance().UploadToFTP(data_clone_conf, str_ftp_file_path, vec_upload_files))
{
IVMS_LOG_ERROR("platform.Maintenance", "Upload to ftp server failed !");
m_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
return false;
}
}
break;
default:
{
IVMS_LOG_ERROR("platform.Maintenance", "Need not Upload to FTP/SFTP!");
}
break;
}
}
return true;
}
FTPTransProgressStruct CTimerBackup::GetFTPUploadProgress()
{
return ftp_upload_progress_;
}
int CTimerBackup::FTPTransCallBack(void* userdata, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
{
ftp_upload_progress_.up_finished_size = ulnow;
if (ftp_upload_progress_.up_total_size != 0)
{
ftp_upload_progress_.up_finished_percent = static_cast<UINT_T>((ftp_upload_progress_.up_finished_size * 100.0) / ftp_upload_progress_.up_total_size);
}
return 0;
}
bool CTimerBackup::GetUploadProgress()
{
switch (dc_bak_conf_Plan_.em_clone_upload_location)
{
case DriveCloneConf::DriveCloneUploadLocation::SFTP:
{
if (nullptr != ptr_ftp_storage_)
{
i_ftp_upload_percent_ = ptr_ftp_storage_->GetTransferProgess().i_persents;
IVMS_LOG_INFO("platform.Maintenance", "SFTP upload persent: %d", i_ftp_upload_percent_.load());
}
}
break;
case DriveCloneConf::DriveCloneUploadLocation::FTP:
{
i_ftp_upload_percent_ = GetFTPUploadProgress().up_finished_percent;
IVMS_LOG_INFO("platform.Maintenance", "FTP upload persent: %d", i_ftp_upload_percent_.load());
}
break;
default:
break;
}
return true;
}
void CTimerBackup::GetClusterBackupResoreStatus(UINT_T status_type)
{
bool is_stop = false;
bool is_sart = false;
while (true)
{
CBackupConfigManager::DistributeBackupInfo restore_status_info;
restore_status_info.https_url = "/ISAPI/Bumblebee/DCC/V0/BackupRestoreStatus";
restore_status_info.https_bodys = R"({"DatabaseRestore":{"RestoreTime":"%s", "BackupFileType":"", "BackupFilePath":"", "BackupFileID":""}})";
if (!CBackupConfigManager::Instance().GetBackupStatus(restore_status_info))
{
IVMS_LOG_ERROR("platform.Maintenance", "GetBackupStatus failed.");
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_RESTORE_FAIL)));
m_res_error_ = DRIVE_CLONE_RESTORE_FAIL;
i_sys_restore_percent_ = 100;
b_is_restore_running_ = false;
return;
}
int i_sys_dump_restore_percent = -1;
bool b_is_dump_restore_running = true;
int plan_status = -1;
CBackupConfigManager::Instance().GetClusterBackupRestoreStatus(i_sys_dump_restore_percent, b_is_dump_restore_running, plan_status);
if (status_type == DEF_BACKUP_PLAN)
{
if (plan_status < 0)
{
b_is_backup_plan_ = false;
IVMS_LOG_ERROR("platform.Maintenance", "GetClusterBackupRestoreStatus failed.");
return;
}
i_backup_plan_ = plan_status;
if (plan_status == 1)
{
b_is_backup_plan_ = false;
break;
}
}
else
{
if (i_sys_dump_restore_percent < 0)
{
IVMS_LOG_ERROR("platform.Maintenance", "GetClusterBackupRestoreStatus failed.");
return;
}
if (status_type == DEF_BACKUP_ONLY_CONFIG)
{
i_sys_dump_percent_ = i_sys_dump_restore_percent;
//b_is_dump_running_ = b_is_dump_restore_running;
}
else if (status_type == DEF_RSMBAK)
{
if (is_first_)
{
b_is_site_dump_percent_ = 0;
is_first_ = false;
}
else
{
b_is_site_dump_percent_ = i_sys_dump_restore_percent;
}
IVMS_LOG_INFO("platform.Maintenance", "b_is_site_dump_percent_ : [%d].", b_is_site_dump_percent_.load());
}
else
{
i_sys_restore_percent_ = i_sys_dump_restore_percent;
//b_is_restore_running_ = b_is_dump_restore_running;
if (i_sys_dump_restore_percent == 50 && !is_stop)
{
// 在执行还原前通知看门狗服务禁止对数据库进行拉起
string control_status = "Stop";
if (!SendMsgToDataBaseService(control_status))
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_RESTORE_FAIL)));
m_res_error_ = DRIVE_CLONE_RESTORE_FAIL;
IVMS_LOG_ERROR("platform.Maintenance", "SendMsgToDataBaseService Stop Failed.");
i_sys_dump_restore_percent = 100;
i_sys_restore_percent_ = i_sys_dump_restore_percent;
b_is_restore_running_ = false;
return;
}
is_stop = true;
CBackupConfigManager::DistributeBackupInfo restore_info;
restore_info.https_url = "/ISAPI/Bumblebee/DCC/V0/DatabaseRestore";
restore_info.https_bodys = Bee::Base::StringUtil::str_fmt(R"({"DatabaseRestore":{"RestoreTime":"%s", "BackupFileType":"%s", "BackupFilePath":"%s", "BackupFileID":"%s", "BackupPlanPath":"%s"}})",
restore_info_.restore_time.c_str(), std::to_string(restore_info_.backup_type).c_str(), restore_info_.backup_path.c_str(), std::to_string(restore_info_.backup_id).c_str(), restore_info_.backup_plan_path.c_str());
IVMS_LOG_INFO("platform.Maintenance", "https_url[%s], https_bodys[%s].", restore_info.https_url.c_str(), restore_info.https_bodys.c_str());
if (!CBackupConfigManager::Instance().IncreBackupRestore(restore_info))
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_RESTORE_FAIL)));
m_res_error_ = DRIVE_CLONE_RESTORE_FAIL;
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecuteDataRestoreOpt Execute Restore Failed.");
i_sys_restore_percent_ = 100;
b_is_restore_running_ = false;
return;
}
}
if (i_sys_dump_restore_percent == 90 && !is_sart)
{
// 文件替换完毕,通知看门狗启动数据库
string control_status = "Start";
if (!SendMsgToDataBaseService(control_status))
{
// Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_RESTORE_FAIL)));
// m_res_error_ = DRIVE_CLONE_RESTORE_FAIL;
IVMS_LOG_ERROR("platform.Maintenance", "SendMsgToDataBaseService Start Failed.");
// i_sys_dump_restore_percent = 100;
// i_sys_restore_percent_ = i_sys_dump_restore_percent;
// b_is_restore_running_ = false;
// return;
}
is_sart = true;
string postgresql_path = Bee::Base::StringUtil::StringReplace(PostgreSQL_path_.c_str(), "\\", "/");
CBackupConfigManager::DistributeBackupInfo special_info;
special_info.https_url = "/ISAPI/Bumblebee/DCC/V0/RestoreSpecial";
special_info.https_bodys = Bee::Base::StringUtil::str_fmt(R"({"DatabaseRestore":{"PostPath":"%s"}})", postgresql_path.c_str());
IVMS_LOG_INFO("platform.Maintenance", "https_url[%s], https_bodys[%s].", special_info.https_url.c_str(), special_info.https_bodys.c_str());
if (!CBackupConfigManager::Instance().IncreBackupRestore(special_info))
{
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_DATABASE_RESTORE_FAIL)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::ExecuteDataRestoreOpt RestoreSpecial Failed.");
i_sys_restore_percent_ = 100;
b_is_restore_running_ = false;
return;
}
// i_sys_restore_percent_ = 100;
// b_is_restore_running_ = false;
}
}
if (i_sys_dump_restore_percent > 100)
{
b_is_restore_running_ = false;
b_is_dump_running_ = false;
b_is_site_backup_finished_ = false;
m_res_error_ = DRIVE_CLONE_RESTORE_FAIL;
m_bak_error_ = DRIVE_CLONE_RESTORE_FAIL;
break;
}
if (i_sys_dump_restore_percent == 100)
{
b_is_restore_running_ = false;
b_is_dump_running_ = false;
b_is_site_backup_finished_ = false;
break;
}
}
Sleep(5000);
}
}
bool CTimerBackup::BackPlanChange(string src_path, string tar_path)
{
if (b_is_backup_plan_)
{
// 日志打印
Error::SetLastError(Error::ErrorCode(ERROR_CODE(CMS_MODULE_CMS), ERROR_CODE(CMS_IS_BACKUPING_RESTORING)));
IVMS_LOG_ERROR("platform.Maintenance", "CTimerBackup::DriveCloneRightAway Is Back Plan Now, Repeat CMDs");
return false;
}
// // 自动备份和手动备份不能同时执行
std::lock_guard<mutex> lock(mutex_pg_dump_);
b_is_backup_plan_ = true;
CBackupConfigManager::DistributeBackupInfo backup_info;
backup_info.https_url = "/ISAPI/Bumblebee/DCC/V0/BackupInfoChange";
backup_info.https_bodys = Bee::Base::StringUtil::str_fmt(R"({"DatabaseBackupRestore":{"SrcBackupFilePath":"%s", "TarBackupFilePath":"%s"}})"
, src_path.c_str(), tar_path.c_str());
IVMS_LOG_INFO("platform.Maintenance", "https_url [%s], https_bodys[%s]", backup_info.https_url.c_str(), backup_info.https_bodys.c_str());
if (!CBackupConfigManager::Instance().IncreBackupRestore(backup_info))
{
b_is_backup_plan_ = false;
IVMS_LOG_ERROR("platform.Maintenance", "Modify postgresql.conf failed.");
return false;
}
CThreadManager::Instance().PostTask(string(__FUNCTION__) + "[GetClusterBackupResoreStatus]",
std::bind(&CTimerBackup::GetClusterBackupResoreStatus, this, DEF_BACKUP_PLAN));
return true;
}
void CTimerBackup::CheckAndRecordStatue(vector<string> vec_db_path, string backup_info_xml)
{
IVMS_LOG_INFO("platform.Maintenance", "START CheckAndRecordStatue and clear.");
boost::system::error_code ec;
string abnormal_db;
string db_root_path;
for (auto sigle_db_path : vec_db_path)
{
if (!boost::filesystem::exists(sigle_db_path), ec)
{
IVMS_LOG_WARN("platform.Maintenance", "Backup DB file is missing, NO check DB status.");
return;
}
if (!CheckDBIsNormal(sigle_db_path))
{
boost::filesystem::path whole_db_path(sigle_db_path, (void*)boost::filesystem::native);
abnormal_db = whole_db_path.filename().string();
db_root_path = whole_db_path.parent_path().string();
break;
}
}
// 首先对加密内容进行解密
string encrypt_buf;
if (!CFileBak::ReadFile(encrypt_buf, backup_info_xml))
{
IVMS_LOG_ERROR("platform.Maintenance", "Read encrypt BackupInfo.xml fail, path = %s", backup_info_xml.c_str());
return;
}
// 解密后的内容进行保存
string decrypt_buf;
if (!PrivateEncrypt::PrivateAESDecryptDBSetup(decrypt_buf, encrypt_buf))
{
IVMS_LOG_ERROR("platform.Maintenance", "Decryption BackupInfo.xml failed");
return;
}
if (!CFileBak::WriteFile(backup_info_xml, decrypt_buf))
{
IVMS_LOG_FATAL("platform.Maintenance", "Write Decryption BackupInfo.xml File error");
return;
}
Sleep(500);
if (!boost::filesystem::exists(backup_info_xml), ec)
{
IVMS_LOG_WARN("platform.Maintenance", "BackupInfo.xml is missing, NO record DB status.");
return;
}
tinyxml2::XMLDocument doc;
doc.LoadFile(backup_info_xml.c_str());
tinyxml2::XMLElement *ptr_root = doc.RootElement();
if (ptr_root != nullptr)
{
tinyxml2::XMLElement *ptr_schema = ptr_root->FirstChildElement("DBInfo");
if (ptr_schema != nullptr)
{
// 记录之前先清空文件中的内容
ptr_schema->DeleteChildren();
// 开始向文件中插入备份文件中的数据模式及版本
int is_normal_status = -1; // 1代表正常,0代表异常
tinyxml2::XMLElement *ptr_element = doc.NewElement("DB");
//元素的属性 id,属性值为1
if (abnormal_db.empty())
{
IVMS_LOG_INFO("platform.Maintenance", "Backup DB File is normal.");
is_normal_status = 1;
}
else
{
is_normal_status = 0;
IVMS_LOG_WARN("platform.Maintenance", "DB - %s is error, path : %s.", abnormal_db.c_str(), db_root_path.c_str());
}
ptr_element->SetAttribute("Name", abnormal_db.c_str());
ptr_element->SetAttribute("Status", is_normal_status);
ptr_schema->InsertEndChild(ptr_element);
}
}
doc.SaveFile(backup_info_xml.c_str());
// 对写好的明文内容进行加密
if (!CFileBak::ReadFile(decrypt_buf, backup_info_xml))
{
IVMS_LOG_ERROR("platform.Maintenance", "Read encrypt BackupInfo.xml fail, path = %s", backup_info_xml.c_str());
return;
}
if (!PrivateEncrypt::PrivateAESEncryptDBSetup(encrypt_buf, decrypt_buf))
{
IVMS_LOG_ERROR("platform.Maintenance", " BackupInfo.xml Encryption failed");
return;
}
if (!CFileBak::WriteFile(backup_info_xml, encrypt_buf))
{
IVMS_LOG_FATAL("platform.Maintenance", "Write Encrypt BackupInfo.xml File error");
return;
}
Sleep(500);
for (auto file_path : vec_db_path)
{
if (boost::filesystem::exists(file_path, ec))
{
if (!boost::filesystem::remove(file_path, ec))
{
IVMS_LOG_WARN("platform.Maintenance", "DB - %s is missing, remove failed.", file_path.c_str());
break;
}
else
{
IVMS_LOG_INFO("platform.Maintenance", "DB - %s is delete.", file_path.c_str());
}
}
else
{
IVMS_LOG_WARN("platform.Maintenance", "DB - %s is missing, remove failed.", file_path.c_str());
break;
}
}
check_task_id_ = 0;
return;
}
bool CTimerBackup::CheckDBIsNormal(string db_path)
{
bool ret = false;
sqlite3_stmt *integrity = NULL;
sqlite3 *db;
string utf_path = Local2UTF8(db_path);
const char* c_utf_path = utf_path.c_str();
if (sqlite3_open(c_utf_path, &db) != SQLITE_OK)
{
return ret;
}
if (sqlite3_prepare_v2(db, "PRAGMA quick_check;", -1, &integrity, NULL) == SQLITE_OK)
{
while (sqlite3_step(integrity) == SQLITE_ROW)
{
const unsigned char *result = sqlite3_column_text(integrity, 0);
if (result&&strcmp((const char*)result, (const char *)"ok") == 0)
{
ret = true;
break;
}
}
sqlite3_finalize(integrity);
}
sqlite3_close(db);
return ret;
}
bool CTimerBackup::BackupCurDBFile(string src_db_path, string target_db_path)
{
int ret = SQLITE_ERROR;
sqlite3 *memoryDb;
ret = sqlite3_open(src_db_path.c_str(), &memoryDb);
if (ret != SQLITE_OK)
{
IVMS_LOG_ERROR("platform.Maintenance", "Open DB - %s Failed, err_info: %s.", src_db_path.c_str(), sqlite3_errmsg(memoryDb));
return false;
}
sqlite3 *pFile;
sqlite3_backup *pBackup;
string local_target_path = Local2UTF8(target_db_path);
const char* c_target_path = local_target_path.c_str();
ret = sqlite3_open(c_target_path, &pFile);
if (ret != SQLITE_OK)
{
IVMS_LOG_ERROR("platform.Maintenance", "sqlite3_open db[%s] failed, err_code : %d, err_info: %s.", target_db_path.c_str(), sqlite3_errcode(pFile), sqlite3_errmsg(pFile));
(void)sqlite3_close(pFile);
return false;
}
pBackup = sqlite3_backup_init(pFile, "main", memoryDb, "main");
if (pBackup)
{
do
{
ret = sqlite3_backup_step(pBackup, -1);
} while (ret == SQLITE_OK || ret == SQLITE_BUSY || ret == SQLITE_LOCKED);
sqlite3_backup_finish(pBackup);
}
else
{
IVMS_LOG_ERROR("platform.Maintenance", "sqlite3_backup_init failed, err_code : %d, err_info: %s.", sqlite3_errcode(pFile), sqlite3_errmsg(pFile));
sqlite3_close(memoryDb);
sqlite3_close(pFile);
return false;
}
sqlite3_close(memoryDb);
sqlite3_close(pFile);
IVMS_LOG_INFO("platform.Maintenance", "SUCC to backup DB : %s.", target_db_path.c_str());
return true;
}
bool CTimerBackup::CheckFtpPathFormat(const std::string& ftp_path)
{
bool ret = false;
do
{
if (ftp_path.empty())
{
IVMS_LOG_DEBUG("platform.Maintenance", "The ftp path is empty and returns directly.");
ret = true;
break;
}
// 前后不能存在左斜杠,不能存在多个左斜杠在一起的情况
if ('/' == ftp_path[0]
|| '/' == ftp_path[ftp_path.size() - 1]
|| std::string::npos != ftp_path.find("//"))
{
IVMS_LOG_ERROR("platform.Maintenance", "Ftp path format error, path[%s].", ftp_path.c_str());
break;
}
bool is_illegal = false;
std::vector<std::string> vc_path;
Bee::Base::StringUtil::String2Array(vc_path, ftp_path, '/');
for (auto& iter_name : vc_path)
{
// 文件夹名不能为空
if (iter_name.empty())
{
IVMS_LOG_ERROR("platform.Maintenance", "Ftp folder name cannot be empty.");
is_illegal = true;
break;
}
// 前后不能存在空格
if (' ' == iter_name[0]
|| ' ' == iter_name[iter_name.size() - 1]
|| "." == iter_name
|| '.' == iter_name[iter_name.size() - 1])
{
IVMS_LOG_ERROR("platform.Maintenance", "There are spaces and dots before and after the ftp folder name, name[%s].", iter_name.c_str());
is_illegal = true;
break;
}
if (ContainsIllegalCharacters(iter_name))
{
IVMS_LOG_ERROR("platform.Maintenance", "Illegal characters exist before and after the ftp folder name, name[%s].", iter_name.c_str());
is_illegal = true;
break;
}
}
ret = !is_illegal;
} while (false);
if (!ret)
{
SetLastError(CMS_ERR_FTP_PATH_FORMAT_ERROR);
IVMS_LOG_ERROR("platform.Maintenance", "FTP path format error, path[%s].", ftp_path.c_str());
}
return ret;
}
}
浙公网安备 33010602011771号