RemoteConfig.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /**
  2. * Tencent is pleased to support the open source community by making Tars available.
  3. *
  4. * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
  5. *
  6. * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
  7. * in compliance with the License. You may obtain a copy of the License at
  8. *
  9. * https://opensource.org/licenses/BSD-3-Clause
  10. *
  11. * Unless required by applicable law or agreed to in writing, software distributed
  12. * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  13. * CONDITIONS OF ANY KIND, either express or implied. See the License for the
  14. * specific language governing permissions and limitations under the License.
  15. */
  16. #include "servant/RemoteConfig.h"
  17. #include "util/tc_file.h"
  18. #include "servant/Communicator.h"
  19. #include "servant/RemoteNotify.h"
  20. #include "servant/Application.h"
  21. #include <fstream>
  22. namespace tars
  23. {
  24. int RemoteConfig::setConfigInfo(const CommunicatorPtr &comm, const string &obj, const string & app, const string &serverName, const string& basePath,const string& setdivision, int maxBakNum)
  25. {
  26. _comm = comm;
  27. if(!obj.empty())
  28. {
  29. _configPrx = _comm->stringToProxy<ConfigPrx>(obj);
  30. }
  31. _app = app;
  32. _serverName = serverName;
  33. _basePath = basePath;
  34. _maxBakNum = maxBakNum;
  35. _setdivision = setdivision;
  36. return 0;
  37. }
  38. bool RemoteConfig::addConfig(const string & sFileName, string &buffer, bool bAppConfigOnly)
  39. {
  40. TC_LockT<TC_ThreadMutex> lock(_mutex);
  41. try
  42. {
  43. string sFullFileName = _basePath + FILE_SEP + sFileName;
  44. string newFile = getRemoteFile(sFileName, bAppConfigOnly);
  45. if (newFile.empty() || !TC_File::isFileExist(newFile))//拉取不到配置中心的配置文件
  46. {
  47. if(!TC_File::isFileExist(newFile)) //获取本地配置成功,返回成功,但需要告警一下。
  48. {
  49. buffer = "[fail] get remote config:" + sFileName + "fail,use the local config.";
  50. return true;
  51. }
  52. throw runtime_error("access file error:" + newFile);
  53. }
  54. if (TC_File::load2str(newFile) != TC_File::load2str(sFullFileName))
  55. {
  56. for (int i = _maxBakNum - 1; i >= 1; --i)
  57. {
  58. if (TC_File::isFileExist(index2file(sFullFileName, i)))
  59. {
  60. localRename(index2file(sFullFileName, i), index2file(sFullFileName, i+1));
  61. }
  62. }
  63. if (TC_File::isFileExist(sFullFileName))
  64. {
  65. localRename(sFullFileName, index2file(sFullFileName, 1));
  66. }
  67. }
  68. localRename(newFile, sFullFileName);
  69. assert(TC_File::isFileExist(sFullFileName));
  70. //assert(!access(sFullFileName.c_str(), R_OK));
  71. buffer = "[succ] get remote config:" + sFileName;
  72. return true;
  73. }
  74. catch (std::exception& e)
  75. {
  76. buffer = "[fail] get remote config '" + sFileName + "' error:" + string(e.what());
  77. }
  78. catch (...)
  79. {
  80. buffer = "[fail] get remote config '" + sFileName + "' unknown error";
  81. }
  82. return false;
  83. }
  84. string RemoteConfig::getRemoteFile(const string &sFileName, bool bAppConfigOnly)
  85. {
  86. if (_configPrx)
  87. {
  88. string stream;
  89. int ret = -1;
  90. for(int i = 0; i < 2;i++)
  91. {
  92. try
  93. {
  94. if(_setdivision.empty())
  95. {
  96. ret = _configPrx->loadConfig(_app, (bAppConfigOnly ? "" : _serverName), sFileName, stream, ServerConfig::Context);
  97. }
  98. else
  99. {
  100. struct ConfigInfo confInfo;
  101. confInfo.appname = _app;
  102. confInfo.servername = (bAppConfigOnly ? "" : _serverName);
  103. confInfo.filename = sFileName;
  104. confInfo.bAppOnly = bAppConfigOnly;
  105. confInfo.setdivision = _setdivision;
  106. ret = _configPrx->loadConfigByInfo(confInfo,stream, ServerConfig::Context);
  107. }
  108. break;
  109. }catch(std::exception& e){
  110. //
  111. }catch (...){
  112. //
  113. }
  114. }
  115. if (ret != 0 || stream.empty())
  116. {
  117. throw runtime_error("remote config file is empty:" + sFileName);
  118. }
  119. string newFile = _basePath + FILE_SEP + sFileName + "." + TC_Common::tostr(time(NULL));
  120. std::ofstream out(newFile.c_str());
  121. string result;
  122. if (out)
  123. {
  124. out << stream;//如果硬盘满了,是否能写入成功需要进行判断。
  125. out.flush();
  126. if(out.bad())
  127. {
  128. out.close();
  129. result = "[fail] copy stream to disk error." ;
  130. RemoteNotify::getInstance()->report(result);
  131. return "";
  132. }
  133. else
  134. {
  135. out.close();
  136. return newFile;
  137. }
  138. }
  139. }
  140. return "";
  141. }
  142. string RemoteConfig::index2file(const string & sFullFileName, int index)
  143. {
  144. return sFullFileName + "." + TC_Common::tostr(index) + ".bak";
  145. }
  146. void RemoteConfig::localRename(const string& oldFile, const string& newFile)
  147. {
  148. #if TARGET_PLATFORM_WINDOWS
  149. //by goodenpei,windows下面先remove后rename,否则rename会失败
  150. if(TC_File::isFileExist(oldFile) && TC_File::isFileExist(newFile))
  151. {
  152. ::remove(newFile.c_str());
  153. }
  154. #endif
  155. if (::rename(oldFile.c_str(), newFile.c_str()) != 0)
  156. {
  157. throw runtime_error("rename file error:" + oldFile + "->" + newFile);
  158. }
  159. }
  160. string RemoteConfig::recoverSysConfig(const string & sFullFileName)
  161. {
  162. try
  163. {
  164. for (int i = 1; i <= _maxBakNum; ++i)
  165. {
  166. if (TC_File::isFileExist(index2file(sFullFileName, i)))
  167. {
  168. localRename(index2file(sFullFileName, i), sFullFileName);
  169. return "[succ] recover file:" + index2file(sFullFileName, i);
  170. }
  171. }
  172. }
  173. catch (std::exception& e)
  174. {
  175. return "[fail] recover config error:" + string(e.what());
  176. }
  177. catch (...)
  178. {
  179. return "[fail] recover config error";
  180. }
  181. return "[fail] no backup file.";
  182. }
  183. }