mirror of
https://gitee.com/TarsCloud/TarsCpp.git
synced 2024-12-22 22:16:38 +08:00
214 lines
6.2 KiB
C++
Executable File
214 lines
6.2 KiB
C++
Executable File
/**
|
||
* Tencent is pleased to support the open source community by making Tars available.
|
||
*
|
||
* Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
|
||
*
|
||
* Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
|
||
* in compliance with the License. You may obtain a copy of the License at
|
||
*
|
||
* https://opensource.org/licenses/BSD-3-Clause
|
||
*
|
||
* Unless required by applicable law or agreed to in writing, software distributed
|
||
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||
* specific language governing permissions and limitations under the License.
|
||
*/
|
||
|
||
#include "servant/TarsConfig.h"
|
||
#include "util/tc_file.h"
|
||
#include "servant/Communicator.h"
|
||
#include "servant/TarsNotify.h"
|
||
#include "servant/Application.h"
|
||
#include <fstream>
|
||
|
||
namespace tars
|
||
{
|
||
|
||
int TarsRemoteConfig::setConfigInfo(const CommunicatorPtr &comm, const string &obj, const string & app, const string &serverName, const string& basePath,const string& setdivision, int maxBakNum)
|
||
{
|
||
_comm = comm;
|
||
if(!obj.empty())
|
||
{
|
||
_configPrx = _comm->stringToProxy<ConfigPrx>(obj);
|
||
}
|
||
_app = app;
|
||
_serverName = serverName;
|
||
_basePath = basePath;
|
||
_maxBakNum = maxBakNum;
|
||
_setdivision = setdivision;
|
||
return 0;
|
||
}
|
||
|
||
bool TarsRemoteConfig::addConfig(const string & sFileName, string &buffer, bool bAppConfigOnly)
|
||
{
|
||
TC_LockT<TC_ThreadMutex> lock(_mutex);
|
||
|
||
try
|
||
{
|
||
string sFullFileName = _basePath + FILE_SEP + sFileName;
|
||
|
||
string newFile = getRemoteFile(sFileName, bAppConfigOnly);
|
||
|
||
if (newFile.empty() || !TC_File::isFileExist(newFile))//拉取不到配置中心的配置文件
|
||
{
|
||
if(!TC_File::isFileExist(newFile)) //获取本地配置成功,返回成功,但需要告警一下。
|
||
{
|
||
buffer = "[fail] get remote config:" + sFileName + "fail,use the local config.";
|
||
|
||
return true;
|
||
}
|
||
throw runtime_error("access file error:" + newFile);
|
||
}
|
||
|
||
if (TC_File::load2str(newFile) != TC_File::load2str(sFullFileName))
|
||
{
|
||
for (int i = _maxBakNum - 1; i >= 1; --i)
|
||
{
|
||
if (TC_File::isFileExist(index2file(sFullFileName, i)))
|
||
{
|
||
localRename(index2file(sFullFileName, i), index2file(sFullFileName, i+1));
|
||
}
|
||
}
|
||
|
||
if (TC_File::isFileExist(sFullFileName))
|
||
{
|
||
localRename(sFullFileName, index2file(sFullFileName, 1));
|
||
}
|
||
}
|
||
|
||
localRename(newFile, sFullFileName);
|
||
|
||
assert(TC_File::isFileExist(sFullFileName));
|
||
//assert(!access(sFullFileName.c_str(), R_OK));
|
||
|
||
buffer = "[succ] get remote config:" + sFileName;
|
||
|
||
return true;
|
||
}
|
||
catch (std::exception& e)
|
||
{
|
||
buffer = "[fail] get remote config '" + sFileName + "' error:" + string(e.what());
|
||
}
|
||
catch (...)
|
||
{
|
||
buffer = "[fail] get remote config '" + sFileName + "' unknown error";
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
string TarsRemoteConfig::getRemoteFile(const string &sFileName, bool bAppConfigOnly)
|
||
{
|
||
if (_configPrx)
|
||
{
|
||
string stream;
|
||
int ret = -1;
|
||
for(int i = 0; i < 2;i++)
|
||
{
|
||
try
|
||
{
|
||
if(_setdivision.empty())
|
||
{
|
||
ret = _configPrx->loadConfig(_app, (bAppConfigOnly ? "" : _serverName), sFileName, stream, ServerConfig::Context);
|
||
}
|
||
else
|
||
{
|
||
struct ConfigInfo confInfo;
|
||
confInfo.appname = _app;
|
||
confInfo.servername = (bAppConfigOnly ? "" : _serverName);
|
||
confInfo.filename = sFileName;
|
||
confInfo.bAppOnly = bAppConfigOnly;
|
||
confInfo.setdivision = _setdivision;
|
||
ret = _configPrx->loadConfigByInfo(confInfo,stream, ServerConfig::Context);
|
||
}
|
||
|
||
break;
|
||
}catch(std::exception& e){
|
||
//
|
||
}catch (...){
|
||
//
|
||
}
|
||
}
|
||
|
||
if (ret != 0 || stream.empty())
|
||
{
|
||
throw runtime_error("remote config file is empty:" + sFileName);
|
||
}
|
||
|
||
|
||
string newFile = _basePath + "/" + sFileName + "." + TC_Common::tostr(time(NULL));
|
||
|
||
std::ofstream out(newFile.c_str());
|
||
|
||
string result;
|
||
if (out)
|
||
{
|
||
out << stream;//如果硬盘满了,是否能写入成功需要进行判断。
|
||
out.flush();
|
||
if(out.bad())
|
||
{
|
||
out.close();
|
||
result = "[fail] copy stream to disk error." ;
|
||
TarsRemoteNotify::getInstance()->report(result);
|
||
return "";
|
||
}
|
||
else
|
||
{
|
||
out.close();
|
||
return newFile;
|
||
}
|
||
}
|
||
}
|
||
return "";
|
||
}
|
||
|
||
string TarsRemoteConfig::index2file(const string & sFullFileName, int index)
|
||
{
|
||
return sFullFileName + "." + TC_Common::tostr(index) + ".bak";
|
||
}
|
||
|
||
void TarsRemoteConfig::localRename(const string& oldFile, const string& newFile)
|
||
{
|
||
#if TARGET_PLATFORM_WINDOWS
|
||
//by goodenpei,windows下面先remove后rename,否则rename会失败
|
||
if (TC_File::isFileExist(oldFile) && TC_File::isFileExist(newFile))
|
||
{
|
||
::remove(newFile.c_str());
|
||
}
|
||
#endif
|
||
if (::rename(oldFile.c_str(), newFile.c_str()) != 0)
|
||
{
|
||
throw runtime_error("rename file error:" + oldFile + "->" + newFile);
|
||
}
|
||
}
|
||
|
||
string TarsRemoteConfig::recoverSysConfig(const string & sFullFileName)
|
||
{
|
||
try
|
||
{
|
||
for (int i = 1; i <= _maxBakNum; ++i)
|
||
{
|
||
if (TC_File::isFileExist(index2file(sFullFileName, i)))
|
||
{
|
||
localRename(index2file(sFullFileName, i), sFullFileName);
|
||
|
||
return "[succ] recover file:" + index2file(sFullFileName, i);
|
||
}
|
||
}
|
||
}
|
||
catch (std::exception& e)
|
||
{
|
||
return "[fail] recover config error:" + string(e.what());
|
||
}
|
||
catch (...)
|
||
{
|
||
return "[fail] recover config error";
|
||
}
|
||
|
||
return "[fail] no backup file.";
|
||
}
|
||
|
||
}
|
||
|
||
|