ws_workunitsHelpers.cpp 106 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297
  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 "jlib.hpp"
  14. #include "ws_workunitsHelpers.hpp"
  15. #include "exception_util.hpp"
  16. #include "daclient.hpp"
  17. #include "dalienv.hpp"
  18. #include "daaudit.hpp"
  19. #include "portlist.h"
  20. #include "dadfs.hpp"
  21. #include "fileview.hpp"
  22. #include "wuwebview.hpp"
  23. #include "dllserver.hpp"
  24. #include "wujobq.hpp"
  25. #include "hqlexpr.hpp"
  26. #ifndef _NO_LDAP
  27. #include "ldapsecurity.ipp"
  28. #endif
  29. #ifdef _USE_ZLIB
  30. #include "zcrypt.hpp"
  31. #endif
  32. namespace ws_workunits {
  33. SecAccessFlags chooseWuAccessFlagsByOwnership(const char *user, const char *owner, SecAccessFlags accessOwn, SecAccessFlags accessOthers)
  34. {
  35. return (isEmpty(owner) || (user && streq(user, owner))) ? accessOwn : accessOthers;
  36. }
  37. SecAccessFlags chooseWuAccessFlagsByOwnership(const char *user, IConstWorkUnitInfo& cw, SecAccessFlags accessOwn, SecAccessFlags accessOthers)
  38. {
  39. return chooseWuAccessFlagsByOwnership(user, cw.queryUser(), accessOwn, accessOthers);
  40. }
  41. const char *getWuAccessType(const char *owner, const char *user)
  42. {
  43. return (isEmpty(owner) || (user && streq(user, owner))) ? OWN_WU_ACCESS : OTHERS_WU_ACCESS;
  44. }
  45. const char *getWuAccessType(IConstWorkUnit& cw, const char *user)
  46. {
  47. return getWuAccessType(cw.queryUser(), user);
  48. }
  49. void getUserWuAccessFlags(IEspContext& context, SecAccessFlags& accessOwn, SecAccessFlags& accessOthers, bool except)
  50. {
  51. if (!context.authorizeFeature(OWN_WU_ACCESS, accessOwn))
  52. accessOwn = SecAccess_None;
  53. if (!context.authorizeFeature(OTHERS_WU_ACCESS, accessOthers))
  54. accessOthers = SecAccess_None;
  55. if (except && (accessOwn == SecAccess_None) && (accessOthers == SecAccess_None))
  56. {
  57. AuditSystemAccess(context.queryUserId(), false, "Access Denied: User can't view any workunits");
  58. VStringBuffer msg("Access Denied: User %s does not have rights to access workunits.", context.queryUserId());
  59. throw MakeStringException(ECLWATCH_ECL_WU_ACCESS_DENIED, "%s", msg.str());
  60. }
  61. }
  62. SecAccessFlags getWsWorkunitAccess(IEspContext& cxt, IConstWorkUnit& cw)
  63. {
  64. SecAccessFlags accessFlag = SecAccess_None;
  65. cxt.authorizeFeature(getWuAccessType(cw, cxt.queryUserId()), accessFlag);
  66. return accessFlag;
  67. }
  68. void ensureWsWorkunitAccessByOwnerId(IEspContext& cxt, const char* owner, SecAccessFlags minAccess)
  69. {
  70. if (!cxt.validateFeatureAccess(getWuAccessType(owner, cxt.queryUserId()), minAccess, false))
  71. throw MakeStringException(ECLWATCH_ECL_WU_ACCESS_DENIED, "Failed to access workunit. Permission denied.");
  72. }
  73. void ensureWsWorkunitAccess(IEspContext& cxt, IConstWorkUnit& cw, SecAccessFlags minAccess)
  74. {
  75. if (!cxt.validateFeatureAccess(getWuAccessType(cw, cxt.queryUserId()), minAccess, false))
  76. throw MakeStringException(ECLWATCH_ECL_WU_ACCESS_DENIED, "Failed to access workunit. Permission denied.");
  77. }
  78. void ensureWsWorkunitAccess(IEspContext& context, const char* wuid, SecAccessFlags minAccess)
  79. {
  80. Owned<IWorkUnitFactory> wf = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  81. Owned<IConstWorkUnit> cw = wf->openWorkUnit(wuid);
  82. if (!cw)
  83. throw MakeStringException(ECLWATCH_CANNOT_OPEN_WORKUNIT, "Failed to open workunit %s when ensuring workunit access", wuid);
  84. ensureWsWorkunitAccess(context, *cw, minAccess);
  85. }
  86. void ensureWsCreateWorkunitAccess(IEspContext& cxt)
  87. {
  88. if (!cxt.validateFeatureAccess(OWN_WU_ACCESS, SecAccess_Write, false))
  89. throw MakeStringException(ECLWATCH_ECL_WU_ACCESS_DENIED, "Failed to create workunit. Permission denied.");
  90. }
  91. StringBuffer &getWuidFromLogicalFileName(IEspContext &context, const char *logicalName, StringBuffer &wuid)
  92. {
  93. Owned<IUserDescriptor> userdesc = createUserDescriptor();
  94. userdesc->set(context.queryUserId(), context.queryPassword());
  95. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(logicalName, userdesc);
  96. if (!df)
  97. throw MakeStringException(ECLWATCH_FILE_NOT_EXIST,"Cannot find file %s.",logicalName);
  98. return wuid.append(df->queryAttributes().queryProp("@workunit"));
  99. }
  100. void formatDuration(StringBuffer &s, unsigned ms)
  101. {
  102. unsigned days = ms / (1000*60*60*24);
  103. ms %= (1000*60*60*24);
  104. unsigned hours = ms / (1000*60*60);
  105. ms %= (1000*60*60);
  106. unsigned mins = ms / (1000*60);
  107. ms %= (1000*60);
  108. unsigned secs = ms / 1000;
  109. ms %= 1000;
  110. if (days)
  111. s.appendf("%d days ", days);
  112. if (hours || s.length())
  113. s.appendf("%d:", hours);
  114. if (mins || s.length())
  115. s.appendf("%d:", mins);
  116. if (s.length())
  117. s.appendf("%02d.%03d", secs, ms);
  118. else
  119. s.appendf("%d.%03d", secs, ms);
  120. }
  121. WsWUExceptions::WsWUExceptions(IConstWorkUnit& wu): numerr(0), numwrn(0), numinf(0), numalert(0)
  122. {
  123. Owned<IConstWUExceptionIterator> it = &wu.getExceptions();
  124. ForEach(*it)
  125. {
  126. IConstWUException & cur = it->query();
  127. SCMStringBuffer src, msg, file;
  128. Owned<IEspECLException> e= createECLException("","");
  129. e->setCode(cur.getExceptionCode());
  130. e->setSource(cur.getExceptionSource(src).str());
  131. e->setMessage(cur.getExceptionMessage(msg).str());
  132. e->setFileName(cur.getExceptionFileName(file).str());
  133. e->setLineNo(cur.getExceptionLineNo());
  134. e->setColumn(cur.getExceptionColumn());
  135. if (cur.getActivityId())
  136. e->setActivity(cur.getActivityId());
  137. const char * label = "";
  138. switch (cur.getSeverity())
  139. {
  140. default:
  141. case SeverityError: label = "Error"; numerr++; break;
  142. case SeverityWarning: label = "Warning"; numwrn++; break;
  143. case SeverityInformation: label = "Info"; numinf++; break;
  144. case SeverityAlert: label = "Alert"; numalert++; break;
  145. }
  146. e->setSeverity(label);
  147. errors.append(*e.getLink());
  148. }
  149. }
  150. #define SDS_LOCK_TIMEOUT 30000
  151. void getSashaNode(SocketEndpoint &ep)
  152. {
  153. Owned<IEnvironmentFactory> factory = getEnvironmentFactory();
  154. Owned<IConstEnvironment> env = factory->openEnvironment();
  155. if (!env)
  156. throw MakeStringException(ECLWATCH_CANNOT_GET_ENV_INFO,"Cannot get environment information.");
  157. Owned<IPropertyTree> root = &env->getPTree();
  158. IPropertyTree *pt = root->queryPropTree("Software/SashaServerProcess[1]/Instance[1]");
  159. if (!pt)
  160. throw MakeStringException(ECLWATCH_ARCHIVE_SERVER_NOT_FOUND, "Archive Server not found.");
  161. ep.set(pt->queryProp("@netAddress"), pt->getPropInt("@port",DEFAULT_SASHA_PORT));
  162. }
  163. void WsWuInfo::getSourceFiles(IEspECLWorkunit &info, unsigned long flags)
  164. {
  165. if (!(flags & WUINFO_IncludeSourceFiles))
  166. return;
  167. try
  168. {
  169. Owned<IUserDescriptor> userdesc;
  170. StringBuffer username;
  171. context.getUserID(username);
  172. const char* passwd = context.queryPassword();
  173. userdesc.setown(createUserDescriptor());
  174. userdesc->set(username.str(), passwd);
  175. IArrayOf<IEspECLSourceFile> files;
  176. if (version < 1.27)
  177. {
  178. Owned<IPropertyTreeIterator> f=&cw->getFilesReadIterator();
  179. ForEach(*f)
  180. {
  181. IPropertyTree &query = f->query();
  182. const char *clusterName = query.queryProp("@cluster");
  183. const char *fileName = query.queryProp("@name");
  184. int fileCount = query.getPropInt("@useCount");
  185. Owned<IEspECLSourceFile> file= createECLSourceFile("","");
  186. if(clusterName && *clusterName)
  187. {
  188. file->setFileCluster(clusterName);
  189. }
  190. if (version > 1.11)
  191. {
  192. Owned<IPropertyTreeIterator> filetrees= query.getElements("Subfile");
  193. if (filetrees->first())
  194. file->setIsSuperFile(true);
  195. }
  196. if (fileName && *fileName)
  197. {
  198. file->setName(fileName);
  199. }
  200. file->setCount(fileCount);
  201. files.append(*file.getLink());
  202. }
  203. }
  204. else
  205. {
  206. StringArray fileNames;
  207. Owned<IPropertyTreeIterator> f=&cw->getFilesReadIterator();
  208. ForEach(*f)
  209. {
  210. IPropertyTree &query = f->query();
  211. const char *clusterName = query.queryProp("@cluster");
  212. const char *fileName = query.queryProp("@name");
  213. int fileCount = query.getPropInt("@useCount");
  214. bool bFound = false;
  215. if (fileName && *fileName && (fileNames.length() > 0))
  216. {
  217. for (unsigned i = 0; i < fileNames.length(); i++ ) // MORE - unnecessary n^2 process
  218. {
  219. const char *fileName0 = fileNames.item(i);
  220. if (!stricmp(fileName, fileName0))
  221. {
  222. bFound = true;
  223. break;
  224. }
  225. }
  226. }
  227. if (bFound)
  228. continue;
  229. Owned<IEspECLSourceFile> file= createECLSourceFile("","");
  230. if(clusterName && *clusterName)
  231. {
  232. file->setFileCluster(clusterName);
  233. }
  234. if (fileName && *fileName)
  235. {
  236. file->setName(fileName);
  237. }
  238. file->setCount(fileCount);
  239. Owned<IPropertyTreeIterator> filetrees= query.getElements("Subfile");
  240. if (filetrees->first())
  241. {
  242. file->setIsSuperFile(true);
  243. getSubFiles(filetrees, file, fileNames);
  244. }
  245. files.append(*file.getLink());
  246. }
  247. }
  248. info.setSourceFiles(files);
  249. }
  250. catch(IException* e)
  251. {
  252. StringBuffer eMsg;
  253. ERRLOG("%s", e->errorMessage(eMsg).str());
  254. info.setSourceFilesDesc(eMsg.str());
  255. e->Release();
  256. }
  257. }
  258. void WsWuInfo::getExceptions(IEspECLWorkunit &info, unsigned long flags)
  259. {
  260. if ((flags & WUINFO_IncludeExceptions) || version > 1.16)
  261. {
  262. WsWUExceptions errors(*cw);
  263. if (version > 1.16)
  264. {
  265. info.setErrorCount(errors.ErrCount());
  266. info.setWarningCount(errors.WrnCount());
  267. info.setInfoCount(errors.InfCount());
  268. info.setAlertCount(errors.AlertCount());
  269. }
  270. if ((flags & WUINFO_IncludeExceptions))
  271. info.setExceptions(errors);
  272. }
  273. }
  274. void WsWuInfo::getVariables(IEspECLWorkunit &info, unsigned long flags)
  275. {
  276. if (!(flags & WUINFO_IncludeVariables))
  277. return;
  278. try
  279. {
  280. IArrayOf<IEspECLResult> results;
  281. Owned<IConstWUResultIterator> vars = &cw->getVariables();
  282. ForEach(*vars)
  283. getResult(vars->query(), results, flags);
  284. info.setVariables(results);
  285. results.kill();
  286. }
  287. catch(IException* e)
  288. {
  289. StringBuffer eMsg;
  290. ERRLOG("%s", e->errorMessage(eMsg).str());
  291. info.setVariablesDesc(eMsg.str());
  292. e->Release();
  293. }
  294. }
  295. void WsWuInfo::addTimerToList(SCMStringBuffer& name, const char * scope, IConstWUStatistic & stat, IArrayOf<IEspECLTimer>& timers)
  296. {
  297. StringBuffer fd;
  298. formatStatistic(fd, stat.getValue(), stat.getMeasure());
  299. Owned<IEspECLTimer> t= createECLTimer("","");
  300. name.s.replace('_', ' '); // yuk!
  301. t->setName(name.str());
  302. t->setValue(fd.str());
  303. //Theoretically this could overflow, in practice it is unlikely - fix in the new stats interface when implemented
  304. t->setCount((unsigned)stat.getCount());
  305. if (version > 1.19)
  306. {
  307. StringAttr graphName;
  308. unsigned graphNum;
  309. unsigned subGraphNum = 0;
  310. unsigned subId = 0;
  311. if (parseGraphScope(scope, graphName, graphNum, subId) ||
  312. parseGraphTimerLabel(name.str(), graphName, graphNum, subGraphNum, subId)) // leacy
  313. {
  314. if (graphName.length() > 0)
  315. t->setGraphName(graphName);
  316. if (subId > 0)
  317. t->setSubGraphId((int)subId);
  318. }
  319. }
  320. timers.append(*t.getLink());
  321. }
  322. void WsWuInfo::doGetTimers(IArrayOf<IEspECLTimer>& timers)
  323. {
  324. unsigned __int64 totalThorTimeValue = 0;
  325. unsigned __int64 totalThorTimerCount = 0; //Do we need this?
  326. StatisticsFilter filter;
  327. filter.setScopeDepth(1, 2);
  328. filter.setMeasure(SMeasureTimeNs);
  329. Owned<IConstWUStatisticIterator> it = &cw->getStatistics(&filter);
  330. if (it->first())
  331. {
  332. ForEach(*it)
  333. {
  334. IConstWUStatistic & cur = it->query();
  335. SCMStringBuffer name, scope;
  336. cur.getDescription(name, true);
  337. cur.getScope(scope);
  338. bool isThorTiming = false;//Should it be renamed as isClusterTiming?
  339. if ((cur.getCreatorType() == SCTsummary) && (cur.getKind() == StTimeElapsed) && streq(scope.str(), GLOBAL_SCOPE))
  340. {
  341. SCMStringBuffer creator;
  342. cur.getCreator(creator);
  343. if (streq(creator.str(), "thor") || streq(creator.str(), "hthor") ||
  344. streq(creator.str(), "roxie"))
  345. isThorTiming = true;
  346. }
  347. else if (strieq(name.str(), TOTALTHORTIME)) // legacy
  348. isThorTiming = true;
  349. if (isThorTiming)
  350. {
  351. totalThorTimeValue += cur.getValue();
  352. totalThorTimerCount += cur.getCount();
  353. }
  354. else
  355. addTimerToList(name, scope.str(), cur, timers);
  356. }
  357. }
  358. if (totalThorTimeValue > 0)
  359. {
  360. StringBuffer totalThorTimeText;
  361. formatStatistic(totalThorTimeText, totalThorTimeValue, SMeasureTimeNs);
  362. Owned<IEspECLTimer> t= createECLTimer("","");
  363. if (version > 1.52)
  364. t->setName(TOTALCLUSTERTIME);
  365. else
  366. t->setName(TOTALTHORTIME);
  367. t->setValue(totalThorTimeText.str());
  368. t->setCount((unsigned)totalThorTimerCount);
  369. timers.append(*t.getLink());
  370. }
  371. }
  372. void WsWuInfo::getTimers(IEspECLWorkunit &info, unsigned long flags)
  373. {
  374. if (!(flags & WUINFO_IncludeTimers))
  375. return;
  376. try
  377. {
  378. IArrayOf<IEspECLTimer> timers;
  379. doGetTimers(timers);
  380. info.setTimers(timers);
  381. }
  382. catch(IException* e)
  383. {
  384. StringBuffer eMsg;
  385. ERRLOG("%s", e->errorMessage(eMsg).str());
  386. info.setTimersDesc(eMsg.str());
  387. e->Release();
  388. }
  389. }
  390. unsigned WsWuInfo::getTimerCount()
  391. {
  392. unsigned numTimers = 0;
  393. try
  394. {
  395. //This filter must match the filter in the function above, otherwise it will be inconsistent
  396. StatisticsFilter filter;
  397. filter.setScopeDepth(1, 2);
  398. filter.setMeasure(SMeasureTimeNs);
  399. Owned<IConstWUStatisticIterator> it = &cw->getStatistics(&filter);
  400. ForEach(*it)
  401. numTimers++;
  402. }
  403. catch(IException* e)
  404. {
  405. StringBuffer eMsg;
  406. ERRLOG("%s", e->errorMessage(eMsg).str());
  407. e->Release();
  408. }
  409. return numTimers;
  410. }
  411. mapEnums queryFileTypes[] = {
  412. { FileTypeCpp, "cpp" },
  413. { FileTypeDll, "dll" },
  414. { FileTypeResText, "res" },
  415. { FileTypeHintXml, "hint" },
  416. { FileTypeXml, "xml" },
  417. { FileTypeSize, NULL },
  418. };
  419. void WsWuInfo::getHelpers(IEspECLWorkunit &info, unsigned long flags)
  420. {
  421. try
  422. {
  423. IArrayOf<IEspECLHelpFile> helpers;
  424. unsigned helpersCount = 2; // ECL + Workunit XML are also helpers...
  425. Owned <IConstWUQuery> query = cw->getQuery();
  426. if(!query)
  427. {
  428. ERRLOG("Cannot get Query for this workunit.");
  429. info.setHelpersDesc("Cannot get Query for this workunit.");
  430. }
  431. else
  432. {
  433. if (flags & WUINFO_IncludeECL)
  434. {
  435. SCMStringBuffer queryText;
  436. query->getQueryShortText(queryText);
  437. if (queryText.length())
  438. {
  439. if((flags & WUINFO_TruncateEclTo64k) && (queryText.length() > 64000))
  440. queryText.setLen(queryText.str(), 64000);
  441. IEspECLQuery* q=&info.updateQuery();
  442. q->setText(queryText.str());
  443. }
  444. }
  445. if (version > 1.34)
  446. {
  447. SCMStringBuffer mainDefinition;
  448. query->getQueryMainDefinition(mainDefinition);
  449. if(mainDefinition.length())
  450. {
  451. IEspECLQuery* q=&info.updateQuery();
  452. q->setQueryMainDefinition(mainDefinition.str());
  453. }
  454. }
  455. if (version > 1.30)
  456. {
  457. info.setHasArchiveQuery(query->hasArchive());
  458. }
  459. for (unsigned i = 0; i < FileTypeSize; i++)
  460. getHelpFiles(query, (WUFileType) i, helpers, flags, helpersCount);
  461. }
  462. getWorkunitThorLogInfo(helpers, info, flags, helpersCount);
  463. if (cw->getWuidVersion() > 0)
  464. {
  465. Owned<IPropertyTreeIterator> eclAgents = cw->getProcesses("EclAgent", NULL);
  466. ForEach (*eclAgents)
  467. {
  468. StringBuffer logName;
  469. IPropertyTree& eclAgent = eclAgents->query();
  470. eclAgent.getProp("@log",logName);
  471. if (!logName.length())
  472. continue;
  473. helpersCount++;
  474. if (!(flags & WUINFO_IncludeHelpers))
  475. continue;
  476. Owned<IEspECLHelpFile> h= createECLHelpFile("","");
  477. h->setName(logName.str());
  478. h->setType(File_EclAgentLog);
  479. if (version >= 1.43)
  480. {
  481. offset_t fileSize;
  482. if (getFileSize(logName.str(), NULL, fileSize))
  483. h->setFileSize(fileSize);
  484. if (version >= 1.44)
  485. {
  486. if (eclAgent.hasProp("@pid"))
  487. h->setPID(eclAgent.getPropInt("@pid"));
  488. else
  489. h->setPID(cw->getAgentPID());
  490. }
  491. }
  492. helpers.append(*h.getLink());
  493. }
  494. }
  495. else // legacy wuid
  496. {
  497. Owned<IStringIterator> eclAgentLogs = cw->getLogs("EclAgent");
  498. ForEach (*eclAgentLogs)
  499. {
  500. SCMStringBuffer name;
  501. eclAgentLogs->str(name);
  502. if (name.length() < 1)
  503. continue;
  504. helpersCount++;
  505. if (!(flags & WUINFO_IncludeHelpers))
  506. break;
  507. Owned<IEspECLHelpFile> h= createECLHelpFile("","");
  508. h->setName(name.str());
  509. h->setType(File_EclAgentLog);
  510. if (version >= 1.43)
  511. {
  512. offset_t fileSize;
  513. if (getFileSize(name.str(), NULL, fileSize))
  514. h->setFileSize(fileSize);
  515. }
  516. helpers.append(*h.getLink());
  517. break;
  518. }
  519. }
  520. info.setHelpers(helpers);
  521. info.setHelpersCount(helpersCount);
  522. }
  523. catch(IException* e)
  524. {
  525. StringBuffer eMsg;
  526. ERRLOG("%s", e->errorMessage(eMsg).str());
  527. info.setHelpersDesc(eMsg.str());
  528. e->Release();
  529. }
  530. }
  531. void WsWuInfo::getApplicationValues(IEspECLWorkunit &info, unsigned long flags)
  532. {
  533. if (!(flags & WUINFO_IncludeApplicationValues))
  534. return;
  535. try
  536. {
  537. IArrayOf<IEspApplicationValue> av;
  538. Owned<IConstWUAppValueIterator> app(&cw->getApplicationValues());
  539. ForEach(*app)
  540. {
  541. IConstWUAppValue& val=app->query();
  542. Owned<IEspApplicationValue> t= createApplicationValue("","");
  543. t->setApplication(val.queryApplication());
  544. t->setName(val.queryName());
  545. t->setValue(val.queryValue());
  546. av.append(*t.getLink());
  547. }
  548. info.setApplicationValues(av);
  549. }
  550. catch(IException* e)
  551. {
  552. StringBuffer eMsg;
  553. ERRLOG("%s", e->errorMessage(eMsg).str());
  554. info.setApplicationValuesDesc(eMsg.str());
  555. e->Release();
  556. }
  557. }
  558. void WsWuInfo::getDebugValues(IEspECLWorkunit &info, unsigned long flags)
  559. {
  560. if (!(flags & WUINFO_IncludeDebugValues))
  561. {
  562. if (version >= 1.50)
  563. {
  564. unsigned debugValueCount = 0;
  565. Owned<IStringIterator> debugs(&cw->getDebugValues());
  566. ForEach(*debugs)
  567. debugValueCount++;
  568. info.setDebugValueCount(debugValueCount);
  569. }
  570. return;
  571. }
  572. try
  573. {
  574. IArrayOf<IEspDebugValue> dv;
  575. Owned<IStringIterator> debugs(&cw->getDebugValues());
  576. ForEach(*debugs)
  577. {
  578. SCMStringBuffer name, val;
  579. debugs->str(name);
  580. cw->getDebugValue(name.str(),val);
  581. Owned<IEspDebugValue> t= createDebugValue("","");
  582. t->setName(name.str());
  583. t->setValue(val.str());
  584. dv.append(*t.getLink());
  585. }
  586. if (version >= 1.50)
  587. info.setDebugValueCount(dv.length());
  588. info.setDebugValues(dv);
  589. }
  590. catch(IException* e)
  591. {
  592. StringBuffer eMsg;
  593. ERRLOG("%s", e->errorMessage(eMsg).str());
  594. info.setDebugValuesDesc(eMsg.str());
  595. e->Release();
  596. }
  597. }
  598. const char *getGraphNum(const char *s,unsigned &num)
  599. {
  600. while (*s && !isdigit(*s))
  601. s++;
  602. num = 0;
  603. while (isdigit(*s))
  604. {
  605. num = num*10+*s-'0';
  606. s++;
  607. }
  608. return s;
  609. }
  610. bool WsWuInfo::hasSubGraphTimings()
  611. {
  612. StatisticsFilter filter;
  613. filter.setScopeType(SSTsubgraph);
  614. filter.setKind(StTimeElapsed);
  615. Owned<IConstWUStatisticIterator> times = &cw->getStatistics(&filter);
  616. return times->first();
  617. }
  618. bool WsWuInfo::legacyHasSubGraphTimings()
  619. {
  620. StatisticsFilter filter;
  621. filter.setScopeDepth(1); // only "global" timers.
  622. filter.setMeasure(SMeasureTimeNs);
  623. Owned<IConstWUStatisticIterator> times = &cw->getStatistics(&filter);
  624. ForEach(*times)
  625. {
  626. IConstWUStatistic & cur = times->query();
  627. SCMStringBuffer name;
  628. cur.getDescription(name, false);
  629. StringAttr graphName;
  630. unsigned graphNum;
  631. unsigned subGraphNum;
  632. unsigned subId;
  633. if (parseGraphTimerLabel(name.str(), graphName, graphNum, subGraphNum, subId))
  634. return true;
  635. }
  636. return false;
  637. }
  638. void WsWuInfo::doGetGraphs(IArrayOf<IEspECLGraph>& graphs)
  639. {
  640. SCMStringBuffer runningGraph;
  641. WUGraphIDType id;
  642. WUState st = cw->getState();
  643. bool running = (!(st==WUStateFailed || st==WUStateAborted || st==WUStateCompleted) && cw->getRunningGraph(runningGraph,id));
  644. Owned<IConstWUGraphMetaIterator> it = &cw->getGraphsMeta(GraphTypeAny);
  645. ForEach(*it)
  646. {
  647. IConstWUGraphMeta &graph = it->query();
  648. SCMStringBuffer name, label, type;
  649. graph.getName(name);
  650. graph.getLabel(label);
  651. graph.getTypeName(type);
  652. WUGraphState graphState = graph.getState();
  653. Owned<IEspECLGraph> g= createECLGraph();
  654. g->setName(name.str());
  655. g->setLabel(label.str());
  656. g->setType(type.str());
  657. if (WUGraphComplete == graphState)
  658. g->setComplete(true);
  659. else if (running && (WUGraphRunning == graphState))
  660. {
  661. g->setRunning(true);
  662. g->setRunningId(id);
  663. }
  664. else if (WUGraphFailed == graphState)
  665. g->setFailed(true);
  666. if (version >= 1.53)
  667. {
  668. SCMStringBuffer s;
  669. Owned<IConstWUStatistic> whenGraphStarted = cw->getStatistic(NULL, name.str(), StWhenGraphStarted);
  670. Owned<IConstWUStatistic> whenGraphFinished = cw->getStatistic(NULL, name.str(), StWhenGraphFinished);
  671. if (whenGraphStarted)
  672. g->setWhenStarted(whenGraphStarted->getFormattedValue(s).str());
  673. if (whenGraphFinished)
  674. g->setWhenFinished(whenGraphFinished->getFormattedValue(s).str());
  675. }
  676. graphs.append(*g.getLink());
  677. }
  678. }
  679. void WsWuInfo::getGraphInfo(IEspECLWorkunit &info, unsigned long flags)
  680. {
  681. if (version > 1.01)
  682. {
  683. info.setHaveSubGraphTimings(false);
  684. if (hasSubGraphTimings() || legacyHasSubGraphTimings())
  685. info.setHaveSubGraphTimings(true);
  686. }
  687. if (!(flags & WUINFO_IncludeGraphs))
  688. return;
  689. try
  690. {
  691. IArrayOf<IEspECLGraph> graphs;
  692. doGetGraphs(graphs);
  693. info.setGraphs(graphs);
  694. }
  695. catch(IException* e)
  696. {
  697. StringBuffer eMsg;
  698. ERRLOG("%s", e->errorMessage(eMsg).str());
  699. info.setGraphsDesc(eMsg.str());
  700. e->Release();
  701. }
  702. }
  703. void WsWuInfo::getWUGraphNameAndTypes(WUGraphType graphType, IArrayOf<IEspNameAndType>& graphNameAndTypes)
  704. {
  705. Owned<IConstWUGraphMetaIterator> it = &cw->getGraphsMeta(graphType);
  706. ForEach(*it)
  707. {
  708. SCMStringBuffer name, type;
  709. IConstWUGraphMeta &graph = it->query();
  710. Owned<IEspNameAndType> nameAndType = createNameAndType();
  711. nameAndType->setName(graph.getName(name).str());
  712. nameAndType->setType(graph.getTypeName(type).str());
  713. graphNameAndTypes.append(*nameAndType.getLink());
  714. }
  715. }
  716. void WsWuInfo::getGraphTimingData(IArrayOf<IConstECLTimingData> &timingData)
  717. {
  718. StatisticsFilter filter(SCTall, SSTsubgraph, SMeasureTimeNs, StTimeElapsed);
  719. Owned<IConstWUStatisticIterator> times = &cw->getStatistics(&filter);
  720. bool matched = false;
  721. ForEach(*times)
  722. {
  723. IConstWUStatistic & cur = times->query();
  724. SCMStringBuffer scope;
  725. cur.getScope(scope);
  726. StringAttr graphName;
  727. unsigned graphNum;
  728. unsigned subGraphId;
  729. if (parseGraphScope(scope.str(), graphName, graphNum, subGraphId))
  730. {
  731. unsigned time = (unsigned)nanoToMilli(cur.getValue());
  732. SCMStringBuffer name;
  733. cur.getDescription(name, true);
  734. Owned<IEspECLTimingData> g = createECLTimingData();
  735. g->setName(name.str());
  736. g->setGraphNum(graphNum);
  737. g->setSubGraphNum(subGraphId); // Use the Id - the number is not known
  738. g->setGID(subGraphId);
  739. g->setMS(time);
  740. g->setMin(time/60000);
  741. timingData.append(*g.getClear());
  742. matched = true;
  743. }
  744. }
  745. if (!matched)
  746. legacyGetGraphTimingData(timingData);
  747. }
  748. void WsWuInfo::legacyGetGraphTimingData(IArrayOf<IConstECLTimingData> &timingData)
  749. {
  750. StatisticsFilter filter;
  751. filter.setScopeDepth(1);
  752. filter.setMeasure(SMeasureTimeNs);
  753. Owned<IConstWUStatisticIterator> times = &cw->getStatistics(&filter);
  754. ForEach(*times)
  755. {
  756. IConstWUStatistic & cur = times->query();
  757. SCMStringBuffer name;
  758. cur.getDescription(name, false); // was previously always filled in.
  759. StringAttr graphName;
  760. unsigned graphNum;
  761. unsigned subGraphNum;
  762. unsigned subId;
  763. if (parseGraphTimerLabel(name.str(), graphName, graphNum, subGraphNum, subId))
  764. {
  765. unsigned time = (unsigned)nanoToMilli(cur.getValue());
  766. Owned<IEspECLTimingData> g = createECLTimingData();
  767. g->setName(name.str());
  768. g->setGraphNum(graphNum);
  769. g->setSubGraphNum(subGraphNum);
  770. g->setGID(subId);
  771. g->setMS(time);
  772. g->setMin(time/60000);
  773. timingData.append(*g.getClear());
  774. }
  775. }
  776. }
  777. void WsWuInfo::getEventScheduleFlag(IEspECLWorkunit &info)
  778. {
  779. info.setEventSchedule(0);
  780. if (info.getState() && !stricmp(info.getState(), "wait"))
  781. {
  782. info.setEventSchedule(2); //Can deschedule
  783. }
  784. else
  785. {
  786. Owned<IConstWorkflowItemIterator> it = cw->getWorkflowItems();
  787. if (it)
  788. {
  789. ForEach(*it)
  790. {
  791. IConstWorkflowItem *r = it->query();
  792. if (!r)
  793. continue;
  794. Owned<IWorkflowEvent> wfevent = r->getScheduleEvent();
  795. if (!wfevent)
  796. continue;
  797. if ((!r->hasScheduleCount() || (r->queryScheduleCountRemaining() > 0))
  798. && info.getState() && !strieq(info.getState(), "scheduled")
  799. && !strieq(info.getState(), "aborting") && !strieq(info.getState(), "aborted")
  800. && !strieq(info.getState(), "failed") && !strieq(info.getState(), "archived"))
  801. {
  802. info.setEventSchedule(1); //Can reschedule
  803. break;
  804. }
  805. }
  806. }
  807. }
  808. }
  809. unsigned WsWuInfo::getTotalThorTime()
  810. {
  811. StatisticsFilter filter;
  812. filter.setCreatorType(SCTsummary);
  813. filter.setScope(GLOBAL_SCOPE);
  814. filter.setKind(StTimeElapsed);
  815. //Should only be a single value
  816. unsigned totalThorTimeMS = 0;
  817. Owned<IConstWUStatisticIterator> times = &cw->getStatistics(&filter);
  818. ForEach(*times)
  819. {
  820. totalThorTimeMS += (unsigned)nanoToMilli(times->query().getValue());
  821. }
  822. return totalThorTimeMS;
  823. }
  824. unsigned WsWuInfo::getLegacyTotalThorTime()
  825. {
  826. //4.2.x backward compatibility - only scope depth and measure filters work
  827. StatisticsFilter filter;
  828. filter.setScopeDepth(1); // only global
  829. filter.setMeasure(SMeasureTimeNs);
  830. Owned<IConstWUStatisticIterator> times = &cw->getStatistics(&filter);
  831. SCMStringBuffer oldname;
  832. ForEach(*times)
  833. {
  834. times->query().getDescription(oldname, false); // description will be set up
  835. if (streq(oldname.str(), TOTALTHORTIME))
  836. return (unsigned)nanoToMilli(times->query().getValue());
  837. }
  838. return 0;
  839. }
  840. void WsWuInfo::getCommon(IEspECLWorkunit &info, unsigned long flags)
  841. {
  842. info.setWuid(cw->queryWuid());
  843. info.setProtected(cw->isProtected() ? 1 : 0);
  844. info.setJobname(cw->queryJobName());
  845. info.setOwner(cw->queryUser());
  846. clusterName.set(cw->queryClusterName());
  847. info.setCluster(clusterName.str());
  848. SCMStringBuffer s;
  849. info.setSnapshot(cw->getSnapshot(s).str());
  850. if ((cw->getState() == WUStateScheduled) && cw->aborting())
  851. {
  852. info.setStateID(WUStateAborting);
  853. info.setState("aborting");
  854. }
  855. else
  856. {
  857. info.setStateID(cw->getState());
  858. info.setState(cw->queryStateDesc());
  859. }
  860. if (cw->isPausing())
  861. info.setIsPausing(true);
  862. getEventScheduleFlag(info);
  863. if (version > 1.27)
  864. {
  865. unsigned totalThorTimeMS = getTotalThorTime();
  866. if (totalThorTimeMS == 0)
  867. totalThorTimeMS = getLegacyTotalThorTime();
  868. if (totalThorTimeMS)
  869. {
  870. StringBuffer totalThorTimeStr;
  871. formatDuration(totalThorTimeStr, totalThorTimeMS);
  872. if (version > 1.52)
  873. info.setTotalClusterTime(totalThorTimeStr.str());
  874. else
  875. info.setTotalThorTime(totalThorTimeStr.str());
  876. }
  877. }
  878. WsWuDateTime dt;
  879. cw->getTimeScheduled(dt);
  880. if(dt.isValid())
  881. info.setDateTimeScheduled(dt.getString(s).str());
  882. }
  883. void WsWuInfo::setWUAbortTime(IEspECLWorkunit &info, unsigned __int64 abortTS)
  884. {
  885. StringBuffer abortTimeStr;
  886. formatStatistic(abortTimeStr, abortTS, SMeasureTimestampUs);
  887. if ((abortTimeStr.length() > 19) && (abortTimeStr.charAt(10) == 'T') && (abortTimeStr.charAt(19) == '.'))
  888. {
  889. abortTimeStr.setCharAt(10, ' ');
  890. abortTimeStr.setLength(19);
  891. }
  892. info.setAbortTime(abortTimeStr.str());
  893. }
  894. void WsWuInfo::getInfo(IEspECLWorkunit &info, unsigned long flags)
  895. {
  896. getCommon(info, flags);
  897. SecAccessFlags accessFlag = getWsWorkunitAccess(context, *cw);
  898. info.setAccessFlag(accessFlag);
  899. SCMStringBuffer s;
  900. info.setStateEx(cw->getStateEx(s).str());
  901. WUState state = cw->getState();
  902. if ((state == WUStateAborting) || (state == WUStateAborted))
  903. {
  904. unsigned __int64 abortTS = cw->getAbortTimeStamp();
  905. if (abortTS > 0) //AbortTimeStamp may not be set in old wu
  906. {
  907. setWUAbortTime(info, abortTS);
  908. cw->getAbortBy(s);
  909. if (s.length())
  910. info.setAbortBy(s.str());
  911. }
  912. }
  913. info.setPriorityClass(cw->getPriority());
  914. info.setPriorityLevel(cw->getPriorityLevel());
  915. if (context.querySecManager())
  916. info.setScope(cw->queryWuScope());
  917. info.setActionEx(cw->queryActionDesc());
  918. info.setDescription(cw->getDebugValue("description", s).str());
  919. if (version > 1.21)
  920. info.setXmlParams(cw->getXmlParams(s, true).str());
  921. info.setResultLimit(cw->getResultLimit());
  922. info.setArchived(false);
  923. info.setGraphCount(cw->getGraphCount());
  924. info.setSourceFileCount(cw->getSourceFileCount());
  925. info.setResultCount(cw->getResultCount());
  926. info.setWorkflowCount(cw->queryEventScheduledCount());
  927. info.setVariableCount(cw->getVariableCount());
  928. info.setTimerCount(getTimerCount());
  929. info.setSourceFileCount(cw->getSourceFileCount());
  930. info.setApplicationValueCount(cw->getApplicationValueCount());
  931. info.setHasDebugValue(cw->hasDebugValue("__calculated__complexity__"));
  932. getClusterInfo(info, flags);
  933. getExceptions(info, flags);
  934. getHelpers(info, flags);
  935. getGraphInfo(info, flags);
  936. getSourceFiles(info, flags);
  937. getResults(info, flags);
  938. getVariables(info, flags);
  939. getTimers(info, flags);
  940. getDebugValues(info, flags);
  941. getApplicationValues(info, flags);
  942. getWorkflow(info, flags);
  943. }
  944. unsigned WsWuInfo::getWorkunitThorLogInfo(IArrayOf<IEspECLHelpFile>& helpers, IEspECLWorkunit &info, unsigned long flags, unsigned& helpersCount)
  945. {
  946. unsigned countThorLog = 0;
  947. IArrayOf<IConstThorLogInfo> thorLogList;
  948. if (cw->getWuidVersion() > 0)
  949. {
  950. StringAttr clusterName(cw->queryClusterName());
  951. if (!clusterName.length()) //Cluster name may not be set yet
  952. return countThorLog;
  953. Owned<IConstWUClusterInfo> clusterInfo = getTargetClusterInfo(clusterName.str());
  954. if (!clusterInfo)
  955. {
  956. WARNLOG("Cannot find TargetClusterInfo for workunit %s", cw->queryWuid());
  957. return countThorLog;
  958. }
  959. unsigned numberOfSlaveLogs = clusterInfo->getNumberOfSlaveLogs();
  960. BoolHash uniqueProcesses;
  961. Owned<IStringIterator> thorInstances = cw->getProcesses("Thor");
  962. ForEach (*thorInstances)
  963. {
  964. SCMStringBuffer processName;
  965. thorInstances->str(processName);
  966. if (processName.length() < 1)
  967. continue;
  968. bool* found = uniqueProcesses.getValue(processName.str());
  969. if (found && *found)
  970. continue;
  971. uniqueProcesses.setValue(processName.str(), true);
  972. StringBuffer groupName;
  973. getClusterThorGroupName(groupName, processName.str());
  974. Owned<IStringIterator> thorLogs = cw->getLogs("Thor", processName.str());
  975. ForEach (*thorLogs)
  976. {
  977. SCMStringBuffer logName;
  978. thorLogs->str(logName);
  979. if (logName.length() < 1)
  980. continue;
  981. countThorLog++;
  982. StringBuffer fileType;
  983. if (countThorLog < 2)
  984. fileType.append(File_ThorLog);
  985. else
  986. fileType.appendf("%s%d", File_ThorLog, countThorLog);
  987. helpersCount++;
  988. if (flags & WUINFO_IncludeHelpers)
  989. {
  990. Owned<IEspECLHelpFile> h= createECLHelpFile("","");
  991. h->setName(logName.str());
  992. h->setDescription(processName.str());
  993. h->setType(fileType.str());
  994. if (version >= 1.43)
  995. {
  996. offset_t fileSize;
  997. if (getFileSize(logName.str(), NULL, fileSize))
  998. h->setFileSize(fileSize);
  999. }
  1000. helpers.append(*h.getLink());
  1001. }
  1002. if (version < 1.38)
  1003. continue;
  1004. const char* pStr = logName.str();
  1005. const char* ppStr = strstr(pStr, "/thormaster.");
  1006. if (!ppStr)
  1007. {
  1008. WARNLOG("Invalid thorlog entry in workunit xml: %s", logName.str());
  1009. continue;
  1010. }
  1011. ppStr += 12;
  1012. StringBuffer logDate = ppStr;
  1013. logDate.setLength(10);
  1014. Owned<IEspThorLogInfo> thorLog = createThorLogInfo("","");
  1015. thorLog->setProcessName(processName.str());
  1016. thorLog->setClusterGroup(groupName.str());
  1017. thorLog->setLogDate(logDate.str());
  1018. thorLog->setNumberSlaves(numberOfSlaveLogs);
  1019. thorLogList.append(*thorLog.getLink());
  1020. }
  1021. }
  1022. }
  1023. else //legacy wuid
  1024. {
  1025. Owned<IStringIterator> thorLogs = cw->getLogs("Thor");
  1026. ForEach (*thorLogs)
  1027. {
  1028. SCMStringBuffer name;
  1029. thorLogs->str(name);
  1030. if (name.length() < 1)
  1031. continue;
  1032. countThorLog++;
  1033. StringBuffer fileType;
  1034. if (countThorLog < 2)
  1035. fileType.append(File_ThorLog);
  1036. else
  1037. fileType.appendf("%s%d", File_ThorLog, countThorLog);
  1038. helpersCount++;
  1039. if (flags & WUINFO_IncludeHelpers)
  1040. {
  1041. Owned<IEspECLHelpFile> h= createECLHelpFile("","");
  1042. h->setName(name.str());
  1043. h->setType(fileType.str());
  1044. if (version >= 1.43)
  1045. {
  1046. offset_t fileSize;
  1047. if (getFileSize(name.str(), NULL, fileSize))
  1048. h->setFileSize(fileSize);
  1049. }
  1050. helpers.append(*h.getLink());
  1051. }
  1052. }
  1053. StringBuffer logDir;
  1054. Owned<IEnvironmentFactory> envFactory = getEnvironmentFactory();
  1055. Owned<IConstEnvironment> constEnv = envFactory->openEnvironment();
  1056. Owned<IPropertyTree> logTree = &constEnv->getPTree();
  1057. if (logTree)
  1058. logTree->getProp("EnvSettings/log", logDir);
  1059. if (logDir.length() > 0)
  1060. {
  1061. Owned<IStringIterator> debugs = cw->getLogs("Thor");
  1062. ForEach(*debugs)
  1063. {
  1064. SCMStringBuffer val;
  1065. debugs->str(val);
  1066. if (val.length() < 1)
  1067. continue;
  1068. const char* pStr = val.str();
  1069. const char* ppStr = strstr(pStr, logDir.str());
  1070. if (!ppStr)
  1071. {
  1072. WARNLOG("Invalid thorlog entry in workunit xml: %s", val.str());
  1073. continue;
  1074. }
  1075. const char* pProcessName = ppStr + logDir.length();
  1076. char sep = pProcessName[0];
  1077. StringBuffer processName = pProcessName + 1;
  1078. ppStr = strchr(pProcessName + 1, sep);
  1079. if (!ppStr)
  1080. {
  1081. WARNLOG("Invalid thorlog entry in workunit xml: %s", val.str());
  1082. continue;
  1083. }
  1084. processName.setLength(ppStr - pProcessName - 1);
  1085. StringBuffer groupName;
  1086. getClusterThorGroupName(groupName, processName.str());
  1087. StringBuffer logDate = ppStr + 12;
  1088. logDate.setLength(10);
  1089. Owned<IEspThorLogInfo> thorLog = createThorLogInfo("","");
  1090. thorLog->setProcessName(processName.str());
  1091. thorLog->setClusterGroup(groupName.str());
  1092. thorLog->setLogDate(logDate.str());
  1093. //for legacy wuid, the log name does not contain slaveNum. So, a user may not specify
  1094. //a slaveNum and we only display the first slave log if > 1 per IP.
  1095. thorLog->setNumberSlaves(0);
  1096. thorLogList.append(*thorLog.getLink());
  1097. }
  1098. }
  1099. }
  1100. if (thorLogList.length() > 0)
  1101. info.setThorLogList(thorLogList);
  1102. thorLogList.kill();
  1103. return countThorLog;
  1104. }
  1105. bool WsWuInfo::getClusterInfo(IEspECLWorkunit &info, unsigned long flags)
  1106. {
  1107. if ((flags & WUINFO_IncludeAllowedClusters) && (version > 1.04))
  1108. {
  1109. StringArray allowedClusters;
  1110. SCMStringBuffer val;
  1111. cw->getAllowedClusters(val);
  1112. if (val.length() > 0)
  1113. {
  1114. const char* ptr = val.str();
  1115. while(*ptr != '\0')
  1116. {
  1117. StringBuffer onesub;
  1118. while(*ptr != '\0' && *ptr != ',')
  1119. {
  1120. onesub.append((char)(*ptr));
  1121. ptr++;
  1122. }
  1123. if(onesub.length() > 0)
  1124. allowedClusters.append(onesub.str());
  1125. if(*ptr != '\0')
  1126. ptr++;
  1127. }
  1128. }
  1129. if (allowedClusters.length() > 0)
  1130. info.setAllowedClusters(allowedClusters);
  1131. }
  1132. if (version > 1.23 && clusterName.length())
  1133. {
  1134. int clusterTypeFlag = 0;
  1135. Owned<IEnvironmentFactory> envFactory = getEnvironmentFactory();
  1136. Owned<IConstEnvironment> constEnv = envFactory->openEnvironment();
  1137. Owned<IPropertyTree> root = &constEnv->getPTree();
  1138. if (!root)
  1139. throw MakeStringException(ECLWATCH_CANNOT_CONNECT_DALI,"Cannot connect to DALI server.");
  1140. Owned<IConstWUClusterInfo> clusterInfo = getTargetClusterInfo(clusterName.str());
  1141. if (clusterInfo.get())
  1142. {//Set thor flag or roxie flag in order to display some options for thor or roxie
  1143. ClusterType platform = clusterInfo->getPlatform();
  1144. if (isThorCluster(platform))
  1145. {
  1146. clusterTypeFlag=1;
  1147. if (version > 1.29)
  1148. info.setThorLCR(ThorLCRCluster == platform);
  1149. }
  1150. else if (RoxieCluster == platform)
  1151. clusterTypeFlag=2;
  1152. }
  1153. info.setClusterFlag(clusterTypeFlag);
  1154. }
  1155. return true;
  1156. }
  1157. void WsWuInfo::getWorkflow(IEspECLWorkunit &info, unsigned long flags)
  1158. {
  1159. if (!(flags & WUINFO_IncludeWorkflows))
  1160. return;
  1161. try
  1162. {
  1163. Owned<IConstWorkflowItemIterator> it = cw->getWorkflowItems();
  1164. if (!it)
  1165. return;
  1166. IArrayOf<IConstECLWorkflow> workflows;
  1167. ForEach(*it)
  1168. {
  1169. IConstWorkflowItem* r = it->query();
  1170. if (!r)
  1171. continue;
  1172. IWorkflowEvent* wfevent = r->getScheduleEvent();
  1173. if (!wfevent)
  1174. continue;
  1175. StringBuffer id;
  1176. Owned<IEspECLWorkflow> g = createECLWorkflow();
  1177. g->setWFID(id.appendf("%d", r->queryWfid()).str());
  1178. g->setEventName(wfevent->queryName());
  1179. g->setEventText(wfevent->queryText());
  1180. if (r->hasScheduleCount())
  1181. {
  1182. g->setCount(r->queryScheduleCount());
  1183. g->setCountRemaining(r->queryScheduleCountRemaining());
  1184. }
  1185. workflows.append(*g.getLink());
  1186. }
  1187. if (workflows.length() > 0)
  1188. info.setWorkflows(workflows);
  1189. }
  1190. catch(IException* e)
  1191. {
  1192. StringBuffer eMsg;
  1193. ERRLOG("%s", e->errorMessage(eMsg).str());
  1194. info.setWorkflowsDesc(eMsg.str());
  1195. e->Release();
  1196. }
  1197. }
  1198. IDistributedFile* WsWuInfo::getLogicalFileData(IEspContext& context, const char* logicalName, bool& showFileContent)
  1199. {
  1200. StringBuffer username;
  1201. context.getUserID(username);
  1202. Owned<IUserDescriptor> userdesc(createUserDescriptor());
  1203. userdesc->set(username.str(), context.queryPassword());
  1204. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(logicalName, userdesc);
  1205. if (!df)
  1206. return NULL;
  1207. bool blocked;
  1208. if (df->isCompressed(&blocked) && !blocked)
  1209. return df.getClear();
  1210. IPropertyTree& properties = df->queryAttributes();
  1211. const char * format = properties.queryProp("@format");
  1212. if (format && (stricmp(format,"csv")==0 || memicmp(format, "utf", 3) == 0))
  1213. {
  1214. showFileContent = true;
  1215. return df.getClear();
  1216. }
  1217. const char * recordEcl = properties.queryProp("ECL");
  1218. if (!recordEcl)
  1219. return df.getClear();
  1220. MultiErrorReceiver errs;
  1221. Owned<IHqlExpression> ret = ::parseQuery(recordEcl, &errs);
  1222. showFileContent = errs.errCount() == 0;
  1223. return df.getClear();
  1224. }
  1225. void WsWuInfo::getEclSchemaChildFields(IArrayOf<IEspECLSchemaItem>& schemas, IHqlExpression * expr, bool isConditional)
  1226. {
  1227. if(!expr)
  1228. return;
  1229. ForEachChild(idx, expr)
  1230. getEclSchemaFields(schemas, expr->queryChild(idx), isConditional);
  1231. }
  1232. void WsWuInfo::getEclSchemaFields(IArrayOf<IEspECLSchemaItem>& schemas, IHqlExpression * expr, bool isConditional)
  1233. {
  1234. if(!expr)
  1235. return;
  1236. int ret = expr->getOperator();
  1237. switch (ret)
  1238. {
  1239. case no_record:
  1240. getEclSchemaChildFields(schemas, expr, isConditional);
  1241. break;
  1242. case no_ifblock:
  1243. {
  1244. getEclSchemaChildFields(schemas, expr->queryChild(1), true);
  1245. break;
  1246. }
  1247. case no_field:
  1248. {
  1249. if (expr->hasAttribute(__ifblockAtom))
  1250. break;
  1251. ITypeInfo * type = expr->queryType();
  1252. IAtom * name = expr->queryName();
  1253. IHqlExpression * nameAttr = expr->queryAttribute(namedAtom);
  1254. StringBuffer outname;
  1255. if (nameAttr && nameAttr->queryChild(0) && nameAttr->queryChild(0)->queryValue())
  1256. nameAttr->queryChild(0)->queryValue()->getStringValue(outname);
  1257. else
  1258. outname.append(name).toLowerCase();
  1259. if(type)
  1260. {
  1261. type_t tc = type->getTypeCode();
  1262. if (tc == type_row)
  1263. {
  1264. getEclSchemaChildFields(schemas, expr->queryRecord(), isConditional);
  1265. }
  1266. else
  1267. {
  1268. if (type->getTypeCode() == type_alien)
  1269. {
  1270. IHqlAlienTypeInfo * alien = queryAlienType(type);
  1271. type = alien->queryPhysicalType();
  1272. }
  1273. Owned<IEspECLSchemaItem> schema = createECLSchemaItem("","");
  1274. StringBuffer eclType;
  1275. type->getECLType(eclType);
  1276. schema->setColumnName(outname);
  1277. schema->setColumnType(eclType.str());
  1278. schema->setColumnTypeCode(tc);
  1279. schema->setIsConditional(isConditional);
  1280. schemas.append(*schema.getClear());
  1281. }
  1282. }
  1283. break;
  1284. }
  1285. }
  1286. }
  1287. bool WsWuInfo::getResultEclSchemas(IConstWUResult &r, IArrayOf<IEspECLSchemaItem>& schemas)
  1288. {
  1289. SCMStringBuffer schema;
  1290. r.getResultEclSchema(schema);
  1291. if (!schema.length())
  1292. return false;
  1293. MultiErrorReceiver errs;
  1294. Owned<IHqlExpression> expr = ::parseQuery(schema.str(), &errs);
  1295. if (errs.errCount() != 0)
  1296. return false;
  1297. getEclSchemaFields(schemas, expr, false);
  1298. return true;
  1299. }
  1300. void WsWuInfo::getResult(IConstWUResult &r, IArrayOf<IEspECLResult>& results, unsigned long flags)
  1301. {
  1302. SCMStringBuffer name;
  1303. r.getResultName(name);
  1304. SCMStringBuffer filename;
  1305. r.getResultLogicalName(filename);
  1306. bool showFileContent = false;
  1307. Owned<IDistributedFile> df = NULL;
  1308. if (filename.length())
  1309. df.setown(getLogicalFileData(context, filename.str(), showFileContent));
  1310. StringBuffer value, link;
  1311. if (r.getResultStatus() == ResultStatusUndefined)
  1312. value.set("[undefined]");
  1313. else if (r.isResultScalar())
  1314. {
  1315. try
  1316. {
  1317. SCMStringBuffer xml;
  1318. r.getResultXml(xml, true);
  1319. Owned<IPropertyTree> props = createPTreeFromXMLString(xml.str(), ipt_caseInsensitive);
  1320. IPropertyTree *val = props->queryPropTree("Row/*");
  1321. if(val)
  1322. value.set(val->queryProp(NULL));
  1323. else
  1324. {
  1325. Owned<IResultSetFactory> resultSetFactory = getSecResultSetFactory(context.querySecManager(), context.queryUser(), context.queryUserId(), context.queryPassword());
  1326. Owned<INewResultSet> result;
  1327. result.setown(resultSetFactory->createNewResultSet(&r, wuid.str()));
  1328. Owned<IResultSetCursor> cursor(result->createCursor());
  1329. cursor->first();
  1330. if (cursor->getIsAll(0))
  1331. {
  1332. value.set("<All/>");
  1333. }
  1334. else
  1335. {
  1336. Owned<IResultSetCursor> childCursor = cursor->getChildren(0);
  1337. if (childCursor)
  1338. {
  1339. ForEach(*childCursor)
  1340. {
  1341. StringBuffer out;
  1342. StringBufferAdaptor adaptor(out);
  1343. childCursor->getDisplayText(adaptor, 0);
  1344. if (!value.length())
  1345. value.append('[');
  1346. else
  1347. value.append(", ");
  1348. value.append('\'').append(out.str()).append('\'');
  1349. }
  1350. if (value.length())
  1351. value.append(']');
  1352. }
  1353. }
  1354. }
  1355. }
  1356. catch(...)
  1357. {
  1358. value.append("[value not available]");
  1359. }
  1360. }
  1361. else
  1362. {
  1363. value.append('[').append(r.getResultTotalRowCount()).append(" rows]");
  1364. if((r.getResultSequence()>=0) && (!filename.length() || (df && df->queryAttributes().hasProp("ECL"))))
  1365. link.append(r.getResultSequence());
  1366. }
  1367. Owned<IEspECLResult> result= createECLResult("","");
  1368. if (flags & WUINFO_IncludeEclSchemas)
  1369. {
  1370. IArrayOf<IEspECLSchemaItem> schemas;
  1371. if (getResultEclSchemas(r, schemas))
  1372. result->setECLSchemas(schemas);
  1373. }
  1374. if (flags & WUINFO_IncludeXmlSchema)
  1375. {
  1376. Owned<IResultSetFactory> resultSetFactory = getSecResultSetFactory(context.querySecManager(), context.queryUser(), context.queryUserId(), context.queryPassword());
  1377. Owned<INewResultSet> rs = resultSetFactory->createNewResultSet(&r, wuid.str());
  1378. Owned<IResultSetCursor> cursor(rs->createCursor());
  1379. SCMStringBuffer xsd;
  1380. const IResultSetMetaData & meta = cursor->queryResultSet()->getMetaData();
  1381. meta.getXmlXPathSchema(xsd, false);
  1382. result->setXmlSchema(xsd.str());
  1383. }
  1384. if (filename.length())
  1385. result->setShowFileContent(showFileContent);
  1386. result->setName(name.str());
  1387. result->setLink(link.str());
  1388. result->setSequence(r.getResultSequence());
  1389. result->setValue(value.str());
  1390. result->setFileName(filename.str());
  1391. result->setIsSupplied(r.getResultStatus() == ResultStatusSupplied);
  1392. result->setTotal(r.getResultTotalRowCount());
  1393. results.append(*result.getLink());
  1394. }
  1395. void WsWuInfo::getResults(IEspECLWorkunit &info, unsigned long flags)
  1396. {
  1397. if (!(flags & WUINFO_IncludeResults))
  1398. return;
  1399. try
  1400. {
  1401. IArrayOf<IEspECLResult> results;
  1402. Owned<IConstWUResultIterator> it = &(cw->getResults());
  1403. ForEach(*it)
  1404. {
  1405. IConstWUResult &r = it->query();
  1406. if(r.getResultSequence()>=0)
  1407. getResult(r, results, flags);
  1408. }
  1409. if (results.length())
  1410. info.setResults(results);
  1411. results.kill();
  1412. }
  1413. catch(IException* e)
  1414. {
  1415. StringBuffer eMsg;
  1416. ERRLOG("%s", e->errorMessage(eMsg).str());
  1417. info.setResultsDesc(eMsg.str());
  1418. e->Release();
  1419. }
  1420. }
  1421. void WsWuInfo::getStats(StatisticsFilter& filter, bool createDescriptions, IArrayOf<IEspWUStatisticItem>& statistics)
  1422. {
  1423. Owned<IConstWUStatisticIterator> stats = &cw->getStatistics(&filter);
  1424. ForEach(*stats)
  1425. {
  1426. IConstWUStatistic & cur = stats->query();
  1427. StringBuffer xmlBuf, tsValue;
  1428. SCMStringBuffer curCreator, curScope, curDescription, curFormattedValue;
  1429. StatisticCreatorType curCreatorType = cur.getCreatorType();
  1430. StatisticScopeType curScopeType = cur.getScopeType();
  1431. StatisticMeasure curMeasure = cur.getMeasure();
  1432. StatisticKind curKind = cur.getKind();
  1433. unsigned __int64 value = cur.getValue();
  1434. unsigned __int64 count = cur.getCount();
  1435. unsigned __int64 max = cur.getMax();
  1436. unsigned __int64 ts = cur.getTimestamp();
  1437. cur.getCreator(curCreator);
  1438. cur.getScope(curScope);
  1439. cur.getDescription(curDescription, createDescriptions);
  1440. cur.getFormattedValue(curFormattedValue);
  1441. Owned<IEspWUStatisticItem> wuStatistic = createWUStatisticItem();
  1442. if (version > 1.61)
  1443. wuStatistic->setWuid(wuid);
  1444. if (curCreatorType != SCTnone)
  1445. wuStatistic->setCreatorType(queryCreatorTypeName(curCreatorType));
  1446. if (curCreator.length())
  1447. wuStatistic->setCreator(curCreator.str());
  1448. if (curScopeType != SSTnone)
  1449. wuStatistic->setScopeType(queryScopeTypeName(curScopeType));
  1450. if (curScope.length())
  1451. wuStatistic->setScope(curScope.str());
  1452. if (curMeasure != SMeasureNone)
  1453. wuStatistic->setMeasure(queryMeasureName(curMeasure));
  1454. if (curKind != StKindNone)
  1455. wuStatistic->setKind(queryStatisticName(curKind));
  1456. wuStatistic->setRawValue(value);
  1457. wuStatistic->setValue(curFormattedValue.str());
  1458. if (count != 1)
  1459. wuStatistic->setCount(count);
  1460. if (max)
  1461. wuStatistic->setMax(max);
  1462. if (ts)
  1463. {
  1464. formatStatistic(tsValue, ts, SMeasureTimestampUs);
  1465. wuStatistic->setTimeStamp(tsValue.str());
  1466. }
  1467. if (curDescription.length())
  1468. wuStatistic->setDescription(curDescription.str());
  1469. statistics.append(*wuStatistic.getClear());
  1470. }
  1471. }
  1472. bool WsWuInfo::getFileSize(const char* fileName, const char* IPAddress, offset_t& fileSize)
  1473. {
  1474. if (!fileName || !*fileName)
  1475. return false;
  1476. Owned<IFile> aFile;
  1477. if (!IPAddress || !*IPAddress)
  1478. {
  1479. aFile.setown(createIFile(fileName));
  1480. }
  1481. else
  1482. {
  1483. RemoteFilename rfn;
  1484. rfn.setRemotePath(fileName);
  1485. SocketEndpoint ep(IPAddress);
  1486. rfn.setIp(ep);
  1487. aFile.setown(createIFile(rfn));
  1488. }
  1489. if (!aFile)
  1490. return false;
  1491. bool isDir;
  1492. CDateTime modtime;
  1493. if (!aFile->getInfo(isDir, fileSize, modtime) || isDir)
  1494. return false;
  1495. return true;
  1496. }
  1497. void WsWuInfo::getHelpFiles(IConstWUQuery* query, WUFileType type, IArrayOf<IEspECLHelpFile>& helpers, unsigned long flags, unsigned& helpersCount)
  1498. {
  1499. if (!query)
  1500. return;
  1501. Owned<IConstWUAssociatedFileIterator> iter = &query->getAssociatedFiles();
  1502. ForEach(*iter)
  1503. {
  1504. SCMStringBuffer name, Ip, description;
  1505. IConstWUAssociatedFile & cur = iter->query();
  1506. if (cur.getType() != type)
  1507. continue;
  1508. helpersCount++;
  1509. if (!(flags & WUINFO_IncludeHelpers))
  1510. continue;
  1511. cur.getName(name);
  1512. Owned<IEspECLHelpFile> h= createECLHelpFile("","");
  1513. h->setName(name.str());
  1514. h->setType(getEnumText(type, queryFileTypes));
  1515. if (version > 1.31)
  1516. {
  1517. cur.getIp(Ip);
  1518. h->setIPAddress(Ip.str());
  1519. cur.getDescription(description);
  1520. if ((description.length() < 1) && (name.length() > 0))
  1521. {
  1522. const char* desc = pathTail(name.str());
  1523. if (desc && *desc)
  1524. description.set(desc);
  1525. }
  1526. if (description.length() < 1)
  1527. description.set("Help File");
  1528. h->setDescription(description.str());
  1529. if (version >= 1.43)
  1530. {
  1531. offset_t fileSize;
  1532. if (getFileSize(name.str(), Ip.str(), fileSize))
  1533. h->setFileSize(fileSize);
  1534. }
  1535. if (version >= 1.58)
  1536. {
  1537. h->setMinActivityId(cur.getMinActivityId());
  1538. h->setMaxActivityId(cur.getMaxActivityId());
  1539. }
  1540. }
  1541. helpers.append(*h.getLink());
  1542. }
  1543. }
  1544. void WsWuInfo::getSubFiles(IPropertyTreeIterator* f, IEspECLSourceFile* eclSuperFile, StringArray& fileNames)
  1545. {
  1546. IArrayOf<IEspECLSourceFile> files;
  1547. ForEach(*f)
  1548. {
  1549. IPropertyTree &query = f->query();
  1550. const char *clusterName = query.queryProp("@cluster");
  1551. const char *fileName = query.queryProp("@name");
  1552. int fileCount = query.getPropInt("@useCount");
  1553. bool bFound = false;
  1554. if (fileName && *fileName && (fileNames.length() > 0)) // MORE - this is an n^2 process and as far as I can tell unnecessary as there will be no dups
  1555. {
  1556. for (unsigned i = 0; i < fileNames.length(); i++ )
  1557. {
  1558. const char *fileName0 = fileNames.item(i);
  1559. if (!stricmp(fileName, fileName0))
  1560. {
  1561. bFound = true;
  1562. break;
  1563. }
  1564. }
  1565. }
  1566. if (bFound)
  1567. continue;
  1568. Owned<IEspECLSourceFile> file= createECLSourceFile("","");
  1569. if(clusterName && *clusterName)
  1570. {
  1571. file->setFileCluster(clusterName);
  1572. }
  1573. if (fileName && *fileName)
  1574. {
  1575. file->setName(fileName);
  1576. fileNames.append(fileName);
  1577. }
  1578. file->setCount(fileCount);
  1579. Owned<IPropertyTreeIterator> filetrees= query.getElements("Subfile"); // We do not store subfiles of subfiles like this - so this code will never be triggered
  1580. if (filetrees->first())
  1581. {
  1582. file->setIsSuperFile(true);
  1583. getSubFiles(filetrees, file, fileNames);
  1584. }
  1585. files.append(*file.getLink());
  1586. }
  1587. eclSuperFile->setECLSourceFiles(files);
  1588. return;
  1589. }
  1590. bool WsWuInfo::getResourceInfo(StringArray &viewnames, StringArray &urls, unsigned long flags)
  1591. {
  1592. if (!(flags & (WUINFO_IncludeResultsViewNames | WUINFO_IncludeResourceURLs)))
  1593. return true;
  1594. try
  1595. {
  1596. Owned<IWuWebView> wv = createWuWebView(*cw, NULL, NULL, NULL, false);
  1597. if (wv)
  1598. {
  1599. if (flags & WUINFO_IncludeResultsViewNames)
  1600. wv->getResultViewNames(viewnames);
  1601. if (flags & WUINFO_IncludeResourceURLs)
  1602. wv->getResourceURLs(urls, NULL);
  1603. }
  1604. return true;
  1605. }
  1606. catch(IException* e)
  1607. {
  1608. StringBuffer eMsg;
  1609. ERRLOG("%s", e->errorMessage(eMsg).str());
  1610. e->Release();
  1611. }
  1612. return false;
  1613. }
  1614. unsigned WsWuInfo::getResourceURLCount()
  1615. {
  1616. try
  1617. {
  1618. Owned<IWuWebView> wv = createWuWebView(*cw, NULL, NULL, NULL, false);
  1619. if (wv)
  1620. return wv->getResourceURLCount();
  1621. }
  1622. catch(IException* e)
  1623. {
  1624. StringBuffer eMsg;
  1625. ERRLOG("%s", e->errorMessage(eMsg).str());
  1626. e->Release();
  1627. }
  1628. return 0;
  1629. }
  1630. void appendIOStreamContent(MemoryBuffer &mb, IFileIOStream *ios, bool forDownload)
  1631. {
  1632. StringBuffer line;
  1633. bool eof = false;
  1634. while (!eof)
  1635. {
  1636. line.clear();
  1637. for (;;)
  1638. {
  1639. char c;
  1640. size32_t numRead = ios->read(1, &c);
  1641. if (!numRead)
  1642. {
  1643. eof = true;
  1644. break;
  1645. }
  1646. line.append(c);
  1647. if (c=='\n')
  1648. break;
  1649. }
  1650. mb.append(line.length(), line.str());
  1651. if (!forDownload && (mb.length() > 640000))
  1652. break;
  1653. }
  1654. }
  1655. void WsWuInfo::getWorkunitEclAgentLog(const char* fileName, const char* agentPid, MemoryBuffer& buf)
  1656. {
  1657. if(!fileName || !*fileName)
  1658. throw MakeStringException(ECLWATCH_ECLAGENT_LOG_NOT_FOUND,"Log file not specified");
  1659. Owned<IFile> rFile = createIFile(fileName);
  1660. if(!rFile)
  1661. throw MakeStringException(ECLWATCH_CANNOT_OPEN_FILE, "Cannot open file %s.", fileName);
  1662. OwnedIFileIO rIO = rFile->openShared(IFOread,IFSHfull);
  1663. if(!rIO)
  1664. throw MakeStringException(ECLWATCH_CANNOT_READ_FILE, "Cannot read file %s.", fileName);
  1665. OwnedIFileIOStream ios = createBufferedIOStream(rIO);
  1666. StringBuffer line;
  1667. bool eof = false;
  1668. bool wuidFound = false;
  1669. StringBuffer pidstr;
  1670. if (agentPid && *agentPid)
  1671. pidstr.appendf(" %s ", agentPid);
  1672. else
  1673. pidstr.appendf(" %5d ", cw->getAgentPID());
  1674. /*
  1675. Scan the master daily logfile for given PID/WUID. We make the following assumptions
  1676. Column ordering (time, date, pid) is unknown, but we must assume it is constant throughout the logfile.
  1677. It is assumed that the first column is the 8 digit workunit logfile line number.
  1678. Rows from concurrent workunits are intermixed.
  1679. Logfiles are searched via PID and WUID. You are not assured of a match until you have both.
  1680. PIDS and TIDS can and are reused. Beware that a TID could match the search PID.
  1681. Once you have both, you know the offset of the PID column. It is assumed this offset remains constant.
  1682. Search stops at EOF, or early exit if the search PID reappears on different WUID.
  1683. */
  1684. char const * pidchars = pidstr.str();
  1685. size32_t pidLen = pidstr.length();
  1686. unsigned pidOffset = 0;//offset of PID in logfile entry
  1687. while(!eof)
  1688. {
  1689. line.clear();
  1690. for (;;)
  1691. {
  1692. char c;
  1693. size32_t numRead = ios->read(1, &c);
  1694. if (!numRead)
  1695. {
  1696. eof = true;
  1697. break;
  1698. }
  1699. line.append(c);
  1700. if (c=='\n')
  1701. break;
  1702. }
  1703. //Retain all rows that match a unique program instance - by retaining all rows that match a pid
  1704. const char * pPid = strstr(line.str() + pidOffset, pidchars);
  1705. if (pPid)
  1706. {
  1707. //Check if this is a new instance using line sequence number (PIDs are often reused)
  1708. if (strncmp(line.str(), "00000000", 8) == 0)
  1709. {
  1710. if (wuidFound) //If the correct instance has been found, return that instance before the next instance.
  1711. break;
  1712. //The last instance is not a correct instance. Clean the buf in order to start a new instance.
  1713. buf.clear();
  1714. }
  1715. //If we spot the workunit id anywhere in the tracing for this pid then assume it is the correct instance.
  1716. if(!wuidFound && strstr(line.str(), wuid.str()))
  1717. {
  1718. pidOffset = pPid - line.str();//remember offset of PID within line
  1719. wuidFound = true;
  1720. }
  1721. if (pidOffset && 0 == strncmp(line.str() + pidOffset, pidchars, pidLen))//this makes sure the match was the PID and not the TID or something else
  1722. buf.append(line.length(), line.str());
  1723. }
  1724. }
  1725. if (buf.length() < 1)
  1726. {
  1727. const char * msg = "(No logfile entries found for this workunit)";
  1728. buf.append(strlen(msg), msg);
  1729. }
  1730. }
  1731. void WsWuInfo::getWorkunitThorLog(const char* fileName, MemoryBuffer& buf)
  1732. {
  1733. if(!fileName || !*fileName)
  1734. throw MakeStringException(ECLWATCH_ECLAGENT_LOG_NOT_FOUND,"Log file not specified");
  1735. Owned<IFile> rFile = createIFile(fileName);
  1736. if (!rFile)
  1737. throw MakeStringException(ECLWATCH_CANNOT_OPEN_FILE,"Cannot open file %s.",fileName);
  1738. OwnedIFileIO rIO = rFile->openShared(IFOread,IFSHfull);
  1739. if (!rIO)
  1740. throw MakeStringException(ECLWATCH_CANNOT_READ_FILE,"Cannot read file %s.",fileName);
  1741. OwnedIFileIOStream ios = createBufferedIOStream(rIO);
  1742. StringBuffer line;
  1743. bool eof = false;
  1744. bool include = false;
  1745. VStringBuffer startwuid("Started wuid=%s", wuid.str());
  1746. VStringBuffer endwuid("Finished wuid=%s", wuid.str());
  1747. const char *sw = startwuid.str();
  1748. const char *ew = endwuid.str();
  1749. while (!eof)
  1750. {
  1751. line.clear();
  1752. for (;;)
  1753. {
  1754. char c;
  1755. size32_t numRead = ios->read(1, &c);
  1756. if (!numRead)
  1757. {
  1758. eof = true;
  1759. break;
  1760. }
  1761. line.append(c);
  1762. if (c=='\n')
  1763. break;
  1764. }
  1765. if (strstr(line.str(), sw))
  1766. include = true;
  1767. if (include)
  1768. buf.append(line.length(), line.str());
  1769. if (strstr(line.str(), ew))
  1770. include = false;
  1771. }
  1772. }
  1773. void WsWuInfo::getWorkunitThorSlaveLog(const char *groupName, const char *ipAddress, const char* logDate, const char* logDir, int slaveNum, MemoryBuffer& buf, bool forDownload)
  1774. {
  1775. if (isEmpty(logDir))
  1776. throw MakeStringException(ECLWATCH_INVALID_INPUT,"ThorSlave log path not specified.");
  1777. if (isEmpty(logDate))
  1778. throw MakeStringException(ECLWATCH_INVALID_INPUT,"ThorSlave log date not specified.");
  1779. StringBuffer slaveIPAddress, logName;
  1780. if (slaveNum > 0)
  1781. {
  1782. if (isEmpty(groupName))
  1783. throw MakeStringException(ECLWATCH_INVALID_INPUT,"Thor group not specified.");
  1784. Owned<IGroup> nodeGroup = queryNamedGroupStore().lookup(groupName);
  1785. if (!nodeGroup || (nodeGroup->ordinality() == 0))
  1786. {
  1787. WARNLOG("Node group %s not found", groupName);
  1788. return;
  1789. }
  1790. nodeGroup->queryNode(slaveNum-1).endpoint().getIpText(slaveIPAddress);
  1791. if (slaveIPAddress.length() < 1)
  1792. throw MakeStringException(ECLWATCH_INVALID_INPUT,"ThorSlave log network address not found.");
  1793. logName.appendf("thorslave.%d.%s.log", slaveNum, logDate);
  1794. }
  1795. else
  1796. {//legacy wuid: a user types in an IP address for a thor slave
  1797. if (isEmpty(ipAddress))
  1798. throw MakeStringException(ECLWATCH_INVALID_INPUT,"ThorSlave address not specified.");
  1799. //thorslave.10.239.219.6_20100.2012_05_23.log
  1800. logName.appendf("thorslave.%s*.%s.log", ipAddress, logDate);
  1801. const char* portPtr = strchr(ipAddress, '_');
  1802. if (!portPtr)
  1803. slaveIPAddress.append(ipAddress);
  1804. else
  1805. {
  1806. StringBuffer ipAddressStr = ipAddress;
  1807. ipAddressStr.setLength(portPtr - ipAddress);
  1808. slaveIPAddress.append(ipAddressStr.str());
  1809. }
  1810. }
  1811. RemoteFilename rfn;
  1812. rfn.setRemotePath(logDir);
  1813. SocketEndpoint ep(slaveIPAddress.str());
  1814. rfn.setIp(ep);
  1815. Owned<IFile> dir = createIFile(rfn);
  1816. Owned<IDirectoryIterator> diriter = dir->directoryFiles(logName.str());
  1817. if (!diriter->first())
  1818. throw MakeStringException(ECLWATCH_FILE_NOT_EXIST,"Cannot find Thor slave log file %s.", logName.str());
  1819. Linked<IFile> logfile = &diriter->query();
  1820. diriter.clear();
  1821. dir.clear();
  1822. // logfile is now the file to load
  1823. OwnedIFileIO rIO = logfile->openShared(IFOread,IFSHfull);
  1824. if (!rIO)
  1825. throw MakeStringException(ECLWATCH_CANNOT_READ_FILE,"Cannot read file %s.",logName.str());
  1826. OwnedIFileIOStream ios = createBufferedIOStream(rIO);
  1827. if (slaveNum > 0)
  1828. {
  1829. StringBuffer line;
  1830. bool eof = false;
  1831. bool include = false;
  1832. VStringBuffer startwuid("Started wuid=%s", wuid.str());
  1833. VStringBuffer endwuid("Finished wuid=%s", wuid.str());
  1834. const char *sw = startwuid.str();
  1835. const char *ew = endwuid.str();
  1836. while (!eof)
  1837. {
  1838. line.clear();
  1839. for (;;)
  1840. {
  1841. char c;
  1842. size32_t numRead = ios->read(1, &c);
  1843. if (!numRead)
  1844. {
  1845. eof = true;
  1846. break;
  1847. }
  1848. line.append(c);
  1849. if (c=='\n')
  1850. break;
  1851. }
  1852. if (strstr(line.str(), sw))
  1853. include = true;
  1854. if (include)
  1855. buf.append(line.length(), line.str());
  1856. if (strstr(line.str(), ew))
  1857. include = false;
  1858. }
  1859. }
  1860. else
  1861. {//legacy wuid
  1862. appendIOStreamContent(buf, ios.get(), forDownload);
  1863. }
  1864. }
  1865. void WsWuInfo::getWorkunitResTxt(MemoryBuffer& buf)
  1866. {
  1867. Owned<IConstWUQuery> query = cw->getQuery();
  1868. if(!query)
  1869. throw MakeStringException(ECLWATCH_QUERY_NOT_FOUND_FOR_WU,"No query for workunit %s.",wuid.str());
  1870. SCMStringBuffer resname;
  1871. queryDllServer().getDll(query->getQueryResTxtName(resname).str(), buf);
  1872. }
  1873. IConstWUQuery* WsWuInfo::getEmbeddedQuery()
  1874. {
  1875. Owned<IWuWebView> wv = createWuWebView(*cw, NULL, NULL, NULL, false);
  1876. if (wv)
  1877. return wv->getEmbeddedQuery();
  1878. return NULL;
  1879. }
  1880. void WsWuInfo::getWorkunitArchiveQuery(MemoryBuffer& buf)
  1881. {
  1882. Owned<IConstWUQuery> query = cw->getQuery();
  1883. if(!query)
  1884. throw MakeStringException(ECLWATCH_QUERY_NOT_FOUND_FOR_WU,"No query for workunit %s.",wuid.str());
  1885. SCMStringBuffer queryText;
  1886. query->getQueryText(queryText);
  1887. if ((queryText.length() < 1) || !isArchiveQuery(queryText.str()))
  1888. {
  1889. if (!query->hasArchive())
  1890. throw MakeStringException(ECLWATCH_CANNOT_GET_WORKUNIT, "Archive query not found for workunit %s.", wuid.str());
  1891. Owned<IConstWUQuery> embeddedQuery = getEmbeddedQuery();
  1892. if (!embeddedQuery)
  1893. throw MakeStringException(ECLWATCH_CANNOT_GET_WORKUNIT, "Embedded query not found for workunit %s.", wuid.str());
  1894. embeddedQuery->getQueryText(queryText);
  1895. if ((queryText.length() < 1) || !isArchiveQuery(queryText.str()))
  1896. throw MakeStringException(ECLWATCH_CANNOT_GET_WORKUNIT, "Archive query not found for workunit %s.", wuid.str());
  1897. }
  1898. buf.append(queryText.length(), queryText.str());
  1899. }
  1900. void WsWuInfo::getWorkunitQueryShortText(MemoryBuffer& buf)
  1901. {
  1902. Owned<IConstWUQuery> query = cw->getQuery();
  1903. if(!query)
  1904. throw MakeStringException(ECLWATCH_QUERY_NOT_FOUND_FOR_WU,"No query for workunit %s.",wuid.str());
  1905. SCMStringBuffer queryText;
  1906. query->getQueryShortText(queryText);
  1907. if (queryText.length() < 1)
  1908. throw MakeStringException(ECLWATCH_QUERY_NOT_FOUND_FOR_WU, "No query for workunit %s.",wuid.str());
  1909. buf.append(queryText.length(), queryText.str());
  1910. }
  1911. void WsWuInfo::getWorkunitDll(StringBuffer &dllname, MemoryBuffer& buf)
  1912. {
  1913. Owned<IConstWUQuery> query = cw->getQuery();
  1914. if(!query)
  1915. throw MakeStringException(ECLWATCH_QUERY_NOT_FOUND_FOR_WU,"No query for workunit %s.",wuid.str());
  1916. StringBufferAdaptor isvName(dllname);
  1917. query->getQueryDllName(isvName);
  1918. queryDllServer().getDll(dllname.str(), buf);
  1919. }
  1920. void WsWuInfo::getWorkunitXml(const char* plainText, MemoryBuffer& buf)
  1921. {
  1922. const char* header;
  1923. if (plainText && (!stricmp(plainText, "yes")))
  1924. header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
  1925. else
  1926. header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><?xml-stylesheet href=\"../esp/xslt/xmlformatter.xsl\" type=\"text/xsl\"?>";
  1927. StringBuffer xml;
  1928. exportWorkUnitToXML(cw, xml, true, false, true);
  1929. buf.append(strlen(header), header);
  1930. buf.append(xml.length(), xml.str());
  1931. }
  1932. void WsWuInfo::getWorkunitCpp(const char *cppname, const char* description, const char* ipAddress, MemoryBuffer& buf, bool forDownload)
  1933. {
  1934. if (isEmpty(description))
  1935. throw MakeStringException(ECLWATCH_INVALID_INPUT, "File not specified.");
  1936. if (isEmpty(ipAddress))
  1937. throw MakeStringException(ECLWATCH_INVALID_INPUT, "File location not specified.");
  1938. if (isEmpty(cppname))
  1939. throw MakeStringException(ECLWATCH_INVALID_FILE_NAME, "File path not specified.");
  1940. RemoteFilename rfn;
  1941. rfn.setRemotePath(cppname);
  1942. SocketEndpoint ep(ipAddress);
  1943. rfn.setIp(ep);
  1944. Owned<IFile> cppfile = createIFile(rfn);
  1945. if (!cppfile)
  1946. throw MakeStringException(ECLWATCH_CANNOT_OPEN_FILE, "Cannot open %s.", description);
  1947. OwnedIFileIO rIO = cppfile->openShared(IFOread,IFSHfull);
  1948. if (!rIO)
  1949. throw MakeStringException(ECLWATCH_CANNOT_READ_FILE,"Cannot read %s.", description);
  1950. OwnedIFileIOStream ios = createBufferedIOStream(rIO);
  1951. if (!ios)
  1952. throw MakeStringException(ECLWATCH_CANNOT_READ_FILE,"Cannot read %s.", description);
  1953. appendIOStreamContent(buf, ios.get(), forDownload);
  1954. }
  1955. void WsWuInfo::getWorkunitAssociatedXml(const char* name, const char* ipAddress, const char* plainText,
  1956. const char* description, bool forDownload, bool addXMLDeclaration, MemoryBuffer& buf)
  1957. {
  1958. if (isEmpty(description)) //'File Name' as shown in WU Details page
  1959. throw MakeStringException(ECLWATCH_INVALID_INPUT, "File not specified.");
  1960. if (isEmpty(ipAddress))
  1961. throw MakeStringException(ECLWATCH_INVALID_INPUT, "File location not specified.");
  1962. if (isEmpty(name)) //file name with full path
  1963. throw MakeStringException(ECLWATCH_INVALID_FILE_NAME, "File path not specified.");
  1964. RemoteFilename rfn;
  1965. rfn.setRemotePath(name);
  1966. SocketEndpoint ep(ipAddress);
  1967. rfn.setIp(ep);
  1968. Owned<IFile> rFile = createIFile(rfn);
  1969. if (!rFile)
  1970. throw MakeStringException(ECLWATCH_CANNOT_OPEN_FILE, "Cannot open %s.", description);
  1971. OwnedIFileIO rIO = rFile->openShared(IFOread,IFSHfull);
  1972. if (!rIO)
  1973. throw MakeStringException(ECLWATCH_CANNOT_READ_FILE,"Cannot read %s.", description);
  1974. OwnedIFileIOStream ios = createBufferedIOStream(rIO);
  1975. if (!ios)
  1976. throw MakeStringException(ECLWATCH_CANNOT_READ_FILE,"Cannot read %s.", description);
  1977. if (addXMLDeclaration)
  1978. {
  1979. const char* header;
  1980. if (plainText && (!stricmp(plainText, "yes")))
  1981. header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
  1982. else
  1983. header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><?xml-stylesheet href=\"../esp/xslt/xmlformatter.xsl\" type=\"text/xsl\"?>";
  1984. buf.append(strlen(header), header);
  1985. }
  1986. appendIOStreamContent(buf, ios.get(), forDownload);
  1987. }
  1988. IPropertyTree* WsWuInfo::getWorkunitArchive()
  1989. {
  1990. Owned <IConstWUQuery> query = cw->getQuery();
  1991. if(!query)
  1992. return NULL;
  1993. SCMStringBuffer name, ip;
  1994. Owned<IConstWUAssociatedFileIterator> iter = &query->getAssociatedFiles();
  1995. ForEach(*iter)
  1996. {
  1997. IConstWUAssociatedFile& cur = iter->query();
  1998. if (cur.getType() != FileTypeXml)
  1999. continue;
  2000. cur.getName(name);
  2001. if (name.length() < 15)
  2002. continue;
  2003. const char* pStr = name.str() + name.length() - 15;
  2004. if (strieq(pStr, ".archive.eclxml"))
  2005. {
  2006. cur.getIp(ip);
  2007. break;
  2008. }
  2009. }
  2010. if (!ip.length())
  2011. return NULL;
  2012. MemoryBuffer content;
  2013. getWorkunitAssociatedXml(name.str(), ip.str(), "", "WU archive eclxml", true, false, content);
  2014. if (!content.length())
  2015. return NULL;
  2016. return createPTreeFromXMLString(content.length(), content.toByteArray());
  2017. }
  2018. IEspWUArchiveFile* WsWuInfo::readArchiveFileAttr(IPropertyTree& fileTree, const char* path)
  2019. {
  2020. const char* fileName = fileTree.queryProp("@name");
  2021. if (isEmpty(fileName))
  2022. return NULL;
  2023. Owned<IEspWUArchiveFile> file= createWUArchiveFile();
  2024. file->setName(fileName);
  2025. if (!isEmpty(path))
  2026. file->setPath(path);
  2027. if (fileTree.hasProp("@key"))
  2028. file->setKey(fileTree.queryProp("@key"));
  2029. if (fileTree.hasProp("@sourcePath"))
  2030. file->setSourcePath(fileTree.queryProp("@sourcePath"));
  2031. return file.getClear();
  2032. }
  2033. IEspWUArchiveModule* WsWuInfo::readArchiveModuleAttr(IPropertyTree& moduleTree, const char* path)
  2034. {
  2035. const char* moduleName = moduleTree.queryProp("@name");
  2036. if (isEmpty(moduleName))
  2037. return NULL;
  2038. Owned<IEspWUArchiveModule> module= createWUArchiveModule();
  2039. module->setName(moduleName);
  2040. if (!isEmpty(path))
  2041. module->setPath(path);
  2042. if (moduleTree.hasProp("@fullName"))
  2043. module->setFullName(moduleTree.queryProp("@fullName"));
  2044. if (moduleTree.hasProp("@key"))
  2045. module->setKey(moduleTree.queryProp("@key"));
  2046. if (moduleTree.hasProp("@plugin"))
  2047. module->setPlugin(moduleTree.queryProp("@plugin"));
  2048. if (moduleTree.hasProp("@version"))
  2049. module->setVersion(moduleTree.queryProp("@version"));
  2050. if (moduleTree.hasProp("@sourcePath"))
  2051. module->setSourcePath(moduleTree.queryProp("@sourcePath"));
  2052. if (moduleTree.hasProp("@flags"))
  2053. module->setFlags(moduleTree.getPropInt("@flags", 0));
  2054. return module.getClear();
  2055. }
  2056. void WsWuInfo::readArchiveFiles(IPropertyTree* archiveTree, const char* path, IArrayOf<IEspWUArchiveFile>& files)
  2057. {
  2058. Owned<IPropertyTreeIterator> iter = archiveTree->getElements("Attribute");
  2059. ForEach(*iter)
  2060. {
  2061. IPropertyTree& item = iter->query();
  2062. Owned<IEspWUArchiveFile> file = readArchiveFileAttr(item, path);
  2063. if (file)
  2064. files.append(*file.getClear());
  2065. }
  2066. }
  2067. void WsWuInfo::listArchiveFiles(IPropertyTree* archiveTree, const char* path, IArrayOf<IEspWUArchiveModule>& modules, IArrayOf<IEspWUArchiveFile>& files)
  2068. {
  2069. if (!archiveTree)
  2070. return;
  2071. Owned<IPropertyTreeIterator> iter = archiveTree->getElements("Module");
  2072. ForEach(*iter)
  2073. {
  2074. IPropertyTree& item = iter->query();
  2075. Owned<IEspWUArchiveModule> module = readArchiveModuleAttr(item, path);
  2076. if (!module)
  2077. continue;
  2078. StringBuffer newPath;
  2079. if (isEmpty(path))
  2080. newPath.set(module->getName());
  2081. else
  2082. newPath.setf("%s/%s", path, module->getName());
  2083. IArrayOf<IEspWUArchiveModule> modulesInModule;
  2084. IArrayOf<IEspWUArchiveFile> filesInModule;
  2085. listArchiveFiles(&item, newPath.str(), modulesInModule, filesInModule);
  2086. if (modulesInModule.length())
  2087. module->setArchiveModules(modulesInModule);
  2088. if (filesInModule.length())
  2089. module->setFiles(filesInModule);
  2090. modules.append(*module.getClear());
  2091. }
  2092. readArchiveFiles(archiveTree, path, files);
  2093. }
  2094. void WsWuInfo::getArchiveFile(IPropertyTree* archive, const char* moduleName, const char* attrName, const char* path, StringBuffer& file)
  2095. {
  2096. StringBuffer xPath;
  2097. if (!isEmpty(path))
  2098. {
  2099. StringArray list;
  2100. list.appendListUniq(path, "/");
  2101. ForEachItemIn(m, list)
  2102. {
  2103. const char* module = list.item(m);
  2104. if (!isEmpty(module))
  2105. xPath.appendf("Module[@name=\"%s\"]/", module);
  2106. }
  2107. }
  2108. if (isEmpty(moduleName))
  2109. xPath.appendf("Attribute[@name=\"%s\"]", attrName);
  2110. else
  2111. xPath.appendf("Module[@name=\"%s\"]/Text", moduleName);
  2112. file.set(archive->queryProp(xPath.str()));
  2113. }
  2114. WsWuSearch::WsWuSearch(IEspContext& context,const char* owner,const char* state,const char* cluster,const char* startDate,const char* endDate,const char* jobname)
  2115. {
  2116. SecAccessFlags accessOwn;
  2117. SecAccessFlags accessOthers;
  2118. getUserWuAccessFlags(context, accessOwn, accessOthers, true);
  2119. Owned<IWorkUnitFactory> factory = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  2120. Owned<IConstWorkUnitIterator> it(factory->getWorkUnitsByOwner(owner)); // null owner means fetch all
  2121. StringBuffer wuFrom, wuTo, jobPattern;
  2122. if (startDate && *startDate)
  2123. createWuidFromDate(startDate, wuFrom);
  2124. if (endDate && *endDate)
  2125. createWuidFromDate(endDate, wuTo);
  2126. if (jobname && *jobname)
  2127. jobPattern.appendf("*%s*", jobname);
  2128. ForEach(*it)
  2129. {
  2130. IConstWorkUnitInfo &cw = it->query();
  2131. if (chooseWuAccessFlagsByOwnership(context.queryUserId(), cw, accessOwn, accessOthers) < SecAccess_Read)
  2132. continue;
  2133. if (state && *state && !strieq(cw.queryStateDesc(), state))
  2134. continue;
  2135. if (cluster && *cluster && !strieq(cw.queryClusterName(), cluster))
  2136. continue;
  2137. if (jobPattern.length() && !WildMatch(cw.queryJobName(), jobPattern, true))
  2138. continue;
  2139. const char *wuid = cw.queryWuid();
  2140. if (wuFrom.length() && strcmp(wuid,wuFrom.str())<0)
  2141. continue;
  2142. if (wuTo.length() && strcmp(wuid, wuTo.str())>0)
  2143. continue;
  2144. wuids.push_back(wuid);
  2145. }
  2146. std::sort(wuids.begin(), wuids.end(),std::greater<std::string>());
  2147. }
  2148. StringBuffer& WsWuSearch::createWuidFromDate(const char* timestamp,StringBuffer& s)
  2149. {
  2150. CDateTime wuTime;
  2151. wuTime.setString(timestamp,NULL,true);
  2152. unsigned year, month, day, hour, minute, second, nano;
  2153. wuTime.getDate(year, month, day, true);
  2154. wuTime.getTime(hour, minute, second, nano, true);
  2155. s.appendf("W%4d%02d%02d-%02d%02d%02d",year,month,day,hour,minute,second);
  2156. return s;
  2157. }
  2158. struct CompareData
  2159. {
  2160. CompareData(const char* _filter): filter(_filter) {}
  2161. bool operator()(const Linked<DataCacheElement>& e) const
  2162. {
  2163. return stricmp(e->m_filter.c_str(),filter)==0;
  2164. }
  2165. const char* filter;
  2166. };
  2167. DataCacheElement* DataCache::lookup(IEspContext &context, const char* filter, unsigned timeOutMin)
  2168. {
  2169. CriticalBlock block(crit);
  2170. if (cache.size() < 1)
  2171. return NULL;
  2172. //erase data if it should be
  2173. CDateTime timeNow;
  2174. int timeout = timeOutMin;
  2175. timeNow.setNow();
  2176. timeNow.adjustTime(-timeout);
  2177. while (true)
  2178. {
  2179. std::list<Linked<DataCacheElement> >::iterator list_iter = cache.begin();
  2180. if (list_iter == cache.end())
  2181. break;
  2182. DataCacheElement* awu = list_iter->get();
  2183. if (!awu || (awu->m_timeCached > timeNow))
  2184. break;
  2185. cache.pop_front();
  2186. }
  2187. if (cache.size() < 1)
  2188. return NULL;
  2189. //Check whether we have the data cache for this cluster. If yes, get the version
  2190. std::list<Linked<DataCacheElement> >::iterator it = std::find_if(cache.begin(),cache.end(),CompareData(filter));
  2191. if(it!=cache.end())
  2192. {
  2193. return it->getLink();
  2194. }
  2195. return NULL;
  2196. }
  2197. void DataCache::add(const char* filter, const char* data, const char* name, const char* localName, const char* wuid,
  2198. const char* resultName, unsigned seq, __int64 start, unsigned count, __int64 requested, __int64 total)
  2199. {
  2200. CriticalBlock block(crit);
  2201. //Save new data
  2202. Owned<DataCacheElement> e=new DataCacheElement(filter, data, name, localName, wuid, resultName, seq, start, count, requested, total);
  2203. if (cacheSize > 0)
  2204. {
  2205. if (cache.size() >= cacheSize)
  2206. cache.pop_front();
  2207. cache.push_back(e.get());
  2208. }
  2209. return;
  2210. }
  2211. struct CompareArchivedWUs
  2212. {
  2213. CompareArchivedWUs(const char* _filter): filter(_filter) {}
  2214. bool operator()(const Linked<ArchivedWuCacheElement>& e) const
  2215. {
  2216. return stricmp(e->m_filter.c_str(),filter)==0;
  2217. }
  2218. const char* filter;
  2219. };
  2220. ArchivedWuCacheElement* ArchivedWuCache::lookup(IEspContext &context, const char* filter, const char* sashaUpdatedWhen, unsigned timeOutMin)
  2221. {
  2222. CriticalBlock block(crit);
  2223. if (cache.size() < 1)
  2224. return NULL;
  2225. //erase data if it should be
  2226. CDateTime timeNow;
  2227. int timeout = timeOutMin;
  2228. timeNow.setNow();
  2229. timeNow.adjustTime(-timeout);
  2230. while (true)
  2231. {
  2232. std::list<Linked<ArchivedWuCacheElement> >::iterator list_iter = cache.begin();
  2233. if (list_iter == cache.end())
  2234. break;
  2235. ArchivedWuCacheElement* awu = list_iter->get();
  2236. if (awu && !stricmp(sashaUpdatedWhen, awu->m_sashaUpdatedWhen.c_str()) && (awu->m_timeCached > timeNow))
  2237. break;
  2238. cache.pop_front();
  2239. }
  2240. if (cache.size() < 1)
  2241. return NULL;
  2242. //Check whether we have the data cache for this cluster. If yes, get the version
  2243. std::list<Linked<ArchivedWuCacheElement> >::iterator it = std::find_if(cache.begin(),cache.end(),CompareArchivedWUs(filter));
  2244. if(it!=cache.end())
  2245. return it->getLink();
  2246. return NULL;
  2247. }
  2248. void ArchivedWuCache::add(const char* filter, const char* sashaUpdatedWhen, bool hasNextPage, unsigned numWUsReturned, IArrayOf<IEspECLWorkunit>& wus, IArrayOf<IEspECLWorkunitLW>& lwwus)
  2249. {
  2250. CriticalBlock block(crit);
  2251. //Save new data
  2252. Owned<ArchivedWuCacheElement> e=new ArchivedWuCacheElement(filter, sashaUpdatedWhen, hasNextPage, numWUsReturned, wus, lwwus);
  2253. if (cacheSize > 0)
  2254. {
  2255. if (cache.size() >= cacheSize)
  2256. cache.pop_front();
  2257. cache.push_back(e.get());
  2258. }
  2259. return;
  2260. }
  2261. WsWuJobQueueAuditInfo::WsWuJobQueueAuditInfo(IEspContext &context, const char *cluster, const char *from , const char *to, CHttpResponse* response, const char *xls)
  2262. {
  2263. if(!response)
  2264. return;
  2265. unsigned maxDisplay = 125;
  2266. IArrayOf<IEspThorQueue> items;
  2267. CDateTime fromTime;
  2268. CDateTime toTime;
  2269. StringBuffer fromstr;
  2270. StringBuffer tostr;
  2271. if(from && *from)
  2272. {
  2273. fromTime.setString(from,NULL,false);
  2274. fromTime.getString(fromstr, false);
  2275. }
  2276. if(to && *to)
  2277. {
  2278. toTime.setString(to,NULL,false);
  2279. toTime.getString(tostr, false);
  2280. }
  2281. StringBuffer filter("ThorQueueMonitor");
  2282. if(notEmpty(cluster))
  2283. filter.appendf(",%s", cluster);
  2284. StringAttrArray lines;
  2285. queryAuditLogs(fromTime, toTime, filter.str(), lines);
  2286. unsigned countLines = 0;
  2287. unsigned maxConnected = 0;
  2288. unsigned longestQueue = 0;
  2289. ForEachItemIn(idx, lines)
  2290. {
  2291. const char* line = lines.item(idx).text;
  2292. if(!line || !*line)
  2293. continue;
  2294. if (idx < (lines.length() - 1))
  2295. getAuditLineInfo(line, longestQueue, maxConnected, maxDisplay, 1, items);
  2296. else
  2297. getAuditLineInfo(line, longestQueue, maxConnected, maxDisplay, 2, items);
  2298. countLines++;
  2299. }
  2300. StringBuffer responsebuf;
  2301. if (items.length() < 1)
  2302. {
  2303. responsebuf.append("<script language=\"javascript\">\r\nparent.displayQEnd(\'No data found\')</script>\r\n");
  2304. response->sendChunk(responsebuf.str());
  2305. return;
  2306. }
  2307. unsigned itemCount = items.length();
  2308. if (itemCount > maxDisplay)
  2309. itemCount = maxDisplay;
  2310. responsebuf.append("<script language=\"javascript\">parent.displayQLegend()</script>\r\n");
  2311. response->sendChunk(responsebuf.str());
  2312. responsebuf.clear();
  2313. responsebuf.append("<script language=\"javascript\">parent.displayQBegin(").append(longestQueue).append(",").append(maxConnected).append(",").append(itemCount).append(")</script>\r\n");
  2314. response->sendChunk(responsebuf.str());
  2315. responsebuf.clear();
  2316. responsebuf.append("<script language=\"javascript\">\r\n");
  2317. //bool displayDT = false;
  2318. unsigned count = 0;
  2319. unsigned jobpending=0;
  2320. ForEachItemIn(i,items)
  2321. {
  2322. IEspThorQueue& tq = items.item(i);
  2323. //displayDT = !displayDT;
  2324. count++;
  2325. if (count > maxDisplay)
  2326. break;
  2327. StringBuffer countStr, dtStr;
  2328. countStr.appendulong(count);
  2329. //if (displayDT)
  2330. dtStr = tq.getDT();
  2331. responsebuf.append("parent.displayQueue(\'").append(count).append("\',\'").append(dtStr.str()).append("\',\'").append(tq.getRunningWUs()).append("\',");
  2332. responsebuf.append("\'").append(tq.getQueuedWUs()).append("\',\'").append(tq.getWaitingThors()).append("\',");
  2333. responsebuf.append("\'").append(tq.getConnectedThors()).append("\',\'").append(tq.getIdledThors()).append("\',");
  2334. responsebuf.append("\'").append(tq.getRunningWU1()).append("\',\'").append(tq.getRunningWU2()).append("\')\r\n");
  2335. if(++jobpending>=50)
  2336. {
  2337. responsebuf.append("</script>\r\n");
  2338. response->sendChunk(responsebuf.str());
  2339. responsebuf.clear();
  2340. responsebuf.append("<script language=\"javascript\">\r\n");
  2341. jobpending=0;
  2342. }
  2343. }
  2344. StringBuffer countStr;
  2345. countStr.appendulong(count);
  2346. StringBuffer msg("<table><tr><td>");
  2347. msg.append("Total Records in the Time Period: ").append(items.length()).append(" (<a href=\"/WsWorkunits/WUClusterJobQueueLOG?").append(xls).append("\">txt</a>...<a href=\"/WsWorkunits/WUClusterJobQueueXLS?").append(xls).append("\">xls</a>).");
  2348. msg.append("</td></tr><tr><td>");
  2349. if (count > maxDisplay)
  2350. msg.append("Displayed: First ").append(maxDisplay).append(". ");
  2351. msg.append("Max. Queue Length: ").append(longestQueue).append(".");
  2352. msg.append("</td></tr></table>");
  2353. responsebuf.append("parent.displayQEnd(\'").append(msg).append("\')</script>\r\n");
  2354. response->sendChunk(responsebuf.str());
  2355. }
  2356. void WsWuJobQueueAuditInfo::getAuditLineInfo(const char* line, unsigned& longestQueue, unsigned& maxConnected, unsigned maxDisplay, unsigned showAll, IArrayOf<IEspThorQueue>& items)
  2357. {
  2358. //2009-08-12 02:44:12 ,ThorQueueMonitor,thor400_88_dev,0,0,1,1,114,---,---
  2359. if(!line || !*line)
  2360. return;
  2361. Owned<IEspThorQueue> tq = createThorQueue();
  2362. StringBuffer dt, runningWUs, queuedWUs, waitingThors, connectedThors, idledThors, runningWU1, runningWU2;
  2363. // date/time
  2364. const char* bptr = line;
  2365. const char* eptr = strchr(bptr, ',');
  2366. if(eptr)
  2367. dt.append(eptr - bptr, bptr);
  2368. else
  2369. dt.append(bptr);
  2370. tq->setDT(dt.str());
  2371. if(!eptr)
  2372. {
  2373. if (checkNewThorQueueItem(tq, showAll, items))
  2374. items.append(*tq.getClear());
  2375. return;
  2376. }
  2377. //skip title
  2378. bptr = eptr + 1;
  2379. eptr = strchr(bptr, ',');
  2380. if(!eptr)
  2381. {
  2382. if (checkNewThorQueueItem(tq, showAll, items))
  2383. items.append(*tq.getClear());
  2384. return;
  2385. }
  2386. //skip queue name
  2387. bptr = eptr + 1;
  2388. eptr = strchr(bptr, ',');
  2389. if(!eptr)
  2390. {
  2391. if (checkNewThorQueueItem(tq, showAll, items))
  2392. items.append(*tq.getClear());
  2393. return;
  2394. }
  2395. //running
  2396. bptr = eptr + 1;
  2397. eptr = strchr(bptr, ',');
  2398. if(eptr)
  2399. runningWUs.append(eptr - bptr, bptr);
  2400. else
  2401. runningWUs.append(bptr);
  2402. tq->setRunningWUs(runningWUs.str());
  2403. if(!eptr)
  2404. {
  2405. if (checkNewThorQueueItem(tq, showAll, items))
  2406. items.append(*tq.getClear());
  2407. return;
  2408. }
  2409. //queued
  2410. bptr = eptr + 1;
  2411. eptr = strchr(bptr, ',');
  2412. if(eptr)
  2413. queuedWUs.append(eptr - bptr, bptr);
  2414. else
  2415. queuedWUs.append(bptr);
  2416. if (maxDisplay > items.length())
  2417. {
  2418. unsigned queueLen = atoi(queuedWUs.str());
  2419. if (queueLen > longestQueue)
  2420. longestQueue = queueLen;
  2421. }
  2422. tq->setQueuedWUs(queuedWUs.str());
  2423. if(!eptr)
  2424. {
  2425. if (checkNewThorQueueItem(tq, showAll, items))
  2426. items.append(*tq.getClear());
  2427. return;
  2428. }
  2429. //waiting
  2430. bptr = eptr + 1;
  2431. eptr = strchr(bptr, ',');
  2432. if(eptr)
  2433. waitingThors.append(eptr - bptr, bptr);
  2434. else
  2435. waitingThors.append(bptr);
  2436. tq->setWaitingThors(waitingThors.str());
  2437. if(!eptr)
  2438. {
  2439. if (checkNewThorQueueItem(tq, showAll, items))
  2440. items.append(*tq.getClear());
  2441. return;
  2442. }
  2443. //connected
  2444. bptr = eptr + 1;
  2445. eptr = strchr(bptr, ',');
  2446. if(eptr)
  2447. connectedThors.append(eptr - bptr, bptr);
  2448. else
  2449. connectedThors.append(bptr);
  2450. if (maxDisplay > items.length())
  2451. {
  2452. unsigned connnectedLen = atoi(connectedThors.str());
  2453. if (connnectedLen > maxConnected)
  2454. maxConnected = connnectedLen;
  2455. }
  2456. tq->setConnectedThors(connectedThors.str());
  2457. if(!eptr)
  2458. {
  2459. if (checkNewThorQueueItem(tq, showAll, items))
  2460. items.append(*tq.getClear());
  2461. return;
  2462. }
  2463. //idled
  2464. bptr = eptr + 1;
  2465. eptr = strchr(bptr, ',');
  2466. if(eptr)
  2467. idledThors.append(eptr - bptr, bptr);
  2468. else
  2469. idledThors.append(bptr);
  2470. tq->setIdledThors(idledThors.str());
  2471. if(!eptr)
  2472. {
  2473. items.append(*tq.getClear());
  2474. return;
  2475. }
  2476. //runningWU1
  2477. bptr = eptr + 1;
  2478. eptr = strchr(bptr, ',');
  2479. if(eptr)
  2480. runningWU1.append(eptr - bptr, bptr);
  2481. else
  2482. {
  2483. runningWU1.append(bptr);
  2484. }
  2485. if (!strcmp(runningWU1.str(), "---"))
  2486. runningWU1.clear();
  2487. if (runningWU1.length() > 0)
  2488. tq->setRunningWU1(runningWU1.str());
  2489. if(!eptr)
  2490. {
  2491. if (checkNewThorQueueItem(tq, showAll, items))
  2492. items.append(*tq.getClear());
  2493. return;
  2494. }
  2495. //runningWU2
  2496. bptr = eptr + 1;
  2497. eptr = strchr(bptr, ',');
  2498. if(eptr)
  2499. runningWU2.append(eptr - bptr, bptr);
  2500. else
  2501. {
  2502. runningWU2.append(bptr);
  2503. }
  2504. if (!strcmp(runningWU2.str(), "---"))
  2505. runningWU2.clear();
  2506. if (runningWU2.length() > 0)
  2507. tq->setRunningWU2(runningWU2.str());
  2508. if (checkNewThorQueueItem(tq, showAll, items))
  2509. items.append(*tq.getClear());
  2510. }
  2511. bool WsWuJobQueueAuditInfo::checkSameStrings(const char* s1, const char* s2)
  2512. {
  2513. if (s1)
  2514. {
  2515. if (!s2)
  2516. return false;
  2517. if (strcmp(s1, s2))
  2518. return false;
  2519. }
  2520. else if (s2)
  2521. {
  2522. if (!s1)
  2523. return false;
  2524. }
  2525. return true;
  2526. }
  2527. bool WsWuJobQueueAuditInfo::checkNewThorQueueItem(IEspThorQueue* tq, unsigned showAll, IArrayOf<IEspThorQueue>& items)
  2528. {
  2529. bool bAdd = false;
  2530. if (showAll < 1) //show every lines
  2531. bAdd = true;
  2532. else if (items.length() < 1)
  2533. bAdd = true;
  2534. else if (showAll > 1) //last line now
  2535. {
  2536. IEspThorQueue& tq0 = items.item(items.length()-1);
  2537. if (!checkSameStrings(tq->getDT(), tq0.getDT()))
  2538. bAdd = true;
  2539. }
  2540. else
  2541. {
  2542. IEspThorQueue& tq0 = items.item(items.length()-1);
  2543. if (!checkSameStrings(tq->getRunningWUs(), tq0.getRunningWUs()))
  2544. bAdd = true;
  2545. if (!checkSameStrings(tq->getQueuedWUs(), tq0.getQueuedWUs()))
  2546. bAdd = true;
  2547. if (!checkSameStrings(tq->getConnectedThors(), tq0.getConnectedThors()))
  2548. bAdd = true;
  2549. if (!checkSameStrings(tq->getConnectedThors(), tq0.getConnectedThors()))
  2550. bAdd = true;
  2551. if (!checkSameStrings(tq->getRunningWU1(), tq0.getRunningWU1()))
  2552. bAdd = true;
  2553. if (!checkSameStrings(tq->getRunningWU2(), tq0.getRunningWU2()))
  2554. bAdd = true;
  2555. }
  2556. return bAdd;
  2557. }
  2558. void xsltTransform(const char* xml, const char* sheet, IProperties *params, StringBuffer& ret)
  2559. {
  2560. StringBuffer xsl;
  2561. if(!checkFileExists(sheet))
  2562. throw MakeStringException(ECLWATCH_FILE_NOT_EXIST, "Could not find stylesheet %s.",sheet);
  2563. Owned<IXslProcessor> proc = getXslProcessor();
  2564. Owned<IXslTransform> trans = proc->createXslTransform();
  2565. trans->setXmlSource(xml, strlen(xml));
  2566. trans->loadXslFromFile(sheet);
  2567. trans->copyParameters(params);
  2568. trans->transform(ret);
  2569. }
  2570. bool addToQueryString(StringBuffer &queryString, const char *name, const char *value, const char delim)
  2571. {
  2572. if (isEmpty(name) || isEmpty(value))
  2573. return false;
  2574. if (queryString.length() > 0)
  2575. queryString.append(delim);
  2576. queryString.append(name).append("=").append(value);
  2577. return true;
  2578. }
  2579. int WUSchedule::run()
  2580. {
  2581. try
  2582. {
  2583. PROGLOG("ECLWorkunit WUSchedule Thread started.");
  2584. while(!stopping)
  2585. {
  2586. Owned<IWorkUnitFactory> factory = getWorkUnitFactory();
  2587. Owned<IConstWorkUnitIterator> itr = factory->getScheduledWorkUnits();
  2588. if (itr)
  2589. {
  2590. ForEach(*itr)
  2591. {
  2592. try
  2593. {
  2594. IConstWorkUnitInfo & cw = itr->query();
  2595. if (factory->isAborting(cw.queryWuid()))
  2596. {
  2597. WorkunitUpdate wu(factory->updateWorkUnit(cw.queryWuid()));
  2598. wu->setState(WUStateAborted);
  2599. continue;
  2600. }
  2601. WsWuDateTime dt, now;
  2602. now.setNow();
  2603. cw.getTimeScheduled(dt);
  2604. if (now.compare(dt)>=0)
  2605. runWorkUnit(cw.queryWuid(), cw.queryClusterName());
  2606. }
  2607. catch(IException *e)
  2608. {
  2609. StringBuffer msg;
  2610. ERRLOG("Exception %d:%s in WsWorkunits Schedule::run", e->errorCode(), e->errorMessage(msg).str());
  2611. e->Release();
  2612. }
  2613. }
  2614. }
  2615. semSchedule.wait(1000*60);
  2616. }
  2617. }
  2618. catch(IException *e)
  2619. {
  2620. StringBuffer msg;
  2621. ERRLOG("Exception %d:%s in WsWorkunits Schedule::run", e->errorCode(), e->errorMessage(msg).str());
  2622. e->Release();
  2623. }
  2624. catch(...)
  2625. {
  2626. ERRLOG("Unknown exception in WsWorkunits Schedule::run");
  2627. }
  2628. if (m_container)
  2629. m_container->exitESP();
  2630. return 0;
  2631. }
  2632. void WsWuHelpers::setXmlParameters(IWorkUnit *wu, const char *xml, bool setJobname)
  2633. {
  2634. if (!xml || !*xml)
  2635. return;
  2636. Owned<IPropertyTree> tree = createPTreeFromXMLString(xml, ipt_none, (PTreeReaderOptions)(ptr_ignoreWhiteSpace | ptr_ignoreNameSpaces));
  2637. IPropertyTree *root = tree.get();
  2638. if (strieq(root->queryName(), "Envelope"))
  2639. root = root->queryPropTree("Body/*[1]");
  2640. if (!root)
  2641. return;
  2642. if (setJobname)
  2643. {
  2644. const char *name = wu->queryJobName();
  2645. if (!name || !*name)
  2646. wu->setJobName(root->queryName());
  2647. }
  2648. wu->setXmlParams(LINK(root));
  2649. }
  2650. void WsWuHelpers::setXmlParameters(IWorkUnit *wu, const char *xml, IArrayOf<IConstNamedValue> *variables, bool setJobname)
  2651. {
  2652. StringBuffer extParamXml;
  2653. if (variables && variables->length())
  2654. {
  2655. Owned<IPropertyTree> paramTree = (xml && *xml) ? createPTreeFromXMLString(xml) : createPTree("input");
  2656. ForEachItemIn(i, *variables)
  2657. {
  2658. IConstNamedValue &item = variables->item(i);
  2659. const char *name = item.getName();
  2660. const char *value = item.getValue();
  2661. if (!name || !*name)
  2662. continue;
  2663. if (!value)
  2664. {
  2665. size_t len = strlen(name);
  2666. char last = name[len-1];
  2667. if (last == '-' || last == '+')
  2668. {
  2669. StringAttr s(name, len-1);
  2670. paramTree->setPropInt(s.get(), last == '+' ? 1 : 0);
  2671. }
  2672. else
  2673. paramTree->setPropInt(name, 1);
  2674. continue;
  2675. }
  2676. paramTree->setProp(name, value);
  2677. }
  2678. toXML(paramTree, extParamXml);
  2679. xml=extParamXml.str();
  2680. }
  2681. setXmlParameters(wu, xml, setJobname);
  2682. }
  2683. void WsWuHelpers::submitWsWorkunit(IEspContext& context, IConstWorkUnit* cw, const char* cluster, const char* snapshot, int maxruntime, bool compile, bool resetWorkflow, bool resetVariables,
  2684. const char *paramXml, IArrayOf<IConstNamedValue> *variables, IArrayOf<IConstNamedValue> *debugs, IArrayOf<IConstApplicationValue> *applications)
  2685. {
  2686. ensureWsWorkunitAccess(context, *cw, SecAccess_Write);
  2687. #ifndef _NO_LDAP
  2688. CLdapSecManager* secmgr = dynamic_cast<CLdapSecManager*>(context.querySecManager());
  2689. // View Scope is checked only when LDAP secmgr is available AND checkViewPermissions config is also enabled.
  2690. // Otherwise, the view permission check is skipped, and WU is submitted as normal.
  2691. if (secmgr && secmgr->getCheckViewPermissions())
  2692. {
  2693. StringArray filenames, columnnames;
  2694. if (cw->getFieldUsageArray(filenames, columnnames, cluster)) // check view permission only for a query with fieldUsage information
  2695. {
  2696. if (!secmgr->authorizeViewScope(*context.queryUser(), filenames, columnnames))
  2697. throw MakeStringException(ECLWATCH_VIEW_ACCESS_DENIED, "View Access denied for a WU: %s", cw->queryWuid());
  2698. }
  2699. }
  2700. #endif
  2701. switch(cw->getState())
  2702. {
  2703. case WUStateRunning:
  2704. case WUStateDebugPaused:
  2705. case WUStateDebugRunning:
  2706. case WUStateCompiling:
  2707. case WUStateAborting:
  2708. case WUStateBlocked:
  2709. throw MakeStringException(ECLWATCH_CANNOT_SUBMIT_WORKUNIT, "Cannot submit the workunit. Workunit state is '%s'.", cw->queryStateDesc());
  2710. }
  2711. StringAttr wuid(cw->queryWuid());
  2712. WorkunitUpdate wu(&cw->lock());
  2713. if(!wu.get())
  2714. throw MakeStringException(ECLWATCH_CANNOT_UPDATE_WORKUNIT, "Cannot update workunit %s.", wuid.str());
  2715. wu->clearExceptions();
  2716. if(notEmpty(cluster))
  2717. wu->setClusterName(cluster);
  2718. if(notEmpty(snapshot))
  2719. wu->setSnapshot(snapshot);
  2720. wu->setState(WUStateSubmitted);
  2721. if (maxruntime)
  2722. wu->setDebugValueInt("maxRunTime",maxruntime,true);
  2723. if (debugs && debugs->length())
  2724. {
  2725. ForEachItemIn(i, *debugs)
  2726. {
  2727. IConstNamedValue &item = debugs->item(i);
  2728. const char *name = item.getName();
  2729. const char *value = item.getValue();
  2730. if (!name || !*name)
  2731. continue;
  2732. StringBuffer expanded;
  2733. if (*name=='-')
  2734. name=expanded.append("eclcc").append(name).str();
  2735. if (!value)
  2736. {
  2737. size_t len = strlen(name);
  2738. char last = name[len-1];
  2739. if (last == '-' || last == '+')
  2740. {
  2741. StringAttr s(name, len-1);
  2742. wu->setDebugValueInt(s.get(), last == '+' ? 1 : 0, true);
  2743. }
  2744. else
  2745. wu->setDebugValueInt(name, 1, true);
  2746. continue;
  2747. }
  2748. wu->setDebugValue(name, value, true);
  2749. }
  2750. }
  2751. if (applications)
  2752. {
  2753. ForEachItemIn(ii, *applications)
  2754. {
  2755. IConstApplicationValue& item = applications->item(ii);
  2756. if(notEmpty(item.getApplication()) && notEmpty(item.getName()))
  2757. wu->setApplicationValue(item.getApplication(), item.getName(), item.getValue(), true);
  2758. }
  2759. }
  2760. if (resetWorkflow)
  2761. wu->resetWorkflow();
  2762. if (!compile)
  2763. wu->schedule();
  2764. if (resetVariables)
  2765. {
  2766. SCMStringBuffer varname;
  2767. Owned<IConstWUResultIterator> vars = &wu->getVariables();
  2768. ForEach (*vars)
  2769. {
  2770. vars->query().getResultName(varname);
  2771. Owned<IWUResult> v = wu->updateVariableByName(varname.str());
  2772. if (v)
  2773. v->setResultStatus(ResultStatusUndefined);
  2774. }
  2775. }
  2776. setXmlParameters(wu, paramXml, variables, (wu->getAction()==WUActionExecuteExisting));
  2777. wu->commit();
  2778. wu.clear();
  2779. if (!compile)
  2780. runWorkUnit(wuid.str());
  2781. else if (context.querySecManager())
  2782. secSubmitWorkUnit(wuid.str(), *context.querySecManager(), *context.queryUser());
  2783. else
  2784. submitWorkUnit(wuid.str(), context.queryUserId(), context.queryPassword());
  2785. AuditSystemAccess(context.queryUserId(), true, "Submitted %s", wuid.str());
  2786. }
  2787. void WsWuHelpers::submitWsWorkunit(IEspContext& context, const char *wuid, const char* cluster, const char* snapshot, int maxruntime, bool compile, bool resetWorkflow, bool resetVariables,
  2788. const char *paramXml, IArrayOf<IConstNamedValue> *variables, IArrayOf<IConstNamedValue> *debugs, IArrayOf<IConstApplicationValue> *applications)
  2789. {
  2790. Owned<IWorkUnitFactory> factory = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  2791. Owned<IConstWorkUnit> cw = factory->openWorkUnit(wuid);
  2792. if(!cw)
  2793. throw MakeStringException(ECLWATCH_CANNOT_OPEN_WORKUNIT,"Cannot open workunit %s.",wuid);
  2794. return submitWsWorkunit(context, cw, cluster, snapshot, maxruntime, compile, resetWorkflow, resetVariables, paramXml, variables, debugs, applications);
  2795. }
  2796. void WsWuHelpers::copyWsWorkunit(IEspContext &context, IWorkUnit &wu, const char *srcWuid)
  2797. {
  2798. Owned<IWorkUnitFactory> factory = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  2799. Owned<IConstWorkUnit> src(factory->openWorkUnit(srcWuid));
  2800. queryExtendedWU(&wu)->copyWorkUnit(src, false);
  2801. SCMStringBuffer token;
  2802. wu.setSecurityToken(createToken(wu.queryWuid(), context.queryUserId(), context.queryPassword(), token).str());
  2803. wu.commit();
  2804. }
  2805. void WsWuHelpers::runWsWorkunit(IEspContext &context, StringBuffer &wuid, const char *srcWuid, const char *cluster, const char *paramXml,
  2806. IArrayOf<IConstNamedValue> *variables, IArrayOf<IConstNamedValue> *debugs, IArrayOf<IConstApplicationValue> *applications)
  2807. {
  2808. NewWsWorkunit wu(context);
  2809. wuid.set(wu->queryWuid());
  2810. copyWsWorkunit(context, *wu, srcWuid);
  2811. wu.clear();
  2812. submitWsWorkunit(context, wuid.str(), cluster, NULL, 0, false, true, true, paramXml, variables, debugs, applications);
  2813. }
  2814. void WsWuHelpers::runWsWorkunit(IEspContext &context, IConstWorkUnit *cw, const char *srcWuid, const char *cluster, const char *paramXml,
  2815. IArrayOf<IConstNamedValue> *variables, IArrayOf<IConstNamedValue> *debugs, IArrayOf<IConstApplicationValue> *applications)
  2816. {
  2817. WorkunitUpdate wu(&cw->lock());
  2818. copyWsWorkunit(context, *wu, srcWuid);
  2819. wu.clear();
  2820. submitWsWorkunit(context, cw, cluster, NULL, 0, false, true, true, paramXml, variables, debugs, applications);
  2821. }
  2822. IException * WsWuHelpers::noteException(IWorkUnit *wu, IException *e, ErrorSeverity level)
  2823. {
  2824. if (wu)
  2825. {
  2826. Owned<IWUException> we = wu->createException();
  2827. StringBuffer s;
  2828. we->setExceptionMessage(e->errorMessage(s).str());
  2829. we->setExceptionSource("WsWorkunits");
  2830. we->setSeverity(level);
  2831. if (level==SeverityError)
  2832. wu->setState(WUStateFailed);
  2833. }
  2834. return e;
  2835. }
  2836. StringBuffer & WsWuHelpers::resolveQueryWuid(StringBuffer &wuid, const char *queryset, const char *query, bool notSuspended, IWorkUnit *wu)
  2837. {
  2838. Owned<IPropertyTree> qs = getQueryRegistry(queryset, true);
  2839. if (!qs)
  2840. throw noteException(wu, MakeStringException(ECLWATCH_QUERYSET_NOT_FOUND, "QuerySet '%s' not found", queryset));
  2841. Owned<IPropertyTree> q = resolveQueryAlias(qs, query);
  2842. if (!q)
  2843. throw noteException(wu, MakeStringException(ECLWATCH_QUERYID_NOT_FOUND, "Query '%s/%s' not found", queryset, query));
  2844. if (notSuspended && q->getPropBool("@suspended"))
  2845. throw noteException(wu, MakeStringException(ECLWATCH_QUERY_SUSPENDED, "Query '%s/%s' is suspended", queryset, query));
  2846. return wuid.append(q->queryProp("@wuid"));
  2847. }
  2848. void WsWuHelpers::runWsWuQuery(IEspContext &context, IConstWorkUnit *cw, const char *queryset, const char *query,
  2849. const char *cluster, const char *paramXml, IArrayOf<IConstApplicationValue> *applications)
  2850. {
  2851. StringBuffer srcWuid;
  2852. WorkunitUpdate wu(&cw->lock());
  2853. resolveQueryWuid(srcWuid, queryset, query, true, wu);
  2854. copyWsWorkunit(context, *wu, srcWuid);
  2855. wu.clear();
  2856. submitWsWorkunit(context, cw, cluster, NULL, 0, false, true, true, paramXml, NULL, NULL, applications);
  2857. }
  2858. void WsWuHelpers::runWsWuQuery(IEspContext &context, StringBuffer &wuid, const char *queryset, const char *query,
  2859. const char *cluster, const char *paramXml, IArrayOf<IConstApplicationValue> *applications)
  2860. {
  2861. StringBuffer srcWuid;
  2862. NewWsWorkunit wu(context);
  2863. wuid.set(wu->queryWuid());
  2864. resolveQueryWuid(srcWuid, queryset, query, true, wu);
  2865. copyWsWorkunit(context, *wu, srcWuid);
  2866. wu.clear();
  2867. submitWsWorkunit(context, wuid.str(), cluster, NULL, 0, false, true, true, paramXml, NULL, NULL, applications);
  2868. }
  2869. void WsWuHelpers::checkAndTrimWorkunit(const char* methodName, StringBuffer& input)
  2870. {
  2871. const char* trimmedInput = input.trim().str();
  2872. if (isEmpty(trimmedInput))
  2873. throw MakeStringException(ECLWATCH_INVALID_INPUT, "%s: Workunit ID not set", methodName);
  2874. if (!looksLikeAWuid(trimmedInput, 'W'))
  2875. throw MakeStringException(ECLWATCH_INVALID_INPUT, "%s: Invalid Workunit ID: %s", methodName, trimmedInput);
  2876. return;
  2877. }
  2878. }