ws_topologyService.cpp 63 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #pragma warning (disable : 4786)
  14. #include "math.h"
  15. #include "ws_topologyService.hpp"
  16. #include "workunit.hpp"
  17. #include "mpbase.hpp"
  18. #include "daclient.hpp"
  19. #include "dadfs.hpp"
  20. #include "dafdesc.hpp"
  21. #include "dasds.hpp"
  22. #include "danqs.hpp"
  23. #include "swapnodelib.hpp"
  24. #include "dalienv.hpp"
  25. #ifdef _USE_ZLIB
  26. #include "zcrypt.hpp"
  27. #endif
  28. #include "exception_util.hpp"
  29. #include "jwrapper.hpp"
  30. #define SDS_LOCK_TIMEOUT 30000
  31. static const char* FEATURE_URL = "ClusterTopologyAccess";
  32. static const char* MACHINE_URL = "MachineInfoAccess";
  33. static const unsigned THORSTATUSDETAILS_REFRESH_MINS = 1;
  34. static const long LOGFILESIZELIMIT = 100000; //Limit page size to 100k
  35. static const long AVERAGELOGROWSIZE = 10000;
  36. const char* TEMPZIPDIR = "tempzipfiles";
  37. void CWsTopologyEx::init(IPropertyTree *cfg, const char *process, const char *service)
  38. {
  39. StringBuffer xpath;
  40. if (!daliClientActive())
  41. {
  42. ERRLOG("No Dali Connection Active.");
  43. throw MakeStringException(ECLWATCH_CANNOT_CONNECT_DALI, "No Connection to Dali server is active. Please specify a Dali server in the configuration file.");
  44. }
  45. m_envFactory.setown( getEnvironmentFactory() );
  46. //load threshold values for monitoring cpu load, disk/memory usage
  47. xpath.clear().appendf("Software/EspProcess[@name=\"%s\"]/EspService[@name=\"%s\"]", process, service);
  48. Owned<IPropertyTree> pServiceNode = cfg->getPropTree(xpath.str());
  49. m_cpuThreshold = pServiceNode->getPropInt("@warnIfCpuLoadOver", 95);
  50. loadThresholdValue(pServiceNode, "@warnIfFreeStorageUnder", m_diskThreshold, m_bDiskThresholdIsPercentage);
  51. loadThresholdValue(pServiceNode, "@warnIfFreeMemoryUnder", m_memThreshold, m_bMemThresholdIsPercentage);
  52. m_bEncapsulatedSystem = false;
  53. StringBuffer systemUseRewrite;
  54. xpath.clear().appendf("Software/EspProcess[@name=\"%s\"]/EspService[@name=\"%s\"]/SystemUseRewrite", process, service);
  55. cfg->getProp(xpath.str(), systemUseRewrite);
  56. if (streq(systemUseRewrite.str(), "true"))
  57. m_bEncapsulatedSystem = true;
  58. xpath.clear().appendf("Software/EspProcess[@name=\"%s\"]/EspService[@name=\"%s\"]/PreflightProcessFilter", process, service);
  59. cfg->getProp(xpath.str(), m_preflightProcessFilter);
  60. xpath.clear().appendf("Software/EspProcess[@name=\"%s\"]/EspService[@name=\"%s\"]/DefaultTargetCluster/@name", process, service);
  61. if (cfg->hasProp(xpath.str()))
  62. {
  63. defaultTargetClusterName.set(cfg->queryProp(xpath.str()));
  64. xpath.clear().appendf("Software/EspProcess[@name=\"%s\"]/EspService[@name=\"%s\"]/DefaultTargetCluster/@prefix", process, service);
  65. if (cfg->hasProp(xpath.str()))
  66. defaultTargetClusterPrefix.set(cfg->queryProp(xpath.str()));
  67. }
  68. m_enableSNMP = false;
  69. }
  70. StringBuffer& CWsTopologyEx::getAcceptLanguage(IEspContext& context, StringBuffer& acceptLanguage)
  71. {
  72. context.getAcceptLanguage(acceptLanguage);
  73. if (!acceptLanguage.length())
  74. {
  75. acceptLanguage.set("en");
  76. return acceptLanguage;
  77. }
  78. acceptLanguage.setLength(2);
  79. VStringBuffer languageFile("%ssmc_xslt/nls/%s/hpcc.xml", getCFD(), acceptLanguage.str());
  80. if (!checkFileExists(languageFile.str()))
  81. acceptLanguage.set("en");
  82. return acceptLanguage;
  83. }
  84. void CWsTopologyEx::loadThresholdValue(IPropertyTree* pServiceNode, const char* attrName, unsigned int& thresholdValue,
  85. bool& bThresholdIsPercentage)
  86. {
  87. const char* threshold = pServiceNode->queryProp(attrName);
  88. if (threshold && *threshold)
  89. {
  90. thresholdValue = atoi(threshold);
  91. StringBuffer buf(threshold);
  92. buf.toUpperCase();
  93. bThresholdIsPercentage = strstr(buf.str(), "MB") == NULL;
  94. }
  95. else
  96. {
  97. thresholdValue = 95;
  98. bThresholdIsPercentage = true;
  99. }
  100. }
  101. bool CWsTopologyEx::onTpSwapNode(IEspContext &context,IEspTpSwapNodeRequest &req, IEspTpSwapNodeResponse &resp)
  102. {
  103. try
  104. {
  105. if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Full, false))
  106. throw MakeStringException(ECLWATCH_TOPOLOGY_ACCESS_DENIED, "Failed to Swap Node. Permission denied.");
  107. //another client (like configenv) may have updated the constant environment so reload it
  108. m_envFactory->validateCache();
  109. bool res = swapNode(req.getCluster(),req.getOldIP(),req.getNewIP());
  110. resp.setTpSwapNodeResult(res);
  111. StringBuffer path;
  112. path.appendf("/Environment/Software/ThorCluster[@name='%s']", req.getCluster());
  113. StringBuffer encodedXpath;
  114. JBASE64_Encode(path, path.length(), encodedXpath, false);
  115. path.clear().append("/WsTopology/TpMachineQuery?Type=THORMACHINES&Cluster=");
  116. path.append(req.getCluster()).append("&Path=").append(encodedXpath);
  117. resp.setRedirectUrl(path.str());
  118. }
  119. catch(IException* e)
  120. {
  121. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  122. }
  123. return true;
  124. }
  125. bool CWsTopologyEx::onTpSetMachineStatus(IEspContext &context,IEspTpSetMachineStatusRequest &req, IEspTpSetMachineStatusResponse &resp)
  126. {
  127. try
  128. {
  129. if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Write, false))
  130. throw MakeStringException(ECLWATCH_TOPOLOGY_ACCESS_DENIED, "Failed to Set Machine Status. Permission denied.");
  131. resp.setTpSetMachineStatusResult(true);
  132. }
  133. catch(IException* e)
  134. {
  135. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  136. }
  137. return true;
  138. }
  139. bool CWsTopologyEx::onTpLogFileDisplay(IEspContext &context,IEspTpLogFileRequest &req, IEspTpLogFileResponse &resp)
  140. {
  141. onTpLogFile(context, req, resp);
  142. return true;
  143. }
  144. bool CWsTopologyEx::onTpLogFile(IEspContext &context,IEspTpLogFileRequest &req, IEspTpLogFileResponse &resp)
  145. {
  146. try
  147. {
  148. if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Read, false))
  149. throw MakeStringException(ECLWATCH_TOPOLOGY_ACCESS_DENIED, "Failed to get Log File. Permission denied.");
  150. const char* name = req.getName();
  151. const char* type = req.getType();
  152. if (!name || !*name)
  153. throw MakeStringException(ECLWATCH_INVALID_FILE_NAME,"File name not specified.");
  154. if (!type || !*type)
  155. throw MakeStringException(ECLWATCH_INVALID_FILE_NAME,"File type not specified.");
  156. double version = context.getClientVersion();
  157. if (version >= 1.20)
  158. {
  159. StringBuffer acceptLanguage;
  160. resp.setAcceptLanguage(getAcceptLanguage(context, acceptLanguage).str());
  161. }
  162. if (streq(type,"thormaster_log") || streq(type,"tpcomp_log"))
  163. {
  164. readTpLogFile(context, name, type, req, resp);
  165. }
  166. else if (streq(type,"xml"))
  167. {
  168. StringBuffer redirect;
  169. redirect.append("/WsTopology/TpXMLFile");
  170. redirect.appendf("?Name=%s", req.getName());
  171. resp.setRedirectUrl(redirect.str());
  172. }
  173. }
  174. catch(IException* e)
  175. {
  176. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  177. }
  178. return true;
  179. }
  180. bool CWsTopologyEx::onSystemLog(IEspContext &context,IEspSystemLogRequest &req, IEspSystemLogResponse &resp)
  181. {
  182. try
  183. {
  184. if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Read, false))
  185. throw MakeStringException(ECLWATCH_TOPOLOGY_ACCESS_DENIED, "Failed to get Log File. Permission denied.");
  186. const char* name = req.getName();
  187. if (!name || !*name)
  188. throw MakeStringException(ECLWATCH_INVALID_FILE_NAME,"File name not specified.");
  189. StringBuffer logname;
  190. const char* type = req.getType();
  191. if (type && !strcmp(type,"thormaster_log"))
  192. {
  193. logname.append(CCluster(name)->queryRoot()->queryProp("LogFile"));
  194. }
  195. else
  196. {
  197. logname = name;
  198. }
  199. int nZip = req.getZip();
  200. //Remove path from file name
  201. char* ppStr = (char*) logname.str();
  202. char* pStr = strchr(ppStr, '/');
  203. while (pStr)
  204. {
  205. ppStr = pStr+1;
  206. pStr = strchr(ppStr, '/');
  207. }
  208. pStr = strchr(ppStr, '\\');
  209. while (pStr)
  210. {
  211. ppStr = pStr+1;
  212. pStr = strchr(ppStr, '\\');
  213. }
  214. StringBuffer fileName, headerStr;
  215. if (ppStr && *ppStr)
  216. {
  217. fileName.append(ppStr);
  218. }
  219. else
  220. {
  221. fileName.append("SystemLog");
  222. }
  223. headerStr.appendf("attachment;filename=%s", fileName.str());
  224. if (nZip > 2)
  225. headerStr.append(".gz");
  226. else if (nZip > 1)
  227. headerStr.append(".zip");
  228. Owned<IFile> rFile = createIFile(logname.str());
  229. if (!rFile)
  230. throw MakeStringException(ECLWATCH_CANNOT_OPEN_FILE,"Cannot open file %s.", logname.str());
  231. OwnedIFileIO rIO = rFile->openShared(IFOread,IFSHfull);
  232. if (!rIO)
  233. throw MakeStringException(ECLWATCH_CANNOT_READ_FILE,"Cannot read file %s.",logname.str());
  234. offset_t fileSize = rFile->size();
  235. StringBuffer tmpBuf;
  236. tmpBuf.ensureCapacity((unsigned)fileSize);
  237. tmpBuf.setLength((unsigned)fileSize);
  238. size32_t nRead = rIO->read(0, (size32_t) fileSize, (char*)tmpBuf.str());
  239. if (nRead != fileSize)
  240. throw MakeStringException(ECLWATCH_CANNOT_READ_FILE, "Failed to read file %s.", logname.str());
  241. if (nZip < 2)
  242. {
  243. MemoryBuffer membuff;
  244. membuff.setBuffer(tmpBuf.length(), (void*)tmpBuf.str());
  245. resp.setThefile(membuff);
  246. resp.setThefile_mimetype(HTTP_TYPE_TEXT_PLAIN);
  247. context.addCustomerHeader("Content-disposition", headerStr.str());
  248. }
  249. else
  250. {
  251. #ifndef _USE_ZLIB
  252. throw MakeStringException(ECLWATCH_CANNOT_COMPRESS_DATA,"The data cannot be compressed.");
  253. #else
  254. StringBuffer ifname;
  255. unsigned threadID = (unsigned) (memsize_t) GetCurrentThreadId();
  256. if (nZip > 2)
  257. ifname.appendf("%s%sT%xAT%x", TEMPZIPDIR, PATHSEPSTR, threadID, msTick());
  258. else
  259. ifname.appendf("%s%sT%xAT%x.zip", TEMPZIPDIR, PATHSEPSTR, threadID, msTick());
  260. int ret = 0;
  261. IZZIPor* Zipor = createZZIPor();
  262. if (nZip > 2)
  263. ret = Zipor->gzipToFile(tmpBuf.length(), (void*)tmpBuf.str(), ifname.str());
  264. else
  265. ret = Zipor->zipToFile(tmpBuf.length(), (void*)tmpBuf.str(), fileName.str(), ifname.str());
  266. releaseIZ(Zipor);
  267. if (ret < 0)
  268. {
  269. Owned<IFile> rFile = createIFile(ifname.str());
  270. if (rFile->exists())
  271. rFile->remove();
  272. throw MakeStringException(ECLWATCH_CANNOT_COMPRESS_DATA,"The data cannot be compressed.");
  273. }
  274. int outlen = 0;
  275. unsigned char* outd = NULL;
  276. ret = loadFile(ifname.str(), outlen, outd);
  277. if(ret < 0 || outlen < 1 || !outd || !*outd)
  278. {
  279. Owned<IFile> rFile = createIFile(ifname.str());
  280. if (rFile->exists())
  281. rFile->remove();
  282. if (outd)
  283. free(outd);
  284. throw MakeStringException(ECLWATCH_CANNOT_COMPRESS_DATA,"The data cannot be compressed.");
  285. }
  286. MemoryBuffer membuff;
  287. membuff.setBuffer(outlen, (void*)outd);
  288. resp.setThefile(membuff);
  289. if (nZip > 2)
  290. resp.setThefile_mimetype("application/x-gzip");
  291. else
  292. resp.setThefile_mimetype("application/zip");
  293. context.addCustomerHeader("Content-disposition", headerStr.str());
  294. Owned<IFile> rFile1 = createIFile(ifname.str());
  295. if (rFile1->exists())
  296. rFile1->remove();
  297. if (outd)
  298. free(outd);
  299. #endif
  300. }
  301. }
  302. catch(IException* e)
  303. {
  304. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  305. }
  306. return true;
  307. }
  308. bool CWsTopologyEx::onTpXMLFile(IEspContext &context,IEspTpXMLFileRequest &req, IEspTpXMLFileResponse &resp)
  309. {
  310. try
  311. {
  312. if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Read, false))
  313. throw MakeStringException(ECLWATCH_TOPOLOGY_ACCESS_DENIED, "Failed to get Configuration File. Permission denied.");
  314. StringBuffer strBuff, xmlBuff;
  315. strBuff.append("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><?xml-stylesheet href=\"../esp/xslt/xmlformatter.xsl\" type=\"text/xsl\"?>");
  316. getThorXml(req.getName(),xmlBuff);
  317. strBuff.append(xmlBuff);
  318. MemoryBuffer membuff;
  319. membuff.setBuffer(strBuff.length(), (void*)strBuff.toCharArray());
  320. resp.setThefile_mimetype(HTTP_TYPE_APPLICATION_XML);
  321. resp.setThefile(membuff);
  322. }
  323. catch(IException* e)
  324. {
  325. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  326. }
  327. return true;
  328. }
  329. void CWsTopologyEx::getThorXml(const char *cluster,StringBuffer& returnStr)
  330. {
  331. CCluster conn(cluster);
  332. toXML(conn->queryRoot(), returnStr);
  333. }
  334. void CWsTopologyEx::getThorLog(const char *cluster,MemoryBuffer& returnbuff)
  335. {
  336. StringBuffer logname;
  337. logname.append(CCluster(cluster)->queryRoot()->queryProp("LogFile"));
  338. Owned<IFile> rFile = createIFile(logname.str());
  339. if (!rFile)
  340. throw MakeStringException(ECLWATCH_CANNOT_OPEN_FILE,"Cannot open file %s.",logname.str());
  341. OwnedIFileIO rIO = rFile->openShared(IFOread,IFSHfull);
  342. if (!rIO)
  343. throw MakeStringException(ECLWATCH_CANNOT_READ_FILE,"Cannot read file %s.",logname.str());
  344. read(rIO, 0, (size32_t)-1, returnbuff);
  345. }
  346. int CWsTopologyEx::loadFile(const char* fname, int& len, unsigned char* &buf, bool binary)
  347. {
  348. len = 0;
  349. buf = NULL;
  350. FILE* fp = fopen(fname, binary?"rb":"rt");
  351. if (fp)
  352. {
  353. char* buffer[1024];
  354. int bytes;
  355. for (;;)
  356. {
  357. bytes = fread(buffer, 1, sizeof(buffer), fp);
  358. if (!bytes)
  359. break;
  360. buf = (unsigned char*)realloc(buf, len + bytes + 1);
  361. memcpy(buf + len, buffer, bytes);
  362. len += bytes;
  363. }
  364. fclose(fp);
  365. }
  366. else
  367. {
  368. printf("unable to open file %s\n", fname);
  369. return -1;
  370. }
  371. if(buf)
  372. buf[len] = '\0';
  373. return 0;
  374. }
  375. unsigned CWsTopologyEx::findLineTerminator(const char* dataPtr, const size32_t dataSize)
  376. {
  377. char* pTr = (char*) dataPtr;
  378. size32_t bytesToCheck = dataSize;
  379. while(bytesToCheck > 0)
  380. {
  381. if ((bytesToCheck > 1) && (pTr[0] == '\r') && (pTr[1] == '\n'))
  382. return 2;
  383. if (pTr[0] == '\r' || pTr[0] == '\n')
  384. return 1;
  385. pTr++;
  386. bytesToCheck--;
  387. }
  388. return 0;
  389. }
  390. bool CWsTopologyEx::isLineTerminator(const char* dataPtr, const size32_t dataSize, unsigned ltLength)
  391. {
  392. if (ltLength > 1)
  393. {
  394. if ((dataSize > 1) && (dataPtr[0] == '\r') && (dataPtr[1] == '\n'))
  395. return true;
  396. }
  397. else if (dataPtr[0] == '\r' || dataPtr[0] == '\n')
  398. return true;
  399. return false;
  400. }
  401. bool CWsTopologyEx::readLogLineID(char* linePtr, unsigned long& lineID)
  402. {
  403. char *epTr;
  404. lineID = strtoul(linePtr, &epTr, 16);
  405. if (epTr - linePtr < 8) //LineID is the first 8 bytes of a log line
  406. return false;
  407. return true;
  408. }
  409. bool CWsTopologyEx::readLogTime(char* pTr, int start, int length, CDateTime& dt)
  410. {
  411. bool bRet = false;
  412. try
  413. {
  414. StringBuffer strBuf;
  415. strBuf.append(pTr, start, length);
  416. strBuf.setCharAt(10, 'T');
  417. dt.setString(strBuf.str(), NULL, false);
  418. bRet = true;
  419. }
  420. catch(IException* e)
  421. {
  422. e->Release();
  423. }
  424. return bRet;
  425. }
  426. bool CWsTopologyEx::findTimestampAndLT(StringBuffer logname, IFile* rFile, ReadLog& readLogReq, CDateTime& latestLogTime)
  427. {
  428. OwnedIFileIO rIO = rFile->openShared(IFOread,IFSHfull);
  429. if (!rIO)
  430. throw MakeStringException(ECLWATCH_CANNOT_OPEN_FILE,"Cannot read file %s.",logname.str());
  431. size32_t fileSize = (size32_t) rFile->size();
  432. size32_t readSize = 64000;
  433. if (readSize > fileSize)
  434. readSize = fileSize;
  435. //Read the first chuck of file to find out a timestamp and line terminator
  436. StringBuffer dataBuffer;
  437. size32_t bytesRead = rIO->read(0, readSize, dataBuffer.reserve(readSize));
  438. if (bytesRead != readSize)
  439. throw MakeStringException(ECLWATCH_CANNOT_READ_FILE, "Failed to read file %s.", logname.str());
  440. char* pTr = (char*) dataBuffer.str();
  441. readLogReq.ltBytes = findLineTerminator(pTr, bytesRead);
  442. if (rFile->size() < 28) //lineID + timestamp
  443. return false;//no timestamp in this log
  444. if (!readLogTime(pTr, 9, 19, latestLogTime))
  445. return false;//no timestamp in this log
  446. if ((readLogReq.filterType != GLOLastNHours) && (readLogReq.filterType != GLOTimeRange))
  447. return true;//Not interested in the last timestamp this time
  448. //Search the last chuck to find out the latest timestamp
  449. if (readSize < fileSize)
  450. {
  451. bytesRead = rIO->read(fileSize - readSize, readSize, dataBuffer.clear().reserve(readSize));
  452. if (bytesRead != readSize)
  453. throw MakeStringException(ECLWATCH_CANNOT_READ_FILE, "Failed to read file %s.", logname.str());
  454. pTr = (char*) dataBuffer.str();
  455. }
  456. //skip the first line which may not contain the entire log line
  457. StringBuffer logLine;
  458. size32_t bytesRemaining = bytesRead;
  459. bool hasAnotherLine = false;
  460. pTr = readALogLine(pTr, bytesRemaining, readLogReq.ltBytes, logLine, hasAnotherLine);
  461. if (!hasAnotherLine || (bytesRemaining < 28))
  462. return true;
  463. //Find out the last timestamp
  464. while (hasAnotherLine && bytesRemaining > 27)
  465. {
  466. CDateTime dt;
  467. pTr = readALogLine(pTr, bytesRemaining, readLogReq.ltBytes, logLine, hasAnotherLine);
  468. if ((logLine.length() > 27) && readLogTime((char*) logLine.str(), 9, 19, dt))
  469. latestLogTime = dt;
  470. }
  471. return true;
  472. }
  473. char* CWsTopologyEx::readALogLine(char* dataPtr, size32_t& bytesRemaining, unsigned ltLength, StringBuffer& logLine, bool& hasLineTerminator)
  474. {
  475. char* pTr = dataPtr;
  476. CDateTime dt;
  477. hasLineTerminator = false;
  478. while(bytesRemaining > 0)
  479. {
  480. hasLineTerminator = isLineTerminator(pTr, bytesRemaining, ltLength);
  481. if (hasLineTerminator && (bytesRemaining > ltLength + 27) && readLogTime(pTr+ltLength, 9, 19, dt))
  482. break;
  483. pTr++;
  484. bytesRemaining--;
  485. }
  486. if (hasLineTerminator && (bytesRemaining > 0))
  487. {
  488. pTr += ltLength;
  489. bytesRemaining -= ltLength;
  490. }
  491. logLine.clear();
  492. if (pTr > dataPtr)
  493. logLine.append(dataPtr, 0, pTr - dataPtr);
  494. return pTr;
  495. }
  496. void CWsTopologyEx::addALogLine(offset_t& readFrom, unsigned& locationFlag, StringBuffer dataRow, ReadLog& readLogReq, StringArray& returnbuff)
  497. {
  498. if (readLogReq.filterType == GLOFirstNRows)
  499. {
  500. locationFlag = 1; //enter the area to be retrieved
  501. returnbuff.append(dataRow);
  502. if (returnbuff.length() == readLogReq.firstRows)
  503. locationFlag = 2; //stop now since we have enough rows
  504. }
  505. else if (readLogReq.filterType == GLOLastNRows)
  506. {
  507. if (returnbuff.length() == readLogReq.lastRows)
  508. returnbuff.remove(readLogReq.lastRows - 1);
  509. returnbuff.add(dataRow, 0);
  510. locationFlag = 1; //always in the area to be retrieved, but extra lines may be pushed out later
  511. }
  512. else
  513. {
  514. unsigned long rowID;
  515. if (!readLogLineID((char*)dataRow.str(), rowID)) //row id (and timestamp) not found in this log line
  516. {
  517. if (locationFlag > 0)
  518. returnbuff.append(dataRow);
  519. readFrom += dataRow.length();
  520. return;
  521. }
  522. StringBuffer str;
  523. str.append(dataRow.str(), 20, 8); //Read time
  524. if (readLogReq.endDate.length() > 0 && strcmp(str.str(), readLogReq.endDate.str()) > 0)
  525. locationFlag = 2; //out of the area to be retrieved
  526. else if (readLogReq.startDate.length() > 1 && strcmp(str.str(), readLogReq.startDate.str()) < 0)
  527. readFrom += dataRow.length(); //skip this line
  528. else
  529. {
  530. returnbuff.append(dataRow);
  531. if ((locationFlag < 1) && (readLogReq.filterType == GLOTimeRange))
  532. readLogReq.pageFrom = readFrom;
  533. readFrom += dataRow.length();
  534. locationFlag = 1; //enter the area to be retrieved
  535. }
  536. }
  537. return;
  538. }
  539. void CWsTopologyEx::readLogFileToArray(StringBuffer logname, OwnedIFileIO rIO, ReadLog& readLogReq, StringArray& returnbuf)
  540. {
  541. bool firstChuck = true;
  542. bool lastChuck = false;
  543. offset_t readFrom = 0;
  544. offset_t logLineFrom = 0;
  545. unsigned locationFlag = 0; //0: before the interested log lines are reached, 1: found the log lines, 2: out
  546. StringBuffer logLine;
  547. offset_t bytesLeft = readLogReq.fileSize;
  548. while (bytesLeft > 0)
  549. {
  550. size32_t readSize;
  551. StringBuffer dataBuffer;
  552. //Find out where to read and how many bytes to read
  553. if (!firstChuck || (readLogReq.filterType != GLOLastNRows))
  554. {
  555. if (bytesLeft > LOGFILESIZELIMIT)
  556. readSize = LOGFILESIZELIMIT;
  557. else
  558. {
  559. readSize = (size32_t) bytesLeft;
  560. lastChuck = true;
  561. }
  562. bytesLeft -= readSize;
  563. }
  564. else
  565. {
  566. //read the last chuck since the file is too big
  567. size32_t estimateSize = AVERAGELOGROWSIZE*readLogReq.lastRows;
  568. if (readLogReq.fileSize < estimateSize)
  569. readSize = (size32_t) readLogReq.fileSize;
  570. else
  571. readSize = estimateSize;
  572. readFrom = (size32_t) readLogReq.fileSize-readSize;
  573. bytesLeft = 0;
  574. lastChuck = true;
  575. }
  576. //read a chuck of log to a buffer
  577. if (logLine.length() > 0) //check any left from a previous chunk
  578. dataBuffer.append(logLine.str());
  579. size32_t nRead = rIO->read(readFrom, readSize, dataBuffer.reserve(readSize));
  580. if (nRead != readSize)
  581. throw MakeStringException(ECLWATCH_CANNOT_READ_FILE, "Failed to read file %s.", logname.str());
  582. logLineFrom = readFrom;
  583. readFrom += nRead;
  584. //get the log lines from the buffer
  585. size32_t bytesRemaining = dataBuffer.length();
  586. char* pTr = (char*) dataBuffer.str();
  587. bool hasAnotherLine = true;
  588. while (hasAnotherLine && (bytesRemaining > 0) && (locationFlag < 2))
  589. {
  590. pTr = readALogLine(pTr, bytesRemaining, readLogReq.ltBytes, logLine.clear(), hasAnotherLine);
  591. if (logLine.length() < 1)
  592. continue;
  593. if (lastChuck || hasAnotherLine)
  594. addALogLine(logLineFrom, locationFlag, logLine, readLogReq, returnbuf);
  595. }
  596. if (locationFlag > 1) //interested log lines have been finished
  597. break;
  598. firstChuck = false;
  599. }
  600. return;
  601. }
  602. void CWsTopologyEx::readLogFile(StringBuffer logname, IFile* rFile, ReadLog& readLogReq, StringBuffer& returnbuff)
  603. {
  604. OwnedIFileIO rIO = rFile->openShared(IFOread,IFSHfull);
  605. if (!rIO)
  606. throw MakeStringException(ECLWATCH_CANNOT_OPEN_FILE,"Cannot read file %s.",logname.str());
  607. if ((readLogReq.filterType == GLOFirstPage) || (readLogReq.filterType == GLOLastPage) || (readLogReq.filterType == GLOGoToPage)) //by page number
  608. {
  609. size32_t fileSize = (size32_t) (readLogReq.pageTo - readLogReq.pageFrom);
  610. size32_t nRead = rIO->read(readLogReq.pageFrom, fileSize, returnbuff.reserve(fileSize));
  611. if (nRead != fileSize)
  612. throw MakeStringException(ECLWATCH_CANNOT_READ_FILE, "Failed to read file %s.", logname.str());
  613. }
  614. else
  615. {
  616. StringArray logLines;
  617. readLogFileToArray(logname, rIO, readLogReq, logLines);
  618. ForEachItemIn(i, logLines)
  619. {
  620. StringBuffer logLine = logLines.item(i);
  621. if ((!readLogReq.reverse && (readLogReq.filterType != 5)) ||
  622. (readLogReq.reverse && (readLogReq.filterType == 5)))
  623. returnbuff.append(logLine.str());
  624. else
  625. returnbuff.insert(0, logLine);
  626. }
  627. //Update page information based on log content
  628. if (returnbuff.length() > LOGFILESIZELIMIT)
  629. {
  630. if (readLogReq.filterType == GLOFirstNRows)
  631. readLogReq.pageTo = LOGFILESIZELIMIT;
  632. else if (readLogReq.filterType == GLOTimeRange)
  633. readLogReq.pageTo = readLogReq.pageFrom + LOGFILESIZELIMIT;
  634. else if ((readLogReq.filterType == GLOLastNHours) || (readLogReq.filterType == GLOLastNRows))
  635. {
  636. readLogReq.pageFrom = readLogReq.fileSize - returnbuff.length();
  637. readLogReq.pageTo = readLogReq.pageFrom + LOGFILESIZELIMIT;
  638. }
  639. }
  640. else
  641. {
  642. if (readLogReq.filterType == GLOFirstNRows)
  643. readLogReq.pageTo = returnbuff.length();
  644. else if (readLogReq.filterType == GLOTimeRange)
  645. readLogReq.pageTo = readLogReq.pageFrom + returnbuff.length();
  646. else if ((readLogReq.filterType == GLOLastNHours) || (readLogReq.filterType == GLOLastNRows))
  647. {
  648. readLogReq.pageFrom = readLogReq.fileSize - returnbuff.length();
  649. readLogReq.pageTo = readLogReq.fileSize;
  650. }
  651. }
  652. }
  653. }
  654. void CWsTopologyEx::readTpLogFileRequest(IEspContext &context, const char* fileName, IFile* rFile, IEspTpLogFileRequest &req, ReadLog& readLogReq)
  655. {
  656. readLogReq.filterType = (GetLogOptions) req.getFilterType();
  657. readLogReq.pageNumber = req.getPageNumber();
  658. readLogReq.startDate = req.getStartDate();
  659. readLogReq.endDate = req.getEndDate();
  660. readLogReq.firstRows = req.getFirstRows();
  661. readLogReq.lastRows = req.getLastRows();
  662. readLogReq.reverse = req.getReversely();
  663. readLogReq.loadContent = req.getLoadData();
  664. readLogReq.fileSize = rFile->size();
  665. readLogReq.TotalPages = (int) ceil(((double)readLogReq.fileSize)/LOGFILESIZELIMIT);
  666. readLogReq.prevPage = -1;
  667. readLogReq.nextPage = -1;
  668. readLogReq.lastHours = 0;
  669. CDateTime latestLogTime;
  670. readLogReq.hasTimestamp = findTimestampAndLT(fileName, rFile, readLogReq, latestLogTime);
  671. switch (readLogReq.filterType)
  672. {
  673. case GLOFirstPage:
  674. case GLOGoToPage:
  675. {
  676. if (readLogReq.pageNumber > readLogReq.TotalPages - 1)
  677. readLogReq.pageNumber = readLogReq.TotalPages - 1;
  678. readLogReq.pageFrom = LOGFILESIZELIMIT * readLogReq.pageNumber;
  679. if (readLogReq.pageFrom > 0)
  680. readLogReq.prevPage = readLogReq.pageNumber - 1;
  681. if (readLogReq.pageNumber < readLogReq.TotalPages - 1)
  682. {
  683. readLogReq.nextPage = readLogReq.pageNumber + 1;
  684. readLogReq.pageTo = (long) (readLogReq.pageFrom + LOGFILESIZELIMIT);
  685. }
  686. else
  687. readLogReq.pageTo = (long) readLogReq.fileSize;
  688. break;
  689. }
  690. case GLOLastPage:
  691. {
  692. int pageCount = 1;
  693. readLogReq.pageFrom = 0;
  694. offset_t fileSize = readLogReq.fileSize;
  695. while (fileSize > LOGFILESIZELIMIT)
  696. {
  697. fileSize -= LOGFILESIZELIMIT;
  698. readLogReq.pageFrom += LOGFILESIZELIMIT;
  699. pageCount++;
  700. }
  701. readLogReq.pageTo = readLogReq.pageFrom + fileSize;
  702. readLogReq.pageNumber = pageCount - 1;
  703. if (readLogReq.pageFrom > 0)
  704. readLogReq.prevPage = pageCount - 2;
  705. break;
  706. }
  707. case GLOFirstNRows:
  708. {
  709. if (readLogReq.firstRows < 1)
  710. throw MakeStringException(ECLWATCH_INVALID_INPUT, "'First rows' field should be defined.");
  711. readLogReq.pageFrom = 0;
  712. break;
  713. }
  714. case GLOLastNRows:
  715. {
  716. if (readLogReq.lastRows < 1)
  717. throw MakeStringException(ECLWATCH_INVALID_INPUT, "'Last rows' field should be defined.");
  718. break;
  719. }
  720. case GLOLastNHours:
  721. {
  722. if (!readLogReq.hasTimestamp)
  723. throw MakeStringException(ECLWATCH_INVALID_INPUT, "This log file has no timestamp.");
  724. if (req.getLastHours_isNull())
  725. throw MakeStringException(ECLWATCH_INVALID_INPUT, "Invlid 'Hours' field.");
  726. readLogReq.lastHours = req.getLastHours();
  727. unsigned hour, minute, second, nano;
  728. latestLogTime.getTime(hour, minute, second, nano, false);
  729. int hour2 = hour - readLogReq.lastHours;
  730. if (hour2 < 0)
  731. readLogReq.startDate.set("00:00:00");
  732. else
  733. readLogReq.startDate.clear().appendf("%02d:%02d:%02d", hour2, minute, second);
  734. readLogReq.endDate.clear();
  735. break;
  736. }
  737. case GLOTimeRange:
  738. {
  739. if (!readLogReq.hasTimestamp)
  740. throw MakeStringException(ECLWATCH_INVALID_INPUT, "This log file has no timestamp.");
  741. if ((readLogReq.startDate.length() < 8) && (readLogReq.endDate.length() < 8))
  742. throw MakeStringException(ECLWATCH_INVALID_INPUT, "Invlid 'Time' field.");
  743. break;
  744. }
  745. }
  746. return;
  747. }
  748. void CWsTopologyEx::setTpLogFileResponse(IEspContext &context, ReadLog& readLogReq, const char* fileName,
  749. const char* fileType, StringBuffer& returnbuf, IEspTpLogFileResponse &resp)
  750. {
  751. if (readLogReq.loadContent)
  752. {
  753. if (returnbuf.length() <= LOGFILESIZELIMIT)
  754. resp.setLogData(returnbuf.str());
  755. else
  756. {
  757. StringBuffer returnbuf0;
  758. returnbuf0.append(returnbuf.str(), 0, LOGFILESIZELIMIT);
  759. returnbuf0.appendf("\r\n****** Warning: cannot display all. The page size is limited to %ld bytes. ******", LOGFILESIZELIMIT);
  760. resp.setLogData(returnbuf0.str());
  761. }
  762. }
  763. resp.setHasDate(readLogReq.hasTimestamp);
  764. if (readLogReq.lastHours > 0)
  765. resp.setLastHours(readLogReq.lastHours);
  766. if (readLogReq.startDate.length() > 0)
  767. resp.setStartDate(readLogReq.startDate.str());
  768. if (readLogReq.endDate.length() > 0)
  769. resp.setEndDate(readLogReq.endDate.str());
  770. if (readLogReq.lastRows > 0)
  771. resp.setLastRows(readLogReq.lastRows);
  772. if (readLogReq.firstRows > 0)
  773. resp.setFirstRows(readLogReq.firstRows);
  774. double version = context.getClientVersion();
  775. if (version > 1.05)
  776. resp.setTotalPages( readLogReq.TotalPages );
  777. if (readLogReq.fileSize > 0)
  778. resp.setFileSize(readLogReq.fileSize);
  779. if (readLogReq.pageNumber > 0)
  780. resp.setPageNumber(readLogReq.pageNumber);
  781. if (readLogReq.pageFrom > 0)
  782. resp.setPageFrom(readLogReq.pageFrom);
  783. if (readLogReq.pageTo > 0)
  784. resp.setPageTo(readLogReq.pageTo);
  785. resp.setPrevPage(readLogReq.prevPage);
  786. if (readLogReq.nextPage > 0)
  787. resp.setNextPage(readLogReq.nextPage);
  788. resp.setName(fileName);
  789. resp.setType(fileType);
  790. resp.setFilterType(readLogReq.filterType);
  791. resp.setReversely(readLogReq.reverse);
  792. return;
  793. }
  794. void CWsTopologyEx::readTpLogFile(IEspContext &context,const char* fileName, const char* fileType, IEspTpLogFileRequest &req, IEspTpLogFileResponse &resp)
  795. {
  796. StringBuffer logname;
  797. if (strcmp(fileType,"thormaster_log"))
  798. logname = fileName;
  799. else
  800. logname.append(CCluster(fileName)->queryRoot()->queryProp("LogFile"));
  801. Owned<IFile> rFile = createIFile(logname.str());
  802. if (!rFile || !rFile->exists())
  803. throw MakeStringException(ECLWATCH_CANNOT_OPEN_FILE,"Cannot open file %s.",logname.str());
  804. ReadLog readLogReq;
  805. readTpLogFileRequest(context, fileName, rFile, req, readLogReq);
  806. StringBuffer returnbuf;
  807. if (readLogReq.loadContent)
  808. readLogFile(logname, rFile, readLogReq, returnbuf);
  809. setTpLogFileResponse(context, readLogReq, fileName, fileType, returnbuf, resp);
  810. return;
  811. }
  812. bool CWsTopologyEx::onTpClusterQuery(IEspContext &context, IEspTpClusterQueryRequest &req, IEspTpClusterQueryResponse &resp)
  813. {
  814. try
  815. {
  816. if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Read, false))
  817. throw MakeStringException(ECLWATCH_TOPOLOGY_ACCESS_DENIED, "Failed to do Cluster Query. Permission denied.");
  818. //another client (like configenv) may have updated the constant environment so reload it
  819. m_envFactory->validateCache();
  820. IArrayOf<IEspTpCluster> clusters;
  821. const char* type = req.getType();
  822. if (!type || !*type || (strcmp(eqRootNode,type) == 0) || (strcmp(eqAllClusters,type) == 0))
  823. {
  824. m_TpWrapper.getClusterProcessList(eqHoleCluster, clusters);
  825. m_TpWrapper.getClusterProcessList(eqThorCluster, clusters);
  826. m_TpWrapper.getClusterProcessList(eqRoxieCluster,clusters);
  827. }
  828. else
  829. {
  830. m_TpWrapper.getClusterProcessList(type,clusters);
  831. }
  832. double version = context.getClientVersion();
  833. if (version > 1.07)
  834. {
  835. resp.setEnableSNMP(m_enableSNMP);
  836. }
  837. if (version >= 1.20)
  838. {
  839. StringBuffer acceptLanguage;
  840. resp.setAcceptLanguage(getAcceptLanguage(context, acceptLanguage).str());
  841. }
  842. resp.setTpClusters(clusters);
  843. }
  844. catch(IException* e)
  845. {
  846. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  847. }
  848. return false;
  849. }
  850. bool CWsTopologyEx::onTpListTargetClusters(IEspContext &context, IEspTpListTargetClustersRequest &req, IEspTpListTargetClustersResponse &resp)
  851. {
  852. try
  853. {
  854. if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Read, false))
  855. throw MakeStringException(ECLWATCH_TOPOLOGY_ACCESS_DENIED, "Failed to do Cluster Query. Permission denied.");
  856. //another client (like configenv) may have updated the constant environment so reload it
  857. m_envFactory->validateCache();
  858. Owned<IRemoteConnection> conn = querySDS().connect("Environment", myProcessSession(), RTM_LOCK_READ, SDS_LOCK_TIMEOUT);
  859. if (!conn)
  860. return false;
  861. bool foundDefault = false;
  862. bool hasHThor = false;
  863. bool hasThor = false;
  864. const char* defaultClusterName = defaultTargetClusterName.get();
  865. const char* defaultClusterPrefix = defaultTargetClusterPrefix.get();
  866. IArrayOf<IEspTpClusterNameType> clusters;
  867. Owned<IPropertyTreeIterator> targets = conn->queryRoot()->getElements("Software/Topology/Cluster");
  868. ForEach(*targets)
  869. {
  870. IPropertyTree &target = targets->query();
  871. const char* name = target.queryProp("@name");
  872. const char* prefix = target.queryProp("@prefix");
  873. if (!name || !*name || !prefix || !*prefix)
  874. continue;//invalid entry
  875. Owned<IEspTpClusterNameType> tc = new CTpClusterNameType("", "");
  876. tc->setName(name);
  877. tc->setType(prefix);
  878. if (defaultClusterName && defaultClusterPrefix && strieq(defaultClusterName, name) &&
  879. strieq(defaultClusterPrefix, prefix))
  880. {
  881. foundDefault = true;
  882. tc->setIsDefault(true);
  883. }
  884. if (!foundDefault && !hasHThor)
  885. {
  886. ClusterType targetClusterType = HThorCluster;
  887. getClusterType(prefix, targetClusterType);
  888. if (targetClusterType == HThorCluster)
  889. hasHThor = true;
  890. else if (targetClusterType == ThorLCRCluster)
  891. hasThor = true;
  892. }
  893. clusters.append(*tc.getLink());
  894. }
  895. if (!foundDefault)
  896. { //No default target is specified or the default target does not match with any. Use the
  897. //following rules to decide a default target: if an hthor is found, it will be the 'default';
  898. //if no hthor, the first thor cluster will be the 'default';
  899. //If no hthor and no thor, the first roxie cluster will be the 'default'.
  900. ForEachItemIn(i, clusters)
  901. {
  902. IEspTpClusterNameType& tc = clusters.item(i);
  903. if (hasHThor)
  904. {
  905. ClusterType targetClusterType = HThorCluster;
  906. if (HThorCluster == getClusterType(tc.getType(), targetClusterType))
  907. {
  908. tc.setIsDefault(true);
  909. break;
  910. }
  911. }
  912. else if (hasThor)
  913. {
  914. ClusterType targetClusterType = HThorCluster;
  915. if (ThorLCRCluster == getClusterType(tc.getType(), targetClusterType))
  916. {
  917. tc.setIsDefault(true);
  918. break;
  919. }
  920. }
  921. else
  922. {
  923. tc.setIsDefault(true);
  924. break;
  925. }
  926. }
  927. }
  928. resp.setTargetClusters(clusters);
  929. }
  930. catch(IException* e)
  931. {
  932. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  933. }
  934. return false;
  935. }
  936. bool CWsTopologyEx::onTpTargetClusterQuery(IEspContext &context, IEspTpTargetClusterQueryRequest &req, IEspTpTargetClusterQueryResponse &resp)
  937. {
  938. try
  939. {
  940. if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Read, false))
  941. throw MakeStringException(ECLWATCH_TOPOLOGY_ACCESS_DENIED, "Failed to do Cluster Query. Permission denied.");
  942. //another client (like configenv) may have updated the constant environment so reload it
  943. m_envFactory->validateCache();
  944. double version = context.getClientVersion();
  945. IArrayOf<IEspTpTargetCluster> clusters;
  946. const char* type = req.getType();
  947. const char* name = req.getName();
  948. if (!type || !*type || (strcmp(eqRootNode,type) == 0) || (strcmp(eqAllClusters,type) == 0))
  949. {
  950. m_TpWrapper.queryTargetClusters(version, eqAllClusters, NULL, clusters);
  951. }
  952. else if (!name || !*name)
  953. {
  954. m_TpWrapper.queryTargetClusters(version, type, NULL, clusters);
  955. }
  956. else
  957. {
  958. m_TpWrapper.queryTargetClusters(version, type, name, clusters);
  959. }
  960. resp.setMemThreshold( m_memThreshold );
  961. resp.setDiskThreshold( m_diskThreshold );
  962. resp.setCpuThreshold( m_cpuThreshold );
  963. resp.setMemThresholdType( m_bMemThresholdIsPercentage ? "0" : "1");
  964. resp.setDiskThresholdType( m_bDiskThresholdIsPercentage ? "0" : "1");
  965. resp.setTpTargetClusters(clusters);
  966. resp.setShowDetails(req.getShowDetails());
  967. if ((version > 1.12) && (m_preflightProcessFilter.length() > 0))
  968. {
  969. resp.setPreflightProcessFilter(m_preflightProcessFilter);
  970. }
  971. if (version >= 1.20)
  972. {
  973. StringBuffer acceptLanguage;
  974. resp.setAcceptLanguage(getAcceptLanguage(context, acceptLanguage).str());
  975. }
  976. }
  977. catch(IException* e)
  978. {
  979. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  980. }
  981. return false;
  982. }
  983. bool CWsTopologyEx::onTpLogicalClusterQuery(IEspContext &context, IEspTpLogicalClusterQueryRequest &req, IEspTpLogicalClusterQueryResponse &resp)
  984. {
  985. try
  986. {
  987. if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Read, false))
  988. throw MakeStringException(ECLWATCH_TOPOLOGY_ACCESS_DENIED, "Failed to do Cluster Query. Permission denied.");
  989. Owned<IEnvironmentFactory> factory = getEnvironmentFactory();
  990. Owned<IConstEnvironment> constEnv = factory->openEnvironmentByFile();
  991. Owned<IPropertyTree> root = &constEnv->getPTree();
  992. if (!root)
  993. throw MakeStringException(ECLWATCH_CANNOT_GET_ENV_INFO, "Failed to get environment information.");
  994. IArrayOf<IEspTpLogicalCluster> clusters;
  995. Owned<IPropertyTreeIterator> clusterIterator = root->getElements("Software/Topology/Cluster");
  996. if (clusterIterator->first())
  997. {
  998. do {
  999. IPropertyTree &cluster0 = clusterIterator->query();
  1000. StringBuffer processName;
  1001. const char* clusterName0 = cluster0.queryProp("@name");
  1002. if (!clusterName0 || !*clusterName0)
  1003. continue;
  1004. IEspTpLogicalCluster* pService = createTpLogicalCluster("","");
  1005. pService->setName(clusterName0);
  1006. pService->setLanguageVersion("3.0.0");
  1007. clusters.append(*pService);
  1008. } while (clusterIterator->next());
  1009. }
  1010. resp.setTpLogicalClusters(clusters);
  1011. }
  1012. catch(IException* e)
  1013. {
  1014. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  1015. }
  1016. return true;
  1017. }
  1018. bool CWsTopologyEx::onTpGroupQuery(IEspContext &context, IEspTpGroupQueryRequest &req, IEspTpGroupQueryResponse &resp)
  1019. {
  1020. try
  1021. {
  1022. if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Read, false))
  1023. throw MakeStringException(ECLWATCH_TOPOLOGY_ACCESS_DENIED, "Failed to do Group Query. Permission denied.");
  1024. IArrayOf<IEspTpGroup> Groups;
  1025. m_TpWrapper.getGroupList(Groups);
  1026. resp.setTpGroups(Groups);
  1027. }
  1028. catch(IException* e)
  1029. {
  1030. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  1031. }
  1032. return true;
  1033. }
  1034. bool CWsTopologyEx::onTpClusterInfo(IEspContext &context, IEspTpClusterInfoRequest &req, IEspTpClusterInfoResponse& resp)
  1035. {
  1036. try
  1037. {
  1038. if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Read, false))
  1039. throw MakeStringException(ECLWATCH_TOPOLOGY_ACCESS_DENIED, "Failed to get Cluster Information. Permission denied.");
  1040. Owned<IRemoteConnection> conn = querySDS().connect("/Status/Servers/", myProcessSession(),RTM_SUB,SDS_LOCK_TIMEOUT);
  1041. if (conn)
  1042. {
  1043. Owned<IConstWUClusterInfo> clusterInfo = getTargetClusterInfo(req.getName());
  1044. SCMStringBuffer thorQueues;
  1045. clusterInfo->getThorQueue(thorQueues);
  1046. resp.setName(req.getName());
  1047. StringArray qlist;
  1048. qlist.appendListUniq(thorQueues.str(), ",");
  1049. IArrayOf<IEspTpQueue> Queues;
  1050. // look for the thor processes which are listening to this clusters queue, some may be listening to other clusters queues as well.
  1051. ForEachItemIn(q, qlist)
  1052. {
  1053. const char *queueName = qlist.item(q);
  1054. StringBuffer xpath("Server[@name=\"ThorMaster\"]");
  1055. Owned<IPropertyTreeIterator> iter = conn->getElements(xpath.str());
  1056. ForEach(*iter)
  1057. {
  1058. IPropertyTree &server = iter->query();
  1059. const char *queues = server.queryProp("@queue");
  1060. StringArray thorqlist;
  1061. thorqlist.appendListUniq(queues, ",");
  1062. if (NotFound != thorqlist.find(queueName))
  1063. {
  1064. IEspTpQueue* pQueue = createTpQueue("","");
  1065. pQueue->setName(server.queryProp("@thorname"));
  1066. pQueue->setWorkUnit(server.queryProp("WorkUnit"));
  1067. Queues.append(*pQueue);
  1068. }
  1069. }
  1070. }
  1071. resp.setTpQueues(Queues);
  1072. }
  1073. }
  1074. catch(IException* e)
  1075. {
  1076. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  1077. }
  1078. return true;
  1079. }
  1080. bool CWsTopologyEx::onTpServiceQuery(IEspContext &context, IEspTpServiceQueryRequest &req, IEspTpServiceQueryResponse &resp)
  1081. {
  1082. try
  1083. {
  1084. if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Read, false))
  1085. throw MakeStringException(ECLWATCH_TOPOLOGY_ACCESS_DENIED, "Failed to do Service Query. Permission denied.");
  1086. double version = context.getClientVersion();
  1087. const char* type = req.getType();
  1088. if (!type || !*type || (strcmp(eqAllServices,type) == 0))
  1089. {
  1090. //another client (like configenv) may have updated the constant environment so reload it
  1091. m_envFactory->validateCache();
  1092. IEspTpServices& ServiceList = resp.updateServiceList();
  1093. m_TpWrapper.getTpDaliServers( ServiceList.getTpDalis() );
  1094. m_TpWrapper.getTpEclServers( ServiceList.getTpEclServers() );
  1095. m_TpWrapper.getTpEclCCServers( ServiceList.getTpEclCCServers() );
  1096. m_TpWrapper.getTpEclAgents( ServiceList.getTpEclAgents() );
  1097. m_TpWrapper.getTpEspServers( ServiceList.getTpEspServers() );
  1098. m_TpWrapper.getTpDfuServers( ServiceList.getTpDfuServers() );
  1099. m_TpWrapper.getTpSashaServers( ServiceList.getTpSashaServers() );
  1100. m_TpWrapper.getTpGenesisServers( ServiceList.getTpGenesisServers() );
  1101. m_TpWrapper.getTpLdapServers( ServiceList.getTpLdapServers() );
  1102. m_TpWrapper.getTpDropZones( ServiceList.getTpDropZones() );
  1103. m_TpWrapper.getTpFTSlaves( ServiceList.getTpFTSlaves() );
  1104. m_TpWrapper.getTpDkcSlaves( ServiceList.getTpDkcSlaves() );
  1105. if (version > 1.15)
  1106. {
  1107. m_TpWrapper.getTpEclSchedulers( ServiceList.getTpEclSchedulers() );
  1108. }
  1109. }
  1110. resp.setMemThreshold( m_memThreshold );
  1111. resp.setDiskThreshold( m_diskThreshold );
  1112. resp.setCpuThreshold( m_cpuThreshold );
  1113. resp.setMemThresholdType( m_bMemThresholdIsPercentage ? "0" : "1");
  1114. resp.setDiskThresholdType( m_bDiskThresholdIsPercentage ? "0" : "1");
  1115. if (version > 1.06 && m_bEncapsulatedSystem)
  1116. {
  1117. resp.setEncapsulatedSystem( m_bEncapsulatedSystem );
  1118. }
  1119. if (version > 1.07)
  1120. {
  1121. resp.setEnableSNMP(m_enableSNMP);
  1122. }
  1123. if ((version > 1.12) && (m_preflightProcessFilter.length() > 0))
  1124. {
  1125. resp.setPreflightProcessFilter(m_preflightProcessFilter);
  1126. }
  1127. if (version >= 1.20)
  1128. {
  1129. StringBuffer acceptLanguage;
  1130. resp.setAcceptLanguage(getAcceptLanguage(context, acceptLanguage).str());
  1131. }
  1132. }
  1133. catch(IException* e)
  1134. {
  1135. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  1136. }
  1137. return true;
  1138. }
  1139. bool CWsTopologyEx::onTpMachineQuery(IEspContext &context, IEspTpMachineQueryRequest &req, IEspTpMachineQueryResponse &resp)
  1140. {
  1141. try
  1142. {
  1143. //another client (like configenv) may have updated the constant environment so reload it
  1144. m_envFactory->validateCache();
  1145. if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Read, false))
  1146. throw MakeStringException(ECLWATCH_TOPOLOGY_ACCESS_DENIED, "Failed to do Machine Query. Permission denied.");
  1147. double version = context.getClientVersion();
  1148. IArrayOf<IEspTpMachine> MachineList;
  1149. const char* path = req.getPath();
  1150. const char* directory = req.getDirectory();
  1151. bool hasThorSpareProcess = false;
  1152. const char* type = req.getType();
  1153. if (!type || !*type || (strcmp(eqAllNodes,type) == 0))
  1154. {
  1155. m_TpWrapper.getClusterMachineList(version, eqTHORMACHINES, path, directory, MachineList, hasThorSpareProcess);
  1156. m_TpWrapper.getClusterMachineList(version, eqHOLEMACHINES, path, directory, MachineList, hasThorSpareProcess);
  1157. m_TpWrapper.getClusterMachineList(version, eqROXIEMACHINES,path, directory, MachineList, hasThorSpareProcess);
  1158. }
  1159. else
  1160. {
  1161. m_TpWrapper.getClusterMachineList(version, type, path, directory, MachineList, hasThorSpareProcess, req.getCluster());
  1162. }
  1163. resp.setTpMachines(MachineList);
  1164. resp.setType( req.getType() );
  1165. resp.setCluster( req.getCluster() );
  1166. resp.setOldIP( req.getOldIP() );
  1167. resp.setPath( req.getPath() );
  1168. resp.setLogDirectory( req.getLogDirectory() );
  1169. resp.setMemThreshold( m_memThreshold );
  1170. resp.setDiskThreshold( m_diskThreshold );
  1171. resp.setCpuThreshold( m_cpuThreshold );
  1172. resp.setMemThresholdType( m_bMemThresholdIsPercentage ? "0" : "1");
  1173. resp.setDiskThresholdType( m_bDiskThresholdIsPercentage ? "0" : "1");
  1174. SecAccessFlags access;
  1175. bool bEnablePreflightInfo = context.authorizeFeature(MACHINE_URL, access) &&
  1176. access >= SecAccess_Read;
  1177. resp.setEnablePreflightInfo( bEnablePreflightInfo );
  1178. if (version > 1.07)
  1179. {
  1180. resp.setEnableSNMP(m_enableSNMP);
  1181. }
  1182. if ((version > 1.12) && (m_preflightProcessFilter.length() > 0))
  1183. {
  1184. resp.setPreflightProcessFilter(m_preflightProcessFilter);
  1185. }
  1186. if (version > 1.14 && hasThorSpareProcess)
  1187. {
  1188. resp.setHasThorSpareProcess( hasThorSpareProcess );
  1189. }
  1190. if (version >= 1.20)
  1191. {
  1192. StringBuffer acceptLanguage;
  1193. resp.setAcceptLanguage(getAcceptLanguage(context, acceptLanguage).str());
  1194. }
  1195. }
  1196. catch(IException* e)
  1197. {
  1198. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  1199. }
  1200. return false;
  1201. }
  1202. bool CWsTopologyEx::onTpGetComponentFile(IEspContext &context,
  1203. IEspTpGetComponentFileRequest &req,
  1204. IEspTpGetComponentFileResponse &resp)
  1205. {
  1206. try
  1207. {
  1208. if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Full, false))
  1209. throw MakeStringException(ECLWATCH_TOPOLOGY_ACCESS_DENIED, "Permission denied.");
  1210. const char* fileType = req.getFileType();
  1211. if (!fileType || (0!=stricmp(fileType, "cfg") && 0!=stricmp(fileType, "log")))
  1212. throw MakeStringException(ECLWATCH_INVALID_FILE_TYPE, "A valid file type requested. Only configuration and log files are supported!");
  1213. const char* compType = req.getCompType();
  1214. if (!compType || !*compType)
  1215. throw MakeStringExceptionDirect(ECLWATCH_INVALID_COMPONENT_TYPE, "Component type must be specified!");
  1216. const char* compName = req.getCompName();
  1217. const char* directory = req.getDirectory();
  1218. const char* netAddress = req.getNetAddress();
  1219. const char* fileName = NULL;
  1220. OS_TYPE osType = (OS_TYPE) req.getOsType();
  1221. bool bCluster = false;
  1222. if (!stricmp(fileType, "cfg"))
  1223. {
  1224. if (!stricmp(compType, eqDali))
  1225. fileName = "daliconf.xml";
  1226. else if (!stricmp(compType, eqDfu))
  1227. fileName = "dfuserver.xml";
  1228. else if (!stricmp(compType, eqEclServer))
  1229. fileName = "eclserver.xml";
  1230. else if (!stricmp(compType, eqEclCCServer))
  1231. fileName = "eclccserver.xml";
  1232. else if (!stricmp(compType, eqEclScheduler))
  1233. fileName = "eclscheduler.xml";
  1234. else if (!stricmp(compType, eqAgentExec))
  1235. fileName = "agentexec.xml";
  1236. else if (!stricmp(compType, eqEsp))
  1237. fileName = "esp.xml";
  1238. else if (!stricmp(compType, eqSashaServer))
  1239. fileName = "sashaconf.xml";
  1240. else if (!stricmp(compType, eqEclAgent))
  1241. fileName = osType==OS_WINDOWS ? "setvars.bat" : NULL;
  1242. else
  1243. {
  1244. const unsigned int len = strlen(compType);
  1245. if (len>4)
  1246. {
  1247. if (!strnicmp(compType, "Roxie", 5))
  1248. compType = "RoxieCluster", fileName = "RoxieTopology.xml", bCluster = true;
  1249. else if (!strnicmp(compType, "Thor", 4))
  1250. compType = "ThorCluster", fileName = "thor.xml", bCluster = true;
  1251. else if (!strnicmp(compType, "Hole", 4))
  1252. compType = "HoleCluster", fileName = "edata.ini", bCluster = true;
  1253. }
  1254. }
  1255. }
  1256. else
  1257. {
  1258. fileName = "";
  1259. if (strlen(compType)>4)
  1260. {
  1261. if (!strnicmp(compType, "Roxie", 5))
  1262. compType = "RoxieCluster", bCluster = true;
  1263. else if (!strnicmp(compType, "Thor", 4))
  1264. compType = "ThorCluster", bCluster = true;
  1265. else if (!strnicmp(compType, "Hole", 4))
  1266. compType = "HoleCluster", bCluster = true;
  1267. }
  1268. }
  1269. if (!fileName)
  1270. throw MakeStringExceptionDirect(ECLWATCH_INVALID_COMPONENT_OR_FILE_TYPE, "Unsupported component or file type specified!");
  1271. //the paths are all windows or samba network shares so construct windows network path
  1272. StringBuffer netAddressStr;
  1273. SCMStringBuffer scmNetAddress;
  1274. StringAttr sDirectory;
  1275. if (bCluster && !(netAddress && *netAddress))
  1276. {
  1277. //another client (like configenv) may have updated the constant environment so reload it
  1278. m_envFactory->validateCache();
  1279. Owned<IConstEnvironment> constEnv = m_envFactory->openEnvironmentByFile();
  1280. Owned<IPropertyTree> pRoot = &constEnv->getPTree();
  1281. StringBuffer xpath;
  1282. xpath.appendf("Software/%s[@name='%s']", compType, compName);
  1283. IPropertyTree* pCluster = pRoot->queryPropTree( xpath.str() );
  1284. if (!pCluster)
  1285. throw MakeStringException(ECLWATCH_COMPONENT_NOT_IN_ENV_INFO, "%s '%s' is not defined!", compType, compName);
  1286. if (!directory || !*directory)
  1287. {
  1288. sDirectory.set( pCluster->queryProp("@directory") );
  1289. directory = sDirectory.get();
  1290. }
  1291. xpath.clear();
  1292. if (!stricmp(compType, "RoxieCluster"))
  1293. xpath.append("RoxieServerProcess[1]");
  1294. else
  1295. if (!stricmp(compType, "ThorCluster"))
  1296. xpath.append("ThorMasterProcess");
  1297. else//HoleCluster
  1298. xpath.append("HoleControlProcess");
  1299. xpath.append("@computer");
  1300. const char* computer = pCluster->queryProp(xpath.str());
  1301. if (computer && *computer)
  1302. {
  1303. Owned<IConstMachineInfo> pMachine = constEnv->getMachine(computer);
  1304. if (pMachine)
  1305. {
  1306. pMachine->getNetAddress(scmNetAddress);
  1307. netAddressStr = scmNetAddress.str();
  1308. if (!strcmp(netAddressStr.str(), "."))
  1309. {
  1310. StringBuffer ipStr;
  1311. IpAddress ipaddr = queryHostIP();
  1312. ipaddr.getIpText(ipStr);
  1313. if (ipStr.length() > 0)
  1314. {
  1315. netAddressStr = ipStr.str();
  1316. }
  1317. }
  1318. }
  1319. }
  1320. }
  1321. if (netAddressStr.length() > 0)
  1322. netAddress = netAddressStr.str();
  1323. if (!directory || !*directory)
  1324. throw MakeStringExceptionDirect(ECLWATCH_INVALID_FILE_FOLDER, "Directory must be specified!");
  1325. if (!netAddress || !*netAddress)
  1326. throw MakeStringExceptionDirect(ECLWATCH_INVALID_IP, "Network address must be specified!");
  1327. StringBuffer sDir(directory);
  1328. const char pathSepChar = osType == OS_WINDOWS ? '\\' : '/';
  1329. if (*directory != pathSepChar)
  1330. sDir.insert(0, osType == OS_WINDOWS ? "\\" : "/");
  1331. if (osType == OS_WINDOWS)
  1332. sDir.replace(':', '$');
  1333. if (*fileName)
  1334. {
  1335. const unsigned int dirLen = sDir.length();
  1336. if (*fileName && *(sDir.str() + dirLen - 1) != pathSepChar)
  1337. sDir.append(pathSepChar);
  1338. }
  1339. //access remote path as \\ip\dir\file if we are running on windows, otherwise as //ip/dir/file
  1340. sDir.replace(pathSepChar == '/' ? '\\' : '/', pathSepChar);
  1341. StringBuffer uncPath;
  1342. uncPath.append(pathSepChar).append(pathSepChar).append(netAddress).append(sDir).append(fileName);
  1343. if (stricmp(fileType, "log") == 0)
  1344. {
  1345. StringBuffer url("/WsTopology/TpLogFile/");
  1346. if (bCluster)
  1347. url.appendf("%s?Name=%s&Type=tpcomp_log", compType, uncPath.str());
  1348. else
  1349. url.appendf("%s?Name=%s&Type=tpcomp_log&Reversely=true&FilterType=5&LastRows=300", compType, uncPath.str());
  1350. resp.setRedirectUrl(url.str());
  1351. }
  1352. else
  1353. {
  1354. Owned<IFile> pFile = createIFile(uncPath.str());
  1355. if (!pFile->exists())
  1356. {
  1357. if (!stricmp(fileType, "cfg") && !stricmp(compType, "DfuServerProcess"))
  1358. {
  1359. uncPath.clear().append(pathSepChar).append(pathSepChar).append(netAddress).append(sDir).append("dfuserver.ini");
  1360. pFile.setown(createIFile(uncPath.str()));
  1361. if (!pFile->exists())
  1362. throw MakeStringException(ECLWATCH_FILE_NOT_EXIST, "The file '%s' does not exist!", uncPath.str());
  1363. }
  1364. else if (!stricmp(fileType, "cfg") && !stricmp(compType, "ThorCluster"))
  1365. {
  1366. uncPath.clear().append(pathSepChar).append(pathSepChar).append(netAddress).append(sDir).append("thor.ini");
  1367. pFile.setown(createIFile(uncPath.str()));
  1368. if (!pFile->exists())
  1369. throw MakeStringException(ECLWATCH_FILE_NOT_EXIST, "The file '%s' does not exist!", uncPath.str());
  1370. }
  1371. else
  1372. {
  1373. throw MakeStringException(ECLWATCH_INVALID_FILE_TYPE, "The file '%s' does not exist!", uncPath.str());
  1374. }
  1375. }
  1376. Owned<IFileIO> pFileIO = pFile->openShared(IFOread, IFSHfull);
  1377. if (!pFileIO)
  1378. throw MakeStringException(ECLWATCH_CANNOT_OPEN_FILE, "The file '%s' could not be opened!", uncPath.str());
  1379. offset_t fileSize = pFile->size();
  1380. const long FILESIZELIMIT = 10000000; //In case of a huge file
  1381. if (fileSize > FILESIZELIMIT)
  1382. fileSize = FILESIZELIMIT;
  1383. MemoryBuffer buf;
  1384. size32_t nRead = read(pFileIO, 0, (size32_t)fileSize, buf);
  1385. if (nRead != fileSize)
  1386. throw MakeStringException(ECLWATCH_CANNOT_READ_FILE, "Failed to read file %s.", uncPath.str());
  1387. const char* pchBuf = buf.toByteArray();
  1388. const char* pchExt = strrchr(fileName, '.');
  1389. if (!pchExt || (pchBuf[0] != '<') || stricmp(++pchExt, "xml"))
  1390. {
  1391. resp.setFileContents_mimetype(HTTP_TYPE_TEXT_PLAIN);
  1392. resp.setFileContents(buf);
  1393. }
  1394. else
  1395. {
  1396. const char* plainText = req.getPlainText();
  1397. if (plainText && (!stricmp(plainText, "yes")))
  1398. {
  1399. if (!checkFileExists("xslt/xmlformatter.xsl"))
  1400. throw MakeStringException(ECLWATCH_FILE_NOT_EXIST, "Could not find stylesheet xmlformatter.xsl");
  1401. Owned<IXslProcessor> proc = getXslProcessor();
  1402. Owned<IXslTransform> trans = proc->createXslTransform();
  1403. trans->setXmlSource(pchBuf, buf.length());
  1404. trans->loadXslFromFile("xslt/xmlformatter.xsl");
  1405. StringBuffer htmlBuf;
  1406. trans->transform(htmlBuf);
  1407. MemoryBuffer buf0;
  1408. buf0.append(htmlBuf.str());
  1409. resp.setFileContents(buf0);
  1410. resp.setFileContents_mimetype(HTTP_TYPE_TEXT_HTML);
  1411. }
  1412. else
  1413. {
  1414. //if this is an xml file and is missing the xml tag at the top then add it
  1415. if (strncmp(pchBuf, "<?", 2))
  1416. {
  1417. const char* header="<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><?xml-stylesheet href=\"../esp/xslt/xmlformatter.xsl\" type=\"text/xsl\"?>";
  1418. const unsigned int headerLen = strlen(header);
  1419. buf.insertDirect(0, headerLen);
  1420. buf.writeDirect(0, headerLen, header);
  1421. }
  1422. else
  1423. {
  1424. const char* pBuf = strstr(pchBuf+2, "?>");
  1425. if (pBuf)
  1426. {
  1427. const char* header="<?xml-stylesheet href=\"../esp/xslt/xmlformatter.xsl\" type=\"text/xsl\"?>";
  1428. const unsigned int headerLen = strlen(header);
  1429. unsigned pos = pBuf - pchBuf + 2;
  1430. buf.insertDirect(pos, headerLen);
  1431. buf.writeDirect(pos, headerLen, header);
  1432. }
  1433. }
  1434. resp.setFileContents(buf);
  1435. resp.setFileContents_mimetype(HTTP_TYPE_APPLICATION_XML);
  1436. }
  1437. }
  1438. }
  1439. }
  1440. catch(IException* e)
  1441. {
  1442. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  1443. }
  1444. return true;
  1445. }
  1446. bool CWsTopologyEx::onTpThorStatus(IEspContext &context, IEspTpThorStatusRequest &req, IEspTpThorStatusResponse &resp)
  1447. {
  1448. try
  1449. {
  1450. if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Read, false))
  1451. throw MakeStringException(ECLWATCH_TOPOLOGY_ACCESS_DENIED, "Failed to access Thor status. Permission denied.");
  1452. const char* name = req.getName();
  1453. if (!name || !*name)
  1454. throw MakeStringException(ECLWATCH_INVALID_INPUT, "Thor name not specified.");
  1455. CCluster conn(name);
  1456. IPropertyTree *root = conn->queryRoot();
  1457. if (!root)
  1458. throw MakeStringException(ECLWATCH_INVALID_INPUT, "Failed to access Thor status.");
  1459. resp.setName( name );
  1460. resp.setQueue( root->queryProp("@queue") );
  1461. resp.setGroup( root->queryProp("@nodeGroup") );
  1462. resp.setThorMasterIPAddress( root->queryProp("@node"));
  1463. resp.setPort( root->getPropInt("@mpport", -1));
  1464. resp.setStartTime( root->queryProp("@started") );
  1465. const char *LogFile = root->queryProp("LogFile");
  1466. if (LogFile && *LogFile)
  1467. resp.setLogFile( LogFile );
  1468. const char *wuid = root->queryProp("WorkUnit");
  1469. if (wuid && *wuid)
  1470. {
  1471. resp.setWuid( wuid );
  1472. const char *graph = root->queryProp("@graph");
  1473. if (graph && *graph)
  1474. {
  1475. resp.setGraph( graph );
  1476. int subgraph = root->getPropInt("@subgraph", -1);
  1477. if (subgraph > -1)
  1478. {
  1479. resp.setSubGraph( subgraph );
  1480. }
  1481. int duration = root->getPropInt("@sg_duration", -1);
  1482. if (duration > -1)
  1483. {
  1484. resp.setSubGraphDuration( duration );
  1485. }
  1486. }
  1487. }
  1488. resp.setAutoRefresh(THORSTATUSDETAILS_REFRESH_MINS);
  1489. }
  1490. catch(IException* e)
  1491. {
  1492. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  1493. }
  1494. return false;
  1495. }