ws_workunitsAuditLogs.cpp 60 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787
  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. #include "ws_workunitsService.hpp"
  14. #include "jlib.hpp"
  15. #include "daclient.hpp"
  16. #include "dalienv.hpp"
  17. #include "dadfs.hpp"
  18. #include "daaudit.hpp"
  19. #include "exception_util.hpp"
  20. #include "wujobq.hpp"
  21. #include "eventqueue.hpp"
  22. #include "fileview.hpp"
  23. #include "hqlerror.hpp"
  24. #include "sacmd.hpp"
  25. #include "wuwebview.hpp"
  26. #include "portlist.h"
  27. #include "dllserver.hpp"
  28. #include "schedulectrl.hpp"
  29. #include "scheduleread.hpp"
  30. #define REQPATH_CREATEANDDOWNLOADZAP "/WsWorkunits/WUCreateAndDownloadZAPInfo"
  31. #define REQPATH_DOWNLOADFILES "/WsWorkunits/WUDownloadFiles"
  32. bool getClusterJobQueueXLS(StringBuffer &xml, const char* cluster, const char* startDate, const char* endDate, const char* showType)
  33. {
  34. CDateTime fromTime;
  35. if(notEmpty(startDate))
  36. fromTime.setString(startDate, NULL, false);
  37. CDateTime toTime;
  38. if(notEmpty(endDate))
  39. toTime.setString(endDate, NULL, false);
  40. xml.append("<XmlSchema name=\"MySchema\">"
  41. "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" elementFormDefault=\"qualified\" attributeFormDefault=\"unqualified\">\n"
  42. "<xs:element name=\"Dataset\">"
  43. "<xs:complexType>"
  44. "<xs:sequence minOccurs=\"0\" maxOccurs=\"unbounded\">\n"
  45. "<xs:element name=\"Row\">"
  46. "<xs:complexType>"
  47. "<xs:sequence>\n");
  48. xml.append("<xs:element name=\"datetime\" type=\"xs:string\"/>\n");
  49. xml.append("<xs:element name=\"running\" type=\"xs:string\"/>\n");
  50. xml.append("<xs:element name=\"queued\" type=\"xs:string\"/>\n");
  51. xml.append("<xs:element name=\"connected\" type=\"xs:string\"/>\n");
  52. xml.append("<xs:element name=\"waiting\" type=\"xs:string20\"/>\n");
  53. xml.append("<xs:element name=\"idlecount\" type=\"xs:string20\"/>\n");
  54. xml.append("<xs:element name=\"running_wuid1\" type=\"xs:string\"/>\n");
  55. xml.append("<xs:element name=\"running_wuid2\" type=\"xs:string\"/>\n");
  56. xml.append( "</xs:sequence>"
  57. "</xs:complexType>"
  58. "</xs:element>\n"
  59. "</xs:sequence>"
  60. "</xs:complexType>"
  61. "</xs:element>\n");
  62. xml.append("<xs:simpleType name=\"string20\"><xs:restriction base=\"xs:string\"><xs:maxLength value=\"20\"/></xs:restriction></xs:simpleType>\n");
  63. xml.append("</xs:schema>");
  64. xml.append("</XmlSchema>").newline();
  65. xml.append("<Dataset");
  66. xml.append(" name=\"data\" xmlSchema=\"MySchema\" ");
  67. xml.append(">").newline();
  68. StringBuffer filter("ThorQueueMonitor");
  69. if (notEmpty(cluster))
  70. filter.appendf(",%s", cluster);
  71. StringAttrArray lines;
  72. queryAuditLogs(fromTime, toTime, filter.str(), lines);
  73. unsigned longest = 0;
  74. unsigned maxConnected = 0;
  75. unsigned maxDisplay = 0;
  76. unsigned showVal = (showType && strieq(showType, "InGraph")) ? 1 : 0;
  77. IArrayOf<IEspThorQueue> items;
  78. WsWuJobQueueAuditInfo jq;
  79. ForEachItemIn(idx, lines)
  80. {
  81. const char* line = lines.item(idx).text;
  82. if(isEmpty(line))
  83. continue;
  84. bool isLast = (idx == (lines.length() - 1));
  85. jq.getAuditLineInfo(lines.item(idx).text, longest, maxConnected, maxDisplay, (isLast && showVal==1) ? 2 : showVal, items);
  86. }
  87. ForEachItemIn(i,items)
  88. {
  89. IEspThorQueue& tq = items.item(i);
  90. xml.append(" <Row>");
  91. appendXMLTag(xml, "datetime", tq.getDT());
  92. appendXMLTag(xml, "running", tq.getRunningWUs());
  93. appendXMLTag(xml, "queued", tq.getQueuedWUs());
  94. appendXMLTag(xml, "connected", tq.getConnectedThors());
  95. appendXMLTag(xml, "waiting", tq.getWaitingThors());
  96. appendXMLTag(xml, "idlecount", tq.getIdledThors());
  97. if (notEmpty(tq.getRunningWU1()))
  98. appendXMLTag(xml, "running_wuid1", tq.getRunningWU1());
  99. if (notEmpty(tq.getRunningWU2()))
  100. appendXMLTag(xml, "running_wuid2", tq.getRunningWU2());
  101. xml.append("</Row>");
  102. xml.newline();
  103. }
  104. xml.append("</Dataset>").newline();
  105. return true;
  106. }
  107. static const long LOGFILESIZELIMIT = 500000; //Limit page size to 500k
  108. inline float timeStrToFloat(const char *timestr, float &val)
  109. {
  110. if (!timestr)
  111. return val;
  112. int hours = 0;
  113. int mins = 0;
  114. while(isdigit(*timestr))
  115. {
  116. hours = 10 * hours + *timestr - '0';
  117. timestr++;
  118. }
  119. if(*timestr == ':')
  120. timestr++;
  121. while(isdigit(*timestr))
  122. {
  123. mins = 10 * mins + (*timestr - '0');
  124. timestr++;
  125. }
  126. val = hours + mins/60.0F;
  127. return val;
  128. }
  129. StringBuffer &getNextStrItem(StringBuffer &s, const char *&finger, const char delim=',')
  130. {
  131. if (!finger)
  132. return s;
  133. const char *endp = strchr(finger, delim);
  134. if (endp)
  135. {
  136. s.append(endp - finger, finger);
  137. finger = endp+1;
  138. }
  139. else
  140. {
  141. s.append(finger);
  142. finger=NULL;
  143. }
  144. return s;
  145. }
  146. IEspECLJob* createEclJobFromAuditLine(double version, const char* str)
  147. {
  148. if(isEmpty(str))
  149. return NULL;
  150. Owned<IEspECLJob> job = createECLJob("", "");
  151. StringBuffer sdate;
  152. getNextStrItem(sdate, str);
  153. if (sdate.length()>=9)
  154. sdate.setCharAt(10, 'T');
  155. if(!str)
  156. return job.getClear();
  157. StringBuffer s;
  158. getNextStrItem(s, str);
  159. if(!str)
  160. return job.getClear();
  161. getNextStrItem(s.clear(), str);
  162. if(!str)
  163. return job.getClear();
  164. job->setCluster(getNextStrItem(s.clear(), str).str());
  165. if(!str)
  166. return job.getClear();
  167. job->setWuid(getNextStrItem(s.clear(), str).str());
  168. if(!str)
  169. return job.getClear();
  170. getNextStrItem(s.clear(), str);
  171. if (version > 1.05)
  172. job->setGraphNum(s.str());
  173. StringBuffer graph("graph");
  174. job->setGraph(graph.append(s).str());
  175. if(!str)
  176. return job.getClear();
  177. getNextStrItem(s.clear(), str);
  178. if (version > 1.05)
  179. job->setSubGraphNum(s.str());
  180. if(!str)
  181. return job.getClear();
  182. getNextStrItem(s.clear(), str);
  183. if (version > 1.05)
  184. job->setNumOfRuns(s.str());
  185. if(!str)
  186. return job.getClear();
  187. getNextStrItem(s.clear(), str);
  188. if (version > 1.05)
  189. job->setDuration(atoi(s.str()) / 1000);
  190. if(!str)
  191. return job.getClear();
  192. if(!strncmp("FAILED", getNextStrItem(s.clear(), str).str(), 6))
  193. job->setState("failed");
  194. else
  195. job->setState("finished");
  196. CDateTime endDT;
  197. endDT.setString(sdate.str(), NULL, true);
  198. CDateTime startDT;
  199. startDT.set(endDT.getSimple() - job->getDuration());
  200. job->setStartedDate(startDT.getString(s.clear(), false).append('Z').str());
  201. job->setFinishedDate(endDT.getString(s.clear(), false).append('Z').str());
  202. return job.getClear();
  203. }
  204. bool getClusterJobXLS(double version, StringBuffer &xml, const char* cluster, const char* startDate, const char* endDate, bool showall, const char* busStartStr, const char* busEndStr)
  205. {
  206. float busStart = 0;
  207. float busEnd = 24;
  208. if(showall)
  209. {
  210. timeStrToFloat(busStartStr, busStart);
  211. timeStrToFloat(busEndStr, busEnd);
  212. if(busStart <= 0 || busStart > 24 || busStart >= busEnd)
  213. throw MakeStringException(ECLWATCH_INVALID_INPUT, "Invalid business hours");
  214. }
  215. CDateTime fromTime;
  216. if(notEmpty(startDate))
  217. fromTime.setString(startDate, NULL, false);
  218. CDateTime toTime;
  219. if(notEmpty(endDate))
  220. toTime.setString(endDate, NULL, false);
  221. xml.append("<XmlSchema name=\"MySchema\">");
  222. xml.append("<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" elementFormDefault=\"qualified\" attributeFormDefault=\"unqualified\">\n"
  223. "<xs:element name=\"Dataset\">"
  224. "<xs:complexType>"
  225. "<xs:sequence minOccurs=\"0\" maxOccurs=\"unbounded\">\n"
  226. "<xs:element name=\"Row\">"
  227. "<xs:complexType>"
  228. "<xs:sequence>\n");
  229. xml.append("<xs:element name=\"wuid\" type=\"xs:string\"/>\n");
  230. xml.append("<xs:element name=\"graph\" type=\"xs:string\"/>\n");
  231. xml.append("<xs:element name=\"sub-graph\" type=\"xs:string\"/>\n");
  232. xml.append("<xs:element name=\"runs\" type=\"xs:string\"/>\n");
  233. xml.append("<xs:element name=\"started\" type=\"xs:string20\"/>\n");
  234. xml.append("<xs:element name=\"finished\" type=\"xs:string20\"/>\n");
  235. xml.append("<xs:element name=\"duration\" type=\"xs:string\"/>\n");
  236. xml.append("<xs:element name=\"cluster\" type=\"xs:string\"/>\n");
  237. xml.append("<xs:element name=\"state\" type=\"xs:string\"/>\n");
  238. xml.append( "</xs:sequence>"
  239. "</xs:complexType>"
  240. "</xs:element>\n"
  241. "</xs:sequence>"
  242. "</xs:complexType>"
  243. "</xs:element>\n");
  244. xml.append("<xs:simpleType name=\"string20\"><xs:restriction base=\"xs:string\"><xs:maxLength value=\"20\"/></xs:restriction></xs:simpleType>\n");
  245. xml.append("</xs:schema>");
  246. xml.append("</XmlSchema>").newline();
  247. xml.append("<Dataset name=\"data\" xmlSchema=\"MySchema\">").newline();
  248. StringBuffer filter("Timing,ThorGraph");
  249. if(notEmpty(cluster))
  250. filter.append(',').append(cluster);
  251. StringAttrArray jobs;
  252. queryAuditLogs(fromTime, toTime, filter.str(), jobs);
  253. IArrayOf<IEspECLJob> jobList;
  254. ForEachItemIn(idx, jobs)
  255. {
  256. if(jobs.item(idx).text.isEmpty())
  257. continue;
  258. Owned<IEspECLJob> job = createEclJobFromAuditLine(version, jobs.item(idx).text.get());
  259. CDateTime tTime;
  260. unsigned year, month, day, hour, minute, second, nano;
  261. tTime.setString(job->getStartedDate(), NULL, true);
  262. tTime.getDate(year, month, day, true);
  263. tTime.getTime(hour, minute, second, nano, true);
  264. StringBuffer started;
  265. started.appendf("%4d-%02d-%02d %02d:%02d:%02d",year,month,day,hour,minute,second);
  266. tTime.setString(job->getFinishedDate(), NULL, true);
  267. tTime.getDate(year, month, day, true);
  268. tTime.getTime(hour, minute, second, nano, true);
  269. StringBuffer finished;
  270. finished.appendf("%4d-%02d-%02d %02d:%02d:%02d",year,month,day,hour,minute,second);
  271. xml.append(" <Row>");
  272. appendXMLTag(xml, "wuid", job->getWuid());
  273. appendXMLTag(xml, "graph", job->getGraphNum());
  274. appendXMLTag(xml, "sub-graph", job->getSubGraphNum());
  275. appendXMLTag(xml, "runs", job->getNumOfRuns());
  276. appendXMLTag(xml, "started", started.str());
  277. appendXMLTag(xml, "finished", finished.str());
  278. xml.appendf("<duration>%d</duration>", job->getDuration());
  279. appendXMLTag(xml, "cluster", job->getCluster());
  280. appendXMLTag(xml, "state", job->getState());
  281. xml.append("</Row>").newline();
  282. jobList.append(*job.getClear());
  283. }
  284. xml.append("</Dataset>").newline();
  285. return true;
  286. }
  287. class CJobUsage : public CInterface
  288. {
  289. public:
  290. StringBuffer m_date;
  291. float m_usage, m_busage, m_nbusage;
  292. public:
  293. IMPLEMENT_IINTERFACE;
  294. CJobUsage()
  295. {
  296. m_usage = 0.0;
  297. m_busage = 0.0;
  298. m_nbusage = 0.0;
  299. };
  300. };
  301. typedef CIArrayOf<CJobUsage> JobUsageArray;
  302. //what???
  303. int ZCMJD(unsigned y, unsigned m, unsigned d)
  304. {
  305. if (m<3)
  306. {
  307. m += 12 ;
  308. y--;
  309. }
  310. return -678973 + d + (((153*m-2)/5)|0) + 365*y + ((y/4)|0) - ((y/100)|0) + ((y/400)|0);
  311. }
  312. void AddToClusterJobXLS(JobUsageArray& jobsummary, CDateTime &adjStart, CDateTime &adjEnd, int first, float busStart, float busEnd)
  313. {
  314. unsigned year0, month0, day0, hour0, minute0, second0, nano0;
  315. adjStart.getDate(year0, month0, day0, true);
  316. adjStart.getTime(hour0, minute0, second0, nano0, true);
  317. unsigned year1, month1, day1, hour1, minute1, second1, nano1;
  318. adjEnd.getDate(year1, month1, day1, true);
  319. adjEnd.getTime(hour1, minute1, second1, nano1, true);
  320. busStart *= 3600.0;
  321. busEnd *= 3600.0;
  322. float x1 = 3600.0F*hour0 + 60.0F*minute0 + second0;
  323. int y1 = ZCMJD(year0, month0, day0)-first;
  324. float x2 = 3600.0F*hour1 + 60.0F*minute1 + second1;
  325. int y2 = ZCMJD(year1, month1, day1)-first;
  326. for(int y=y1; y<=y2; y++)
  327. {
  328. if ((y < 0) || (y > (int)jobsummary.length() - 1))
  329. continue;
  330. CJobUsage& jobUsage = jobsummary.item(y);
  331. float xx1= (y==y1 ? x1 : 0.0F);
  332. float xx2= (y==y2 ? x2 : 86400.0F);
  333. if (xx2<=xx1)
  334. continue;
  335. jobUsage.m_usage += (xx2-xx1)/864.0F;
  336. float bhours = ((busEnd < xx2)? busEnd : xx2) - ((busStart > xx1) ? busStart : xx1);
  337. if(bhours < 0.0)
  338. bhours = 0.0;
  339. float nbhours = (xx2 - xx1 - bhours);
  340. if(busStart + (86400.0 - busEnd) > 0.001)
  341. jobUsage.m_nbusage += 100 * nbhours/(busStart + (86400.0F - busEnd));
  342. if(busEnd - busStart > 0.001)
  343. jobUsage.m_busage += 100*bhours/(busEnd - busStart);
  344. }
  345. return;
  346. }
  347. bool readECLWUCurrentJob(const char* curjob, const char* clusterName, const char* toDate, StringBuffer& dtStr, StringBuffer& actionStr, StringBuffer& wuidStr, StringBuffer& graphStr, StringBuffer& subGraphStr, StringBuffer& clusterStr)
  348. {
  349. if(!curjob || !*curjob)
  350. return false;
  351. // startdate
  352. const char* bptr = curjob;
  353. const char* eptr = strchr(bptr, ',');
  354. if(!eptr)
  355. return false;
  356. StringBuffer dt;
  357. dt.clear().append(eptr - bptr, bptr);
  358. dt.setCharAt(10, 'T');
  359. if (strcmp(dt.str(), toDate) > 0)
  360. return false;
  361. CDateTime enddt;
  362. enddt.setString(dt.str(), NULL, true);
  363. dt.clear();
  364. enddt.getString(dt, false);
  365. dt.append('Z');
  366. //Progress
  367. bptr = eptr + 1;
  368. eptr = strchr(bptr, ',');
  369. if(!eptr)
  370. return false;
  371. //Thor
  372. bptr = eptr + 1;
  373. eptr = strchr(bptr, ',');
  374. if(!eptr)
  375. return false;
  376. // action name
  377. char action[256];
  378. bptr = eptr + 1;
  379. eptr = strchr(bptr, ',');
  380. if(!eptr)
  381. return false;
  382. int len = eptr - bptr;
  383. strncpy(action, bptr, len);
  384. action[len] = 0;
  385. // cluster name
  386. char cluster[256];
  387. bptr = eptr + 1;
  388. eptr = strchr(bptr, ',');
  389. if(!eptr)
  390. return false;
  391. len = eptr - bptr;
  392. strncpy(cluster, bptr, len);
  393. cluster[len] = 0;
  394. if (cluster && *cluster)
  395. {
  396. clusterStr.clear().append(cluster);
  397. if (clusterName && *clusterName && stricmp(cluster, clusterName))
  398. return false;
  399. }
  400. dtStr = dt;
  401. actionStr.clear().append(action);
  402. if (!stricmp(action, "startup") || !stricmp(action, "terminate"))
  403. return true;
  404. //WUID
  405. bptr = eptr + 1;
  406. eptr = strchr(bptr, ',');
  407. if(!eptr)
  408. return false;
  409. wuidStr.clear().append(eptr - bptr, bptr);
  410. //graph number
  411. bptr = eptr + 1;
  412. eptr = strchr(bptr, ',');
  413. if(!eptr)
  414. return false;
  415. if (bptr[0] == 'g' && len > 5)
  416. bptr += 5;
  417. graphStr.clear().append(eptr - bptr, bptr);
  418. if (!stricmp(action, "start") || !stricmp(action, "stop"))
  419. return true;
  420. //subgraph number
  421. StringBuffer subgraph;
  422. bptr = eptr + 1;
  423. eptr = strchr(bptr, ',');
  424. if (!eptr)
  425. subgraph.append(bptr);
  426. else
  427. subgraph.append(eptr - bptr, bptr);
  428. subGraphStr.clear().append(subgraph);
  429. return true;
  430. }
  431. void addUnfinishedECLWUs(IArrayOf<IEspECLJob>& eclJobList, const char* wuid, const char* graph, const char* subGraph,
  432. const char* cluster, const char* dt, const char* dt1, StringArray& unfinishedWUIDs, StringArray& unfinishedGraphs,
  433. StringArray& unfinishedSubGraphs, StringArray& unfinishedClusters, StringArray& unfinishedWUStarttime, StringArray& unfinishedWUEndtime)
  434. {
  435. bool bFound = false;
  436. ForEachItemIn(idx, eclJobList)
  437. {
  438. IConstECLJob& curECLJob = eclJobList.item(idx);
  439. const char *eclwuid = curECLJob.getWuid();
  440. const char *eclgraph = curECLJob.getGraphNum();
  441. const char *eclsubgraph = curECLJob.getSubGraphNum();
  442. const char *ecldate = curECLJob.getFinishedDate();
  443. if (!eclwuid || !*eclwuid || stricmp(eclwuid, wuid))
  444. continue;
  445. if (!eclgraph || !*eclgraph || stricmp(eclgraph, graph))
  446. continue;
  447. if (!eclsubgraph || !*eclsubgraph || stricmp(eclsubgraph, subGraph))
  448. continue;
  449. //if (!ecldate || !*ecldate || (stricmp(ecldate, dt) < 0) || (stricmp(ecldate, dt1) > 0))
  450. // continue;
  451. if (!ecldate || !*ecldate)
  452. continue;
  453. int test = stricmp(ecldate, dt);
  454. if (test < 0)
  455. continue;
  456. test = stricmp(ecldate, dt1);
  457. if (test > 0)
  458. continue;
  459. bFound = true;
  460. break;
  461. }
  462. if (!bFound)
  463. {
  464. unfinishedWUIDs.append(wuid);
  465. StringBuffer graph0("graph");
  466. graph0.append(graph);
  467. unfinishedGraphs.append(graph0);
  468. unfinishedSubGraphs.append(subGraph);
  469. unfinishedClusters.append(cluster);
  470. unfinishedWUStarttime.append(dt);
  471. unfinishedWUEndtime.append(dt1);
  472. }
  473. return;
  474. }
  475. const unsigned MAXSUBGRAPHDAYS = 10;
  476. bool getPreviousUnfinishedECLWU(CDateTime fromTime, CDateTime toTime, const char* toDate, const char* cluster,
  477. StringBuffer& wuidStr, StringBuffer& graphStr, StringBuffer& subGraphStr, StringBuffer& clusterStr, StringBuffer& dtStr)
  478. {
  479. bool bFound = false;
  480. wuidStr.clear();
  481. graphStr.clear();
  482. subGraphStr.clear();
  483. dtStr.clear();
  484. StringBuffer filter0("Progress,Thor");
  485. CDateTime fromTime1 = fromTime, toTime1;
  486. bool bStop = false;
  487. for (unsigned day = 0; !bStop && day < MAXSUBGRAPHDAYS; day++)
  488. {
  489. toTime1 = fromTime1;
  490. fromTime1.adjustTime(-1440);
  491. StringAttrArray jobs1;
  492. queryAuditLogs(fromTime1, toTime1, filter0.str(), jobs1);
  493. #if 0
  494. char* str1 = "2010-10-04 07:39:04 ,Progress,Thor,StartSubgraph,thor,W20100929-073902,5,1,thor,thor.thor";
  495. char* str2 = "2010-10-04 15:53:43 ,Progress,Thor,Startup,thor,thor,thor.thor,//10.173.51.20/c$/thor_logs/09_29_2010_15_52_39/THORMASTER.log";
  496. char* str3 = "2010-10-04 17:52:31 ,Progress,Thor,Start,thor,W20100929-075230,graph1,r3gression,thor,thor.thor";
  497. jobs1.append(*new StringAttrItem(str2, strlen(str2)));
  498. jobs1.append(*new StringAttrItem(str1, strlen(str1)));
  499. jobs1.append(*new StringAttrItem(str3, strlen(str3)));
  500. #endif
  501. ForEachItemInRev(idx1, jobs1)
  502. {
  503. const char* curjob = jobs1.item(idx1).text;
  504. if(!curjob || !*curjob)
  505. continue;
  506. StringBuffer actionStr, clusterStr;
  507. if (!readECLWUCurrentJob(curjob, cluster, toDate, dtStr, actionStr, wuidStr, graphStr, subGraphStr, clusterStr))
  508. continue;
  509. if (!stricmp(actionStr.str(), "StartSubgraph") && (wuidStr.length() > 0) && (graphStr.length() > 0))
  510. {
  511. bFound = true;
  512. bStop = true;
  513. break;
  514. }
  515. if (!stricmp(actionStr.str(), "Startup") || !stricmp(actionStr.str(), "Terminate"))
  516. {
  517. bStop = true;
  518. break;
  519. }
  520. }
  521. }
  522. return bFound;
  523. }
  524. //Tony ToBeRefactored
  525. void findUnfinishedECLWUs(IArrayOf<IEspECLJob>& eclJobList, CDateTime fromTime, CDateTime toTime, const char* toDate, const char* cluster, StringArray& unfinishedWUIDs,
  526. StringArray& unfinishedGraphs, StringArray& unfinishedSubGraphs, StringArray& unfinishedClusters, StringArray& unfinishedWUStarttime, StringArray& unfinishedWUEndtime)
  527. {
  528. StringAttrArray jobs1;
  529. StringBuffer filter1("Progress,Thor");
  530. queryAuditLogs(fromTime, toTime, filter1.str(), jobs1);
  531. bool bAbnormalWU = false;
  532. int len = jobs1.length();
  533. StringBuffer dtStr, actionStr, wuidStr, graphStr, subGraphStr, clusterStr;
  534. ForEachItemIn(idx1, jobs1)
  535. {
  536. const char* curjob = jobs1.item(idx1).text;
  537. if(!curjob || !*curjob)
  538. continue;
  539. wuidStr.clear();
  540. graphStr.clear();
  541. subGraphStr.clear();
  542. if (!readECLWUCurrentJob(curjob, cluster, toDate, dtStr, actionStr, wuidStr, graphStr, subGraphStr, clusterStr))
  543. continue;
  544. if (stricmp(actionStr.str(), "Start"))
  545. continue;
  546. bAbnormalWU = true;
  547. int nextIndex = idx1 + 1;
  548. int idx2 = nextIndex;
  549. while (idx2 < len)
  550. {
  551. const char* curjob1 = jobs1.item(idx2).text;
  552. if(!curjob1 || !*curjob1)
  553. continue;
  554. StringBuffer dtStr1, actionStr1, wuidStr1, graphStr1, subGraphStr1, clusterStr1;
  555. if (readECLWUCurrentJob(curjob1, cluster, toDate, dtStr1, actionStr1, wuidStr1, graphStr1, subGraphStr1, clusterStr1))
  556. {
  557. if (!stricmp(wuidStr.str(), wuidStr1.str()) && !stricmp(graphStr.str(), graphStr1.str()))
  558. {
  559. if (!stricmp(actionStr1.str(), "Stop") )
  560. {
  561. bAbnormalWU = false;
  562. break;
  563. }
  564. else if (!stricmp(actionStr1.str(), "Start"))
  565. {
  566. break;
  567. }
  568. }
  569. }
  570. idx2++;
  571. }
  572. //If the WU did not finish by itself, let's check whether the cluster was stopped before the WU finished.
  573. if (bAbnormalWU)
  574. {
  575. int idx2 = nextIndex;
  576. while (idx2 < len)
  577. {
  578. const char* curjob1 = jobs1.item(idx2).text;
  579. if(!curjob1 || !*curjob1)
  580. continue;
  581. StringBuffer dtStr1, actionStr1, wuidStr1, graphStr1, subGraphStr1, clusterStr1;
  582. if (!readECLWUCurrentJob(curjob1, cluster, toDate, dtStr1, actionStr1, wuidStr1, graphStr1, subGraphStr1, clusterStr1))
  583. {
  584. idx2++;
  585. continue;
  586. }
  587. if (!stricmp(actionStr1.str(), "StartSubgraph") && !stricmp(wuidStr.str(), wuidStr1.str()) && !stricmp(graphStr.str(), graphStr1.str()))
  588. {
  589. //update subgraph number
  590. subGraphStr.clear().append(subGraphStr1.str());
  591. dtStr.clear().append(dtStr1.str());
  592. clusterStr.clear().append(clusterStr1.str());
  593. idx2++;
  594. continue;
  595. }
  596. if (stricmp(actionStr1.str(), "Startup") && stricmp(actionStr1.str(), "Terminate"))
  597. {
  598. idx2++;
  599. continue;
  600. }
  601. addUnfinishedECLWUs(eclJobList, wuidStr.str(), graphStr.str(), subGraphStr.str(), clusterStr.str(), dtStr.str(), dtStr1.str(),
  602. unfinishedWUIDs, unfinishedGraphs, unfinishedSubGraphs, unfinishedClusters, unfinishedWUStarttime, unfinishedWUEndtime);
  603. bAbnormalWU = false;
  604. break;
  605. }
  606. if (bAbnormalWU)
  607. {
  608. addUnfinishedECLWUs(eclJobList, wuidStr.str(), graphStr.str(), subGraphStr.str(), clusterStr.str(), dtStr.str(), toDate,
  609. unfinishedWUIDs, unfinishedGraphs, unfinishedSubGraphs, unfinishedClusters, unfinishedWUStarttime, unfinishedWUEndtime);
  610. bAbnormalWU = false;
  611. }
  612. }
  613. }
  614. //What if a WU started before *and* ended after the search time range
  615. if ((eclJobList.length() < 1) && (unfinishedWUIDs.length() < 1))
  616. {
  617. if (getPreviousUnfinishedECLWU(fromTime, toTime, toDate, cluster, wuidStr, graphStr, subGraphStr, clusterStr, dtStr))
  618. {
  619. addUnfinishedECLWUs(eclJobList, wuidStr.str(), graphStr.str(), subGraphStr.str(), clusterStr.str(), dtStr.str(), toDate,
  620. unfinishedWUIDs, unfinishedGraphs, unfinishedSubGraphs, unfinishedClusters, unfinishedWUStarttime, unfinishedWUEndtime);
  621. }
  622. }
  623. return;
  624. }
  625. bool getClusterJobSummaryXLS(double version, StringBuffer &xml, const char* cluster, const char* startDate, const char* endDate, bool showall, const char* busStartStr, const char* busEndStr)
  626. {
  627. float busStart = 0;
  628. float busEnd = 24;
  629. if(showall)
  630. {
  631. timeStrToFloat(busStartStr, busStart);
  632. timeStrToFloat(busEndStr, busEnd);
  633. if(busStart <= 0 || busStart > 24 || busStart >= busEnd)
  634. throw MakeStringException(ECLWATCH_INVALID_INPUT, "Invalid business hours");
  635. }
  636. CDateTime fromTime;
  637. if(notEmpty(startDate))
  638. fromTime.setString(startDate, NULL, false);
  639. CDateTime toTime;
  640. int delayTime = -240; //4 hour time difference
  641. bool extendedToNextDay = false;
  642. if(notEmpty(endDate))
  643. {
  644. toTime.setString(endDate, NULL, false);
  645. unsigned year, month, day, day1;
  646. CDateTime tTime = toTime;
  647. tTime.getDate(year, month, day);
  648. tTime.adjustTime(delayTime);
  649. tTime.getDate(year, month, day1);
  650. if (day1 < day)
  651. extendedToNextDay = true;
  652. }
  653. StringAttrArray jobs;
  654. StringBuffer filter("Timing,ThorGraph");
  655. if(notEmpty(cluster))
  656. filter.append(',').append(cluster);
  657. queryAuditLogs(fromTime, toTime, filter.str(), jobs);
  658. unsigned year, month, day;
  659. fromTime.getDate(year, month, day);
  660. int first = ZCMJD(year, month, day);
  661. toTime.getDate(year, month, day);
  662. int last = ZCMJD(year, month, day);
  663. if (last < first)
  664. throw MakeStringException(ECLWATCH_INVALID_INPUT, "Invalid day range");
  665. CDateTime usageDT(fromTime);
  666. JobUsageArray jobUsages;
  667. for (int i = first; i <= last; i++)
  668. {
  669. Owned<CJobUsage> jobUsage = new CJobUsage();
  670. jobUsage->m_busage = 0.0;
  671. jobUsage->m_nbusage = 0.0;
  672. jobUsage->m_usage = 0.0;
  673. usageDT.getDateString(jobUsage->m_date);
  674. jobUsages.append(*jobUsage.getClear());
  675. usageDT.adjustTime(60*24);
  676. }
  677. IArrayOf<IEspECLJob> jobList;
  678. ForEachItemIn(idx, jobs)
  679. {
  680. if(jobs.item(idx).text.isEmpty())
  681. continue;
  682. Owned<IEspECLJob> job = createEclJobFromAuditLine(version, jobs.item(idx).text.get());
  683. CDateTime adjStart;
  684. adjStart.setString(job->getStartedDate(),NULL,true);
  685. adjStart.adjustTime(delayTime);
  686. CDateTime adjEnd;
  687. adjEnd.setString(job->getFinishedDate(),NULL,true);
  688. adjEnd.adjustTime(delayTime);
  689. AddToClusterJobXLS(jobUsages, adjStart, adjEnd, first, busStart, busEnd);
  690. jobList.append(*job.getClear());
  691. }
  692. StringBuffer s;
  693. StringArray unfinishedWUIDs, unfinishedGraphs, unfinishedSubGraphs, unfinishedClusters, unfinishedWUStarttime, unfinishedWUEndtime;
  694. findUnfinishedECLWUs(jobList, fromTime, toTime, toTime.getString(s).str(), cluster, unfinishedWUIDs, unfinishedGraphs, unfinishedSubGraphs, unfinishedClusters, unfinishedWUStarttime, unfinishedWUEndtime);
  695. ForEachItemIn(idx3, unfinishedWUIDs)
  696. {
  697. CDateTime adjStart;
  698. adjStart.setString(unfinishedWUStarttime.item(idx3), NULL, true);
  699. adjStart.adjustTime(delayTime);
  700. CDateTime adjEnd;
  701. adjEnd.setString(unfinishedWUEndtime.item(idx3),NULL,true);
  702. adjEnd.adjustTime(delayTime);
  703. AddToClusterJobXLS(jobUsages, adjStart, adjEnd, first, busStart, busEnd);
  704. }
  705. xml.append("<XmlSchema name=\"MySchema\">");
  706. xml.append(
  707. "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" elementFormDefault=\"qualified\" attributeFormDefault=\"unqualified\">\n"
  708. "<xs:element name=\"Dataset\">"
  709. "<xs:complexType>"
  710. "<xs:sequence minOccurs=\"0\" maxOccurs=\"unbounded\">\n"
  711. "<xs:element name=\"Row\">"
  712. "<xs:complexType>"
  713. "<xs:sequence>\n");
  714. xml.append("<xs:element name=\"Date\" type=\"xs:string\"/>\n");
  715. xml.append("<xs:element name=\"Business\" type=\"xs:string\"/>\n");
  716. xml.append("<xs:element name=\"Non-business\" type=\"xs:string\"/>\n");
  717. xml.append("<xs:element name=\"Overall\" type=\"xs:string\"/>\n");
  718. xml.append( "</xs:sequence>"
  719. "</xs:complexType>"
  720. "</xs:element>\n"
  721. "</xs:sequence>"
  722. "</xs:complexType>"
  723. "</xs:element>\n");
  724. xml.append("<xs:simpleType name=\"string20\"><xs:restriction base=\"xs:string\"><xs:maxLength value=\"20\"/></xs:restriction></xs:simpleType>\n");
  725. xml.append("</xs:schema>");
  726. xml.append("</XmlSchema>").newline();
  727. xml.append("<Dataset name=\"data\" xmlSchema=\"MySchema\" >").newline();
  728. StringBuffer percentageStr;
  729. percentageStr.append("%");
  730. int lastUsage = jobUsages.length();
  731. if (extendedToNextDay)
  732. lastUsage --;
  733. for (int i0 = 0; i0 < lastUsage; i0++)
  734. {
  735. CJobUsage& jobUsage = jobUsages.item(i0);
  736. xml.append(" <Row>");
  737. xml.appendf("<Date>%s</Date>", jobUsage.m_date.str());
  738. xml.appendf("<Business>%3.0f %s</Business>", jobUsage.m_busage, percentageStr.str());
  739. xml.appendf("<Non-business>%3.0f %s</Non-business>", jobUsage.m_nbusage, percentageStr.str());
  740. xml.appendf("<Overall>%3.0f %s</Overall>", jobUsage.m_usage, percentageStr.str());
  741. xml.append(" </Row>");
  742. }
  743. xml.append("</Dataset>").newline();
  744. return true;
  745. }
  746. inline StringBuffer &appendQuoted(StringBuffer &s, const char *val, bool first=false, const char q='\'')
  747. {
  748. if (!first)
  749. s.append(',');
  750. return s.append(q).append(val).append(q);
  751. }
  752. inline StringBuffer &appendQuoted(StringBuffer &s, float val, bool first=false, const char q='\'')
  753. {
  754. if (!first)
  755. s.append(',');
  756. return s.append(q).append(val).append(q);
  757. }
  758. inline StringBuffer &appendQuoted(StringBuffer &s, unsigned val, bool first=false, const char q='\'')
  759. {
  760. if (!first)
  761. s.append(',');
  762. return s.append(q).append(val).append(q);
  763. }
  764. void streamJobListResponse(IEspContext &context, const char *cluster, const char *from , const char *to, CHttpResponse* response, bool showall, float bbtime, float betime, const char *xls)
  765. {
  766. CDateTime fromTime;
  767. StringBuffer fromstr;
  768. if (notEmpty(from))
  769. {
  770. fromTime.setString(from, NULL, false);
  771. fromTime.getString(fromstr, false);
  772. }
  773. CDateTime toTime;
  774. StringBuffer tostr;
  775. if(notEmpty(to))
  776. {
  777. toTime.setString(to,NULL,false);
  778. toTime.getString(tostr, false);
  779. }
  780. response->setContentType(HTTP_TYPE_TEXT_HTML_UTF8);
  781. response->setStatus(HTTP_STATUS_OK);
  782. response->startSend();
  783. StringBuffer sb;
  784. sb.append("<script language=\"javascript\">parent.displayLegend(");
  785. appendQuoted(sb, fromstr.str(), true);
  786. appendQuoted(sb, tostr.str());
  787. appendQuoted(sb, showall ? "1" : "0");
  788. sb.append(")</script>\r\n");
  789. response->sendChunk(sb.str());
  790. sb.clear();
  791. sb.append("<script language=\"javascript\">parent.displayBegin(");
  792. appendQuoted(sb, fromstr.str(), true);
  793. appendQuoted(sb, tostr.str());
  794. appendQuoted(sb, showall ? "1" : "0");
  795. sb.append(")</script>\r\n");
  796. response->sendChunk(sb.str());
  797. sb.clear();
  798. StringBuffer filter("Timing,ThorGraph");
  799. if(notEmpty(cluster))
  800. filter.appendf(",%s", cluster);
  801. StringAttrArray jobs;
  802. queryAuditLogs(fromTime, toTime, filter.str(), jobs);
  803. sb.append("<script language=\"javascript\">\r\n");
  804. unsigned count=0;
  805. IArrayOf<IEspECLJob> eclJobList;
  806. ForEachItemIn(idx, jobs)
  807. {
  808. if(!jobs.item(idx).text.length())
  809. continue;
  810. Owned<IEspECLJob> job = createEclJobFromAuditLine(context.getClientVersion(), jobs.item(idx).text.get());
  811. sb.append("parent.displayJob(");
  812. appendQuoted(sb, job->getWuid(), true);
  813. appendQuoted(sb, job->getGraph());
  814. appendQuoted(sb, job->getStartedDate());
  815. appendQuoted(sb, job->getFinishedDate());
  816. appendQuoted(sb, job->getCluster());
  817. appendQuoted(sb, job->getState());
  818. if (showall)
  819. sb.append(",\'\',\'1\'");
  820. else
  821. sb.append(",\'\',\'0\'");
  822. sb.append(',').append(bbtime).append(',').append(betime).append(")\r\n");
  823. if(++count>=50)
  824. {
  825. sb.append("</script>\r\n");
  826. response->sendChunk(sb.str());
  827. sb.clear().append("<script language=\"javascript\">\r\n");
  828. count=0;
  829. }
  830. eclJobList.append(*job.getClear());
  831. }
  832. //Find out which WUs stopped by abnormal thor termination
  833. StringArray unfinishedWUIDs, unfinishedGraphs, unfinishedSubGraphs, unfinishedClusters, unfinishedWUStarttime, unfinishedWUEndtime;
  834. findUnfinishedECLWUs(eclJobList, fromTime, toTime, tostr.str(), cluster, unfinishedWUIDs, unfinishedGraphs, unfinishedSubGraphs, unfinishedClusters, unfinishedWUStarttime, unfinishedWUEndtime);
  835. if (unfinishedWUIDs.ordinality())
  836. {
  837. ForEachItemIn(idx3, unfinishedWUIDs)
  838. {
  839. CDateTime tTime;
  840. unsigned year, month, day, hour, minute, second, nano;
  841. tTime.setString(unfinishedWUStarttime.item(idx3),NULL,true);
  842. tTime.getDate(year, month, day, true);
  843. tTime.getTime(hour, minute, second, nano, true);
  844. StringBuffer started, finished;
  845. started.appendf("%4d-%02d-%02dT%02d:%02d:%02dZ",year,month,day,hour,minute,second);
  846. if (notEmpty(unfinishedWUEndtime.item(idx3)))
  847. {
  848. tTime.setString(unfinishedWUEndtime.item(idx3),NULL,true);
  849. tTime.getDate(year, month, day, true);
  850. tTime.getTime(hour, minute, second, nano, true);
  851. finished.appendf("%4d-%02d-%02dT%02d:%02d:%02dZ",year,month,day,hour,minute,second);
  852. }
  853. sb.append("parent.displayJob(");
  854. appendQuoted(sb, unfinishedWUIDs.item(idx3), true);
  855. appendQuoted(sb, unfinishedGraphs.item(idx3));
  856. appendQuoted(sb, started.str());
  857. appendQuoted(sb, finished.str());
  858. appendQuoted(sb, unfinishedClusters.item(idx3));
  859. appendQuoted(sb, "not finished");
  860. if (showall)
  861. sb.append(",\'\',\'1\'");
  862. else
  863. sb.append(",\'\',\'0\'");
  864. sb.append(',').append(bbtime).append(',').append(betime).append(")\r\n");
  865. if(++count>=50)
  866. {
  867. sb.append("</script>\r\n");
  868. response->sendChunk(sb.str());
  869. sb.clear().append("<script language=\"javascript\">\r\n");
  870. count=0;
  871. }
  872. }
  873. }
  874. sb.append("</script>\r\n");
  875. response->sendChunk(sb.str());
  876. sb.clear().append("<script language=\"javascript\">\r\n");
  877. sb.append("parent.displaySasha();\r\nparent.displayEnd(");
  878. appendQuoted(sb, xls, true).append(")</script>\r\n");
  879. response->sendFinalChunk(sb.str());
  880. }
  881. bool checkSameStrings(const char* s1, const char* s2)
  882. {
  883. if (s1)
  884. {
  885. if (s2 && streq(s1, s2))
  886. return true;
  887. }
  888. else if (!s2)
  889. return true;
  890. return false;
  891. }
  892. bool checkNewThorQueueItem(IEspThorQueue* tq, unsigned showAll, IArrayOf<IEspThorQueue>& items)
  893. {
  894. bool bAdd = false;
  895. if (showAll < 1) //show every lines
  896. bAdd = true;
  897. else if (items.length() < 1)
  898. bAdd = true;
  899. else if (showAll > 1) //last line now
  900. {
  901. IEspThorQueue& tq0 = items.item(items.length()-1);
  902. if (!checkSameStrings(tq->getDT(), tq0.getDT()))
  903. bAdd = true;
  904. }
  905. else
  906. {
  907. IEspThorQueue& tq0 = items.item(items.length()-1);
  908. if (!checkSameStrings(tq->getRunningWUs(), tq0.getRunningWUs()))
  909. bAdd = true;
  910. if (!checkSameStrings(tq->getQueuedWUs(), tq0.getQueuedWUs()))
  911. bAdd = true;
  912. if (!checkSameStrings(tq->getConnectedThors(), tq0.getConnectedThors()))
  913. bAdd = true;
  914. if (!checkSameStrings(tq->getConnectedThors(), tq0.getConnectedThors()))
  915. bAdd = true;
  916. if (!checkSameStrings(tq->getRunningWU1(), tq0.getRunningWU1()))
  917. bAdd = true;
  918. if (!checkSameStrings(tq->getRunningWU2(), tq0.getRunningWU2()))
  919. bAdd = true;
  920. }
  921. return bAdd;
  922. }
  923. void appendQueueInfoFromAuditLine(IArrayOf<IEspThorQueue>& items, const char* line, unsigned& longestQueue, unsigned& maxConnected, unsigned maxDisplay, unsigned showAll)
  924. {
  925. //2009-08-12 02:44:12 ,ThorQueueMonitor,thor400_88_dev,0,0,1,1,114,---,---
  926. if(!line || !*line)
  927. return;
  928. Owned<IEspThorQueue> tq = createThorQueue();
  929. StringBuffer dt, runningWUs, queuedWUs, waitingThors, connectedThors, idledThors, runningWU1, runningWU2;
  930. // date/time
  931. const char* bptr = line;
  932. const char* eptr = strchr(bptr, ',');
  933. if(eptr)
  934. dt.append(eptr - bptr, bptr);
  935. else
  936. dt.append(bptr);
  937. tq->setDT(dt.str());
  938. if(!eptr)
  939. {
  940. if (checkNewThorQueueItem(tq, showAll, items))
  941. items.append(*tq.getClear());
  942. return;
  943. }
  944. //skip title
  945. bptr = eptr + 1;
  946. eptr = strchr(bptr, ',');
  947. if(!eptr)
  948. {
  949. if (checkNewThorQueueItem(tq, showAll, items))
  950. items.append(*tq.getClear());
  951. return;
  952. }
  953. //skip queue name
  954. bptr = eptr + 1;
  955. eptr = strchr(bptr, ',');
  956. if(!eptr)
  957. {
  958. if (checkNewThorQueueItem(tq, showAll, items))
  959. items.append(*tq.getClear());
  960. return;
  961. }
  962. //running
  963. bptr = eptr + 1;
  964. eptr = strchr(bptr, ',');
  965. if(eptr)
  966. runningWUs.append(eptr - bptr, bptr);
  967. else
  968. runningWUs.append(bptr);
  969. tq->setRunningWUs(runningWUs.str());
  970. if(!eptr)
  971. {
  972. if (checkNewThorQueueItem(tq, showAll, items))
  973. items.append(*tq.getClear());
  974. return;
  975. }
  976. //queued
  977. bptr = eptr + 1;
  978. eptr = strchr(bptr, ',');
  979. if(eptr)
  980. queuedWUs.append(eptr - bptr, bptr);
  981. else
  982. queuedWUs.append(bptr);
  983. if (maxDisplay > items.length())
  984. {
  985. unsigned queueLen = atoi(queuedWUs.str());
  986. if (queueLen > longestQueue)
  987. longestQueue = queueLen;
  988. }
  989. tq->setQueuedWUs(queuedWUs.str());
  990. if(!eptr)
  991. {
  992. if (checkNewThorQueueItem(tq, showAll, items))
  993. items.append(*tq.getClear());
  994. return;
  995. }
  996. //waiting
  997. bptr = eptr + 1;
  998. eptr = strchr(bptr, ',');
  999. if(eptr)
  1000. waitingThors.append(eptr - bptr, bptr);
  1001. else
  1002. waitingThors.append(bptr);
  1003. tq->setWaitingThors(waitingThors.str());
  1004. if(!eptr)
  1005. {
  1006. if (checkNewThorQueueItem(tq, showAll, items))
  1007. items.append(*tq.getClear());
  1008. return;
  1009. }
  1010. //connected
  1011. bptr = eptr + 1;
  1012. eptr = strchr(bptr, ',');
  1013. if(eptr)
  1014. connectedThors.append(eptr - bptr, bptr);
  1015. else
  1016. connectedThors.append(bptr);
  1017. if (maxDisplay > items.length())
  1018. {
  1019. unsigned connnectedLen = atoi(connectedThors.str());
  1020. if (connnectedLen > maxConnected)
  1021. maxConnected = connnectedLen;
  1022. }
  1023. tq->setConnectedThors(connectedThors.str());
  1024. if(!eptr)
  1025. {
  1026. if (checkNewThorQueueItem(tq, showAll, items))
  1027. items.append(*tq.getClear());
  1028. return;
  1029. }
  1030. //idled
  1031. bptr = eptr + 1;
  1032. eptr = strchr(bptr, ',');
  1033. if(eptr)
  1034. idledThors.append(eptr - bptr, bptr);
  1035. else
  1036. idledThors.append(bptr);
  1037. tq->setIdledThors(idledThors.str());
  1038. if(!eptr)
  1039. {
  1040. items.append(*tq.getClear());
  1041. return;
  1042. }
  1043. //runningWU1
  1044. bptr = eptr + 1;
  1045. eptr = strchr(bptr, ',');
  1046. if(eptr)
  1047. runningWU1.append(eptr - bptr, bptr);
  1048. else
  1049. {
  1050. runningWU1.append(bptr);
  1051. }
  1052. if (!strcmp(runningWU1.str(), "---"))
  1053. runningWU1.clear();
  1054. if (runningWU1.length() > 0)
  1055. tq->setRunningWU1(runningWU1.str());
  1056. if(!eptr)
  1057. {
  1058. if (checkNewThorQueueItem(tq, showAll, items))
  1059. items.append(*tq.getClear());
  1060. return;
  1061. }
  1062. //runningWU2
  1063. bptr = eptr + 1;
  1064. eptr = strchr(bptr, ',');
  1065. if(eptr)
  1066. runningWU2.append(eptr - bptr, bptr);
  1067. else
  1068. {
  1069. runningWU2.append(bptr);
  1070. }
  1071. if (!strcmp(runningWU2.str(), "---"))
  1072. runningWU2.clear();
  1073. if (runningWU2.length() > 0)
  1074. tq->setRunningWU2(runningWU2.str());
  1075. if (checkNewThorQueueItem(tq, showAll, items))
  1076. items.append(*tq.getClear());
  1077. }
  1078. void streamJobQueueListResponse(IEspContext &context, const char *cluster, const char *from , const char *to, CHttpResponse* response, const char *xls)
  1079. {
  1080. if(!response)
  1081. return;
  1082. unsigned maxDisplay = 125;
  1083. IArrayOf<IEspThorQueue> items;
  1084. CDateTime fromTime;
  1085. StringBuffer fromstr;
  1086. if (notEmpty(from))
  1087. {
  1088. fromTime.setString(from, NULL, false);
  1089. fromTime.getString(fromstr, false);
  1090. }
  1091. CDateTime toTime;
  1092. StringBuffer tostr;
  1093. if(notEmpty(to))
  1094. {
  1095. toTime.setString(to,NULL,false);
  1096. toTime.getString(tostr, false);
  1097. }
  1098. StringBuffer filter("ThorQueueMonitor");
  1099. if (notEmpty(cluster))
  1100. filter.appendf(",%s", cluster);
  1101. StringAttrArray lines;
  1102. queryAuditLogs(fromTime, toTime, filter.str(), lines);
  1103. unsigned countLines = 0;
  1104. unsigned maxConnected = 0;
  1105. unsigned longestQueue = 0;
  1106. ForEachItemIn(idx, lines)
  1107. {
  1108. if(!lines.item(idx).text.length())
  1109. continue;
  1110. if (idx < (lines.length() - 1))
  1111. appendQueueInfoFromAuditLine(items, lines.item(idx).text.get(), longestQueue, maxConnected, maxDisplay, 1);
  1112. else
  1113. appendQueueInfoFromAuditLine(items, lines.item(idx).text.get(), longestQueue, maxConnected, maxDisplay, 2);
  1114. countLines++;
  1115. }
  1116. response->setContentType(HTTP_TYPE_TEXT_HTML_UTF8);
  1117. response->setStatus(HTTP_STATUS_OK);
  1118. response->startSend();
  1119. if (items.length() < 1)
  1120. {
  1121. response->sendChunk("<script language=\"javascript\">\r\nparent.displayQEnd(\'No data found\')</script>\r\n");
  1122. return;
  1123. }
  1124. unsigned itemCount = items.length();
  1125. if (itemCount > maxDisplay)
  1126. itemCount = maxDisplay;
  1127. StringBuffer sb;
  1128. sb.append("<script language=\"javascript\">parent.displayQLegend()</script>\r\n");
  1129. sb.append("<script language=\"javascript\">parent.displayQBegin(");
  1130. sb.append(longestQueue).append(',').append(maxConnected).append(',').append(itemCount).append(")</script>\r\n");
  1131. response->sendChunk(sb.str());
  1132. sb.clear().append("<script language=\"javascript\">\r\n");
  1133. unsigned count = 0;
  1134. unsigned sbcount=0;
  1135. ForEachItemIn(i,items)
  1136. {
  1137. IEspThorQueue& tq = items.item(i);
  1138. count++;
  1139. if (count > maxDisplay)
  1140. break;
  1141. sb.append("parent.displayQueue(");
  1142. appendQuoted(sb, count, true);
  1143. appendQuoted(sb, tq.getDT());
  1144. appendQuoted(sb, tq.getRunningWUs());
  1145. appendQuoted(sb, tq.getQueuedWUs());
  1146. appendQuoted(sb, tq.getWaitingThors());
  1147. appendQuoted(sb, tq.getConnectedThors());
  1148. appendQuoted(sb, tq.getIdledThors());
  1149. appendQuoted(sb, tq.getRunningWU1());
  1150. appendQuoted(sb, tq.getRunningWU2());
  1151. sb.append(")\r\n");
  1152. if(++sbcount>=50)
  1153. {
  1154. sb.append("</script>\r\n");
  1155. response->sendChunk(sb.str());
  1156. sb.clear().append("<script language=\"javascript\">\r\n");
  1157. sbcount=0;
  1158. }
  1159. }
  1160. sb.append("parent.displayQEnd(\'<table><tr><td>");
  1161. sb.append("Total Records in the Time Period: ").append(items.length());
  1162. sb.append(" (<a href=\"/WsWorkunits/WUClusterJobQueueLOG?").append(xls);
  1163. sb.append("\">job_queue_log</a>...<a href=\"/WsWorkunits/WUClusterJobQueueXLS?").append(xls).append("\">job_queue.html</a>).");
  1164. sb.append("</td></tr><tr><td>");
  1165. if (count > maxDisplay)
  1166. sb.append("Displayed: First ").append(maxDisplay).append(". ");
  1167. sb.append("Max. Queue Length: ").append(longestQueue).append(".");
  1168. sb.append("</td></tr></table>\')</script>\r\n");
  1169. response->sendFinalChunk(sb.str());
  1170. }
  1171. void logWUClusterJobESPCall(const char* method, const char* cluster, const char* from, const char* to)
  1172. {
  1173. StringBuffer logMsg = method;
  1174. if (notEmpty(cluster))
  1175. logMsg.appendf(" cluster %s,", cluster);
  1176. if (notEmpty(from))
  1177. logMsg.appendf(" from %s,", from);
  1178. if (notEmpty(to))
  1179. logMsg.appendf(" to %s", to);
  1180. PROGLOG("%s", logMsg.str());
  1181. }
  1182. void CWsWorkunitsSoapBindingEx::createAndDownloadWUZAPFile(IEspContext& context, CHttpRequest* request, CHttpResponse* response)
  1183. {
  1184. CWsWuZAPInfoReq zapInfoReq;
  1185. request->getParameter("Wuid", zapInfoReq.wuid);
  1186. WsWuHelpers::checkAndTrimWorkunit("createAndDownloadWUZAPFile", zapInfoReq.wuid);
  1187. Owned<IWorkUnitFactory> factory = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  1188. Owned<IConstWorkUnit> cwu = factory->openWorkUnit(zapInfoReq.wuid.str());
  1189. if(!cwu.get())
  1190. throw MakeStringException(ECLWATCH_CANNOT_OPEN_WORKUNIT, "Cannot open workunit %s.", zapInfoReq.wuid.str());
  1191. ensureWsWorkunitAccess(context, *cwu, SecAccess_Read);
  1192. request->getParameter("URL", zapInfoReq.url);
  1193. request->getParameter("ESPIPAddress", zapInfoReq.espIP);
  1194. request->getParameter("ThorIPAddress", zapInfoReq.thorIP);
  1195. request->getParameter("ProblemDescription", zapInfoReq.problemDesc);
  1196. request->getParameter("WhatChanged", zapInfoReq.whatChanged);
  1197. request->getParameter("WhereSlow", zapInfoReq.whereSlow);
  1198. request->getParameter("IncludeThorSlaveLog", zapInfoReq.includeThorSlaveLog);
  1199. request->getParameter("ZAPFileName", zapInfoReq.zapFileName);
  1200. StringBuffer sendEmailStr, attachZAPReportToEmailStr, portStr;
  1201. request->getParameter("SendEmail", sendEmailStr);
  1202. zapInfoReq.sendEmail = atoi(sendEmailStr.str()) ? true : false;
  1203. if (zapInfoReq.sendEmail)
  1204. {
  1205. request->getParameter("AttachZAPReportToEmail", attachZAPReportToEmailStr);
  1206. zapInfoReq.attachZAPReportToEmail = atoi(attachZAPReportToEmailStr.str()) ? true : false;
  1207. request->getParameter("EmailSubject", zapInfoReq.emailSubject);
  1208. request->getParameter("EmailBody", zapInfoReq.emailBody);
  1209. if (!zapInfoReq.url.isEmpty())
  1210. zapInfoReq.emailBody.append("\r\nURL:").append(zapInfoReq.url.str());
  1211. //Read maxAttachmentSize from setting.
  1212. zapInfoReq.maxAttachmentSize = wswService->zapEmailMaxAttachmentSize;
  1213. zapInfoReq.emailServer.set(wswService->zapEmailServer.get());
  1214. zapInfoReq.port = wswService->zapEmailServerPort;
  1215. zapInfoReq.emailTo.set(wswService->zapEmailTo.str());
  1216. request->getParameter("EmailFrom", zapInfoReq.emailFrom);
  1217. if (zapInfoReq.emailFrom.isEmpty())
  1218. zapInfoReq.emailFrom.set(wswService->zapEmailFrom.str());
  1219. }
  1220. double version = context.getClientVersion();
  1221. if (version >= 1.70)
  1222. request->getParameter("ZAPPassword", zapInfoReq.password);
  1223. else
  1224. request->getParameter("Password", zapInfoReq.password);
  1225. //CWsWuFileHelper may need ESP's <Directories> settings to locate log files.
  1226. CWsWuFileHelper helper(directories);
  1227. response->setContent(helper.createWUZAPFileIOStream(context, cwu, zapInfoReq));
  1228. response->setContentType(HTTP_TYPE_OCTET_STREAM);
  1229. response->send();
  1230. }
  1231. void CWsWorkunitsSoapBindingEx::downloadWUFiles(IEspContext& context, CHttpRequest* request, CHttpResponse* response)
  1232. {
  1233. try
  1234. {
  1235. StringBuffer wuid;
  1236. request->getParameter("Wuid", wuid);
  1237. if (wuid.trim().isEmpty())
  1238. {
  1239. StringBuffer querySet, queryReq;
  1240. request->getParameter("QuerySet", querySet);
  1241. request->getParameter("Query", queryReq);
  1242. if (queryReq.trim().isEmpty() || querySet.trim().isEmpty())
  1243. throw MakeStringException(ECLWATCH_INVALID_INPUT, "WU ID or QuerySet/Query not specified");
  1244. Owned<IPropertyTree> registry = getQueryRegistry(querySet.str(), false);
  1245. if (!registry)
  1246. throw MakeStringException(ECLWATCH_QUERYSET_NOT_FOUND, "Queryset %s not found", querySet.str());
  1247. Owned<IPropertyTree> query = resolveQueryAlias(registry, queryReq.str());
  1248. if (!query)
  1249. throw MakeStringException(ECLWATCH_QUERYID_NOT_FOUND, "Query %s not found", queryReq.str());
  1250. wuid.set(query->queryProp("@wuid"));
  1251. }
  1252. if (!looksLikeAWuid(wuid, 'W'))
  1253. throw MakeStringException(ECLWATCH_INVALID_INPUT, "Invalid Workunit ID");
  1254. ensureWsWorkunitAccess(context, wuid, SecAccess_Read);
  1255. Owned<CWUDownloadFilesRequest> espRequest = new CWUDownloadFilesRequest(&context, "WsWorkunits", request->queryParameters(), request->queryAttachments());
  1256. IArrayOf<IConstWUFileOption>& wuFileOptions = espRequest->getWUFileOptions();
  1257. if (!wuFileOptions.ordinality())
  1258. throw MakeStringException(ECLWATCH_INVALID_INPUT, "No WU file specified");
  1259. CWUFileDownloadOption opt = espRequest->getDownloadOption();
  1260. if ((wuFileOptions.length() > 1) && ((opt == CWUFileDownloadOption_OriginalText) || (opt == CWUFileDownloadOption_Attachment)))
  1261. throw MakeStringException(ECLWATCH_INVALID_INPUT, "Cannot download multiple files without zip");
  1262. StringBuffer contentType;
  1263. //CWsWuFileHelper may need ESP's <Directories> settings to locate log files.
  1264. CWsWuFileHelper helper(directories);
  1265. response->setContent(helper.createWUFileIOStream(context, wuid.str(), wuFileOptions, opt, contentType));
  1266. response->setContentType(contentType);
  1267. response->send();
  1268. }
  1269. catch(IException* e)
  1270. {
  1271. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  1272. }
  1273. return;
  1274. }
  1275. int CWsWorkunitsSoapBindingEx::onGet(CHttpRequest* request, CHttpResponse* response)
  1276. {
  1277. IEspContext *ctx = request->queryContext();
  1278. IProperties *params = request->queryParameters();
  1279. try
  1280. {
  1281. StringBuffer path;
  1282. request->getPath(path);
  1283. if(!strnicmp(path.str(), "/WsWorkunits/res/", strlen("/WsWorkunits/res/")))
  1284. {
  1285. const char *pos = path.str();
  1286. skipPathNodes(pos, 1);
  1287. PROGLOG("getWuResourceByPath: %s", path.str());
  1288. MemoryBuffer mb;
  1289. StringBuffer mimetype;
  1290. getWuResourceByPath(pos, mb, mimetype);
  1291. response->setContent(mb.length(), mb.toByteArray());
  1292. response->setContentType(mimetype.str());
  1293. response->setStatus(HTTP_STATUS_OK);
  1294. response->send();
  1295. return 0;
  1296. }
  1297. if(!strnicmp(path.str(), "/WsWorkunits/manifest/", strlen("/WsWorkunits/manifest/")))
  1298. {
  1299. const char *pos = path.str();
  1300. skipPathNodes(pos, 1);
  1301. PROGLOG("getWuManifestByPath: %s", path.str());
  1302. StringBuffer mf;
  1303. getWuManifestByPath(pos, mf);
  1304. response->setContent(mf.str());
  1305. response->setContentType("text/xml");
  1306. response->setStatus(HTTP_STATUS_OK);
  1307. response->send();
  1308. return 0;
  1309. }
  1310. if(!strnicmp(path.str(), "/WsWorkunits/JobList", 20))
  1311. {
  1312. SecAccessFlags accessOwn;
  1313. SecAccessFlags accessOthers;
  1314. getUserWuAccessFlags(*ctx, accessOwn, accessOthers, true);
  1315. if (ctx->getClientVersion()<=0)
  1316. ctx->setClientVersion(1.51);
  1317. const char *cluster = params->queryProp("Cluster");
  1318. const char *startDate = params->queryProp("StartDate");
  1319. const char *endDate = params->queryProp("EndDate");
  1320. const char *showAll = params->queryProp("ShowAll");
  1321. const char *busStart = params->queryProp("BusinessStartTime");
  1322. const char *busEnd = params->queryProp("BusinessEndTime");
  1323. float fBusStart = 0;
  1324. float fBusEnd = 24;
  1325. bool bShowAll = (isEmpty(showAll) ? false : (atoi(showAll)==1));
  1326. if (bShowAll)
  1327. {
  1328. timeStrToFloat(busStart, fBusStart);
  1329. timeStrToFloat(busEnd, fBusEnd);
  1330. if(fBusStart <= 0 || fBusEnd > 24 || fBusStart >= fBusEnd)
  1331. throw MakeStringException(ECLWATCH_INVALID_INPUT, "Invalid business hours");
  1332. }
  1333. response->addHeader("Expires", "0");
  1334. response->setContentType(HTTP_TYPE_TEXT_HTML_UTF8);
  1335. StringBuffer xls("ShowAll=1");
  1336. addToQueryString(xls, "Cluster", cluster);
  1337. addToQueryString(xls, "StartDate", startDate);
  1338. addToQueryString(xls, "EndDate", endDate);
  1339. addToQueryString(xls, "BusinessStartTime", busStart);
  1340. addToQueryString(xls, "BusinessEndTime", busEnd);
  1341. PROGLOG("WUJobList: %s", xls.str());
  1342. streamJobListResponse(*ctx, cluster, startDate, endDate, response, bShowAll, fBusStart, fBusEnd, xls.str());
  1343. return 0;
  1344. }
  1345. else if(!strnicmp(path.str(), "/WsWorkunits/JobQueue", 21))
  1346. {
  1347. SecAccessFlags accessOwn;
  1348. SecAccessFlags accessOthers;
  1349. getUserWuAccessFlags(*ctx, accessOwn, accessOthers, true);
  1350. const char *cluster = params->queryProp("Cluster");
  1351. const char *startDate = params->queryProp("StartDate");
  1352. const char *endDate = params->queryProp("EndDate");
  1353. response->addHeader("Expires", "0");
  1354. response->setContentType(HTTP_TYPE_TEXT_HTML_UTF8);
  1355. StringBuffer xls;
  1356. xls.append("ShowType=InGraph");
  1357. addToQueryString(xls, "Cluster", cluster);
  1358. addToQueryString(xls, "StartDate", startDate);
  1359. addToQueryString(xls, "EndDate", endDate);
  1360. PROGLOG("WUJobQueue: %s", xls.str());
  1361. streamJobQueueListResponse(*ctx, cluster, startDate, endDate, response, xls.str());
  1362. return 0;
  1363. }
  1364. else if(!strnicmp(path.str(), "/WsWorkunits/filesInUse", 28))
  1365. {
  1366. StringBuffer xml;
  1367. wswService->filesInUse.toStr(xml);
  1368. response->setContent(xml);
  1369. response->setContentType("text/xml");
  1370. response->setStatus(HTTP_STATUS_OK);
  1371. response->send();
  1372. return 0;
  1373. }
  1374. else if (!strnicmp(path.str(), REQPATH_CREATEANDDOWNLOADZAP, sizeof(REQPATH_CREATEANDDOWNLOADZAP) - 1))
  1375. {
  1376. createAndDownloadWUZAPFile(*ctx, request, response);
  1377. return 0;
  1378. }
  1379. else if (!strnicmp(path.str(), REQPATH_DOWNLOADFILES, sizeof(REQPATH_DOWNLOADFILES) - 1))
  1380. {
  1381. downloadWUFiles(*ctx, request, response);
  1382. return 0;
  1383. }
  1384. }
  1385. catch(IException* e)
  1386. {
  1387. onGetException(*request->queryContext(), request, response, *e);
  1388. FORWARDEXCEPTION(*request->queryContext(), e, ECLWATCH_INTERNAL_ERROR);
  1389. }
  1390. return CWsWorkunitsSoapBinding::onGet(request,response);
  1391. }
  1392. bool CWsWorkunitsEx::onWUClusterJobQueueXLS(IEspContext &context, IEspWUClusterJobQueueXLSRequest &req, IEspWUClusterJobQueueXLSResponse &resp)
  1393. {
  1394. try
  1395. {
  1396. SecAccessFlags accessOwn;
  1397. SecAccessFlags accessOthers;
  1398. getUserWuAccessFlags(context, accessOwn, accessOthers, true);
  1399. logWUClusterJobESPCall("WUClusterJobQueueXLS", req.getCluster(), req.getStartDate(), req.getEndDate());
  1400. StringBuffer xml("<WUResultExcel><Result>");
  1401. getClusterJobQueueXLS(xml, req.getCluster(), req.getStartDate(), req.getEndDate(), req.getShowType());
  1402. xml.append("</Result></WUResultExcel>");
  1403. Owned<IProperties> params(createProperties());
  1404. params->setProp("showCount",0);
  1405. StringBuffer xls;
  1406. xsltTransform(xml.str(), StringBuffer(getCFD()).append("./smc_xslt/result.xslt").str(), params, xls);
  1407. MemoryBuffer mb;
  1408. mb.setBuffer(xls.length(), (void*)xls.str());
  1409. resp.setResult(mb);
  1410. resp.setResult_mimetype(HTTP_TYPE_TEXT_HTML);
  1411. context.addCustomerHeader("Content-disposition", "attachment;filename=job_queue.html");
  1412. }
  1413. catch(IException* e)
  1414. {
  1415. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  1416. }
  1417. return true;
  1418. }
  1419. bool CWsWorkunitsEx::onWUClusterJobQueueLOG(IEspContext &context,IEspWUClusterJobQueueLOGRequest &req, IEspWUClusterJobQueueLOGResponse &resp)
  1420. {
  1421. try
  1422. {
  1423. SecAccessFlags accessOwn;
  1424. SecAccessFlags accessOthers;
  1425. getUserWuAccessFlags(context, accessOwn, accessOthers, true);
  1426. StringBuffer logMsg = "WUClusterJobQueueLOG: ";
  1427. CDateTime fromTime;
  1428. if(notEmpty(req.getStartDate()))
  1429. {
  1430. fromTime.setString(req.getStartDate(), NULL, false);
  1431. logMsg.appendf(" from %s,", req.getStartDate());
  1432. }
  1433. CDateTime toTime;
  1434. if(notEmpty(req.getEndDate()))
  1435. {
  1436. toTime.setString(req.getEndDate(), NULL, false);
  1437. logMsg.appendf(" to %s,", req.getEndDate());
  1438. }
  1439. const char *cluster = req.getCluster();
  1440. StringBuffer filter("ThorQueueMonitor");
  1441. if (notEmpty(cluster))
  1442. filter.appendf(",%s", cluster);
  1443. PROGLOG("%s filter %s", logMsg.str(), filter.str());
  1444. StringAttrArray lines;
  1445. queryAuditLogs(fromTime, toTime, filter.str(), lines);
  1446. StringBuffer text;
  1447. ForEachItemIn(idx, lines)
  1448. {
  1449. if (lines.item(idx).text.isEmpty())
  1450. continue;
  1451. text.append(lines.item(idx).text.get()).append("\r\n");
  1452. if (text.length()>LOGFILESIZELIMIT)
  1453. {
  1454. text.appendf("... ...");
  1455. break;
  1456. }
  1457. }
  1458. MemoryBuffer mb;
  1459. mb.setBuffer(text.length(), (void*)text.str());
  1460. resp.setThefile(mb);
  1461. resp.setThefile_mimetype(HTTP_TYPE_TEXT_PLAIN);
  1462. }
  1463. catch(IException* e)
  1464. {
  1465. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  1466. }
  1467. return true;
  1468. }
  1469. bool CWsWorkunitsEx::onWUJobList(IEspContext &context, IEspWUJobListRequest &req, IEspWUJobListResponse &resp)
  1470. {
  1471. return true;
  1472. }
  1473. bool CWsWorkunitsEx::onWUClusterJobXLS(IEspContext &context, IEspWUClusterJobXLSRequest &req, IEspWUClusterJobXLSResponse &resp)
  1474. {
  1475. try
  1476. {
  1477. SecAccessFlags accessOwn;
  1478. SecAccessFlags accessOthers;
  1479. getUserWuAccessFlags(context, accessOwn, accessOthers, true);
  1480. logWUClusterJobESPCall("WUClusterJobXLS", req.getCluster(), req.getStartDate(), req.getEndDate());
  1481. StringBuffer xml("<WUResultExcel><Result>");
  1482. getClusterJobXLS(context.getClientVersion(), xml, req.getCluster(), req.getStartDate(), req.getEndDate(), req.getShowAll(), req.getBusinessStartTime(), req.getBusinessEndTime());
  1483. xml.append("</Result></WUResultExcel>");
  1484. Owned<IProperties> params(createProperties());
  1485. params->setProp("showCount",0);
  1486. StringBuffer xls;
  1487. xsltTransform(xml.str(), StringBuffer(getCFD()).append("./smc_xslt/result.xslt").str(), params, xls);
  1488. MemoryBuffer mb;
  1489. mb.setBuffer(xls.length(), (void*)xls.str());
  1490. resp.setResult(mb);
  1491. resp.setResult_mimetype(HTTP_TYPE_TEXT_HTML);
  1492. context.addCustomerHeader("Content-disposition", "attachment;filename=cluster_jobs.html");
  1493. }
  1494. catch(IException* e)
  1495. {
  1496. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  1497. }
  1498. return true;
  1499. }
  1500. bool CWsWorkunitsEx::onWUClusterJobSummaryXLS(IEspContext &context, IEspWUClusterJobSummaryXLSRequest &req, IEspWUClusterJobSummaryXLSResponse &resp)
  1501. {
  1502. try
  1503. {
  1504. SecAccessFlags accessOwn;
  1505. SecAccessFlags accessOthers;
  1506. getUserWuAccessFlags(context, accessOwn, accessOthers, true);
  1507. logWUClusterJobESPCall("WUClusterJobSummaryXLS", req.getCluster(), req.getStartDate(), req.getEndDate());
  1508. StringBuffer xml("<WUResultExcel><Result>");
  1509. getClusterJobSummaryXLS(context.getClientVersion(), xml, req.getCluster(), req.getStartDate(), req.getEndDate(), req.getShowAll(), req.getBusinessStartTime(), req.getBusinessEndTime());
  1510. xml.append("</Result></WUResultExcel>");
  1511. StringBuffer xls;
  1512. Owned<IProperties> params(createProperties());
  1513. params->setProp("showCount",0);
  1514. xsltTransform(xml.str(), StringBuffer(getCFD()).append("./smc_xslt/result.xslt").str(), params, xls);
  1515. MemoryBuffer mb;
  1516. mb.setBuffer(xls.length(), (void*)xls.str());
  1517. resp.setResult(mb);
  1518. resp.setResult_mimetype(HTTP_TYPE_TEXT_HTML);
  1519. }
  1520. catch(IException* e)
  1521. {
  1522. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  1523. }
  1524. return true;
  1525. }