ws_topologyService.cpp 63 KB

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