ws_workunitsService.cpp 156 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #include "ws_workunitsService.hpp"
  14. #include "ws_fs.hpp"
  15. #include "jlib.hpp"
  16. #include "jflz.hpp"
  17. #include "daclient.hpp"
  18. #include "dalienv.hpp"
  19. #include "dadfs.hpp"
  20. #include "daaudit.hpp"
  21. #include "exception_util.hpp"
  22. #include "wujobq.hpp"
  23. #include "eventqueue.hpp"
  24. #include "fileview.hpp"
  25. #include "hqlerror.hpp"
  26. #include "sacmd.hpp"
  27. #include "wuwebview.hpp"
  28. #include "portlist.h"
  29. #include "dllserver.hpp"
  30. #include "schedulectrl.hpp"
  31. #include "scheduleread.hpp"
  32. #include "dadfs.hpp"
  33. #include "dfuwu.hpp"
  34. #include "thorplugin.hpp"
  35. #include "roxiecontrol.hpp"
  36. #include "package.h"
  37. #ifdef _USE_ZLIB
  38. #include "zcrypt.hpp"
  39. #endif
  40. #define ESP_WORKUNIT_DIR "workunits/"
  41. #define SDS_LOCK_TIMEOUT (5*60*1000) // 5 mins
  42. const unsigned CHECK_QUERY_STATUS_THREAD_POOL_SIZE = 25;
  43. class ExecuteExistingQueryInfo
  44. {
  45. public:
  46. ExecuteExistingQueryInfo(IConstWorkUnit *cw)
  47. {
  48. const char *name = cw->queryJobName();
  49. const char *div = strchr(name, '.');
  50. if (div)
  51. {
  52. queryset.set(name, div-name);
  53. query.set(div+1);
  54. }
  55. }
  56. public:
  57. StringAttr queryset;
  58. StringAttr query;
  59. };
  60. typedef enum _WuActionType
  61. {
  62. ActionDelete=0,
  63. ActionProtect,
  64. ActionAbort,
  65. ActionRestore,
  66. ActionEventSchedule,
  67. ActionEventDeschedule,
  68. ActionChangeState,
  69. ActionPause,
  70. ActionPauseNow,
  71. ActionResume,
  72. ActionUnknown
  73. } WsWuActionType;
  74. void setActionResult(const char* wuid, int action, const char* result, StringBuffer& strAction, IArrayOf<IConstWUActionResult>* results)
  75. {
  76. if (!results || !wuid || !*wuid || !result || !*result)
  77. return;
  78. switch(action)
  79. {
  80. case ActionDelete:
  81. {
  82. strAction = "Delete";
  83. break;
  84. }
  85. case ActionProtect:
  86. {
  87. strAction = "Protect";
  88. break;
  89. }
  90. case ActionAbort:
  91. {
  92. strAction = "Abort";
  93. break;
  94. }
  95. case ActionRestore:
  96. {
  97. strAction = "Restore";
  98. break;
  99. }
  100. case ActionEventSchedule:
  101. {
  102. strAction = "EventSchedule";
  103. break;
  104. }
  105. case ActionEventDeschedule:
  106. {
  107. strAction = "EventDeschedule";
  108. break;
  109. }
  110. case ActionChangeState:
  111. {
  112. strAction = "ChangeState";
  113. break;
  114. }
  115. case ActionPause:
  116. {
  117. strAction = "Pause";
  118. break;
  119. }
  120. case ActionPauseNow:
  121. {
  122. strAction = "PauseNow";
  123. break;
  124. }
  125. case ActionResume:
  126. {
  127. strAction = "Resume";
  128. break;
  129. }
  130. default:
  131. {
  132. strAction = "Unknown";
  133. break;
  134. }
  135. }
  136. Owned<IEspWUActionResult> res = createWUActionResult("", "");
  137. res->setWuid(wuid);
  138. res->setAction(strAction.str());
  139. res->setResult(result);
  140. results->append(*res.getClear());
  141. }
  142. bool doAction(IEspContext& context, StringArray& wuids, int action, IProperties* params, IArrayOf<IConstWUActionResult>* results)
  143. {
  144. if (!wuids.length())
  145. return true;
  146. Owned<IWorkUnitFactory> factory = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  147. bool bAllSuccess = true;
  148. for(aindex_t i=0; i<wuids.length();i++)
  149. {
  150. StringBuffer strAction;
  151. StringBuffer wuidStr = wuids.item(i);
  152. const char* wuid = wuidStr.trim().str();
  153. if (isEmpty(wuid))
  154. {
  155. WARNLOG("Empty Workunit ID");
  156. continue;
  157. }
  158. try
  159. {
  160. if (!looksLikeAWuid(wuid, 'W'))
  161. throw MakeStringException(ECLWATCH_INVALID_INPUT, "Invalid Workunit ID: %s", wuid);
  162. if ((action == ActionRestore) || (action == ActionEventDeschedule))
  163. {
  164. switch(action)
  165. {
  166. case ActionRestore:
  167. {
  168. SocketEndpoint ep;
  169. if (params->hasProp("sashaServerIP"))
  170. ep.set(params->queryProp("sashaServerIP"), params->getPropInt("sashaServerPort"));
  171. else
  172. getSashaNode(ep);
  173. Owned<ISashaCommand> cmd = createSashaCommand();
  174. cmd->setAction(SCA_RESTORE);
  175. cmd->addId(wuid);
  176. Owned<INode> node = createINode(ep);
  177. if (!node)
  178. throw MakeStringException(ECLWATCH_INODE_NOT_FOUND,"INode not found.");
  179. StringBuffer s;
  180. if (!cmd->send(node, 1*60*1000))
  181. throw MakeStringException(ECLWATCH_CANNOT_CONNECT_ARCHIVE_SERVER,"Cannot connect to Archive server at %s.", ep.getUrlStr(s).str());
  182. if (cmd->numIds()==0)
  183. throw MakeStringException(ECLWATCH_CANNOT_UPDATE_WORKUNIT,"Could not Archive/restore %s",wuid);
  184. StringBuffer reply;
  185. cmd->getId(0,reply);
  186. AuditSystemAccess(context.queryUserId(), true, "Updated %s", wuid);
  187. ensureWsWorkunitAccess(context, wuid, SecAccess_Write);
  188. break;
  189. }
  190. case ActionEventDeschedule:
  191. if (!context.validateFeatureAccess(OWN_WU_ACCESS, SecAccess_Full, false)
  192. || !context.validateFeatureAccess(OTHERS_WU_ACCESS, SecAccess_Full, false))
  193. ensureWsWorkunitAccess(context, wuid, SecAccess_Full);
  194. descheduleWorkunit(wuid);
  195. AuditSystemAccess(context.queryUserId(), true, "Updated %s", wuid);
  196. break;
  197. }
  198. }
  199. else
  200. {
  201. Owned<IWorkUnitFactory> factory = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  202. Owned<IConstWorkUnit> cw = factory->openWorkUnit(wuid, false);
  203. if(!cw)
  204. throw MakeStringException(ECLWATCH_CANNOT_OPEN_WORKUNIT,"Cannot open workunit %s.",wuid);
  205. if ((action == ActionDelete) && (cw->getState() == WUStateWait))
  206. throw MakeStringException(ECLWATCH_CANNOT_DELETE_WORKUNIT,"Cannot delete a workunit which is in a 'Wait' status.");
  207. switch(action)
  208. {
  209. case ActionPause:
  210. {
  211. ensureWsWorkunitAccess(context, *cw, SecAccess_Full);
  212. WorkunitUpdate wu(&cw->lock());
  213. wu->setAction(WUActionPause);
  214. break;
  215. }
  216. case ActionPauseNow:
  217. {
  218. ensureWsWorkunitAccess(context, *cw, SecAccess_Full);
  219. WorkunitUpdate wu(&cw->lock());
  220. wu->setAction(WUActionPauseNow);
  221. break;
  222. }
  223. case ActionResume:
  224. {
  225. ensureWsWorkunitAccess(context, *cw, SecAccess_Full);
  226. WorkunitUpdate wu(&cw->lock());
  227. wu->setAction(WUActionResume);
  228. break;
  229. }
  230. case ActionDelete:
  231. ensureWsWorkunitAccess(context, *cw, SecAccess_Full);
  232. {
  233. int state = cw->getState();
  234. switch (state)
  235. {
  236. case WUStateWait:
  237. case WUStateAborted:
  238. case WUStateCompleted:
  239. case WUStateFailed:
  240. case WUStateArchived:
  241. case WUStateCompiled:
  242. case WUStateUploadingFiles:
  243. break;
  244. default:
  245. {
  246. WorkunitUpdate wu(&cw->lock());
  247. wu->setState(WUStateFailed);
  248. }
  249. }
  250. cw.clear();
  251. factory->deleteWorkUnit(wuid);
  252. AuditSystemAccess(context.queryUserId(), true, "Deleted %s", wuid);
  253. }
  254. break;
  255. case ActionAbort:
  256. ensureWsWorkunitAccess(context, *cw, SecAccess_Full);
  257. {
  258. if (cw->getState() == WUStateWait)
  259. {
  260. WorkunitUpdate wu(&cw->lock());
  261. wu->deschedule();
  262. wu->setState(WUStateAborted);
  263. }
  264. else
  265. secAbortWorkUnit(wuid, *context.querySecManager(), *context.queryUser());
  266. AuditSystemAccess(context.queryUserId(), true, "Aborted %s", wuid);
  267. }
  268. break;
  269. case ActionProtect:
  270. cw->protect(!params || params->getPropBool("Protect",true));
  271. AuditSystemAccess(context.queryUserId(), true, "Updated %s", wuid);
  272. break;
  273. case ActionChangeState:
  274. {
  275. if (params)
  276. {
  277. WUState state = (WUState) params->getPropInt("State");
  278. if (state > WUStateUnknown && state < WUStateSize)
  279. {
  280. WorkunitUpdate wu(&cw->lock());
  281. wu->setState(state);
  282. AuditSystemAccess(context.queryUserId(), true, "Updated %s", wuid);
  283. }
  284. }
  285. }
  286. break;
  287. case ActionEventSchedule:
  288. {
  289. WorkunitUpdate wu(&cw->lock());
  290. wu->schedule();
  291. AuditSystemAccess(context.queryUserId(), true, "Updated %s", wuid);
  292. }
  293. break;
  294. }
  295. }
  296. setActionResult(wuid, action, "Success", strAction, results);
  297. }
  298. catch (IException *e)
  299. {
  300. bAllSuccess = false;
  301. StringBuffer eMsg;
  302. StringBuffer failedMsg("Failed: ");
  303. setActionResult(wuid, action, failedMsg.append(e->errorMessage(eMsg)).str(), strAction, results);
  304. WARNLOG("Failed to %s for workunit: %s, %s", strAction.str(), wuid, eMsg.str());
  305. AuditSystemAccess(context.queryUserId(), false, "Failed to %s %s", strAction.str(), wuid);
  306. e->Release();
  307. continue;
  308. }
  309. catch (...)
  310. {
  311. bAllSuccess = false;
  312. StringBuffer failedMsg;
  313. failedMsg.appendf("Unknown exception");
  314. setActionResult(wuid, action, failedMsg.str(), strAction, results);
  315. WARNLOG("Failed to %s for workunit: %s, %s", strAction.str(), wuid, failedMsg.str());
  316. AuditSystemAccess(context.queryUserId(), false, "Failed to %s %s", strAction.str(), wuid);
  317. continue;
  318. }
  319. }
  320. int timeToWait = 0;
  321. if (params)
  322. timeToWait = params->getPropInt("BlockTillFinishTimer");
  323. if (timeToWait != 0)
  324. {
  325. for(aindex_t i=0; i<wuids.length();i++)
  326. {
  327. const char* wuid=wuids.item(i);
  328. if (isEmpty(wuid))
  329. continue;
  330. waitForWorkUnitToComplete(wuid, timeToWait);
  331. }
  332. }
  333. return bAllSuccess;
  334. }
  335. static void checkUpdateQuerysetLibraries()
  336. {
  337. Owned<IRemoteConnection> globalLock = querySDS().connect("/QuerySets/", myProcessSession(), RTM_LOCK_WRITE|RTM_CREATE_QUERY, SDS_LOCK_TIMEOUT);
  338. if (!globalLock)
  339. return;
  340. IPropertyTree *root = globalLock->queryRoot();
  341. if (!root)
  342. return;
  343. Owned<IWorkUnitFactory> factory = getWorkUnitFactory();
  344. Owned<IPropertyTreeIterator> querySets = root->getElements("QuerySet");
  345. ForEach(*querySets)
  346. {
  347. IPropertyTree &querySet = querySets->query();
  348. if (querySet.hasProp("@updatedLibraries")) //only need to do this once, then publish and copy will keep up to date
  349. continue;
  350. Owned<IPropertyTreeIterator> queries = querySet.getElements("Query");
  351. ForEach(*queries)
  352. {
  353. IPropertyTree &query = queries->query();
  354. if (query.hasProp("@libCount"))
  355. continue;
  356. const char *wuid = query.queryProp("@wuid");
  357. if (!wuid || !*wuid)
  358. continue;
  359. Owned<IConstWorkUnit> cw = factory->openWorkUnit(wuid, false);
  360. if (!cw)
  361. continue;
  362. checkAddLibrariesToQueryEntry(&query, cw);
  363. }
  364. querySet.setPropBool("@updatedLibraries", true);
  365. }
  366. }
  367. MapStringTo<int> wuActionTable;
  368. void CWsWorkunitsEx::init(IPropertyTree *cfg, const char *process, const char *service)
  369. {
  370. if (!daliClientActive())
  371. {
  372. ERRLOG("No Dali Connection Active.");
  373. throw MakeStringException(-1, "No Dali Connection Active. Please Specify a Dali to connect to in you configuration file");
  374. }
  375. setPasswordsFromSDS();
  376. DBGLOG("Initializing %s service [process = %s]", service, process);
  377. checkUpdateQuerysetLibraries();
  378. refreshValidClusters();
  379. daliServers.set(cfg->queryProp("Software/EspProcess/@daliServers"));
  380. const char *computer = cfg->queryProp("Software/EspProcess/@computer");
  381. if (daliServers.isEmpty() || !computer || streq(computer, "localhost")) //otherwise can't assume environment "." netAddresses are the same as my address
  382. queryHostIP().getIpText(envLocalAddress);
  383. else
  384. {
  385. //a bit weird, but other netAddresses in the environment are not the same localhost as this server
  386. //use the address of the DALI
  387. const char *finger = daliServers.get();
  388. while (*finger && !strchr(":;,", *finger))
  389. envLocalAddress.append(*finger++);
  390. }
  391. wuActionTable.setValue("delete", ActionDelete);
  392. wuActionTable.setValue("abort", ActionAbort);
  393. wuActionTable.setValue("pausenow", ActionPauseNow);
  394. wuActionTable.setValue("pause", ActionPause);
  395. wuActionTable.setValue("resume", ActionResume);
  396. wuActionTable.setValue("protect", ActionProtect);
  397. wuActionTable.setValue("unprotect", ActionProtect);
  398. wuActionTable.setValue("restore", ActionRestore);
  399. wuActionTable.setValue("reschedule", ActionEventSchedule);
  400. wuActionTable.setValue("deschedule", ActionEventDeschedule);
  401. wuActionTable.setValue("settofailed", ActionChangeState);
  402. awusCacheMinutes = AWUS_CACHE_MIN_DEFAULT;
  403. VStringBuffer xpath("Software/EspProcess[@name=\"%s\"]/EspService[@name=\"%s\"]/AWUsCacheMinutes", process, service);
  404. cfg->getPropInt(xpath.str(), awusCacheMinutes);
  405. xpath.setf("Software/EspProcess[@name=\"%s\"]/EspService[@name=\"%s\"]/serverForArchivedECLWU/@netAddress", process, service);
  406. if (cfg->hasProp(xpath.str()))
  407. {
  408. sashaServerIp.set(cfg->queryProp(xpath.str()));
  409. xpath.setf("Software/EspProcess[@name=\"%s\"]/EspService[@name=\"%s\"]/serverForArchivedECLWU/@port", process, service);
  410. sashaServerPort = cfg->getPropInt(xpath.str(), DEFAULT_SASHA_PORT);
  411. }
  412. maxRequestEntityLength = cfg->getPropInt("Software[1]/EspProcess[1]/EspProtocol[@type='http_protocol'][1]/@maxRequestEntityLength");
  413. directories.set(cfg->queryPropTree("Software/Directories"));
  414. const char *name = cfg->queryProp("Software/EspProcess/@name");
  415. getConfigurationDirectory(directories, "query", "esp", name ? name : "esp", queryDirectory);
  416. recursiveCreateDirectory(queryDirectory.str());
  417. xpath.setf("Software/EspProcess[@name=\"%s\"]/EspBinding[@service=\"%s\"]/Authenticate", process, service);
  418. Owned<IPropertyTree> authCFG = cfg->getPropTree(xpath.str());
  419. if(authCFG)
  420. authMethod.set(authCFG->queryProp("@method"));
  421. dataCache.setown(new DataCache(DATA_SIZE));
  422. archivedWuCache.setown(new ArchivedWuCache(AWUS_CACHE_SIZE));
  423. //Create a folder for temporarily holding gzip files by WUResultBin()
  424. Owned<IFile> tmpdir = createIFile(TEMPZIPDIR);
  425. if(!tmpdir->exists())
  426. tmpdir->createDirectory();
  427. recursiveCreateDirectory(ESP_WORKUNIT_DIR);
  428. m_sched.start();
  429. filesInUse.subscribe();
  430. //Start thread pool
  431. xpath.setf("Software/EspProcess[@name=\"%s\"]/EspService[@name=\"%s\"]/ClusterQueryStateThreadPoolSize", process, service);
  432. Owned<CClusterQueryStateThreadFactory> threadFactory = new CClusterQueryStateThreadFactory();
  433. clusterQueryStatePool.setown(createThreadPool("CheckAndSetClusterQueryState Thread Pool", threadFactory, NULL,
  434. cfg->getPropInt(xpath.str(), CHECK_QUERY_STATUS_THREAD_POOL_SIZE)));
  435. }
  436. void CWsWorkunitsEx::refreshValidClusters()
  437. {
  438. validClusters.kill();
  439. Owned<IStringIterator> it = getTargetClusters(NULL, NULL);
  440. ForEach(*it)
  441. {
  442. SCMStringBuffer s;
  443. IStringVal &val = it->str(s);
  444. bool* found = validClusters.getValue(val.str());
  445. if (!found || !*found)
  446. validClusters.setValue(val.str(), true);
  447. }
  448. }
  449. bool CWsWorkunitsEx::isValidCluster(const char *cluster)
  450. {
  451. if (!cluster || !*cluster)
  452. return false;
  453. CriticalBlock block(crit);
  454. bool* found = validClusters.getValue(cluster);
  455. if (found && *found)
  456. return true;
  457. if (validateTargetClusterName(cluster))
  458. {
  459. refreshValidClusters();
  460. return true;
  461. }
  462. return false;
  463. }
  464. bool CWsWorkunitsEx::onWUCreate(IEspContext &context, IEspWUCreateRequest &req, IEspWUCreateResponse &resp)
  465. {
  466. try
  467. {
  468. if (!context.validateFeatureAccess(OWN_WU_ACCESS, SecAccess_Write, false))
  469. throw MakeStringException(ECLWATCH_ECL_WU_ACCESS_DENIED, "Failed to create workunit. Permission denied.");
  470. NewWsWorkunit wu(context);
  471. resp.updateWorkunit().setWuid(wu->queryWuid());
  472. AuditSystemAccess(context.queryUserId(), true, "Updated %s", wu->queryWuid());
  473. }
  474. catch(IException* e)
  475. {
  476. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  477. }
  478. return true;
  479. }
  480. static bool origValueChanged(const char *newValue, const char *origValue, StringBuffer &s, bool nillable=true)
  481. {
  482. if (!nillable && isEmpty(newValue))
  483. return false;
  484. if(newValue && origValue)
  485. {
  486. if (!streq(origValue, newValue))
  487. {
  488. s.append(newValue).trim();
  489. return true;
  490. }
  491. return false;
  492. }
  493. if (newValue)
  494. {
  495. s.append(newValue).trim();
  496. return true;
  497. }
  498. return (origValue!=NULL);
  499. }
  500. bool CWsWorkunitsEx::onWUUpdate(IEspContext &context, IEspWUUpdateRequest &req, IEspWUUpdateResponse &resp)
  501. {
  502. try
  503. {
  504. StringBuffer wuid = req.getWuid();
  505. WsWuHelpers::checkAndTrimWorkunit("WUUpdate", wuid);
  506. ensureWsWorkunitAccess(context, wuid.str(), SecAccess_Write);
  507. Owned<IWorkUnitFactory> factory = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  508. Owned<IConstWorkUnit> cw = factory->openWorkUnit(wuid.str(), false);
  509. if(!cw)
  510. throw MakeStringException(ECLWATCH_CANNOT_UPDATE_WORKUNIT,"Cannot open workunit %s.",wuid.str());
  511. if(req.getProtected() != req.getProtectedOrig())
  512. {
  513. cw->protect(req.getProtected());
  514. cw.clear();
  515. cw.setown(factory->openWorkUnit(wuid.str(), false));
  516. if(!cw)
  517. throw MakeStringException(ECLWATCH_CANNOT_UPDATE_WORKUNIT,"Cannot open workunit %s.",wuid.str());
  518. }
  519. if ((req.getState() == WUStateRunning)||(req.getState() == WUStateDebugPaused)||(req.getState() == WUStateDebugRunning))
  520. {
  521. WsWuInfo winfo(context, cw);
  522. winfo.getInfo(resp.updateWorkunit(), WUINFO_All);
  523. resp.setRedirectUrl(StringBuffer("/WsWorkunits/WUInfo?Wuid=").append(wuid).str());
  524. AuditSystemAccess(context.queryUserId(), true, "Updated %s", wuid.str());
  525. return true;
  526. }
  527. WorkunitUpdate wu(&cw->lock());
  528. if(!req.getState_isNull() && (req.getStateOrig_isNull() || req.getState() != req.getStateOrig()))
  529. {
  530. if (!req.getStateOrig_isNull() && cw->getState() != (WUState) req.getStateOrig())
  531. throw MakeStringException(ECLWATCH_CANNOT_UPDATE_WORKUNIT, "Cannot update workunit %s because its state has been changed internally. Please refresh the page and try again.", wuid.str());
  532. WUState state = (WUState) req.getState();
  533. if(state < WUStateSize)
  534. wu->setState(state);
  535. }
  536. StringBuffer s;
  537. if (origValueChanged(req.getJobname(), req.getJobnameOrig(), s))
  538. wu->setJobName(s.trim().str());
  539. if (origValueChanged(req.getDescription(), req.getDescriptionOrig(), s.clear()))
  540. wu->setDebugValue("description", (req.getDescription() && *req.getDescription()) ? s.trim().str() : NULL, true);
  541. double version = context.getClientVersion();
  542. if (version > 1.04)
  543. {
  544. if (origValueChanged(req.getClusterSelection(), req.getClusterOrig(), s.clear(), false))
  545. {
  546. if (!isValidCluster(s.str()))
  547. throw MakeStringException(ECLWATCH_INVALID_CLUSTER_NAME, "Invalid cluster name: %s", s.str());
  548. if (req.getState() == WUStateBlocked)
  549. switchWorkUnitQueue(wu.get(), s.str());
  550. else if ((req.getState() != WUStateSubmitted) && (req.getState() != WUStateRunning) && (req.getState() != WUStateDebugPaused) && (req.getState() != WUStateDebugRunning))
  551. wu->setClusterName(s.str());
  552. }
  553. }
  554. WsWuHelpers::setXmlParameters(wu, req.getXmlParams(), (req.getAction()==WUActionExecuteExisting));
  555. if (notEmpty(req.getQueryText()))
  556. {
  557. Owned<IWUQuery> query=wu->updateQuery();
  558. query->setQueryText(req.getQueryText());
  559. }
  560. if (version > 1.34 && notEmpty(req.getQueryMainDefinition()))
  561. {
  562. Owned<IWUQuery> query=wu->updateQuery();
  563. query->setQueryMainDefinition(req.getQueryMainDefinition());
  564. }
  565. if (!req.getResultLimit_isNull())
  566. wu->setResultLimit(req.getResultLimit());
  567. if (!req.getAction_isNull())
  568. {
  569. WUAction action = (WUAction) req.getAction();
  570. if(action < WUActionSize)
  571. wu->setAction(action);
  572. }
  573. if (!req.getPriorityClass_isNull())
  574. {
  575. WUPriorityClass priority = (WUPriorityClass) req.getPriorityClass();
  576. if(priority<PriorityClassSize)
  577. wu->setPriority(priority);
  578. }
  579. if (!req.getPriorityLevel_isNull())
  580. wu->setPriorityLevel(req.getPriorityLevel());
  581. if (origValueChanged(req.getScope(), req.getScopeOrig(), s.clear(), false))
  582. wu->setWuScope(s.str());
  583. ForEachItemIn(di, req.getDebugValues())
  584. {
  585. IConstDebugValue& item = req.getDebugValues().item(di);
  586. if (notEmpty(item.getName()))
  587. wu->setDebugValue(item.getName(), item.getValue(), true);
  588. }
  589. ForEachItemIn(ai, req.getApplicationValues())
  590. {
  591. IConstApplicationValue& item=req.getApplicationValues().item(ai);
  592. if(notEmpty(item.getApplication()) && notEmpty(item.getName()))
  593. wu->setApplicationValue(item.getApplication(), item.getName(), item.getValue(), true);
  594. }
  595. wu->commit();
  596. wu.clear();
  597. WsWuInfo winfo(context, cw);
  598. winfo.getInfo(resp.updateWorkunit(), WUINFO_All);
  599. StringBuffer thorSlaveIP;
  600. if (version > 1.24 && notEmpty(req.getThorSlaveIP()))
  601. thorSlaveIP = req.getThorSlaveIP();
  602. if (thorSlaveIP.length() > 0)
  603. {
  604. StringBuffer url;
  605. url.appendf("/WsWorkunits/WUInfo?Wuid=%s&ThorSlaveIP=%s", wuid.str(), thorSlaveIP.str());
  606. resp.setRedirectUrl(url.str());
  607. }
  608. else
  609. resp.setRedirectUrl(StringBuffer("/WsWorkunits/WUInfo?Wuid=").append(wuid).str());
  610. AuditSystemAccess(context.queryUserId(), true, "Updated %s", wuid.str());
  611. }
  612. catch(IException* e)
  613. {
  614. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  615. }
  616. return true;
  617. }
  618. bool CWsWorkunitsEx::onWUCreateAndUpdate(IEspContext &context, IEspWUUpdateRequest &req, IEspWUUpdateResponse &resp)
  619. {
  620. try
  621. {
  622. if (!context.validateFeatureAccess(OWN_WU_ACCESS, SecAccess_Write, false))
  623. throw MakeStringException(ECLWATCH_ECL_WU_ACCESS_DENIED, "Failed to create workunit. Permission denied.");
  624. NewWsWorkunit wu(context);
  625. req.setWuid(wu->queryWuid());
  626. }
  627. catch(IException* e)
  628. {
  629. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  630. }
  631. return onWUUpdate(context, req, resp);
  632. }
  633. static inline StringBuffer &appendUrlParameter(StringBuffer &url, const char *name, const char *value, bool &first)
  634. {
  635. if (notEmpty(value))
  636. {
  637. url.append(first ? '?' : '&').append(name).append('=').append(value);
  638. first=false;
  639. }
  640. return url;
  641. }
  642. bool CWsWorkunitsEx::onWUAction(IEspContext &context, IEspWUActionRequest &req, IEspWUActionResponse &resp)
  643. {
  644. try
  645. {
  646. StringBuffer sAction(req.getActionType());
  647. if (!sAction.length())
  648. throw MakeStringException(ECLWATCH_INVALID_INPUT,"Action not defined.");
  649. int *action=wuActionTable.getValue(sAction.toLowerCase().str());
  650. if (!action)
  651. throw MakeStringException(ECLWATCH_INVALID_INPUT,"Invalid Action '%s'.", sAction.str());
  652. Owned<IProperties> params = createProperties(true);
  653. params->setProp("BlockTillFinishTimer", req.getBlockTillFinishTimer());
  654. if (*action==ActionProtect)
  655. params->setProp("Protect", streq(sAction.str(), "protect"));
  656. if (*action==ActionChangeState && streq(sAction.str(), "settofailed"))
  657. params->setProp("State",4);
  658. if ((*action==ActionRestore) && !sashaServerIp.isEmpty())
  659. {
  660. params->setProp("sashaServerIP", sashaServerIp.get());
  661. params->setProp("sashaServerPort", sashaServerPort);
  662. }
  663. IArrayOf<IConstWUActionResult> results;
  664. if (doAction(context, req.getWuids(), *action, params, &results) && *action!=ActionDelete && checkRedirect(context))
  665. {
  666. StringBuffer redirect;
  667. if(req.getPageFrom() && strieq(req.getPageFrom(), "wuid"))
  668. redirect.append("/WsWorkunits/WUInfo?Wuid=").append(req.getWuids().item(0));
  669. else if (req.getPageFrom() && strieq(req.getPageFrom(), "scheduler"))
  670. {
  671. redirect.set("/WsWorkunits/WUShowScheduled");
  672. bool first=true;
  673. appendUrlParameter(redirect, "Cluster", req.getEventServer(), first);
  674. appendUrlParameter(redirect, "EventName", req.getEventName(), first);
  675. }
  676. else
  677. {
  678. redirect.append("/WsWorkunits/WUQuery");
  679. bool first=true;
  680. appendUrlParameter(redirect, "PageSize", req.getPageSize(), first);
  681. appendUrlParameter(redirect, "PageStartFrom", req.getCurrentPage(), first);
  682. appendUrlParameter(redirect, "Sortby", req.getSortby(), first);
  683. appendUrlParameter(redirect, "Descending", req.getDescending() ? "1" : "0", first);
  684. appendUrlParameter(redirect, "State", req.getState(), first);
  685. appendUrlParameter(redirect, "Cluster", req.getCluster(), first);
  686. appendUrlParameter(redirect, "Owner", req.getOwner(), first);
  687. appendUrlParameter(redirect, "StartDate", req.getStartDate(), first);
  688. appendUrlParameter(redirect, "EndDate", req.getEndDate(), first);
  689. appendUrlParameter(redirect, "ECL", req.getECL(), first);
  690. appendUrlParameter(redirect, "Jobname", req.getJobname(), first);
  691. }
  692. resp.setRedirectUrl(redirect.str());
  693. }
  694. else
  695. resp.setActionResults(results);
  696. }
  697. catch(IException* e)
  698. {
  699. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  700. }
  701. return true;
  702. }
  703. bool CWsWorkunitsEx::onWUDelete(IEspContext &context, IEspWUDeleteRequest &req, IEspWUDeleteResponse &resp)
  704. {
  705. try
  706. {
  707. IArrayOf<IConstWUActionResult> results;
  708. Owned<IProperties> params = createProperties(true);
  709. params->setProp("BlockTillFinishTimer", req.getBlockTillFinishTimer());
  710. if (!doAction(context,req.getWuids(), ActionDelete, params, &results))
  711. resp.setActionResults(results);
  712. }
  713. catch(IException* e)
  714. {
  715. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  716. }
  717. return true;
  718. }
  719. bool CWsWorkunitsEx::onWUAbort(IEspContext &context, IEspWUAbortRequest &req, IEspWUAbortResponse &resp)
  720. {
  721. try
  722. {
  723. IArrayOf<IConstWUActionResult> results;
  724. Owned<IProperties> params = createProperties(true);
  725. params->setProp("BlockTillFinishTimer", req.getBlockTillFinishTimer());
  726. if (!doAction(context,req.getWuids(), ActionAbort, params, &results))
  727. resp.setActionResults(results);
  728. }
  729. catch(IException* e)
  730. {
  731. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  732. }
  733. return true;
  734. }
  735. bool CWsWorkunitsEx::onWUProtect(IEspContext &context, IEspWUProtectRequest &req, IEspWUProtectResponse &resp)\
  736. {
  737. try
  738. {
  739. IArrayOf<IConstWUActionResult> results;
  740. Owned<IProperties> params(createProperties(true));
  741. params->setProp("Protect", req.getProtect());
  742. params->setProp("BlockTillFinishTimer", 0);
  743. if (!doAction(context,req.getWuids(), ActionProtect, params, &results))
  744. resp.setActionResults(results);
  745. }
  746. catch(IException* e)
  747. {
  748. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  749. }
  750. return true;
  751. }
  752. bool CWsWorkunitsEx::onWUResubmit(IEspContext &context, IEspWUResubmitRequest &req, IEspWUResubmitResponse &resp)
  753. {
  754. try
  755. {
  756. Owned<IMultiException> me = MakeMultiException();
  757. StringAttr wuid;
  758. StringArray wuids;
  759. double version = context.getClientVersion();
  760. IArrayOf<IEspResubmittedWU> resubmittedWUs;
  761. for(aindex_t i=0; i<req.getWuids().length();i++)
  762. {
  763. StringBuffer requestWuid = req.getWuids().item(i);
  764. WsWuHelpers::checkAndTrimWorkunit("WUResubmit", requestWuid);
  765. ensureWsWorkunitAccess(context, requestWuid.str(), SecAccess_Write);
  766. wuid.set(requestWuid.str());
  767. try
  768. {
  769. Owned<IWorkUnitFactory> factory = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  770. if(req.getCloneWorkunit() || req.getRecompile())
  771. {
  772. Owned<IConstWorkUnit> src(factory->openWorkUnit(wuid.str(), false));
  773. NewWsWorkunit wu(factory, context);
  774. wuid.set(wu->queryWuid());
  775. queryExtendedWU(wu)->copyWorkUnit(src, false);
  776. SCMStringBuffer token;
  777. wu->setSecurityToken(createToken(wuid.str(), context.queryUserId(), context.queryPassword(), token).str());
  778. }
  779. wuids.append(wuid.str());
  780. Owned<IConstWorkUnit> cw(factory->openWorkUnit(wuid.str(), false));
  781. if(!cw)
  782. throw MakeStringException(ECLWATCH_CANNOT_OPEN_WORKUNIT,"Cannot open workunit %s.",wuid.str());
  783. WsWuHelpers::submitWsWorkunit(context, cw, NULL, NULL, 0, req.getRecompile(), req.getResetWorkflow(), false);
  784. if (version < 1.40)
  785. continue;
  786. Owned<IEspResubmittedWU> resubmittedWU = createResubmittedWU();
  787. resubmittedWU->setWUID(wuid.str());
  788. if (!streq(requestWuid.str(), wuid.str()))
  789. resubmittedWU->setParentWUID(requestWuid.str());
  790. resubmittedWUs.append(*resubmittedWU.getClear());
  791. }
  792. catch (IException *E)
  793. {
  794. me->append(*E);
  795. }
  796. catch (...)
  797. {
  798. me->append(*MakeStringException(0,"Unknown exception submitting %s",wuid.str()));
  799. }
  800. }
  801. if(me->ordinality())
  802. throw me.getLink();
  803. int timeToWait = req.getBlockTillFinishTimer();
  804. if (timeToWait != 0)
  805. {
  806. for(aindex_t i=0; i<wuids.length(); i++)
  807. waitForWorkUnitToComplete(wuids.item(i), timeToWait);
  808. }
  809. if (version >= 1.40)
  810. resp.setWUs(resubmittedWUs);
  811. if(wuids.length()==1)
  812. {
  813. resp.setRedirectUrl(StringBuffer("/WsWorkunits/WUInfo?Wuid=").append(wuids.item(0)));
  814. }
  815. }
  816. catch(IException* e)
  817. {
  818. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  819. }
  820. return true;
  821. }
  822. bool CWsWorkunitsEx::onWUPushEvent(IEspContext &context, IEspWUPushEventRequest &req, IEspWUPushEventResponse &resp)
  823. {
  824. try
  825. {
  826. const char *name = req.getEventName();
  827. const char *text = req.getEventText();
  828. const char *target = NULL;
  829. if (notEmpty(name) && notEmpty(text))
  830. {
  831. Owned<IScheduleEventPusher> pusher(getScheduleEventPusher());
  832. pusher->push(name, text, target);
  833. StringBuffer redirect("/WsWorkunits/WUShowScheduled");
  834. bool first=true;
  835. appendUrlParameter(redirect, "PushEventName", name, first);
  836. appendUrlParameter(redirect, "PushEventText", text, first);
  837. resp.setRedirectUrl(redirect.str());
  838. return true;
  839. }
  840. }
  841. catch(IException* e)
  842. {
  843. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  844. }
  845. return false;
  846. }
  847. bool CWsWorkunitsEx::onWUSchedule(IEspContext &context, IEspWUScheduleRequest &req, IEspWUScheduleResponse &resp)
  848. {
  849. try
  850. {
  851. StringBuffer wuid = req.getWuid();
  852. WsWuHelpers::checkAndTrimWorkunit("WUSchedule", wuid);
  853. const char* cluster = req.getCluster();
  854. if (isEmpty(cluster))
  855. throw MakeStringException(ECLWATCH_INVALID_INPUT,"No Cluster defined.");
  856. if (!isValidCluster(cluster))
  857. throw MakeStringException(ECLWATCH_INVALID_CLUSTER_NAME, "Invalid cluster name: %s", cluster);
  858. Owned<IWorkUnitFactory> factory = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  859. WorkunitUpdate wu(factory->updateWorkUnit(wuid.str()));
  860. ensureWsWorkunitAccess(context, *wu.get(), SecAccess_Write);
  861. switch(wu->getState())
  862. {
  863. case WUStateDebugPaused:
  864. case WUStateDebugRunning:
  865. case WUStateRunning:
  866. case WUStateAborting:
  867. case WUStateBlocked:
  868. throw MakeStringException(ECLWATCH_CANNOT_SCHEDULE_WORKUNIT, "Cannot schedule the workunit. Workunit state is '%s'.", wu->queryStateDesc());
  869. }
  870. wu->clearExceptions();
  871. wu->setClusterName(cluster);
  872. if (notEmpty(req.getWhen()))
  873. {
  874. WsWuDateTime dt;
  875. dt.setString(req.getWhen());
  876. wu->setTimeScheduled(dt);
  877. }
  878. if(notEmpty(req.getSnapshot()))
  879. wu->setSnapshot(req.getSnapshot());
  880. wu->setState(WUStateScheduled);
  881. if (req.getMaxRunTime())
  882. wu->setDebugValueInt("maxRunTime", req.getMaxRunTime(), true);
  883. SCMStringBuffer token;
  884. wu->setSecurityToken(createToken(wuid.str(), context.queryUserId(), context.queryPassword(), token).str());
  885. AuditSystemAccess(context.queryUserId(), true, "Scheduled %s", wuid.str());
  886. }
  887. catch(IException* e)
  888. {
  889. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  890. }
  891. return true;
  892. }
  893. bool CWsWorkunitsEx::onWUSubmit(IEspContext &context, IEspWUSubmitRequest &req, IEspWUSubmitResponse &resp)
  894. {
  895. try
  896. {
  897. StringBuffer wuid = req.getWuid();
  898. WsWuHelpers::checkAndTrimWorkunit("WUSubmit", wuid);
  899. const char *cluster = req.getCluster();
  900. if (isEmpty(cluster))
  901. throw MakeStringException(ECLWATCH_INVALID_INPUT,"No Cluster defined.");
  902. if (!isValidCluster(cluster))
  903. throw MakeStringException(ECLWATCH_INVALID_CLUSTER_NAME, "Invalid cluster name: %s", cluster);
  904. Owned<IWorkUnitFactory> factory = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  905. Owned<IConstWorkUnit> cw = factory->openWorkUnit(wuid.str(), false);
  906. if(!cw)
  907. throw MakeStringException(ECLWATCH_CANNOT_OPEN_WORKUNIT,"Cannot open workunit %s.",wuid.str());
  908. if (cw->getAction()==WUActionExecuteExisting)
  909. {
  910. ExecuteExistingQueryInfo info(cw);
  911. if (info.queryset.isEmpty() || info.query.isEmpty())
  912. {
  913. WorkunitUpdate wu(&cw->lock());
  914. throw WsWuHelpers::noteException(wu, MakeStringException(ECLWATCH_INVALID_INPUT,"Queryset and/or query not specified"));
  915. }
  916. WsWuHelpers::runWsWuQuery(context, cw, info.queryset.str(), info.query.str(), cluster, NULL);
  917. }
  918. else
  919. WsWuHelpers::submitWsWorkunit(context, cw, cluster, req.getSnapshot(), req.getMaxRunTime(), true, false, false);
  920. if (req.getBlockTillFinishTimer() != 0)
  921. waitForWorkUnitToComplete(wuid.str(), req.getBlockTillFinishTimer());
  922. resp.setRedirectUrl(StringBuffer("/WsWorkunits/WUInfo?Wuid=").append(wuid).str());
  923. }
  924. catch(IException* e)
  925. {
  926. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  927. }
  928. return true;
  929. }
  930. ErrorSeverity checkGetExceptionSeverity(CWUExceptionSeverity severity)
  931. {
  932. switch (severity)
  933. {
  934. case CWUExceptionSeverity_INFO:
  935. return SeverityInformation;
  936. case CWUExceptionSeverity_WARNING:
  937. return SeverityWarning;
  938. case CWUExceptionSeverity_ERROR:
  939. return SeverityError;
  940. case CWUExceptionSeverity_ALERT:
  941. return SeverityAlert;
  942. }
  943. throw MakeStringExceptionDirect(ECLWATCH_INVALID_INPUT,"invalid exception severity");
  944. }
  945. bool CWsWorkunitsEx::onWURun(IEspContext &context, IEspWURunRequest &req, IEspWURunResponse &resp)
  946. {
  947. try
  948. {
  949. const char *cluster = req.getCluster();
  950. if (notEmpty(cluster) && !isValidCluster(cluster))
  951. throw MakeStringException(ECLWATCH_INVALID_CLUSTER_NAME, "Invalid cluster name: %s", cluster);
  952. StringBuffer wuidStr = req.getWuid();
  953. const char* runWuid = wuidStr.trim().str();
  954. StringBuffer wuid;
  955. ErrorSeverity severity = checkGetExceptionSeverity(req.getExceptionSeverity());
  956. if (runWuid && *runWuid)
  957. {
  958. if (!looksLikeAWuid(runWuid, 'W'))
  959. throw MakeStringException(ECLWATCH_INVALID_INPUT, "Invalid Workunit ID: %s", runWuid);
  960. if (req.getCloneWorkunit())
  961. WsWuHelpers::runWsWorkunit(context, wuid, runWuid, cluster, req.getInput(), &req.getVariables(), &req.getDebugValues());
  962. else
  963. {
  964. WsWuHelpers::submitWsWorkunit(context, runWuid, cluster, NULL, 0, false, true, true, req.getInput(), &req.getVariables(), &req.getDebugValues());
  965. wuid.set(runWuid);
  966. }
  967. }
  968. else if (notEmpty(req.getQuerySet()) && notEmpty(req.getQuery()))
  969. WsWuHelpers::runWsWuQuery(context, wuid, req.getQuerySet(), req.getQuery(), cluster, req.getInput());
  970. else
  971. throw MakeStringException(ECLWATCH_MISSING_PARAMS,"Workunit or Query required");
  972. int timeToWait = req.getWait();
  973. if (timeToWait != 0)
  974. waitForWorkUnitToComplete(wuid.str(), timeToWait);
  975. Owned<IWorkUnitFactory> factory = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  976. Owned<IConstWorkUnit> cw = factory->openWorkUnit(wuid.str(), false);
  977. if (!cw)
  978. throw MakeStringException(ECLWATCH_CANNOT_UPDATE_WORKUNIT,"Cannot open workunit %s.", wuid.str());
  979. resp.setState(cw->queryStateDesc());
  980. resp.setWuid(wuid.str());
  981. switch (cw->getState())
  982. {
  983. case WUStateCompleted:
  984. case WUStateFailed:
  985. case WUStateUnknown:
  986. {
  987. SCMStringBuffer result;
  988. unsigned flags = WorkUnitXML_SeverityTags;
  989. if (req.getNoRootTag())
  990. flags |= WorkUnitXML_NoRoot;
  991. getFullWorkUnitResultsXML(context.queryUserId(), context.queryPassword(), cw.get(), result, flags, severity);
  992. resp.setResults(result.str());
  993. break;
  994. }
  995. default:
  996. break;
  997. }
  998. }
  999. catch(IException* e)
  1000. {
  1001. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  1002. }
  1003. return true;
  1004. }
  1005. bool CWsWorkunitsEx::onWUWaitCompiled(IEspContext &context, IEspWUWaitRequest &req, IEspWUWaitResponse &resp)
  1006. {
  1007. try
  1008. {
  1009. StringBuffer wuid = req.getWuid();
  1010. WsWuHelpers::checkAndTrimWorkunit("WUWaitCompiled", wuid);
  1011. secWaitForWorkUnitToCompile(wuid.str(), *context.querySecManager(), *context.queryUser(), req.getWait());
  1012. Owned<IWorkUnitFactory> factory = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  1013. Owned<IConstWorkUnit> cw = factory->openWorkUnit(wuid.str(), false);
  1014. if(!cw)
  1015. throw MakeStringException(ECLWATCH_CANNOT_OPEN_WORKUNIT,"Cannot open workunit %s.",wuid.str());
  1016. resp.setStateID(cw->getState());
  1017. }
  1018. catch(IException* e)
  1019. {
  1020. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  1021. }
  1022. return true;
  1023. }
  1024. bool CWsWorkunitsEx::onWUWaitComplete(IEspContext &context, IEspWUWaitRequest &req, IEspWUWaitResponse &resp)
  1025. {
  1026. try
  1027. {
  1028. StringBuffer wuid = req.getWuid();
  1029. WsWuHelpers::checkAndTrimWorkunit("WUWaitComplete", wuid);
  1030. resp.setStateID(secWaitForWorkUnitToComplete(wuid.str(), *context.querySecManager(), *context.queryUser(), req.getWait(), req.getReturnOnWait()));
  1031. }
  1032. catch(IException* e)
  1033. {
  1034. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  1035. }
  1036. return true;
  1037. }
  1038. bool CWsWorkunitsEx::onWUCDebug(IEspContext &context, IEspWUDebugRequest &req, IEspWUDebugResponse &resp)
  1039. {
  1040. try
  1041. {
  1042. StringBuffer wuid = req.getWuid();
  1043. WsWuHelpers::checkAndTrimWorkunit("WUCDebug", wuid);
  1044. StringBuffer result;
  1045. secDebugWorkunit(wuid.str(), *context.querySecManager(), *context.queryUser(), req.getCommand(), result);
  1046. resp.setResult(result);
  1047. }
  1048. catch(IException* e)
  1049. {
  1050. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  1051. }
  1052. return true;
  1053. }
  1054. bool CWsWorkunitsEx::onWUSyntaxCheckECL(IEspContext &context, IEspWUSyntaxCheckRequest &req, IEspWUSyntaxCheckResponse &resp)
  1055. {
  1056. try
  1057. {
  1058. Owned<IWorkUnitFactory> factory = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  1059. NewWsWorkunit wu(factory, context);
  1060. wu->setAction(WUActionCheck);
  1061. if(notEmpty(req.getModuleName()) && notEmpty(req.getAttributeName()))
  1062. {
  1063. wu->setApplicationValue("SyntaxCheck", "ModuleName", req.getModuleName(), true);
  1064. wu->setApplicationValue("SyntaxCheck", "AttributeName", req.getAttributeName(), true);
  1065. }
  1066. ForEachItemIn(di, req.getDebugValues())
  1067. {
  1068. IConstDebugValue& item=req.getDebugValues().item(di);
  1069. if(notEmpty(item.getName()))
  1070. wu->setDebugValue(item.getName(), item.getValue(), true);
  1071. }
  1072. wu.setQueryText(req.getECL());
  1073. StringAttr wuid(wu->queryWuid()); // NB queryWuid() not valid after workunit,clear()
  1074. wu->commit();
  1075. wu.clear();
  1076. WsWuHelpers::submitWsWorkunit(context, wuid.str(), req.getCluster(), req.getSnapshot(), 0, true, false, false);
  1077. waitForWorkUnitToComplete(wuid.str(), req.getTimeToWait());
  1078. Owned<IConstWorkUnit> cw(factory->openWorkUnit(wuid.str(), false));
  1079. WsWUExceptions errors(*cw);
  1080. resp.setErrors(errors);
  1081. cw.clear();
  1082. factory->deleteWorkUnit(wuid.str());
  1083. }
  1084. catch(IException* e)
  1085. {
  1086. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  1087. }
  1088. return true;
  1089. }
  1090. bool CWsWorkunitsEx::onWUCompileECL(IEspContext &context, IEspWUCompileECLRequest &req, IEspWUCompileECLResponse &resp)
  1091. {
  1092. try
  1093. {
  1094. ensureWsCreateWorkunitAccess(context);
  1095. Owned<IWorkUnitFactory> factory = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  1096. NewWsWorkunit wu(factory, context);
  1097. if(req.getIncludeComplexity())
  1098. {
  1099. wu->setAction(WUActionCompile);
  1100. wu->setDebugValueInt("calculateComplexity",1,true);
  1101. }
  1102. else
  1103. wu->setAction(WUActionCheck);
  1104. if(req.getModuleName() && req.getAttributeName())
  1105. {
  1106. wu->setApplicationValue("SyntaxCheck","ModuleName",req.getModuleName(),true);
  1107. wu->setApplicationValue("SyntaxCheck","AttributeName",req.getAttributeName(),true);
  1108. }
  1109. if(req.getIncludeDependencies())
  1110. wu->setApplicationValueInt("SyntaxCheck","IncludeDependencies",1,true);
  1111. wu.setQueryText(req.getECL());
  1112. StringAttr wuid(wu->queryWuid()); // NB queryWuid() not valid after workunit,clear() StringAttr wuid(wu->queryWuid());
  1113. WsWuHelpers::submitWsWorkunit(context, wuid.str(), req.getCluster(), req.getSnapshot(), 0, true, false, false);
  1114. waitForWorkUnitToComplete(wuid.str(),req.getTimeToWait());
  1115. Owned<IConstWorkUnit> cw = factory->openWorkUnit(wuid.str(), false);
  1116. SCMStringBuffer s;
  1117. cw->getDebugValue("__Calculated__Complexity__",s);
  1118. if(s.length())
  1119. resp.setComplexity(s.str());
  1120. WsWUExceptions errors(*cw);
  1121. resp.setErrors(errors);
  1122. if(!errors.ErrCount())
  1123. {
  1124. IArrayOf<IEspWUECLAttribute> dependencies;
  1125. for(unsigned count=1;;count++)
  1126. {
  1127. SCMStringBuffer xml;
  1128. cw->getApplicationValue("SyntaxCheck",StringBuffer("Dependency").append(count).str(),xml);
  1129. if(!xml.length())
  1130. break;
  1131. Owned<IPropertyTree> dep=createPTreeFromXMLString(xml.str(), ipt_caseInsensitive);
  1132. if(!dep)
  1133. continue;
  1134. Owned<IEspWUECLAttribute> att = createWUECLAttribute("","");
  1135. att->setModuleName(dep->queryProp("@module"));
  1136. att->setAttributeName(dep->queryProp("@name"));
  1137. int flags = dep->getPropInt("@flags",0);
  1138. if(flags & ob_locked)
  1139. {
  1140. if(flags & ob_lockedself)
  1141. att->setIsCheckedOut(true);
  1142. else
  1143. att->setIsLocked(true);
  1144. }
  1145. if(flags & ob_sandbox)
  1146. att->setIsSandbox(true);
  1147. if(flags & ob_orphaned)
  1148. att->setIsOrphaned(true);
  1149. dependencies.append(*att.getLink());
  1150. }
  1151. resp.setDependencies(dependencies);
  1152. }
  1153. cw.clear();
  1154. factory->deleteWorkUnit(wuid.str());
  1155. }
  1156. catch(IException* e)
  1157. {
  1158. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  1159. }
  1160. return true;
  1161. }
  1162. bool CWsWorkunitsEx::onWUGetDependancyTrees(IEspContext& context, IEspWUGetDependancyTreesRequest& req, IEspWUGetDependancyTreesResponse& resp)
  1163. {
  1164. try
  1165. {
  1166. DBGLOG("WUGetDependancyTrees");
  1167. unsigned int timeMilliSec = 500;
  1168. Owned<IWorkUnitFactory> factory = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  1169. NewWsWorkunit wu(factory, context);
  1170. wu->setAction(WUActionCheck);
  1171. if (notEmpty(req.getCluster()))
  1172. wu->setClusterName(req.getCluster());
  1173. if (notEmpty(req.getSnapshot()))
  1174. wu->setSnapshot(req.getSnapshot());
  1175. wu->setDebugValue("gatherDependenciesSelection",notEmpty(req.getItems()) ? req.getItems() : NULL,true);
  1176. if (context.getClientVersion() > 1.12)
  1177. {
  1178. wu->setDebugValueInt("gatherDependencies", 1, true);
  1179. const char *timeout = req.getTimeoutMilliSec();
  1180. if (notEmpty(timeout))
  1181. {
  1182. const char *finger = timeout;
  1183. while (*finger)
  1184. {
  1185. if (!isdigit(*finger++))
  1186. throw MakeStringException(ECLWATCH_INVALID_INPUT, "Incorrect timeout value");
  1187. }
  1188. timeMilliSec = atol(timeout);
  1189. }
  1190. }
  1191. StringAttr wuid(wu->queryWuid()); // NB queryWuid() not valid after workunit,clear()
  1192. wu->commit();
  1193. wu.clear();
  1194. ensureWsWorkunitAccess(context, wuid.str(), SecAccess_Read);
  1195. WsWuHelpers::submitWsWorkunit(context, wuid.str(), req.getCluster(), req.getSnapshot(), 0, true, false, false);
  1196. int state = waitForWorkUnitToComplete(wuid.str(), timeMilliSec);
  1197. Owned<IConstWorkUnit> cw = factory->openWorkUnit(wuid.str(), false);
  1198. WsWUExceptions errors(*cw);
  1199. resp.setErrors(errors);
  1200. MemoryBuffer temp;
  1201. MemoryBuffer2IDataVal xmlresult(temp);
  1202. Owned<IConstWUResult> result = cw->getResultBySequence(0);
  1203. if (result)
  1204. {
  1205. result->getResultRaw(xmlresult, NULL, NULL);
  1206. resp.setDependancyTrees(temp);
  1207. }
  1208. wu.setown(&cw->lock());
  1209. wu->setState(WUStateAborted);
  1210. wu->commit();
  1211. wu.clear();
  1212. factory->deleteWorkUnit(wuid.str());
  1213. }
  1214. catch(IException* e)
  1215. {
  1216. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  1217. }
  1218. return true;
  1219. }
  1220. bool getWsWuInfoFromSasha(IEspContext &context, SocketEndpoint &ep, const char* wuid, IEspECLWorkunit *info)
  1221. {
  1222. Owned<INode> node = createINode(ep);
  1223. Owned<ISashaCommand> cmd = createSashaCommand();
  1224. cmd->addId(wuid);
  1225. cmd->setAction(SCA_GET);
  1226. if (!cmd->send(node, 1*60*1000))
  1227. {
  1228. StringBuffer url;
  1229. DBGLOG("Could not connect to Sasha server at %s", ep.getUrlStr(url).str());
  1230. throw MakeStringException(ECLWATCH_CANNOT_CONNECT_ARCHIVE_SERVER,"Cannot connect to archive server at %s.", url.str());
  1231. }
  1232. if (cmd->numIds()==0)
  1233. {
  1234. DBGLOG("Could not read archived workunit %s",wuid);
  1235. throw MakeStringException(ECLWATCH_CANNOT_GET_WORKUNIT,"Cannot read workunit %s.",wuid);
  1236. }
  1237. unsigned num = cmd->numResults();
  1238. if (num < 1)
  1239. return false;
  1240. StringBuffer res;
  1241. cmd->getResult(0, res);
  1242. if(res.length() < 1)
  1243. return false;
  1244. Owned<IPropertyTree> wpt = createPTreeFromXMLString(res.str());
  1245. if (!wpt)
  1246. return false;
  1247. const char * owner = wpt->queryProp("@submitID");
  1248. ensureWsWorkunitAccessByOwnerId(context, owner, SecAccess_Read);
  1249. info->setWuid(wuid);
  1250. info->setArchived(true);
  1251. if (notEmpty(owner))
  1252. info->setOwner(owner);
  1253. const char * state = wpt->queryProp("@state");
  1254. if (notEmpty(state))
  1255. info->setState(state);
  1256. const char * cluster = wpt->queryProp("@clusterName");
  1257. if (notEmpty(cluster))
  1258. info->setCluster(cluster);
  1259. if (context.querySecManager())
  1260. {
  1261. const char * scope = wpt->queryProp("@scope");
  1262. if (notEmpty(scope))
  1263. info->setScope(scope);
  1264. }
  1265. const char * jobName = wpt->queryProp("@jobName");
  1266. if (notEmpty(jobName))
  1267. info->setJobname(jobName);
  1268. const char * description = wpt->queryProp("Debug/description");
  1269. if (notEmpty(description))
  1270. info->setDescription(description);
  1271. const char * queryText = wpt->queryProp("Query/Text");
  1272. if (notEmpty(queryText))
  1273. info->updateQuery().setText(queryText);
  1274. const char * protectedWU = wpt->queryProp("@protected");
  1275. info->setProtected((protectedWU && *protectedWU!='0'));
  1276. return true;
  1277. }
  1278. #define WUDETAILS_REFRESH_MINS 1
  1279. void getArchivedWUInfo(IEspContext &context, const char* sashaServerIP, unsigned sashaServerPort, const char *wuid, IEspWUInfoResponse &resp)
  1280. {
  1281. SocketEndpoint ep;
  1282. if (sashaServerIP && *sashaServerIP)
  1283. ep.set(sashaServerIP, sashaServerPort);
  1284. else
  1285. getSashaNode(ep);
  1286. if (getWsWuInfoFromSasha(context, ep, wuid, &resp.updateWorkunit()))
  1287. {
  1288. resp.setCanCompile(false);
  1289. return;
  1290. }
  1291. throw MakeStringException(ECLWATCH_CANNOT_GET_WORKUNIT, "Cannot find workunit %s.", wuid);
  1292. return;
  1293. }
  1294. #define WUDETAILS_REFRESH_MINS 1
  1295. bool CWsWorkunitsEx::onWUInfo(IEspContext &context, IEspWUInfoRequest &req, IEspWUInfoResponse &resp)
  1296. {
  1297. try
  1298. {
  1299. StringBuffer wuid = req.getWuid();
  1300. WsWuHelpers::checkAndTrimWorkunit("WUInfo", wuid);
  1301. double version = context.getClientVersion();
  1302. if (req.getType() && strieq(req.getType(), "archived workunits"))
  1303. getArchivedWUInfo(context, sashaServerIp.get(), sashaServerPort, wuid.str(), resp);
  1304. else
  1305. {
  1306. try
  1307. {
  1308. //The access is checked here because getArchivedWUInfo() has its own access check.
  1309. ensureWsWorkunitAccess(context, wuid.str(), SecAccess_Read);
  1310. unsigned flags=0;
  1311. if (req.getTruncateEclTo64k())
  1312. flags|=WUINFO_TruncateEclTo64k;
  1313. if (req.getIncludeExceptions())
  1314. flags|=WUINFO_IncludeExceptions;
  1315. if (req.getIncludeGraphs())
  1316. flags|=WUINFO_IncludeGraphs;
  1317. if (req.getIncludeSourceFiles())
  1318. flags|=WUINFO_IncludeSourceFiles;
  1319. if (req.getIncludeResults())
  1320. flags|=WUINFO_IncludeResults;
  1321. if (req.getIncludeVariables())
  1322. flags|=WUINFO_IncludeVariables;
  1323. if (req.getIncludeTimers())
  1324. flags|=WUINFO_IncludeTimers;
  1325. if (req.getIncludeDebugValues())
  1326. flags|=WUINFO_IncludeDebugValues;
  1327. if (req.getIncludeApplicationValues())
  1328. flags|=WUINFO_IncludeApplicationValues;
  1329. if (req.getIncludeWorkflows())
  1330. flags|=WUINFO_IncludeWorkflows;
  1331. if (!req.getSuppressResultSchemas())
  1332. flags|=WUINFO_IncludeEclSchemas;
  1333. if (req.getIncludeXmlSchemas())
  1334. flags|=WUINFO_IncludeXmlSchema;
  1335. if (req.getIncludeResultsViewNames())
  1336. flags|=WUINFO_IncludeResultsViewNames;
  1337. if (req.getIncludeResourceURLs())
  1338. flags|=WUINFO_IncludeResourceURLs;
  1339. WsWuInfo winfo(context, wuid.str());
  1340. winfo.getInfo(resp.updateWorkunit(), flags);
  1341. if (req.getIncludeResultsViewNames()||req.getIncludeResourceURLs()||(version >= 1.50))
  1342. {
  1343. StringArray views, urls;
  1344. winfo.getResourceInfo(views, urls, WUINFO_IncludeResultsViewNames|WUINFO_IncludeResourceURLs);
  1345. IEspECLWorkunit& eclWU = resp.updateWorkunit();
  1346. if (req.getIncludeResultsViewNames())
  1347. resp.setResultViews(views);
  1348. if (req.getIncludeResourceURLs())
  1349. eclWU.setResourceURLs(urls);
  1350. if (version >= 1.50)
  1351. {
  1352. eclWU.setResultViewCount(views.length());
  1353. eclWU.setResourceURLCount(urls.length());
  1354. }
  1355. }
  1356. }
  1357. catch (IException *e)
  1358. {
  1359. if (e->errorCode() != ECLWATCH_CANNOT_OPEN_WORKUNIT)
  1360. throw e;
  1361. getArchivedWUInfo(context, sashaServerIp.get(), sashaServerPort, wuid.str(), resp);
  1362. e->Release();
  1363. }
  1364. switch (resp.getWorkunit().getStateID())
  1365. {
  1366. case WUStateCompiling:
  1367. case WUStateCompiled:
  1368. case WUStateScheduled:
  1369. case WUStateSubmitted:
  1370. case WUStateRunning:
  1371. case WUStateAborting:
  1372. case WUStateWait:
  1373. case WUStateUploadingFiles:
  1374. case WUStateDebugPaused:
  1375. case WUStateDebugRunning:
  1376. resp.setAutoRefresh(WUDETAILS_REFRESH_MINS);
  1377. break;
  1378. case WUStateBlocked:
  1379. resp.setAutoRefresh(WUDETAILS_REFRESH_MINS*5);
  1380. break;
  1381. }
  1382. resp.setCanCompile(notEmpty(context.queryUserId()));
  1383. if (version > 1.24 && notEmpty(req.getThorSlaveIP()))
  1384. resp.setThorSlaveIP(req.getThorSlaveIP());
  1385. resp.setSecMethod(authMethod.get());
  1386. }
  1387. }
  1388. catch(IException* e)
  1389. {
  1390. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  1391. }
  1392. return true;
  1393. }
  1394. bool CWsWorkunitsEx::onWUInfoDetails(IEspContext &context, IEspWUInfoRequest &req, IEspWUInfoResponse &resp)
  1395. {
  1396. return onWUInfo(context, req, resp);
  1397. }
  1398. bool CWsWorkunitsEx::onWUResultView(IEspContext &context, IEspWUResultViewRequest &req, IEspWUResultViewResponse &resp)
  1399. {
  1400. StringBuffer wuid = req.getWuid();
  1401. WsWuHelpers::checkAndTrimWorkunit("WUResultView", wuid);
  1402. ensureWsWorkunitAccess(context, wuid.str(), SecAccess_Read);
  1403. Owned<IWuWebView> wv = createWuWebView(wuid.str(), NULL, NULL, getCFD(), true);
  1404. StringBuffer html;
  1405. wv->renderSingleResult(req.getViewName(), req.getResultName(), html);
  1406. resp.setResult(html.str());
  1407. resp.setResult_mimetype("text/html");
  1408. return true;
  1409. }
  1410. void doWUQueryBySingleWuid(IEspContext &context, const char *wuid, IEspWUQueryResponse &resp)
  1411. {
  1412. Owned<IEspECLWorkunit> info= createECLWorkunit("","");
  1413. WsWuInfo winfo(context, wuid);
  1414. winfo.getCommon(*info, 0);
  1415. IArrayOf<IEspECLWorkunit> results;
  1416. results.append(*info.getClear());
  1417. resp.setWorkunits(results);
  1418. resp.setPageSize(1);
  1419. resp.setCount(1);
  1420. }
  1421. void doWUQueryByFile(IEspContext &context, const char *logicalFile, IEspWUQueryResponse &resp)
  1422. {
  1423. StringBuffer wuid;
  1424. getWuidFromLogicalFileName(context, logicalFile, wuid);
  1425. if (!wuid.length())
  1426. throw MakeStringException(ECLWATCH_CANNOT_GET_WORKUNIT,"Cannot find the workunit for file %s.", logicalFile);
  1427. Owned<IWorkUnitFactory> factory = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  1428. Owned<IConstWorkUnit> cw= factory->openWorkUnit(wuid.str(), false);
  1429. if (!cw)
  1430. throw MakeStringException(ECLWATCH_CANNOT_OPEN_WORKUNIT,"Cannot find the workunit for file %s.", logicalFile);
  1431. if (getWsWorkunitAccess(context, *cw) < SecAccess_Read)
  1432. throw MakeStringException(ECLWATCH_ECL_WU_ACCESS_DENIED,"Cannot access the workunit for file %s.",logicalFile);
  1433. doWUQueryBySingleWuid(context, wuid.str(), resp);
  1434. resp.setFirst(false);
  1435. resp.setPageSize(1);
  1436. resp.setCount(1);
  1437. }
  1438. void doWUQueryByXPath(IEspContext &context, IEspWUQueryRequest & req, IEspWUQueryResponse & resp)
  1439. {
  1440. IArrayOf<IEspECLWorkunit> results;
  1441. WsWuSearch wlist(context,req.getOwner(),req.getState(),req.getCluster(),req.getStartDate(),req.getEndDate(),req.getECL(),req.getJobname(),req.getApplicationName(),req.getApplicationKey(),req.getApplicationData());
  1442. int count=(int)req.getPageSize();
  1443. if (!count)
  1444. count=100;
  1445. if (wlist.getSize() < 1)
  1446. {
  1447. resp.setNumWUs(0);
  1448. return;
  1449. }
  1450. if (wlist.getSize() < count)
  1451. count = (int) wlist.getSize() - 1;
  1452. WsWuSearch::iterator begin, end;
  1453. if(notEmpty(req.getAfter()))
  1454. {
  1455. begin=wlist.locate(req.getAfter());
  1456. end=min(begin+count,wlist.end());
  1457. }
  1458. else if (notEmpty(req.getBefore()))
  1459. {
  1460. end=wlist.locate(req.getBefore());
  1461. begin=max(end-count,wlist.begin());
  1462. }
  1463. else
  1464. {
  1465. begin=wlist.begin();
  1466. end=min(begin+count,wlist.end());
  1467. }
  1468. if(begin>wlist.begin() && begin<wlist.end())
  1469. resp.setCurrent(begin->c_str());
  1470. if (context.getClientVersion() > 1.02)
  1471. {
  1472. resp.setPageStartFrom(begin - wlist.begin() + 1);
  1473. resp.setNumWUs((int)wlist.getSize());
  1474. resp.setCount(end - begin);
  1475. }
  1476. if(end<wlist.end())
  1477. resp.setNext(end->c_str());
  1478. for(;begin!=end;begin++)
  1479. {
  1480. Owned<IEspECLWorkunit> info = createECLWorkunit("","");
  1481. WsWuInfo winfo(context, begin->c_str());
  1482. winfo.getCommon(*info, 0);
  1483. results.append(*info.getClear());
  1484. }
  1485. resp.setPageSize(abs(count));
  1486. resp.setWorkunits(results);
  1487. return;
  1488. }
  1489. bool addWUQueryFilter(WUSortField *filters, unsigned short &count, MemoryBuffer &buff, const char *name, WUSortField value)
  1490. {
  1491. if (isEmpty(name))
  1492. return false;
  1493. filters[count++] = value;
  1494. buff.append(name);
  1495. return true;
  1496. }
  1497. bool addWUQueryFilterTime(WUSortField *filters, unsigned short &count, MemoryBuffer &buff, const char *stime, WUSortField value)
  1498. {
  1499. if (isEmpty(stime))
  1500. return false;
  1501. CDateTime dt;
  1502. dt.setString(stime, NULL, true);
  1503. unsigned year, month, day, hour, minute, second, nano;
  1504. dt.getDate(year, month, day, true);
  1505. dt.getTime(hour, minute, second, nano, true);
  1506. VStringBuffer wuid("W%4d%02d%02d-%02d%02d%02d",year,month,day,hour,minute,second);
  1507. filters[count++] = value;
  1508. buff.append(wuid.str());
  1509. return true;
  1510. }
  1511. bool addWUQueryFilterApplication(WUSortField *filters, unsigned short &count, MemoryBuffer &buff, const char *appname, const char *appkey, const char *appdata)
  1512. {
  1513. if (isEmpty(appname) && isEmpty(appkey) && isEmpty(appdata)) //no application filter
  1514. return false;
  1515. VStringBuffer path("Application/%s/%s", appname && *appname ? appname : "*", appkey && *appkey ? appkey : "*");
  1516. if(appdata && *appdata)
  1517. path.append("=?~\"").append(appdata).append("\"");
  1518. filters[count++] = WUSFcustom;
  1519. buff.append(path.str());
  1520. return true;
  1521. }
  1522. void doWUQueryWithSort(IEspContext &context, IEspWUQueryRequest & req, IEspWUQueryResponse & resp)
  1523. {
  1524. SecAccessFlags accessOwn;
  1525. SecAccessFlags accessOthers;
  1526. getUserWuAccessFlags(context, accessOwn, accessOthers, true);
  1527. double version = context.getClientVersion();
  1528. IArrayOf<IEspECLWorkunit> results;
  1529. int begin = 0;
  1530. unsigned int count = 100;
  1531. int pagesize = 100;
  1532. if (version > 1.01)
  1533. {
  1534. pagesize = (int)req.getPageSize();
  1535. if (!req.getCount_isNull())
  1536. pagesize = req.getCount();
  1537. if(pagesize < 1)
  1538. pagesize = 100;
  1539. begin = (int)req.getPageStartFrom();
  1540. }
  1541. else
  1542. {
  1543. count=(unsigned)req.getCount();
  1544. if(!count)
  1545. count=100;
  1546. if (notEmpty(req.getAfter()))
  1547. begin=atoi(req.getAfter());
  1548. else if (notEmpty(req.getBefore()))
  1549. begin=atoi(req.getBefore())-count;
  1550. if (begin < 0)
  1551. begin = 0;
  1552. pagesize = count;
  1553. }
  1554. WUSortField sortorder = (WUSortField) (WUSFwuid | WUSFreverse);
  1555. if (notEmpty(req.getSortby()))
  1556. {
  1557. const char *sortby = req.getSortby();
  1558. if (strieq(sortby, "Owner"))
  1559. sortorder = WUSFuser;
  1560. else if (strieq(sortby, "JobName"))
  1561. sortorder = WUSFjob;
  1562. else if (strieq(sortby, "Cluster"))
  1563. sortorder = WUSFcluster;
  1564. else if (strieq(sortby, "RoxieCluster"))
  1565. sortorder = WUSFroxiecluster;
  1566. else if (strieq(sortby, "Protected"))
  1567. sortorder = WUSFprotected;
  1568. else if (strieq(sortby, "State"))
  1569. sortorder = WUSFstate;
  1570. else if (strieq(sortby, "ClusterTime"))
  1571. sortorder = (WUSortField) (WUSFtotalthortime+WUSFnumeric);
  1572. else
  1573. sortorder = WUSFwuid;
  1574. sortorder = (WUSortField) (sortorder | WUSFnocase);
  1575. bool descending = req.getDescending();
  1576. if (descending)
  1577. sortorder = (WUSortField) (sortorder | WUSFreverse);
  1578. }
  1579. WUSortField filters[10];
  1580. unsigned short filterCount = 0;
  1581. MemoryBuffer filterbuf;
  1582. bool bDoubleCheckState = false;
  1583. if(req.getState() && *req.getState())
  1584. {
  1585. filters[filterCount++] = WUSFstate;
  1586. if (!strieq(req.getState(), "unknown"))
  1587. filterbuf.append(req.getState());
  1588. else
  1589. filterbuf.append("");
  1590. if (strieq(req.getState(), "submitted"))
  1591. bDoubleCheckState = true;
  1592. }
  1593. addWUQueryFilter(filters, filterCount, filterbuf, req.getWuid(), WUSFwildwuid);
  1594. addWUQueryFilter(filters, filterCount, filterbuf, req.getCluster(), WUSFcluster);
  1595. if(version > 1.07)
  1596. addWUQueryFilter(filters, filterCount, filterbuf, req.getRoxieCluster(), WUSFroxiecluster);
  1597. addWUQueryFilter(filters, filterCount, filterbuf, req.getLogicalFile(), (WUSortField) (WUSFfileread | WUSFnocase));
  1598. addWUQueryFilter(filters, filterCount, filterbuf, req.getOwner(), (WUSortField) (WUSFuser | WUSFnocase));
  1599. addWUQueryFilter(filters, filterCount, filterbuf, req.getJobname(), (WUSortField) (WUSFjob | WUSFnocase));
  1600. addWUQueryFilter(filters, filterCount, filterbuf, req.getECL(), (WUSortField) (WUSFecl | WUSFwild));
  1601. addWUQueryFilterTime(filters, filterCount, filterbuf, req.getStartDate(), WUSFwuid);
  1602. addWUQueryFilterTime(filters, filterCount, filterbuf, req.getEndDate(), WUSFwuidhigh);
  1603. if (version < 1.55)
  1604. addWUQueryFilterApplication(filters, filterCount, filterbuf, req.getApplicationName(), req.getApplicationKey(), req.getApplicationData());
  1605. else
  1606. {
  1607. IArrayOf<IConstApplicationValue>& applicationFilters = req.getApplicationValues();
  1608. ForEachItemIn(i, applicationFilters)
  1609. {
  1610. IConstApplicationValue &item = applicationFilters.item(i);
  1611. addWUQueryFilterApplication(filters, filterCount, filterbuf, item.getApplication(), item.getName(), item.getValue());
  1612. }
  1613. }
  1614. filters[filterCount] = WUSFterm;
  1615. __int64 cacheHint = 0;
  1616. if (!req.getCacheHint_isNull())
  1617. cacheHint = req.getCacheHint();
  1618. Owned<IWorkUnitFactory> factory = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  1619. unsigned numWUs;
  1620. Owned<IConstWorkUnitIterator> it = factory->getWorkUnitsSorted(sortorder, filters, filterbuf.bufferBase(), begin, pagesize+1, "", &cacheHint, &numWUs);
  1621. if (version >= 1.41)
  1622. resp.setCacheHint(cacheHint);
  1623. unsigned actualCount = 0;
  1624. ForEach(*it)
  1625. {
  1626. IConstWorkUnitInfo& cw = it->query();
  1627. if (chooseWuAccessFlagsByOwnership(context.queryUserId(), cw, accessOwn, accessOthers) < SecAccess_Read)
  1628. {
  1629. numWUs--;
  1630. continue;
  1631. }
  1632. if (bDoubleCheckState && (cw.getState() != WUStateSubmitted))
  1633. {
  1634. numWUs--;
  1635. continue;
  1636. }
  1637. const char* wuid = cw.queryWuid();
  1638. if (!looksLikeAWuid(wuid, 'W'))
  1639. {
  1640. numWUs--;
  1641. continue;
  1642. }
  1643. actualCount++;
  1644. Owned<IEspECLWorkunit> info = createECLWorkunit("","");
  1645. WsWuInfo winfo(context, wuid);
  1646. winfo.getCommon(*info, 0);
  1647. if (version >= 1.55)
  1648. winfo.getApplicationValues(*info, WUINFO_IncludeApplicationValues);
  1649. results.append(*info.getClear());
  1650. }
  1651. if (version > 1.02)
  1652. {
  1653. resp.setPageStartFrom(begin+1);
  1654. resp.setNumWUs(numWUs);
  1655. if (results.length() > (aindex_t)pagesize)
  1656. results.pop();
  1657. if(unsigned (begin + pagesize) < numWUs)
  1658. {
  1659. resp.setNextPage(begin + pagesize);
  1660. resp.setPageEndAt(begin + pagesize);
  1661. int last = begin + pagesize;
  1662. while (numWUs > (unsigned) last + pagesize)
  1663. last += pagesize;
  1664. resp.setLastPage(last);
  1665. }
  1666. else
  1667. {
  1668. resp.setNextPage(-1);
  1669. resp.setPageEndAt(numWUs);
  1670. }
  1671. if(begin > 0)
  1672. {
  1673. resp.setFirst(false);
  1674. if (begin - pagesize > 0)
  1675. resp.setPrevPage(begin - pagesize);
  1676. else
  1677. resp.setPrevPage(0);
  1678. }
  1679. resp.setPageSize(pagesize);
  1680. }
  1681. else
  1682. {
  1683. if(begin>0 && actualCount > 0)
  1684. {
  1685. char buf[10];
  1686. itoa(begin, buf, 10);
  1687. resp.setCurrent(buf);
  1688. }
  1689. if(count<actualCount)
  1690. {
  1691. char buf[10];
  1692. itoa(begin+count, buf, 10);
  1693. resp.setNext(buf);
  1694. resp.setNumWUs(numWUs);
  1695. if (results.length() > count)
  1696. results.pop();
  1697. }
  1698. if(begin == 0 && actualCount <= count)
  1699. resp.setFirst(false);
  1700. resp.setCount(count);
  1701. }
  1702. resp.setWorkunits(results);
  1703. return;
  1704. }
  1705. void doWUQueryFromArchive(IEspContext &context, const char* sashaServerIP, unsigned sashaServerPort,
  1706. ArchivedWuCache &archivedWuCache, unsigned cacheMinutes, IEspWUQueryRequest & req, IEspWUQueryResponse & resp)
  1707. {
  1708. class CArchivedWUsReader : public CInterface, implements IArchivedWUsReader
  1709. {
  1710. IEspContext& context;
  1711. IEspWUQueryRequest& req;
  1712. unsigned pageFrom, pageSize;
  1713. StringAttr sashaServerIP;
  1714. unsigned sashaServerPort;
  1715. unsigned cacheMinutes;
  1716. StringBuffer filterStr;
  1717. ArchivedWuCache& archivedWuCache;
  1718. unsigned numberOfWUsReturned;
  1719. bool hasMoreWU;
  1720. void readDateFilters(StringBuffer& from, StringBuffer& to)
  1721. {
  1722. CDateTime timeFrom, timeTo;
  1723. if(notEmpty(req.getEndDate()))
  1724. timeTo.setString(req.getEndDate(), NULL, true);
  1725. else
  1726. timeTo.setNow();
  1727. unsigned year, month, day, hour, minute, second, nano;
  1728. timeTo.getDate(year, month, day, true);
  1729. timeTo.getTime(hour, minute, second, nano, true);
  1730. to.setf("%4d%02d%02d%02d%02d", year, month, day, hour, minute);
  1731. if(!notEmpty(req.getStartDate()))
  1732. return;
  1733. timeFrom.setString(req.getStartDate(), NULL, true);
  1734. if (timeFrom >= timeTo)
  1735. return;
  1736. unsigned year0, month0, day0, hour0, minute0, second0, nano0;
  1737. timeFrom.getDate(year0, month0, day0, true);
  1738. timeFrom.getTime(hour0, minute0, second0, nano0, true);
  1739. from.setf("%4d%02d%02d%02d%02d", year0, month0, day0, hour0, minute0);
  1740. return;
  1741. }
  1742. bool addToFilterString(const char *name, const char *value)
  1743. {
  1744. if (isEmpty(name) || isEmpty(value))
  1745. return false;
  1746. if (filterStr.length())
  1747. filterStr.append(';');
  1748. filterStr.append(name).append("=").append(value);
  1749. return true;
  1750. }
  1751. bool addToFilterString(const char *name, unsigned value)
  1752. {
  1753. if (isEmpty(name))
  1754. return false;
  1755. if (filterStr.length())
  1756. filterStr.append(';');
  1757. filterStr.append(name).append("=").append(value);
  1758. return true;
  1759. }
  1760. void setFilterString()
  1761. {
  1762. addToFilterString("cluster", req.getCluster());
  1763. addToFilterString("owner", req.getOwner());
  1764. addToFilterString("jobName", req.getJobname());
  1765. addToFilterString("state", req.getState());
  1766. addToFilterString("timeFrom", req.getStartDate());
  1767. addToFilterString("timeTo", req.getEndDate());
  1768. addToFilterString("pageStart", pageFrom);
  1769. addToFilterString("pageSize", pageSize);
  1770. if (sashaServerIP && *sashaServerIP)
  1771. {
  1772. addToFilterString("sashaServerIP", sashaServerIP.get());
  1773. addToFilterString("sashaServerPort", sashaServerPort);
  1774. }
  1775. }
  1776. void setSashaCommand(INode* sashaserver, ISashaCommand* cmd)
  1777. {
  1778. cmd->setAction(SCA_LIST);
  1779. cmd->setOutputFormat("owner,jobname,cluster,state");
  1780. cmd->setOnline(false);
  1781. cmd->setArchived(true);
  1782. cmd->setStart(pageFrom);
  1783. cmd->setLimit(pageSize+1); //read an extra WU to check hasMoreWU
  1784. if (notEmpty(req.getCluster()))
  1785. cmd->setCluster(req.getCluster());
  1786. if (notEmpty(req.getOwner()))
  1787. cmd->setOwner(req.getOwner());
  1788. if (notEmpty(req.getJobname()))
  1789. cmd->setJobName(req.getJobname());
  1790. if (notEmpty(req.getState()))
  1791. cmd->setState(req.getState());
  1792. StringBuffer timeFrom, timeTo;
  1793. readDateFilters(timeFrom, timeTo);
  1794. if (timeFrom.length())
  1795. cmd->setAfter(timeFrom.str());
  1796. if (timeTo.length())
  1797. cmd->setBefore(timeTo.str());
  1798. return;
  1799. }
  1800. IEspECLWorkunit *createArchivedWUEntry(StringArray& wuDataArray, bool canAccess)
  1801. {
  1802. Owned<IEspECLWorkunit> info= createECLWorkunit("","");
  1803. const char* wuid = wuDataArray.item(0);
  1804. const char* owner = wuDataArray.item(1);
  1805. const char* jobName = wuDataArray.item(2);
  1806. const char* cluster = wuDataArray.item(3);
  1807. const char* state = wuDataArray.item(4);
  1808. info->setWuid(wuid);
  1809. if (!canAccess)
  1810. info->setState("<Hidden>");
  1811. else
  1812. {
  1813. if (notEmpty(owner))
  1814. info->setOwner(owner);
  1815. if (notEmpty(jobName))
  1816. info->setJobname(jobName);
  1817. if (notEmpty(cluster))
  1818. info->setCluster(cluster);
  1819. if (notEmpty(state))
  1820. info->setState(state);
  1821. }
  1822. return info.getClear();
  1823. }
  1824. static int compareWuids(IInterface * const *_a, IInterface * const *_b)
  1825. {
  1826. IEspECLWorkunit *a = *(IEspECLWorkunit **)_a;
  1827. IEspECLWorkunit *b = *(IEspECLWorkunit **)_b;
  1828. return strcmp(b->getWuid(), a->getWuid());
  1829. }
  1830. public:
  1831. IMPLEMENT_IINTERFACE_USING(CInterface);
  1832. CArchivedWUsReader(IEspContext& _context, const char* _sashaServerIP, unsigned _sashaServerPort, ArchivedWuCache& _archivedWuCache,
  1833. unsigned _cacheMinutes, unsigned _pageFrom, unsigned _pageSize, IEspWUQueryRequest& _req)
  1834. : context(_context), sashaServerIP(_sashaServerIP), sashaServerPort(_sashaServerPort),
  1835. archivedWuCache(_archivedWuCache), cacheMinutes(_cacheMinutes), pageFrom(_pageFrom), pageSize(_pageSize), req(_req)
  1836. {
  1837. hasMoreWU = false;
  1838. numberOfWUsReturned = 0;
  1839. }
  1840. void getArchivedWUs(IArrayOf<IEspECLWorkunit>& archivedWUs)
  1841. {
  1842. setFilterString();
  1843. Owned<ArchivedWuCacheElement> cachedResults = archivedWuCache.lookup(context, filterStr, "AddWhenAvailable", cacheMinutes);
  1844. if (cachedResults)
  1845. {
  1846. hasMoreWU = cachedResults->m_hasNextPage;
  1847. numberOfWUsReturned = cachedResults->numWUsReturned;
  1848. if (cachedResults->m_results.length())
  1849. {
  1850. ForEachItemIn(ai, cachedResults->m_results)
  1851. archivedWUs.append(*LINK(&cachedResults->m_results.item(ai)));
  1852. }
  1853. }
  1854. else
  1855. {
  1856. SocketEndpoint ep;
  1857. if (sashaServerIP && *sashaServerIP)
  1858. ep.set(sashaServerIP, sashaServerPort);
  1859. else
  1860. getSashaNode(ep);
  1861. Owned<INode> sashaserver = createINode(ep);
  1862. Owned<ISashaCommand> cmd = createSashaCommand();
  1863. setSashaCommand(sashaserver, cmd);
  1864. if (!cmd->send(sashaserver))
  1865. {
  1866. StringBuffer msg("Cannot connect to archive server at ");
  1867. sashaserver->endpoint().getUrlStr(msg);
  1868. throw MakeStringException(ECLWATCH_CANNOT_CONNECT_ARCHIVE_SERVER, "%s", msg.str());
  1869. }
  1870. numberOfWUsReturned = cmd->numIds();
  1871. hasMoreWU = (numberOfWUsReturned > pageSize);
  1872. if (hasMoreWU)
  1873. numberOfWUsReturned--;
  1874. if (numberOfWUsReturned > 0)
  1875. {
  1876. SecAccessFlags accessOwn, accessOthers;
  1877. getUserWuAccessFlags(context, accessOwn, accessOthers, true);
  1878. for (unsigned i=0; i<numberOfWUsReturned; i++)
  1879. {
  1880. const char *csline = cmd->queryId(i);
  1881. if (!csline || !*csline)
  1882. continue;
  1883. StringArray wuDataArray;
  1884. wuDataArray.appendList(csline, ",");
  1885. const char* wuid = wuDataArray.item(0);
  1886. if (isEmpty(wuid))
  1887. {
  1888. WARNLOG("Empty WUID in SCA_LIST response"); // JCS->KW - have u ever seen this happen?
  1889. continue;
  1890. }
  1891. const char* owner = wuDataArray.item(1);
  1892. bool canAccess = chooseWuAccessFlagsByOwnership(context.queryUserId(), owner, accessOwn, accessOthers) >= SecAccess_Read;
  1893. Owned<IEspECLWorkunit> info = createArchivedWUEntry(wuDataArray, canAccess);
  1894. archivedWUs.append(*info.getClear());
  1895. }
  1896. archivedWUs.sort(compareWuids);
  1897. archivedWuCache.add(filterStr, "AddWhenAvailable", hasMoreWU, numberOfWUsReturned, archivedWUs);
  1898. }
  1899. }
  1900. return;
  1901. };
  1902. bool getHasMoreWU() { return hasMoreWU; };
  1903. unsigned getNumberOfWUsReturned() { return numberOfWUsReturned; };
  1904. };
  1905. unsigned pageStart = (unsigned) req.getPageStartFrom();
  1906. unsigned pageSize = (unsigned) req.getPageSize();
  1907. if(pageSize < 1)
  1908. pageSize=500;
  1909. IArrayOf<IEspECLWorkunit> archivedWUs;
  1910. Owned<IArchivedWUsReader> archiveWUsReader = new CArchivedWUsReader(context, sashaServerIP, sashaServerPort, archivedWuCache,
  1911. cacheMinutes, pageStart, pageSize, req);
  1912. archiveWUsReader->getArchivedWUs(archivedWUs);
  1913. resp.setWorkunits(archivedWUs);
  1914. resp.setNumWUs(archiveWUsReader->getNumberOfWUsReturned());
  1915. resp.setType("archived only");
  1916. resp.setPageSize(pageSize);
  1917. resp.setPageStartFrom(pageStart+1);
  1918. resp.setPageEndAt(pageStart + archiveWUsReader->getNumberOfWUsReturned());
  1919. if(pageStart > 0)
  1920. { //This is not the first page;
  1921. resp.setFirst(false);
  1922. resp.setPrevPage((pageStart > pageSize) ? pageStart - pageSize: 0);
  1923. }
  1924. if (archiveWUsReader->getHasMoreWU())
  1925. resp.setNextPage(pageStart + pageSize);
  1926. return;
  1927. }
  1928. bool CWsWorkunitsEx::onWUQuery(IEspContext &context, IEspWUQueryRequest & req, IEspWUQueryResponse & resp)
  1929. {
  1930. try
  1931. {
  1932. StringBuffer wuidStr = req.getWuid();
  1933. const char* wuid = wuidStr.trim().str();
  1934. if (req.getType() && strieq(req.getType(), "archived workunits"))
  1935. doWUQueryFromArchive(context, sashaServerIp.get(), sashaServerPort, *archivedWuCache, awusCacheMinutes, req, resp);
  1936. else if(notEmpty(wuid) && looksLikeAWuid(wuid, 'W'))
  1937. doWUQueryBySingleWuid(context, wuid, resp);
  1938. else if (notEmpty(req.getLogicalFile()) && req.getLogicalFileSearchType() && strieq(req.getLogicalFileSearchType(), "Created"))
  1939. doWUQueryByFile(context, req.getLogicalFile(), resp);
  1940. else
  1941. doWUQueryWithSort(context, req, resp);
  1942. resp.setState(req.getState());
  1943. resp.setCluster(req.getCluster());
  1944. resp.setRoxieCluster(req.getRoxieCluster());
  1945. resp.setOwner(req.getOwner());
  1946. resp.setStartDate(req.getStartDate());
  1947. resp.setEndDate(req.getEndDate());
  1948. double version = context.getClientVersion();
  1949. StringBuffer basicQuery;
  1950. addToQueryString(basicQuery, "State", req.getState());
  1951. addToQueryString(basicQuery, "Cluster", req.getCluster());
  1952. if (version > 1.07)
  1953. addToQueryString(basicQuery, "RoxieCluster", req.getRoxieCluster());
  1954. addToQueryString(basicQuery, "Owner", req.getOwner());
  1955. addToQueryString(basicQuery, "StartDate", req.getStartDate());
  1956. addToQueryString(basicQuery, "EndDate", req.getEndDate());
  1957. if (version > 1.25 && req.getLastNDays() > -1)
  1958. addToQueryString(basicQuery, "LastNDays", StringBuffer().append(req.getLastNDays()).str());
  1959. addToQueryString(basicQuery, "ECL", req.getECL());
  1960. addToQueryString(basicQuery, "Jobname", req.getJobname());
  1961. addToQueryString(basicQuery, "Type", req.getType());
  1962. if (addToQueryString(basicQuery, "LogicalFile", req.getLogicalFile()))
  1963. addToQueryString(basicQuery, "LogicalFileSearchType", req.getLogicalFileSearchType());
  1964. resp.setFilters(basicQuery.str());
  1965. if (notEmpty(req.getSortby()) && !strstr(basicQuery.str(), StringBuffer(req.getSortby()).append('=').str()))
  1966. {
  1967. resp.setSortby(req.getSortby());
  1968. addToQueryString(basicQuery, "Sortby", req.getSortby());
  1969. if (req.getDescending())
  1970. {
  1971. resp.setDescending(req.getDescending());
  1972. addToQueryString(basicQuery, "Descending", "1");
  1973. }
  1974. }
  1975. resp.setBasicQuery(basicQuery.str());
  1976. StringBuffer s;
  1977. if(notEmpty(req.getECL()))
  1978. resp.setECL(Utils::url_encode(req.getECL(), s).str());
  1979. if(notEmpty(req.getJobname()))
  1980. resp.setJobname(Utils::url_encode(req.getJobname(), s.clear()).str());
  1981. }
  1982. catch(IException* e)
  1983. {
  1984. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  1985. }
  1986. return true;
  1987. }
  1988. void appendResultSet(MemoryBuffer& mb, INewResultSet* result, const char *name, __int64 start, unsigned& count, __int64& total, bool bin, bool xsd, ESPSerializationFormat fmt, const IProperties *xmlns)
  1989. {
  1990. if (!result)
  1991. return;
  1992. Owned<IResultSetCursor> cursor(result->createCursor());
  1993. total=result->getNumRows();
  1994. if(bin)
  1995. count = getResultBin(mb, result, (unsigned)start, count);
  1996. else
  1997. {
  1998. struct MemoryBuffer2IStringVal : public CInterface, implements IStringVal
  1999. {
  2000. MemoryBuffer2IStringVal(MemoryBuffer & _buffer) : buffer(_buffer) {}
  2001. IMPLEMENT_IINTERFACE;
  2002. virtual const char * str() const { UNIMPLEMENTED; }
  2003. virtual void set(const char *val) { buffer.append(strlen(val),val); }
  2004. virtual void clear() { } // support appending only
  2005. virtual void setLen(const char *val, unsigned length) { buffer.append(length, val); }
  2006. virtual unsigned length() const { return buffer.length(); };
  2007. MemoryBuffer & buffer;
  2008. } adaptor(mb);
  2009. if (fmt==ESPSerializationJSON)
  2010. count = getResultJSON(adaptor, result, name, (unsigned) start, count, (xsd) ? "myschema" : NULL);
  2011. else
  2012. count = getResultXml(adaptor, result, name, (unsigned) start, count, (xsd) ? "myschema" : NULL, xmlns);
  2013. }
  2014. }
  2015. INewResultSet* createFilteredResultSet(INewResultSet* result, IArrayOf<IConstNamedValue>* filterBy)
  2016. {
  2017. if (!result || !filterBy || !filterBy->length())
  2018. return NULL;
  2019. Owned<IFilteredResultSet> filter = result->createFiltered();
  2020. const IResultSetMetaData &meta = result->getMetaData();
  2021. unsigned columnCount = meta.getColumnCount();
  2022. ForEachItemIn(i, *filterBy)
  2023. {
  2024. IConstNamedValue &item = filterBy->item(i);
  2025. const char *name = item.getName();
  2026. const char *value = item.getValue();
  2027. if (!name || !*name || !value || !*value)
  2028. continue;
  2029. for(unsigned col = 0; col < columnCount; col++)
  2030. {
  2031. SCMStringBuffer scmbuf;
  2032. meta.getColumnLabel(scmbuf, col);
  2033. if (strieq(scmbuf.str(), name))
  2034. {
  2035. filter->addFilter(col, value);
  2036. break;
  2037. }
  2038. }
  2039. }
  2040. return filter->create();
  2041. }
  2042. void getWsWuResult(IEspContext &context, const char* wuid, const char *name, const char *logical, unsigned index, __int64 start,
  2043. unsigned& count, __int64& total, IStringVal& resname, bool bin, IArrayOf<IConstNamedValue>* filterBy, MemoryBuffer& mb,
  2044. WUState& wuState, bool xsd=true)
  2045. {
  2046. Owned<IWorkUnitFactory> factory = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  2047. Owned<IConstWorkUnit> cw = factory->openWorkUnit(wuid, false);
  2048. if(!cw)
  2049. throw MakeStringException(ECLWATCH_CANNOT_OPEN_WORKUNIT,"Cannot open workunit %s.",wuid);
  2050. Owned<IConstWUResult> result;
  2051. if (notEmpty(name))
  2052. result.setown(cw->getResultByName(name));
  2053. else if (notEmpty(logical))
  2054. {
  2055. Owned<IConstWUResultIterator> it = &cw->getResults();
  2056. ForEach(*it)
  2057. {
  2058. IConstWUResult &r = it->query();
  2059. SCMStringBuffer filename;
  2060. if(strieq(r.getResultLogicalName(filename).str(), logical))
  2061. {
  2062. result.setown(LINK(&r));
  2063. break;
  2064. }
  2065. }
  2066. }
  2067. else
  2068. result.setown(cw->getResultBySequence(index));
  2069. if (!result)
  2070. throw MakeStringException(ECLWATCH_CANNOT_GET_WU_RESULT,"Cannot open the workunit result.");
  2071. if (!resname.length())
  2072. result->getResultName(resname);
  2073. Owned<IResultSetFactory> resultSetFactory = getSecResultSetFactory(context.querySecManager(), context.queryUser(), context.queryUserId(), context.queryPassword());
  2074. SCMStringBuffer logicalName;
  2075. result->getResultLogicalName(logicalName);
  2076. Owned<INewResultSet> rs;
  2077. if (logicalName.length())
  2078. {
  2079. rs.setown(resultSetFactory->createNewFileResultSet(logicalName.str(), cw->queryClusterName())); //MORE is this wrong cluster?
  2080. }
  2081. else
  2082. rs.setown(resultSetFactory->createNewResultSet(result, wuid));
  2083. if (!filterBy || !filterBy->length())
  2084. appendResultSet(mb, rs, name, start, count, total, bin, xsd, context.getResponseFormat(), result->queryResultXmlns());
  2085. else
  2086. {
  2087. Owned<INewResultSet> filteredResult = createFilteredResultSet(rs, filterBy);
  2088. appendResultSet(mb, filteredResult, name, start, count, total, bin, xsd, context.getResponseFormat(), result->queryResultXmlns());
  2089. }
  2090. wuState = cw->getState();
  2091. }
  2092. void checkFileSizeLimit(unsigned long xmlSize, unsigned long sizeLimit)
  2093. {
  2094. if ((sizeLimit > 0) && (xmlSize > sizeLimit))
  2095. throw MakeStringException(ECLWATCH_CANNOT_OPEN_FILE,
  2096. "The file size (%ld bytes) exceeds the size limit (%ld bytes). You may set 'Option > 1' or use 'Download_XML' link to get compressed file.",
  2097. xmlSize, sizeLimit);
  2098. }
  2099. void openSaveFile(IEspContext &context, int opt, __int64 sizeLimit, const char* filename, const char* origMimeType, MemoryBuffer& buf, IEspWULogFileResponse &resp)
  2100. {
  2101. if (opt < 1)
  2102. {
  2103. checkFileSizeLimit(buf.length(), sizeLimit);
  2104. resp.setThefile(buf);
  2105. resp.setThefile_mimetype(origMimeType);
  2106. }
  2107. else if (opt < 2)
  2108. {
  2109. checkFileSizeLimit(buf.length(), sizeLimit);
  2110. StringBuffer headerStr("attachment;");
  2111. if (filename && *filename)
  2112. {
  2113. const char* pFileName = strrchr(filename, PATHSEPCHAR);
  2114. if (pFileName)
  2115. headerStr.appendf("filename=%s", pFileName+1);
  2116. else
  2117. headerStr.appendf("filename=%s", filename);
  2118. }
  2119. MemoryBuffer buf0;
  2120. unsigned i = 0;
  2121. char* p = (char*) buf.toByteArray();
  2122. while (i < buf.length())
  2123. {
  2124. if (p[0] != 10)
  2125. buf0.append(p[0]);
  2126. else
  2127. buf0.append(0x0d);
  2128. p++;
  2129. i++;
  2130. }
  2131. resp.setThefile(buf);
  2132. resp.setThefile_mimetype(origMimeType);
  2133. context.addCustomerHeader("Content-disposition", headerStr.str());
  2134. }
  2135. else
  2136. {
  2137. #ifndef _USE_ZLIB
  2138. throw MakeStringException(ECLWATCH_CANNOT_COMPRESS_DATA,"The data cannot be compressed.");
  2139. #else
  2140. StringBuffer fileNameStr, headerStr("attachment;");
  2141. if (notEmpty(filename))
  2142. {
  2143. fileNameStr.append(filename);
  2144. headerStr.append("filename=").append(filename).append((opt>2) ? ".gz" : ".zip");
  2145. }
  2146. else
  2147. fileNameStr.append("file");
  2148. StringBuffer ifname;
  2149. ifname.appendf("%s%sT%xAT%x", TEMPZIPDIR, PATHSEPSTR, (unsigned)(memsize_t)GetCurrentThreadId(), msTick()).append((opt>2)? "" : ".zip");
  2150. IZZIPor* Zipor = createZZIPor();
  2151. int ret = 0;
  2152. if (opt > 2)
  2153. ret = Zipor->gzipToFile(buf.length(), (void*)buf.toByteArray(), ifname.str());
  2154. else
  2155. ret = Zipor->zipToFile(buf.length(), (void*)buf.toByteArray(), fileNameStr.str(), ifname.str());
  2156. releaseIZ(Zipor);
  2157. if (ret < 0)
  2158. {
  2159. Owned<IFile> rFile = createIFile(ifname.str());
  2160. if (rFile->exists())
  2161. rFile->remove();
  2162. throw MakeStringException(ECLWATCH_CANNOT_COMPRESS_DATA,"The data cannot be compressed.");
  2163. }
  2164. Owned <IFile> rf = createIFile(ifname.str());
  2165. if (!rf->exists())
  2166. throw MakeStringException(ECLWATCH_CANNOT_COMPRESS_DATA,"The data cannot be compressed.");
  2167. MemoryBuffer out;
  2168. Owned <IFileIO> fio = rf->open(IFOread);
  2169. read(fio, 0, (size32_t) rf->size(), out);
  2170. resp.setThefile(out);
  2171. fio.clear();
  2172. rf->remove();
  2173. resp.setThefile_mimetype((opt > 2) ? "application/x-gzip" : "application/zip");
  2174. context.addCustomerHeader("Content-disposition", headerStr.str());
  2175. #endif
  2176. }
  2177. }
  2178. bool CWsWorkunitsEx::onWUFile(IEspContext &context,IEspWULogFileRequest &req, IEspWULogFileResponse &resp)
  2179. {
  2180. try
  2181. {
  2182. StringBuffer wuidStr = req.getWuid();
  2183. const char* wuidIn = wuidStr.trim().str();
  2184. if (wuidIn && *wuidIn)
  2185. {
  2186. if (!looksLikeAWuid(wuidIn, 'W'))
  2187. throw MakeStringException(ECLWATCH_INVALID_INPUT, "Invalid Workunit ID");
  2188. ensureWsWorkunitAccess(context, wuidIn, SecAccess_Read);
  2189. }
  2190. StringAttr wuid(wuidIn);
  2191. if (wuid.isEmpty() && notEmpty(req.getQuerySet()) && notEmpty(req.getQuery()))
  2192. {
  2193. Owned<IPropertyTree> registry = getQueryRegistry(req.getQuerySet(), false);
  2194. if (!registry)
  2195. throw MakeStringException(ECLWATCH_QUERYSET_NOT_FOUND, "Queryset %s not found", req.getQuerySet());
  2196. Owned<IPropertyTree> query = resolveQueryAlias(registry, req.getQuery());
  2197. if (!query)
  2198. throw MakeStringException(ECLWATCH_QUERYID_NOT_FOUND, "Query %s not found", req.getQuery());
  2199. resp.setQuerySet(req.getQuerySet());
  2200. resp.setQueryName(query->queryProp("@name"));
  2201. resp.setQueryId(query->queryProp("@id"));
  2202. wuid.set(query->queryProp("@wuid"));
  2203. }
  2204. int opt = req.getOption();
  2205. if (!wuid.isEmpty())
  2206. {
  2207. resp.setWuid(wuid.get());
  2208. MemoryBuffer mb;
  2209. WsWuInfo winfo(context, wuid);
  2210. if (strieq(File_ArchiveQuery, req.getType()))
  2211. {
  2212. winfo.getWorkunitArchiveQuery(mb);
  2213. openSaveFile(context, opt, req.getSizeLimit(), "ArchiveQuery.xml", HTTP_TYPE_APPLICATION_XML, mb, resp);
  2214. }
  2215. else if (strieq(File_Cpp,req.getType()) && notEmpty(req.getName()))
  2216. {
  2217. winfo.getWorkunitCpp(req.getName(), req.getDescription(), req.getIPAddress(),mb, opt > 0);
  2218. openSaveFile(context, opt, req.getSizeLimit(), req.getName(), HTTP_TYPE_TEXT_PLAIN, mb, resp);
  2219. }
  2220. else if (strieq(File_DLL,req.getType()))
  2221. {
  2222. StringBuffer name;
  2223. winfo.getWorkunitDll(name, mb);
  2224. resp.setFileName(name.str());
  2225. resp.setDaliServer(daliServers.get());
  2226. openSaveFile(context, opt, req.getSizeLimit(), req.getName(), HTTP_TYPE_OCTET_STREAM, mb, resp);
  2227. }
  2228. else if (strieq(File_Res,req.getType()))
  2229. {
  2230. winfo.getWorkunitResTxt(mb);
  2231. openSaveFile(context, opt, req.getSizeLimit(), "res.txt", HTTP_TYPE_TEXT_PLAIN, mb, resp);
  2232. }
  2233. else if (strncmp(req.getType(), File_ThorLog, 7) == 0)
  2234. {
  2235. winfo.getWorkunitThorLog(req.getName(), mb);
  2236. openSaveFile(context, opt, req.getSizeLimit(), "thormaster.log", HTTP_TYPE_TEXT_PLAIN, mb, resp);
  2237. }
  2238. else if (strieq(File_ThorSlaveLog,req.getType()))
  2239. {
  2240. StringBuffer logDir;
  2241. getConfigurationDirectory(directories, "log", "thor", req.getProcess(), logDir);
  2242. winfo.getWorkunitThorSlaveLog(req.getClusterGroup(), req.getIPAddress(), req.getLogDate(), logDir.str(), req.getSlaveNumber(), mb, false);
  2243. openSaveFile(context, opt, req.getSizeLimit(), "ThorSlave.log", HTTP_TYPE_TEXT_PLAIN, mb, resp);
  2244. }
  2245. else if (strieq(File_EclAgentLog,req.getType()))
  2246. {
  2247. winfo.getWorkunitEclAgentLog(req.getName(), req.getProcess(), mb);
  2248. openSaveFile(context, opt, req.getSizeLimit(), "eclagent.log", HTTP_TYPE_TEXT_PLAIN, mb, resp);
  2249. }
  2250. else if (strieq(File_XML,req.getType()) && notEmpty(req.getName()))
  2251. {
  2252. const char* name = req.getName();
  2253. const char* ptr = strrchr(name, '/');
  2254. if (ptr)
  2255. ptr++;
  2256. else
  2257. ptr = name;
  2258. winfo.getWorkunitAssociatedXml(name, req.getIPAddress(), req.getPlainText(), req.getDescription(), opt > 0, mb);
  2259. openSaveFile(context, opt, req.getSizeLimit(), ptr, HTTP_TYPE_APPLICATION_XML, mb, resp);
  2260. }
  2261. else if (strieq(File_XML,req.getType()) || strieq(File_WUECL,req.getType()))
  2262. {
  2263. StringBuffer mimeType, fileName;
  2264. if (strieq(File_WUECL,req.getType()))
  2265. {
  2266. fileName.setf("%s.ecl", wuid.get());
  2267. winfo.getWorkunitQueryShortText(mb);
  2268. mimeType.set(HTTP_TYPE_TEXT_PLAIN);
  2269. }
  2270. else
  2271. {
  2272. fileName.setf("%s.xml", wuid.get());
  2273. winfo.getWorkunitXml(req.getPlainText(), mb);
  2274. if (opt < 2)
  2275. {
  2276. const char* plainText = req.getPlainText();
  2277. if (plainText && (!stricmp(plainText, "yes")))
  2278. mimeType.set(HTTP_TYPE_TEXT_PLAIN);
  2279. else
  2280. mimeType.set(HTTP_TYPE_APPLICATION_XML);
  2281. }
  2282. else
  2283. {
  2284. mimeType.set(HTTP_TYPE_APPLICATION_XML);
  2285. }
  2286. }
  2287. openSaveFile(context, opt, req.getSizeLimit(), fileName.str(), mimeType.str(), mb, resp);
  2288. }
  2289. }
  2290. }
  2291. catch(IException* e)
  2292. {
  2293. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  2294. }
  2295. return true;
  2296. }
  2297. bool CWsWorkunitsEx::onWUResultBin(IEspContext &context,IEspWUResultBinRequest &req, IEspWUResultBinResponse &resp)
  2298. {
  2299. try
  2300. {
  2301. StringBuffer wuidStr = req.getWuid();
  2302. const char* wuidIn = wuidStr.trim().str();
  2303. if (wuidIn && *wuidIn)
  2304. {
  2305. if (!looksLikeAWuid(wuidIn, 'W'))
  2306. throw MakeStringException(ECLWATCH_INVALID_INPUT, "Invalid Workunit ID: %s", wuidIn);
  2307. ensureWsWorkunitAccess(context, wuidIn, SecAccess_Read);
  2308. }
  2309. MemoryBuffer mb;
  2310. __int64 total=0;
  2311. __int64 start = req.getStart() > 0 ? req.getStart() : 0;
  2312. unsigned count = req.getCount(), requested=count;
  2313. IArrayOf<IConstNamedValue>* filterBy = &req.getFilterBy();
  2314. SCMStringBuffer name;
  2315. WUState wuState = WUStateUnknown;
  2316. bool bin = (req.getFormat() && strieq(req.getFormat(),"raw"));
  2317. if (notEmpty(wuidIn) && notEmpty(req.getResultName()))
  2318. getWsWuResult(context, wuidIn, req.getResultName(), NULL, 0, start, count, total, name, bin, filterBy, mb, wuState);
  2319. else if (notEmpty(wuidIn) && (req.getSequence() >= 0))
  2320. getWsWuResult(context, wuidIn, NULL, NULL, req.getSequence(), start, count, total, name, bin,filterBy, mb, wuState);
  2321. else if (notEmpty(req.getLogicalName()))
  2322. {
  2323. const char* logicalName = req.getLogicalName();
  2324. StringBuffer wuid;
  2325. getWuidFromLogicalFileName(context, logicalName, wuid);
  2326. if (!wuid.length())
  2327. throw MakeStringException(ECLWATCH_CANNOT_GET_WORKUNIT,"Cannot find the workunit for file %s.",logicalName);
  2328. getWsWuResult(context, wuid.str(), NULL, logicalName, 0, start, count, total, name, bin, filterBy, mb, wuState);
  2329. }
  2330. else
  2331. throw MakeStringException(ECLWATCH_CANNOT_GET_WU_RESULT,"Cannot open the workunit result.");
  2332. if(stricmp(req.getFormat(),"xls")==0)
  2333. {
  2334. Owned<IProperties> params(createProperties());
  2335. params->setProp("showCount",0);
  2336. StringBuffer xml;
  2337. xml.append("<WUResultExcel><Result>").append(mb.length(), mb.toByteArray()).append("</Result></WUResultExcel>");
  2338. if (xml.length() > MAXXLSTRANSFER)
  2339. throw MakeStringException(ECLWATCH_TOO_BIG_DATA_SET, "The data set is too big to be converted to an Excel file. Please use the gzip link to download a compressed XML data file.");
  2340. StringBuffer xls;
  2341. xsltTransform(xml.str(), StringBuffer(getCFD()).append("./smc_xslt/result.xslt").str(), params, xls);
  2342. MemoryBuffer out;
  2343. out.setBuffer(xls.length(), (void*)xls.str());
  2344. resp.setResult(out);
  2345. resp.setResult_mimetype("application/vnd.ms-excel");
  2346. }
  2347. #ifdef _USE_ZLIB
  2348. else if(strieq(req.getFormat(),"zip") || strieq(req.getFormat(),"gzip"))
  2349. {
  2350. bool gzip = strieq(req.getFormat(),"gzip");
  2351. StringBuffer xml("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
  2352. xml.append("<Result>").append(mb.length(),mb.toByteArray()).append("</Result>");
  2353. VStringBuffer ifname("%s%sT%xAT%x%s", TEMPZIPDIR, PATHSEPSTR, (unsigned)(memsize_t)GetCurrentThreadId(), msTick(), gzip ? "" : ".zip");
  2354. IZZIPor* Zipor = createZZIPor();
  2355. int ret = 0;
  2356. if (gzip)
  2357. ret = Zipor->gzipToFile(xml.length(), (void*)xml.str(), ifname.str());
  2358. else
  2359. ret = Zipor->zipToFile(xml.length(), (void*)xml.str(), "WUResult.xml", ifname.str());
  2360. releaseIZ(Zipor);
  2361. if (ret < 0)
  2362. {
  2363. Owned<IFile> rFile = createIFile(ifname.str());
  2364. if (rFile->exists())
  2365. rFile->remove();
  2366. throw MakeStringException(ECLWATCH_CANNOT_COMPRESS_DATA, "The data cannot be compressed.");
  2367. }
  2368. MemoryBuffer out;
  2369. Owned <IFile> rf = createIFile(ifname.str());
  2370. if (rf->exists())
  2371. {
  2372. Owned <IFileIO> fio = rf->open(IFOread);
  2373. read(fio, 0, (size32_t) rf->size(), out);
  2374. resp.setResult(out);
  2375. }
  2376. if (gzip)
  2377. {
  2378. resp.setResult_mimetype("application/x-gzip");
  2379. context.addCustomerHeader("Content-disposition", "attachment;filename=WUResult.xml.gz");
  2380. }
  2381. else
  2382. {
  2383. resp.setResult_mimetype("application/zip");
  2384. context.addCustomerHeader("Content-disposition", "attachment;filename=WUResult.xml.zip");
  2385. }
  2386. Owned<IFile> rFile = createIFile(ifname.str());
  2387. if (rFile->exists())
  2388. rFile->remove();
  2389. }
  2390. #endif
  2391. else
  2392. {
  2393. resp.setResult(mb);
  2394. }
  2395. resp.setName(name.str());
  2396. resp.setWuid(wuidIn);
  2397. resp.setSequence(req.getSequence());
  2398. resp.setStart(start);
  2399. if (requested > total)
  2400. requested = (unsigned)total;
  2401. resp.setRequested(requested);
  2402. resp.setCount(count);
  2403. resp.setTotal(total);
  2404. resp.setFormat(req.getFormat());
  2405. }
  2406. catch(IException* e)
  2407. {
  2408. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  2409. }
  2410. return true;
  2411. }
  2412. bool CWsWorkunitsEx::onWUResultSummary(IEspContext &context, IEspWUResultSummaryRequest &req, IEspWUResultSummaryResponse &resp)
  2413. {
  2414. try
  2415. {
  2416. StringBuffer wuid = req.getWuid();
  2417. WsWuHelpers::checkAndTrimWorkunit("WUResultSummary", wuid);
  2418. Owned<IWorkUnitFactory> factory = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  2419. Owned<IConstWorkUnit> cw = factory->openWorkUnit(wuid.str(), false);
  2420. if(!cw)
  2421. throw MakeStringException(ECLWATCH_CANNOT_OPEN_WORKUNIT,"Cannot open workunit %s.",wuid.str());
  2422. ensureWsWorkunitAccess(context, *cw, SecAccess_Read);
  2423. resp.setWuid(wuid.str());
  2424. resp.setSequence(req.getSequence());
  2425. IArrayOf<IEspECLResult> results;
  2426. Owned<IConstWUResult> r = cw->getResultBySequence(req.getSequence());
  2427. if (r)
  2428. {
  2429. WsWuInfo winfo(context, cw);
  2430. winfo.getResult(*r, results, 0);
  2431. resp.setFormat(r->getResultFormat());
  2432. resp.setResult(results.item(0));
  2433. }
  2434. }
  2435. catch(IException* e)
  2436. {
  2437. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  2438. }
  2439. return true;
  2440. }
  2441. void getFileResults(IEspContext &context, const char* logicalName, const char* cluster,__int64 start, unsigned& count,__int64& total,
  2442. IStringVal& resname,bool bin, IArrayOf<IConstNamedValue>* filterBy, MemoryBuffer& buf, bool xsd)
  2443. {
  2444. Owned<IResultSetFactory> resultSetFactory = getSecResultSetFactory(context.querySecManager(), context.queryUser(), context.queryUserId(), context.queryPassword());
  2445. Owned<INewResultSet> result(resultSetFactory->createNewFileResultSet(logicalName, cluster));
  2446. if (!filterBy || !filterBy->length())
  2447. appendResultSet(buf, result, resname.str(), start, count, total, bin, xsd, context.getResponseFormat(), NULL);
  2448. else
  2449. {
  2450. Owned<INewResultSet> filteredResult = createFilteredResultSet(result, filterBy);
  2451. appendResultSet(buf, filteredResult, resname.str(), start, count, total, bin, xsd, context.getResponseFormat(), NULL);
  2452. }
  2453. }
  2454. void getWorkunitCluster(IEspContext &context, const char* wuid, SCMStringBuffer& cluster, bool checkArchiveWUs)
  2455. {
  2456. if (isEmpty(wuid))
  2457. return;
  2458. Owned<IWorkUnitFactory> factory = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  2459. Owned<IConstWorkUnit> cw = factory->openWorkUnit(wuid, false);
  2460. if (cw)
  2461. cluster.set(cw->queryClusterName());
  2462. else if (checkArchiveWUs)
  2463. {
  2464. Owned<IPropertyTree> wuProps;// = getArchivedWorkUnitProperties(wuid);
  2465. if (wuProps)
  2466. cluster.set(wuProps->queryProp("@clusterName"));
  2467. }
  2468. }
  2469. bool CWsWorkunitsEx::onWUResult(IEspContext &context, IEspWUResultRequest &req, IEspWUResultResponse &resp)
  2470. {
  2471. try
  2472. {
  2473. StringBuffer wuidStr = req.getWuid();
  2474. const char* wuid = wuidStr.trim().str();
  2475. if (wuid && *wuid)
  2476. {
  2477. if (!looksLikeAWuid(wuid, 'W'))
  2478. throw MakeStringException(ECLWATCH_INVALID_INPUT, "Invalid Workunit ID: %s", wuid);
  2479. ensureWsWorkunitAccess(context, wuid, SecAccess_Read);
  2480. }
  2481. MemoryBuffer mb;
  2482. SCMStringBuffer name;
  2483. __int64 total=0;
  2484. __int64 start = req.getStart() > 0 ? req.getStart() : 0;
  2485. unsigned count=req.getCount() ? req.getCount() : 100, requested=count;
  2486. unsigned seq = req.getSequence();
  2487. bool inclXsd = !req.getSuppressXmlSchema();
  2488. VStringBuffer filter("start=%" I64F "d;count=%d", start, count);
  2489. addToQueryString(filter, "clusterName", req.getCluster(), ';');
  2490. addToQueryString(filter, "logicalName", req.getLogicalName(), ';');
  2491. if (wuid && *wuid)
  2492. addToQueryString(filter, "wuid", wuid, ';');
  2493. addToQueryString(filter, "resultName", req.getResultName(), ';');
  2494. filter.appendf(";seq=%d;", seq);
  2495. if (inclXsd)
  2496. filter.append("xsd;");
  2497. if (context.getResponseFormat()==ESPSerializationJSON)
  2498. filter.append("json;");
  2499. IArrayOf<IConstNamedValue>* filterBy = &req.getFilterBy();
  2500. ForEachItemIn(i, *filterBy)
  2501. {
  2502. IConstNamedValue &item = filterBy->item(i);
  2503. const char *name = item.getName();
  2504. const char *value = item.getValue();
  2505. if (name && *name && value && *value)
  2506. addToQueryString(filter, name, value, ';');
  2507. }
  2508. const char* logicalName = req.getLogicalName();
  2509. const char* clusterName = req.getCluster();
  2510. const char* resultName = req.getResultName();
  2511. Owned<DataCacheElement> data = dataCache->lookup(context, filter, awusCacheMinutes);
  2512. if (data)
  2513. {
  2514. mb.append(data->m_data.c_str());
  2515. name.set(data->m_name.c_str());
  2516. logicalName = data->m_logicalName.c_str();
  2517. wuid = data->m_wuid.c_str();
  2518. resultName = data->m_resultName.c_str();
  2519. seq = data->m_seq;
  2520. start = data->m_start;
  2521. count = data->m_rowcount;
  2522. requested = (unsigned)data->m_requested;
  2523. total = data->m_total;
  2524. if (notEmpty(logicalName))
  2525. resp.setLogicalName(logicalName);
  2526. else
  2527. {
  2528. if (notEmpty(wuid))
  2529. resp.setWuid(wuid);
  2530. resp.setSequence(seq);
  2531. }
  2532. }
  2533. else
  2534. {
  2535. WUState wuState = WUStateUnknown;
  2536. if(logicalName && *logicalName)
  2537. {
  2538. StringBuffer lwuid;
  2539. getWuidFromLogicalFileName(context, logicalName, lwuid);
  2540. SCMStringBuffer cluster;
  2541. if (lwuid.length())
  2542. getWorkunitCluster(context, lwuid.str(), cluster, true);
  2543. if (cluster.length())
  2544. {
  2545. getFileResults(context, logicalName, cluster.str(), start, count, total, name, false, filterBy, mb, inclXsd);
  2546. resp.setLogicalName(logicalName);
  2547. }
  2548. else if (notEmpty(clusterName))
  2549. {
  2550. getFileResults(context, logicalName, clusterName, start, count, total, name, false, filterBy, mb, inclXsd);
  2551. resp.setLogicalName(logicalName);
  2552. }
  2553. else
  2554. throw MakeStringException(ECLWATCH_INVALID_INPUT,"Need valid target cluster to browse file %s.",logicalName);
  2555. Owned<IWorkUnitFactory> wf = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  2556. Owned<IConstWorkUnit> cw = wf->openWorkUnit(lwuid.str(), false);
  2557. if (cw)
  2558. wuState = cw->getState();
  2559. }
  2560. else if (notEmpty(wuid) && notEmpty(resultName))
  2561. {
  2562. name.set(resultName);
  2563. getWsWuResult(context, wuid, resultName, NULL, 0, start, count, total, name, false, filterBy, mb, wuState, inclXsd);
  2564. resp.setWuid(wuid);
  2565. resp.setSequence(seq);
  2566. }
  2567. else
  2568. {
  2569. getWsWuResult(context, wuid, NULL, NULL, seq, start, count, total, name, false, filterBy, mb, wuState, inclXsd);
  2570. resp.setWuid(wuid);
  2571. resp.setSequence(seq);
  2572. }
  2573. mb.append(0);
  2574. if (requested > total)
  2575. requested = (unsigned)total;
  2576. switch (wuState)
  2577. {
  2578. case WUStateCompleted:
  2579. case WUStateAborted:
  2580. case WUStateFailed:
  2581. case WUStateArchived:
  2582. dataCache->add(filter, mb.toByteArray(), name.str(), logicalName, wuid, resultName, seq, start, count, requested, total);
  2583. break;
  2584. }
  2585. }
  2586. resp.setName(name.str());
  2587. resp.setStart(start);
  2588. if (clusterName && *clusterName)
  2589. resp.setCluster(clusterName);
  2590. resp.setRequested(requested);
  2591. resp.setCount(count);
  2592. resp.setTotal(total);
  2593. resp.setResult(mb.toByteArray());
  2594. context.queryXslParameters()->setProp("escapeResults","1");
  2595. }
  2596. catch(IException* e)
  2597. {
  2598. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  2599. }
  2600. return true;
  2601. }
  2602. void getScheduledWUs(IEspContext &context, const char *stateReq, const char *serverName, const char *eventName, IArrayOf<IEspScheduledWU> & results)
  2603. {
  2604. double version = context.getClientVersion();
  2605. if (notEmpty(serverName))
  2606. {
  2607. Owned<IWorkUnitFactory> factory = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  2608. Owned<IScheduleReader> reader = getScheduleReader(serverName, eventName);
  2609. Owned<IScheduleReaderIterator> it(reader->getIterator());
  2610. while(it->isValidEventName())
  2611. {
  2612. StringBuffer ieventName;
  2613. it->getEventName(ieventName);
  2614. while(it->isValidEventText())
  2615. {
  2616. StringBuffer ieventText;
  2617. it->getEventText(ieventText);
  2618. while(it->isValidWuid())
  2619. {
  2620. StringBuffer wuid;
  2621. it->getWuid(wuid);
  2622. if (wuid.length())
  2623. {
  2624. bool match = false;
  2625. unsigned stateID = WUStateUnknown;
  2626. StringBuffer jobName, owner;
  2627. SCMStringBuffer state;
  2628. try
  2629. {
  2630. Owned<IConstWorkUnit> cw = factory->openWorkUnit(wuid.str(), false);
  2631. if (!cw && (!stateReq || !*stateReq))
  2632. match = true;
  2633. else if (cw)
  2634. {
  2635. if ((cw->getState() == WUStateScheduled) && cw->aborting())
  2636. {
  2637. stateID = WUStateAborting;
  2638. state.set("aborting");
  2639. }
  2640. else
  2641. {
  2642. stateID = cw->getState();
  2643. state.set(cw->queryStateDesc());
  2644. }
  2645. if (!stateReq || !*stateReq || strieq(stateReq, state.str()))
  2646. {
  2647. match = true;
  2648. jobName.set(cw->queryJobName());
  2649. owner.set(cw->queryUser());
  2650. }
  2651. }
  2652. }
  2653. catch (IException *e)
  2654. {
  2655. EXCLOG(e, "Get scheduled WUs");
  2656. e->Release();
  2657. }
  2658. if (!match)
  2659. {
  2660. it->nextWuid();
  2661. continue;
  2662. }
  2663. Owned<IEspScheduledWU> scheduledWU = createScheduledWU("");
  2664. scheduledWU->setWuid(wuid.str());
  2665. scheduledWU->setCluster(serverName);
  2666. if (ieventName.length())
  2667. scheduledWU->setEventName(ieventName.str());
  2668. if (ieventText.str())
  2669. scheduledWU->setEventText(ieventText.str());
  2670. if (jobName.length())
  2671. scheduledWU->setJobName(jobName.str());
  2672. if (version >= 1.51)
  2673. {
  2674. if (owner.length())
  2675. scheduledWU->setOwner(owner.str());
  2676. if (state.length())
  2677. {
  2678. scheduledWU->setStateID(stateID);
  2679. scheduledWU->setState(state.str());
  2680. }
  2681. }
  2682. results.append(*scheduledWU.getLink());
  2683. }
  2684. it->nextWuid();
  2685. }
  2686. it->nextEventText();
  2687. }
  2688. it->nextEventName();
  2689. }
  2690. }
  2691. return;
  2692. }
  2693. bool CWsWorkunitsEx::onWUShowScheduled(IEspContext &context, IEspWUShowScheduledRequest & req, IEspWUShowScheduledResponse & resp)
  2694. {
  2695. try
  2696. {
  2697. DBGLOG("WUShowScheduled");
  2698. const char *clusterName = req.getCluster();
  2699. const char *eventName = req.getEventName();
  2700. const char *state = req.getState();
  2701. IArrayOf<IEspScheduledWU> results;
  2702. if(notEmpty(req.getPushEventName()))
  2703. resp.setPushEventName(req.getPushEventName());
  2704. if(notEmpty(req.getPushEventText()))
  2705. resp.setPushEventText(req.getPushEventText());
  2706. Owned<IEnvironmentFactory> factory = getEnvironmentFactory();
  2707. Owned<IConstEnvironment> environment = factory->openEnvironment();
  2708. Owned<IPropertyTree> root = &environment->getPTree();
  2709. if (!root)
  2710. throw MakeStringException(ECLWATCH_CANNOT_GET_ENV_INFO, "Failed to get environment information.");
  2711. unsigned i = 0;
  2712. Owned<IPropertyTreeIterator> ic = root->getElements("Software/Topology/Cluster");
  2713. IArrayOf<IEspServerInfo> servers;
  2714. ForEach(*ic)
  2715. {
  2716. IPropertyTree &cluster = ic->query();
  2717. const char *iclusterName = cluster.queryProp("@name");
  2718. if (isEmpty(iclusterName))
  2719. continue;
  2720. if(isEmpty(clusterName))
  2721. getScheduledWUs(context, state, iclusterName, eventName, results);
  2722. else if (strieq(clusterName, iclusterName))
  2723. {
  2724. getScheduledWUs(context, state, clusterName, eventName, results);
  2725. resp.setClusterSelected(i+1);
  2726. }
  2727. Owned<IEspServerInfo> server = createServerInfo("");
  2728. server->setName(iclusterName);
  2729. servers.append(*server.getLink());
  2730. i++;
  2731. }
  2732. if (servers.length())
  2733. resp.setClusters(servers);
  2734. if (results.length())
  2735. resp.setWorkunits(results);
  2736. bool first=false;
  2737. StringBuffer Query("PageFrom=Scheduler");
  2738. appendUrlParameter(Query, "EventName", eventName, first);
  2739. appendUrlParameter(Query, "ECluster", clusterName, first);
  2740. resp.setQuery(Query.str());
  2741. }
  2742. catch(IException* e)
  2743. {
  2744. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  2745. }
  2746. return true;
  2747. }
  2748. bool CWsWorkunitsEx::onWUExport(IEspContext &context, IEspWUExportRequest &req, IEspWUExportResponse &resp)
  2749. {
  2750. try
  2751. {
  2752. Owned<IWorkUnitFactory> factory = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  2753. WsWuSearch ws(context, req.getOwner(), req.getState(), req.getCluster(), req.getStartDate(), req.getEndDate(), req.getECL(), req.getJobname());
  2754. StringBuffer xml("<?xml version=\"1.0\" encoding=\"UTF-8\"?><Workunits>");
  2755. for(WsWuSearch::iterator it=ws.begin(); it!=ws.end(); it++)
  2756. {
  2757. Owned<IConstWorkUnit> cw = factory->openWorkUnit(it->c_str(), false);
  2758. if (cw)
  2759. exportWorkUnitToXML(cw, xml, true, false, true);
  2760. }
  2761. xml.append("</Workunits>");
  2762. MemoryBuffer mb;
  2763. mb.setBuffer(xml.length(),(void*)xml.str());
  2764. resp.setExportData(mb);
  2765. resp.setExportData_mimetype(HTTP_TYPE_APPLICATION_XML);
  2766. }
  2767. catch(IException* e)
  2768. {
  2769. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  2770. }
  2771. return true;
  2772. }
  2773. bool CWsWorkunitsEx::onWUListLocalFileRequired(IEspContext& context, IEspWUListLocalFileRequiredRequest& req, IEspWUListLocalFileRequiredResponse& resp)
  2774. {
  2775. try
  2776. {
  2777. StringBuffer wuid = req.getWuid();
  2778. WsWuHelpers::checkAndTrimWorkunit("WUListLocalFileRequired", wuid);
  2779. ensureWsWorkunitAccess(context, wuid.str(), SecAccess_Read);
  2780. Owned<IWorkUnitFactory> factory = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  2781. Owned<IConstWorkUnit> cw = factory->openWorkUnit(wuid.str(), false);
  2782. if (!cw)
  2783. throw MakeStringException(ECLWATCH_CANNOT_UPDATE_WORKUNIT, "Workunit %s not found.", wuid.str());
  2784. IArrayOf<IEspLogicalFileUpload> localFiles;
  2785. Owned<IConstLocalFileUploadIterator> it = cw->getLocalFileUploads();
  2786. ForEach(*it)
  2787. {
  2788. Owned<IConstLocalFileUpload> file = it->get();
  2789. if(!file)
  2790. continue;
  2791. Owned<IEspLogicalFileUpload> up = createLogicalFileUpload();
  2792. SCMStringBuffer s;
  2793. up->setType(file->queryType());
  2794. up->setSource(file->getSource(s).str());
  2795. up->setDestination(file->getDestination(s).str());
  2796. up->setEventTag(file->getEventTag(s).str());
  2797. localFiles.append(*up.getLink());
  2798. }
  2799. resp.setLocalFileUploads(localFiles);
  2800. }
  2801. catch(IException* e)
  2802. {
  2803. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  2804. }
  2805. return true;
  2806. }
  2807. typedef enum wsEclTypes_
  2808. {
  2809. wsEclTypeUnknown,
  2810. xsdString,
  2811. xsdBoolean,
  2812. xsdDecimal,
  2813. xsdFloat,
  2814. xsdDouble,
  2815. xsdDuration,
  2816. xsdDateTime,
  2817. xsdTime,
  2818. xsdDate,
  2819. xsdYearMonth,
  2820. xsdYear,
  2821. xsdMonthDay,
  2822. xsdDay,
  2823. xsdMonth,
  2824. xsdHexBinary,
  2825. xsdBase64Binary,
  2826. xsdAnyURI,
  2827. xsdQName,
  2828. xsdNOTATION,
  2829. xsdNormalizedString,
  2830. xsdToken,
  2831. xsdLanguage,
  2832. xsdNMTOKEN,
  2833. xsdNMTOKENS,
  2834. xsdName,
  2835. xsdNCName,
  2836. xsdID,
  2837. xsdIDREF,
  2838. xsdIDREFS,
  2839. xsdENTITY,
  2840. xsdENTITIES,
  2841. xsdInteger,
  2842. xsdNonPositiveInteger,
  2843. xsdNegativeInteger,
  2844. xsdLong,
  2845. xsdInt,
  2846. xsdShort,
  2847. xsdByte,
  2848. xsdNonNegativeInteger,
  2849. xsdUnsignedLong,
  2850. xsdUnsignedInt,
  2851. xsdUnsignedShort,
  2852. xsdUnsignedByte,
  2853. xsdPositiveInteger,
  2854. tnsRawDataFile,
  2855. tnsCsvDataFile,
  2856. tnsEspStringArray,
  2857. tnsEspIntArray,
  2858. tnsXmlDataSet,
  2859. maxWsEclType
  2860. } wsEclType;
  2861. bool CWsWorkunitsEx::onWUAddLocalFileToWorkunit(IEspContext& context, IEspWUAddLocalFileToWorkunitRequest& req, IEspWUAddLocalFileToWorkunitResponse& resp)
  2862. {
  2863. try
  2864. {
  2865. StringBuffer wuid = req.getWuid();
  2866. WsWuHelpers::checkAndTrimWorkunit("WUAddLocalFileToWorkunit", wuid);
  2867. ensureWsWorkunitAccess(context, wuid.str(), SecAccess_Write);
  2868. resp.setWuid(wuid.str());
  2869. const char* varname = req.getName();
  2870. if (isEmpty(varname))
  2871. {
  2872. resp.setResult("Name is not defined!");
  2873. return true;
  2874. }
  2875. resp.setName(varname);
  2876. wsEclType type = (wsEclType) req.getType();
  2877. const char *val = req.getVal();
  2878. unsigned len = req.getLength();
  2879. Owned<IWorkUnitFactory> factory = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  2880. WorkunitUpdate wu(factory->updateWorkUnit(wuid.str()));
  2881. if (!wu)
  2882. {
  2883. resp.setResult("Workunit not found!");
  2884. return true;
  2885. }
  2886. Owned<IWUResult> wuRslt = wu->updateResultByName(varname);
  2887. if (isEmpty(val))
  2888. val=req.getDefVal();
  2889. if (notEmpty(val))
  2890. {
  2891. switch (type)
  2892. {
  2893. case xsdBoolean:
  2894. wuRslt->setResultBool((strieq(val, "1") || strieq(val, "true") || strieq(val, "on")));
  2895. wuRslt->setResultStatus(ResultStatusSupplied);
  2896. break;
  2897. case xsdDecimal:
  2898. case xsdFloat:
  2899. case xsdDouble:
  2900. wuRslt->setResultReal(atof(val));
  2901. wuRslt->setResultStatus(ResultStatusSupplied);
  2902. break;
  2903. case xsdInteger:
  2904. case xsdNonPositiveInteger:
  2905. case xsdNegativeInteger:
  2906. case xsdLong:
  2907. case xsdInt:
  2908. case xsdShort:
  2909. case xsdByte:
  2910. case xsdNonNegativeInteger:
  2911. case xsdUnsignedLong:
  2912. case xsdUnsignedInt:
  2913. case xsdUnsignedShort:
  2914. case xsdUnsignedByte:
  2915. case xsdPositiveInteger:
  2916. wuRslt->setResultInt(_atoi64(val));
  2917. wuRslt->setResultStatus(ResultStatusSupplied);
  2918. break;
  2919. case tnsEspIntArray:
  2920. case tnsEspStringArray:
  2921. wuRslt->setResultRaw(len, val, ResultFormatXmlSet);
  2922. break;
  2923. case tnsRawDataFile:
  2924. wuRslt->setResultRaw(len, val, ResultFormatRaw);
  2925. break;
  2926. case tnsXmlDataSet:
  2927. wuRslt->setResultRaw(len, val, ResultFormatXml);
  2928. break;
  2929. case tnsCsvDataFile:
  2930. case xsdBase64Binary: //tbd
  2931. case xsdHexBinary:
  2932. break;
  2933. default:
  2934. wuRslt->setResultString(val, len);
  2935. wuRslt->setResultStatus(ResultStatusSupplied);
  2936. break;
  2937. }
  2938. }
  2939. resp.setResult("Result has been set as required!");
  2940. }
  2941. catch(IException* e)
  2942. {
  2943. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  2944. }
  2945. return true;
  2946. }
  2947. void getClusterConfig(char const * clusterType, char const * clusterName, char const * processName, StringBuffer& netAddress)
  2948. {
  2949. Owned<IEnvironmentFactory> factory = getEnvironmentFactory();
  2950. Owned<IConstEnvironment> environment = factory->openEnvironment();
  2951. Owned<IPropertyTree> pRoot = &environment->getPTree();
  2952. VStringBuffer xpath("Software/%s[@name='%s']", clusterType, clusterName);
  2953. IPropertyTree* pCluster = pRoot->queryPropTree(xpath.str());
  2954. if (!pCluster)
  2955. throw MakeStringException(ECLWATCH_CLUSTER_NOT_IN_ENV_INFO, "'%s %s' is not defined.", clusterType, clusterName);
  2956. const char* port = pCluster->queryProp(xpath.set(processName).append("@port").str());
  2957. const char* computer = pCluster->queryProp(xpath.set(processName).append("@computer").str());
  2958. if (isEmpty(computer))
  2959. throw MakeStringException(ECLWATCH_INVALID_CLUSTER_INFO, "'%s %s: %s' is not defined.", clusterType, clusterName, processName);
  2960. Owned<IConstMachineInfo> pMachine = environment->getMachine(computer);
  2961. if (pMachine)
  2962. {
  2963. StringBufferAdaptor s(netAddress);
  2964. pMachine->getNetAddress(s);
  2965. #ifdef MACHINE_IP
  2966. if (streq(netAddress.str(), "."))
  2967. netAddress = MACHINE_IP;
  2968. #endif
  2969. netAddress.append(':').append(port);
  2970. }
  2971. return;
  2972. }
  2973. bool CWsWorkunitsEx::onWUProcessGraph(IEspContext &context,IEspWUProcessGraphRequest &req, IEspWUProcessGraphResponse &resp)
  2974. {
  2975. try
  2976. {
  2977. StringBuffer wuid = req.getWuid();
  2978. WsWuHelpers::checkAndTrimWorkunit("WUProcessGraph", wuid);
  2979. Owned<IWorkUnitFactory> factory = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  2980. Owned<IConstWorkUnit> cw = factory->openWorkUnit(wuid.str(), false);
  2981. if(!cw)
  2982. throw MakeStringException(ECLWATCH_CANNOT_OPEN_WORKUNIT,"Cannot open workunit %s.",wuid.str());
  2983. ensureWsWorkunitAccess(context, *cw, SecAccess_Read);
  2984. Owned <IConstWUGraph> graph = cw->getGraph(req.getName());
  2985. Owned <IPropertyTree> xgmml = graph->getXGMMLTree(true); // merge in graph progress information
  2986. StringBuffer xml;
  2987. resp.setTheGraph(toXML(xgmml.get(), xml).str());
  2988. }
  2989. catch(IException* e)
  2990. {
  2991. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  2992. }
  2993. return true;
  2994. }
  2995. bool isRunning(IConstWorkUnit &cw)
  2996. {
  2997. // MORE - move into workunit interface
  2998. switch (cw.getState())
  2999. {
  3000. case WUStateFailed:
  3001. case WUStateAborted:
  3002. case WUStateCompleted:
  3003. return false;
  3004. default:
  3005. return true;
  3006. }
  3007. }
  3008. void CWsWorkunitsEx::readGraph(IEspContext& context, const char* subGraphId, WUGraphIDType& id, bool running,
  3009. IConstWUGraph* graph, IArrayOf<IEspECLGraphEx>& graphs)
  3010. {
  3011. SCMStringBuffer name, label, type;
  3012. graph->getName(name);
  3013. graph->getLabel(label);
  3014. graph->getTypeName(type);
  3015. Owned<IEspECLGraphEx> g = createECLGraphEx("","");
  3016. g->setName(name.str());
  3017. g->setLabel(label.str());
  3018. g->setType(type.str());
  3019. WUGraphState graphState = graph->getState();
  3020. if (running && (WUGraphRunning == graphState))
  3021. {
  3022. g->setRunning(true);
  3023. g->setRunningId(id);
  3024. }
  3025. else if (context.getClientVersion() > 1.20)
  3026. {
  3027. if (WUGraphComplete == graphState)
  3028. g->setComplete(true);
  3029. else if (WUGraphFailed == graphState)
  3030. g->setFailed(true);
  3031. }
  3032. Owned<IPropertyTree> xgmml = graph->getXGMMLTree(true);
  3033. // New functionality, if a subgraph id is specified and we only want to load the xgmml for that subgraph
  3034. // then we need to conditionally pull a propertytree from the xgmml graph one and use that for the xgmml.
  3035. //JCSMORE this should be part of the API and therefore allow *only* the subtree to be pulled from the backend.
  3036. StringBuffer xml;
  3037. if (notEmpty(subGraphId))
  3038. {
  3039. VStringBuffer xpath("//node[@id='%s']", subGraphId);
  3040. toXML(xgmml->queryPropTree(xpath.str()), xml);
  3041. }
  3042. else
  3043. toXML(xgmml, xml);
  3044. g->setGraph(xml.str());
  3045. graphs.append(*g.getClear());
  3046. }
  3047. bool CWsWorkunitsEx::onWUGetGraph(IEspContext& context, IEspWUGetGraphRequest& req, IEspWUGetGraphResponse& resp)
  3048. {
  3049. try
  3050. {
  3051. StringBuffer wuid = req.getWuid();
  3052. WsWuHelpers::checkAndTrimWorkunit("WUGetGraph", wuid);
  3053. Owned<IWorkUnitFactory> factory = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  3054. Owned<IConstWorkUnit> cw = factory->openWorkUnit(wuid.str(), false);
  3055. if(!cw)
  3056. throw MakeStringException(ECLWATCH_CANNOT_OPEN_WORKUNIT,"Cannot open workunit %s.",wuid.str());
  3057. ensureWsWorkunitAccess(context, *cw, SecAccess_Read);
  3058. WUGraphIDType id;
  3059. SCMStringBuffer runningGraph;
  3060. bool running = (isRunning(*cw) && cw->getRunningGraph(runningGraph,id));
  3061. IArrayOf<IEspECLGraphEx> graphs;
  3062. if (isEmpty(req.getGraphName())) // JCS->GS - is this really required??
  3063. {
  3064. Owned<IConstWUGraphIterator> it = &cw->getGraphs(GraphTypeAny);
  3065. ForEach(*it)
  3066. readGraph(context, req.getSubGraphId(), id, running, &it->query(), graphs);
  3067. }
  3068. else
  3069. {
  3070. Owned<IConstWUGraph> graph = cw->getGraph(req.getGraphName());
  3071. readGraph(context, req.getSubGraphId(), id, running, graph, graphs);
  3072. }
  3073. resp.setGraphs(graphs);
  3074. }
  3075. catch(IException* e)
  3076. {
  3077. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  3078. }
  3079. return true;
  3080. }
  3081. bool CWsWorkunitsEx::onGVCAjaxGraph(IEspContext &context, IEspGVCAjaxGraphRequest &req, IEspGVCAjaxGraphResponse &resp)
  3082. {
  3083. try
  3084. {
  3085. resp.setName(req.getName());
  3086. resp.setGraphName(req.getGraphName());
  3087. resp.setGraphType("eclwatch");
  3088. double version = context.getClientVersion();
  3089. if (version > 1.19)
  3090. resp.setSubGraphId(req.getSubGraphId());
  3091. if (version > 1.20)
  3092. resp.setSubGraphOnly(req.getSubGraphOnly());
  3093. }
  3094. catch(IException* e)
  3095. {
  3096. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  3097. }
  3098. return true;
  3099. }
  3100. bool CWsWorkunitsEx::onWUGraphInfo(IEspContext &context,IEspWUGraphInfoRequest &req, IEspWUGraphInfoResponse &resp)
  3101. {
  3102. try
  3103. {
  3104. StringBuffer wuid = req.getWuid();
  3105. WsWuHelpers::checkAndTrimWorkunit("WUGraphInfo", wuid);
  3106. Owned<IWorkUnitFactory> factory = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  3107. Owned<IConstWorkUnit> cw = factory->openWorkUnit(wuid.str(), false);
  3108. if(!cw)
  3109. throw MakeStringException(ECLWATCH_CANNOT_UPDATE_WORKUNIT,"Cannot open workunit %s.",wuid.str());
  3110. ensureWsWorkunitAccess(context, *cw, SecAccess_Write);
  3111. resp.setWuid(wuid.str());
  3112. resp.setName(req.getName());
  3113. resp.setRunning(isRunning(*cw));
  3114. if (notEmpty(req.getGID()))
  3115. resp.setGID(req.getGID());
  3116. if(!req.getBatchWU_isNull())
  3117. resp.setBatchWU(req.getBatchWU());
  3118. }
  3119. catch(IException* e)
  3120. {
  3121. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  3122. }
  3123. return true;
  3124. }
  3125. bool CWsWorkunitsEx::onWUGVCGraphInfo(IEspContext &context,IEspWUGVCGraphInfoRequest &req, IEspWUGVCGraphInfoResponse &resp)
  3126. {
  3127. try
  3128. {
  3129. StringBuffer wuid = req.getWuid();
  3130. WsWuHelpers::checkAndTrimWorkunit("WUGVCGraphInfo", wuid);
  3131. Owned<IWorkUnitFactory> factory = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  3132. Owned<IConstWorkUnit> cw = factory->openWorkUnit(wuid.str(), false);
  3133. if(!cw)
  3134. throw MakeStringException(ECLWATCH_CANNOT_UPDATE_WORKUNIT,"Cannot open workunit %s.",wuid.str());
  3135. ensureWsWorkunitAccess(context, *cw, SecAccess_Read);
  3136. resp.setWuid(wuid.str());
  3137. resp.setName(req.getName());
  3138. resp.setRunning(isRunning(*cw));
  3139. if (notEmpty(req.getGID()))
  3140. resp.setGID(req.getGID());
  3141. if(!req.getBatchWU_isNull())
  3142. resp.setBatchWU(req.getBatchWU());
  3143. StringBuffer xml("<Control><Endpoint><Query id=\"Gordon.Extractor.0\">");
  3144. xml.appendf("<Graph id=\"%s\">", req.getName());
  3145. if (context.getClientVersion() > 1.17)
  3146. {
  3147. xml.append("<Subgraph>");
  3148. xml.append(req.getSubgraphId_isNull() ? 0 : req.getSubgraphId());
  3149. xml.append("</Subgraph>");
  3150. }
  3151. xml.append("</Graph></Query></Endpoint></Control>");
  3152. resp.setTheGraph(xml.str());
  3153. }
  3154. catch(IException* e)
  3155. {
  3156. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  3157. }
  3158. return true;
  3159. }
  3160. bool CWsWorkunitsEx::onWUGraphTiming(IEspContext &context, IEspWUGraphTimingRequest &req, IEspWUGraphTimingResponse &resp)
  3161. {
  3162. try
  3163. {
  3164. StringBuffer wuid = req.getWuid();
  3165. WsWuHelpers::checkAndTrimWorkunit("WUGraphTiming", wuid);
  3166. Owned<IWorkUnitFactory> factory = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  3167. Owned<IConstWorkUnit> cw = factory->openWorkUnit(wuid.str(), false);
  3168. if(!cw)
  3169. throw MakeStringException(ECLWATCH_CANNOT_UPDATE_WORKUNIT,"Cannot open workunit %s.",wuid.str());
  3170. ensureWsWorkunitAccess(context, *cw, SecAccess_Read);
  3171. resp.updateWorkunit().setWuid(wuid.str());
  3172. WsWuInfo winfo(context, cw);
  3173. IArrayOf<IConstECLTimingData> timingData;
  3174. winfo.getGraphTimingData(timingData, 0);
  3175. resp.updateWorkunit().setTimingData(timingData);
  3176. }
  3177. catch(IException* e)
  3178. {
  3179. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  3180. }
  3181. return true;
  3182. }
  3183. int CWsWorkunitsSoapBindingEx::onGetForm(IEspContext &context, CHttpRequest* request, CHttpResponse* response, const char *service, const char *method)
  3184. {
  3185. try
  3186. {
  3187. StringBuffer xml;
  3188. StringBuffer xslt;
  3189. if(strieq(method,"WUQuery") || strieq(method,"WUJobList"))
  3190. {
  3191. Owned<IEnvironmentFactory> factory = getEnvironmentFactory();
  3192. Owned<IConstEnvironment> environment = factory->openEnvironment();
  3193. Owned<IPropertyTree> root = &environment->getPTree();
  3194. if (!root)
  3195. throw MakeStringException(ECLWATCH_CANNOT_GET_ENV_INFO, "Failed to get environment information.");
  3196. if(strieq(method,"WUQuery"))
  3197. {
  3198. SecAccessFlags accessOwn;
  3199. SecAccessFlags accessOthers;
  3200. getUserWuAccessFlags(context, accessOwn, accessOthers, false);
  3201. xml.append("<WUQuery>");
  3202. if ((accessOwn == SecAccess_None) && (accessOthers == SecAccess_None))
  3203. xml.appendf("<ErrorMessage>Access to workunit is denied.</ErrorMessage>");
  3204. else
  3205. {
  3206. MapStringTo<bool> added;
  3207. Owned<IPropertyTreeIterator> it = root->getElements("Software/Topology/Cluster");
  3208. ForEach(*it)
  3209. {
  3210. const char *name = it->query().queryProp("@name");
  3211. if (notEmpty(name) && !added.getValue(name))
  3212. {
  3213. added.setValue(name, true);
  3214. appendXMLTag(xml, "Cluster", name);
  3215. }
  3216. }
  3217. }
  3218. xml.append("</WUQuery>");
  3219. xslt.append(getCFD()).append("./smc_xslt/wuid_search.xslt");
  3220. }
  3221. else if (strieq(method,"WUJobList"))
  3222. {
  3223. StringBuffer cluster, defaultProcess, range;
  3224. request->getParameter("Cluster", cluster);
  3225. request->getParameter("Process",defaultProcess);
  3226. request->getParameter("Range",range);
  3227. Owned<IConstWUClusterInfo> clusterInfo = getTargetClusterInfo(cluster);
  3228. xml.append("<WUJobList>");
  3229. if (range.length())
  3230. appendXMLTag(xml, "Range", range.str());
  3231. if (clusterInfo)
  3232. {
  3233. const StringArray &thorInstances = clusterInfo->getThorProcesses();
  3234. ForEachItemIn(i, thorInstances)
  3235. {
  3236. const char* instance = thorInstances.item(i);
  3237. if (defaultProcess.length() && strieq(instance, defaultProcess.str()))
  3238. xml.append("<Cluster selected=\"1\">").append(instance).append("</Cluster>");
  3239. else
  3240. xml.append("<Cluster>").append(instance).append("</Cluster>");
  3241. }
  3242. }
  3243. xml.append("<TargetCluster>").append(cluster).append("</TargetCluster>");
  3244. xml.append("</WUJobList>");
  3245. xslt.append(getCFD()).append("./smc_xslt/jobs_search.xslt");
  3246. response->addHeader("Expires", "0");
  3247. }
  3248. }
  3249. if (xslt.length() && xml.length())
  3250. {
  3251. StringBuffer html;
  3252. xsltTransform(xml.str(), xslt.str(), NULL, html);
  3253. response->setContent(html.str());
  3254. response->setContentType(HTTP_TYPE_TEXT_HTML_UTF8);
  3255. response->send();
  3256. return 0;
  3257. }
  3258. }
  3259. catch(IException* e)
  3260. {
  3261. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  3262. }
  3263. return onGetNotFound(context, request, response, service);
  3264. }
  3265. bool isDeploymentTypeCompressed(const char *type)
  3266. {
  3267. if (type && *type)
  3268. return (0==strncmp(type, "compressed_", strlen("compressed_")));
  3269. return false;
  3270. }
  3271. const char *skipCompressedTypeQualifier(const char *type)
  3272. {
  3273. if (isDeploymentTypeCompressed(type))
  3274. type += strlen("compressed_");
  3275. return type;
  3276. }
  3277. void deployEclOrArchive(IEspContext &context, IEspWUDeployWorkunitRequest & req, IEspWUDeployWorkunitResponse & resp)
  3278. {
  3279. NewWsWorkunit wu(context);
  3280. StringAttr wuid(wu->queryWuid()); // NB queryWuid() not valid after workunit,clear()
  3281. wu->setAction(WUActionCompile);
  3282. StringBuffer name(req.getName());
  3283. if (!name.trim().length() && notEmpty(req.getFileName()))
  3284. splitFilename(req.getFileName(), NULL, NULL, &name, NULL);
  3285. if (name.length())
  3286. wu->setJobName(name.str());
  3287. if (req.getObject().length())
  3288. {
  3289. MemoryBuffer mb;
  3290. const MemoryBuffer *uncompressed = &req.getObject();
  3291. if (isDeploymentTypeCompressed(req.getObjType()))
  3292. {
  3293. fastLZDecompressToBuffer(mb, req.getObject().bufferBase());
  3294. uncompressed = &mb;
  3295. }
  3296. StringBuffer text(uncompressed->length(), uncompressed->toByteArray());
  3297. wu.setQueryText(text.str());
  3298. }
  3299. if (req.getQueryMainDefinition())
  3300. wu.setQueryMain(req.getQueryMainDefinition());
  3301. if (req.getSnapshot())
  3302. wu->setSnapshot(req.getSnapshot());
  3303. if (!req.getResultLimit_isNull())
  3304. wu->setResultLimit(req.getResultLimit());
  3305. wu->commit();
  3306. wu.clear();
  3307. WsWuHelpers::submitWsWorkunit(context, wuid.str(), req.getCluster(), NULL, 0, true, false, false, NULL, NULL, &req.getDebugValues());
  3308. waitForWorkUnitToCompile(wuid.str(), req.getWait());
  3309. WsWuInfo winfo(context, wuid.str());
  3310. winfo.getCommon(resp.updateWorkunit(), WUINFO_All);
  3311. winfo.getExceptions(resp.updateWorkunit(), WUINFO_All);
  3312. name.clear();
  3313. if (notEmpty(resp.updateWorkunit().getJobname()))
  3314. origValueChanged(req.getName(), resp.updateWorkunit().getJobname(), name, false);
  3315. if (name.length()) //non generated user specified name, so override #Workunit('name')
  3316. {
  3317. WorkunitUpdate wx(&winfo.cw->lock());
  3318. wx->setJobName(name.str());
  3319. resp.updateWorkunit().setJobname(name.str());
  3320. }
  3321. AuditSystemAccess(context.queryUserId(), true, "Updated %s", wuid.str());
  3322. }
  3323. StringBuffer &sharedObjectFileName(StringBuffer &filename, const char *name, const char *ext, unsigned copy)
  3324. {
  3325. filename.append((name && *name) ? name : "workunit");
  3326. if (copy)
  3327. filename.append('-').append(copy);
  3328. if (notEmpty(ext))
  3329. filename.append(ext);
  3330. return filename;
  3331. }
  3332. inline StringBuffer &buildFullDllPath(StringBuffer &dllpath, StringBuffer &dllname, const char *dir, const char *name, const char *ext, unsigned copy)
  3333. {
  3334. return addPathSepChar(dllpath.set(dir)).append(sharedObjectFileName(dllname, name, ext, copy));
  3335. }
  3336. void writeSharedObject(const char *srcpath, const MemoryBuffer &obj, const char *dir, StringBuffer &dllpath, StringBuffer &dllname, unsigned crc)
  3337. {
  3338. StringBuffer name, ext;
  3339. if (srcpath && *srcpath)
  3340. splitFilename(srcpath, NULL, NULL, &name, &ext);
  3341. unsigned copy=0;
  3342. buildFullDllPath(dllpath.clear(), dllname.clear(), dir, name.str(), ext.str(), copy);
  3343. while (checkFileExists(dllpath.str()))
  3344. {
  3345. if (crc && crc == crc_file(dllpath.str()))
  3346. {
  3347. DBGLOG("Workunit dll already exists: %s", dllpath.str());
  3348. return;
  3349. }
  3350. buildFullDllPath(dllpath.clear(), dllname.clear(), dir, name.str(), ext.str(), ++copy);
  3351. }
  3352. DBGLOG("Writing workunit dll: %s", dllpath.str());
  3353. Owned<IFile> f = createIFile(dllpath.str());
  3354. Owned<IFileIO> io = f->open(IFOcreate);
  3355. io->write(0, obj.length(), obj.toByteArray());
  3356. }
  3357. void deploySharedObject(IEspContext &context, StringBuffer &wuid, const char *filename, const char *cluster, const char *name, const MemoryBuffer &obj, const char *dir, const char *xml)
  3358. {
  3359. StringBuffer dllpath, dllname;
  3360. StringBuffer srcname(filename);
  3361. unsigned crc = 0;
  3362. Owned<IPropertyTree> srcxml;
  3363. if (xml && *xml)
  3364. {
  3365. srcxml.setown(createPTreeFromXMLString(xml));
  3366. if (srcxml && wuid.length())
  3367. {
  3368. crc = srcxml->getPropInt("Query[1]/Associated[1]/File[@type='dll'][1]/@crc", 0);
  3369. if (crc)
  3370. {
  3371. Owned<IWorkUnitFactory> factory = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  3372. Owned<IConstWorkUnit> cw = factory->openWorkUnit(wuid, false);
  3373. if (cw)
  3374. {
  3375. //is this a previous copy of same query, or a WUID collision?
  3376. if (cw->getHash() == (unsigned) srcxml->getPropInt64("@hash", 0))
  3377. {
  3378. Owned<IConstWUQuery> query = cw->getQuery();
  3379. if (query && crc == query->getQueryDllCrc())
  3380. return;
  3381. }
  3382. }
  3383. }
  3384. }
  3385. }
  3386. if (!srcname.length())
  3387. srcname.append(name).append(SharedObjectExtension);
  3388. writeSharedObject(srcname.str(), obj, dir, dllpath, dllname, crc);
  3389. NewWsWorkunit wu(context, wuid); //duplicate wuid made unique
  3390. wuid.set(wu->queryWuid());
  3391. wu->setClusterName(cluster);
  3392. wu->commit();
  3393. StringBuffer dllXML;
  3394. if (getWorkunitXMLFromFile(dllpath.str(), dllXML))
  3395. {
  3396. Owned<ILocalWorkUnit> embeddedWU = createLocalWorkUnit(dllXML.str());
  3397. queryExtendedWU(wu)->copyWorkUnit(embeddedWU, true);
  3398. }
  3399. wu.associateDll(dllpath.str(), dllname.str());
  3400. if (name && *name)
  3401. wu->setJobName(name);
  3402. //clean slate, copy only select items from processed workunit xml
  3403. if (srcxml)
  3404. {
  3405. if (srcxml->hasProp("@jobName"))
  3406. wu->setJobName(srcxml->queryProp("@jobName"));
  3407. if (srcxml->hasProp("@token"))
  3408. wu->setSecurityToken(srcxml->queryProp("@token"));
  3409. if (srcxml->hasProp("Query/Text"))
  3410. wu.setQueryText(srcxml->queryProp("Query/Text"));
  3411. }
  3412. wu->setState(WUStateCompiled);
  3413. wu->commit();
  3414. wu.clear();
  3415. AuditSystemAccess(context.queryUserId(), true, "Updated %s", wuid.str());
  3416. }
  3417. void CWsWorkunitsEx::deploySharedObjectReq(IEspContext &context, IEspWUDeployWorkunitRequest & req, IEspWUDeployWorkunitResponse & resp, const char *dir, const char *xml)
  3418. {
  3419. if (isEmpty(req.getFileName()))
  3420. throw MakeStringException(ECLWATCH_INVALID_INPUT, "File name required when deploying a shared object.");
  3421. const char *cluster = req.getCluster();
  3422. if (isEmpty(cluster))
  3423. throw MakeStringException(ECLWATCH_INVALID_INPUT, "Cluster name required when deploying a shared object.");
  3424. const MemoryBuffer *uncompressed = &req.getObject();
  3425. MemoryBuffer mb;
  3426. if (isDeploymentTypeCompressed(req.getObjType()))
  3427. {
  3428. fastLZDecompressToBuffer(mb, req.getObject().bufferBase());
  3429. uncompressed = &mb;
  3430. }
  3431. StringBuffer wuid;
  3432. deploySharedObject(context, wuid, req.getFileName(), cluster, req.getName(), *uncompressed, dir, xml);
  3433. WsWuInfo winfo(context, wuid.str());
  3434. winfo.getCommon(resp.updateWorkunit(), WUINFO_All);
  3435. AuditSystemAccess(context.queryUserId(), true, "Updated %s", wuid.str());
  3436. }
  3437. bool CWsWorkunitsEx::onWUDeployWorkunit(IEspContext &context, IEspWUDeployWorkunitRequest & req, IEspWUDeployWorkunitResponse & resp)
  3438. {
  3439. const char *type = skipCompressedTypeQualifier(req.getObjType());
  3440. try
  3441. {
  3442. if (!context.validateFeatureAccess(OWN_WU_ACCESS, SecAccess_Write, false))
  3443. throw MakeStringException(ECLWATCH_ECL_WU_ACCESS_DENIED, "Failed to create workunit. Permission denied.");
  3444. if (notEmpty(req.getCluster()) && !isValidCluster(req.getCluster()))
  3445. throw MakeStringException(ECLWATCH_INVALID_CLUSTER_NAME, "Invalid cluster name: %s", req.getCluster());
  3446. if (!type || !*type)
  3447. throw MakeStringExceptionDirect(ECLWATCH_INVALID_INPUT, "WUDeployWorkunit unspecified object type.");
  3448. if (strieq(type, "archive")|| strieq(type, "ecl_text"))
  3449. deployEclOrArchive(context, req, resp);
  3450. else if (strieq(type, "shared_object"))
  3451. deploySharedObjectReq(context, req, resp, queryDirectory.str());
  3452. else
  3453. throw MakeStringException(ECLWATCH_INVALID_INPUT, "WUDeployWorkunit '%s' unknown object type.", type);
  3454. }
  3455. catch(IException* e)
  3456. {
  3457. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  3458. }
  3459. return true;
  3460. }
  3461. void CWsWorkunitsEx::createZAPFile(const char* fileName, size32_t len, const void* data)
  3462. {
  3463. if (!fileName || !*fileName)
  3464. throw MakeStringException(ECLWATCH_CANNOT_COMPRESS_DATA,"File name not specified.");
  3465. Owned<IFile> wuInfoIFile = createIFile(fileName);
  3466. Owned<IFileIO> wuInfoIO = wuInfoIFile->open(IFOcreate);
  3467. if (wuInfoIO)
  3468. wuInfoIO->write(0, len, data);
  3469. }
  3470. void CWsWorkunitsEx::cleanZAPFolder(IFile* zipDir, bool removeFolder)
  3471. {
  3472. if (!zipDir)
  3473. throw MakeStringException(ECLWATCH_CANNOT_COMPRESS_DATA,"Invalid file interface for the zip folder.");
  3474. Owned<IDirectoryIterator> iter = zipDir->directoryFiles(NULL,false,false);
  3475. ForEach(*iter)
  3476. {
  3477. OwnedIFile thisFile = createIFile(iter->query().queryFilename());
  3478. if (thisFile->isFile() == foundYes)
  3479. thisFile->remove();
  3480. }
  3481. if (removeFolder)
  3482. zipDir->remove();
  3483. }
  3484. void CWsWorkunitsEx::addProcessLogfile(Owned<IConstWorkUnit>& cwu, WsWuInfo& winfo, const char* process, const char* path)
  3485. {
  3486. Owned<IPropertyTreeIterator> procs = cwu->getProcesses(process, NULL);
  3487. ForEach (*procs)
  3488. {
  3489. StringBuffer logSpec;
  3490. IPropertyTree& proc = procs->query();
  3491. proc.getProp("@log",logSpec);
  3492. if (!logSpec.length())
  3493. continue;
  3494. StringBuffer pid;
  3495. pid.appendf("%d",proc.getPropInt("@pid"));
  3496. MemoryBuffer mb;
  3497. try
  3498. {
  3499. if (strieq(process, "EclAgent"))
  3500. winfo.getWorkunitEclAgentLog(logSpec.str(), pid.str(), mb);
  3501. else if (strieq(process, "Thor"))
  3502. winfo.getWorkunitThorLog(logSpec.str(), mb);
  3503. }
  3504. catch(IException *e)
  3505. {
  3506. StringBuffer s;
  3507. e->errorMessage(s);
  3508. DBGLOG("Error accessing Process Log file %s: %s", logSpec.str(), s.str());
  3509. mb.append(s.str());
  3510. e->Release();
  3511. }
  3512. if (!mb.length())
  3513. continue;
  3514. const char * logName = logSpec.str();
  3515. for (const char * p=logSpec; *p; p++)
  3516. {
  3517. if (*p == '\\' || *p == '/')
  3518. logName = p+1;
  3519. }
  3520. VStringBuffer fileName("%s%c%s", path, PATHSEPCHAR, logName);
  3521. createZAPFile(fileName.str(), mb.length(), mb.bufferBase());
  3522. }
  3523. }
  3524. void CWsWorkunitsEx::createZAPWUInfoFile(IEspWUCreateZAPInfoRequest &req, Owned<IConstWorkUnit>& cwu, const char* pathNameStr)
  3525. {
  3526. StringBuffer sb;
  3527. sb.append("Workunit: ").append(cwu->queryWuid()).append("\r\n");
  3528. sb.append("User: ").append(cwu->queryUser()).append("\r\n");
  3529. sb.append("Build Version:").append(req.getBuildVersion()).append("\r\n");
  3530. sb.append("Cluster: ").append(cwu->queryClusterName()).append("\r\n");
  3531. if (req.getESPIPAddress())
  3532. sb.append("ESP: ").append(req.getESPIPAddress()).append("\r\n");
  3533. if (req.getThorIPAddress())
  3534. sb.append("Thor: ").append(req.getThorIPAddress()).append("\r\n");
  3535. //Exceptions/Warnings/Info
  3536. Owned<IConstWUExceptionIterator> exceptions = &cwu->getExceptions();
  3537. StringBuffer info, warn, err, alert;
  3538. ForEach(*exceptions)
  3539. {
  3540. SCMStringBuffer temp;
  3541. switch (exceptions->query().getSeverity())
  3542. {
  3543. case SeverityInformation:
  3544. info.append("\t").append(exceptions->query().getExceptionMessage(temp)).append("\r\n\r\n");
  3545. break;
  3546. case SeverityWarning:
  3547. warn.append("\t").append(exceptions->query().getExceptionMessage(temp)).append("\r\n\r\n");
  3548. break;
  3549. case SeverityError:
  3550. err.append("\t").append(exceptions->query().getExceptionMessage(temp)).append("\r\n\r\n");
  3551. break;
  3552. case SeverityAlert:
  3553. alert.append("\t").append(exceptions->query().getExceptionMessage(temp)).append("\r\n\r\n");
  3554. break;
  3555. }
  3556. }
  3557. if (err.length())
  3558. sb.append("Exceptions: ").append("\r\n").append(err);
  3559. if (warn.length())
  3560. sb.append("Warnings: ").append("\r\n").append(warn);
  3561. if (info.length())
  3562. sb.append("Information: ").append("\r\n").append(info);
  3563. if (alert.length())
  3564. sb.append("Alert: ").append("\r\n").append(alert);
  3565. //User provided Information
  3566. sb.append("Problem: ").append(req.getProblemDescription()).append("\r\n\r\n");
  3567. sb.append("What Changed: ").append(req.getWhatChanged()).append("\r\n\r\n");
  3568. sb.append("Timing: ").append(req.getWhereSlow()).append("\r\n\r\n");
  3569. VStringBuffer fileName("%s.txt", pathNameStr);
  3570. createZAPFile(fileName.str(), sb.length(), sb.str());
  3571. }
  3572. void CWsWorkunitsEx::createZAPWUXMLFile(WsWuInfo &winfo, const char* pathNameStr)
  3573. {
  3574. MemoryBuffer mb;
  3575. winfo.getWorkunitXml(NULL, mb);
  3576. VStringBuffer fileName("%s.xml", pathNameStr);
  3577. createZAPFile(fileName.str(), mb.length(), mb.bufferBase());
  3578. }
  3579. void CWsWorkunitsEx::createZAPECLQueryArchiveFiles(Owned<IConstWorkUnit>& cwu, const char* pathNameStr)
  3580. {
  3581. Owned<IConstWUQuery> query = cwu->getQuery();
  3582. if(!query)
  3583. return;
  3584. //Add archive if present
  3585. Owned<IConstWUAssociatedFileIterator> iter = &query->getAssociatedFiles();
  3586. ForEach(*iter)
  3587. {
  3588. IConstWUAssociatedFile & cur = iter->query();
  3589. SCMStringBuffer ssb;
  3590. cur.getDescription(ssb);
  3591. if (!strieq(ssb.str(), "archive"))
  3592. continue;
  3593. cur.getName(ssb);
  3594. if (!ssb.length())
  3595. continue;
  3596. StringBuffer fileName, archiveContents;
  3597. try
  3598. {
  3599. archiveContents.loadFile(ssb.str());
  3600. }
  3601. catch (IException *e)
  3602. {
  3603. StringBuffer s;
  3604. e->errorMessage(s);
  3605. DBGLOG("Error accessing archive file %s: %s", ssb.str(), s.str());
  3606. archiveContents.insert(0, "Error accessing archive file ").appendf("%s: %s\r\n\r\n", ssb.str(), s.str());
  3607. e->Release();
  3608. }
  3609. fileName.setf("%s.archive", pathNameStr);
  3610. createZAPFile(fileName.str(), archiveContents.length(), archiveContents.str());
  3611. break;
  3612. }
  3613. //Add Query
  3614. SCMStringBuffer temp;
  3615. query->getQueryText(temp);
  3616. if (temp.length())
  3617. {
  3618. VStringBuffer fileName("%s.ecl", pathNameStr);
  3619. createZAPFile(fileName.str(), temp.length(), temp.str());
  3620. }
  3621. }
  3622. bool CWsWorkunitsEx::onWUCreateZAPInfo(IEspContext &context, IEspWUCreateZAPInfoRequest &req, IEspWUCreateZAPInfoResponse &resp)
  3623. {
  3624. try
  3625. {
  3626. Owned<IWorkUnitFactory> factory = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  3627. Owned<IConstWorkUnit> cwu = factory->openWorkUnit(req.getWuid(), false);
  3628. if(!cwu.get())
  3629. throw MakeStringException(ECLWATCH_CANNOT_OPEN_WORKUNIT, "Cannot open workunit %s.", req.getWuid());
  3630. StringBuffer userName, nameStr, fileName;
  3631. StringBuffer zipFileName, zipFileNameWithPath, zipCommand, folderToZIP;
  3632. if (context.queryUser())
  3633. userName.append(context.queryUser()->getName());
  3634. nameStr.append("ZAPReport_").append(req.getWuid()).append('_').append(userName.str());
  3635. //create a folder for WU ZAP files
  3636. const char* zipFolder = "tempzipfiles" PATHSEPSTR;
  3637. folderToZIP.append(zipFolder).append(nameStr.str());
  3638. Owned<IFile> zipDir = createIFile(folderToZIP.str());
  3639. if (!zipDir->exists())
  3640. zipDir->createDirectory();
  3641. else
  3642. cleanZAPFolder(zipDir, false);
  3643. //create WU ZAP files
  3644. VStringBuffer pathNameStr("%s/%s", folderToZIP.str(), nameStr.str());
  3645. createZAPWUInfoFile(req, cwu, pathNameStr.str());
  3646. createZAPECLQueryArchiveFiles(cwu, pathNameStr.str());
  3647. WsWuInfo winfo(context, cwu);
  3648. createZAPWUXMLFile(winfo, pathNameStr.str());
  3649. addProcessLogfile(cwu, winfo, "EclAgent", folderToZIP.str());
  3650. addProcessLogfile(cwu, winfo, "Thor", folderToZIP.str());
  3651. //Write out to ZIP file
  3652. zipFileName.append(nameStr.str()).append(".zip");
  3653. zipFileNameWithPath.append(zipFolder).append(zipFileName.str());
  3654. pathNameStr.set(folderToZIP.str()).append("/*");
  3655. const char* password = req.getPassword();
  3656. if (password && *password)
  3657. zipCommand.appendf("zip -j --password %s %s %s", password, zipFileNameWithPath.str(), pathNameStr.str());
  3658. else
  3659. zipCommand.appendf("zip -j %s %s", zipFileNameWithPath.str(), pathNameStr.str());
  3660. int zipRet = system(zipCommand.str());
  3661. //Remove the temporary files and the folder
  3662. cleanZAPFolder(zipDir, true);
  3663. if (zipRet != 0)
  3664. throw MakeStringException(ECLWATCH_CANNOT_COMPRESS_DATA,"Failed to execute system command 'zip'. Please make sure that zip utility is installed.");
  3665. //Download ZIP file to user
  3666. Owned<IFile> f = createIFile(zipFileNameWithPath.str());
  3667. Owned<IFileIO> io = f->open(IFOread);
  3668. MemoryBuffer mb;
  3669. void * data = mb.reserve((unsigned)io->size());
  3670. size32_t read = io->read(0, (unsigned)io->size(), data);
  3671. mb.setLength(read);
  3672. resp.setThefile(mb);
  3673. resp.setThefile_mimetype(HTTP_TYPE_OCTET_STREAM);
  3674. StringBuffer headerStr("attachment;filename=");
  3675. headerStr.append(zipFileName.str());
  3676. context.addCustomerHeader("Content-disposition", headerStr.str());
  3677. io->close();
  3678. f->remove();
  3679. }
  3680. catch(IException* e)
  3681. {
  3682. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  3683. }
  3684. return true;
  3685. }
  3686. bool CWsWorkunitsEx::onWUGetZAPInfo(IEspContext &context, IEspWUGetZAPInfoRequest &req, IEspWUGetZAPInfoResponse &resp)
  3687. {
  3688. try
  3689. {
  3690. StringBuffer wuid = req.getWUID();
  3691. WsWuHelpers::checkAndTrimWorkunit("WUGetZAPInfo", wuid);
  3692. Owned<IWorkUnitFactory> factory = getWorkUnitFactory(context.querySecManager(), context.queryUser());
  3693. Owned<IConstWorkUnit> cw = factory->openWorkUnit(wuid, false);
  3694. if(!cw)
  3695. throw MakeStringException(ECLWATCH_CANNOT_OPEN_WORKUNIT,"Cannot open workunit %s.",wuid.str());
  3696. StringBuffer EspIP, ThorIP;
  3697. resp.setWUID(wuid.str());
  3698. resp.setBuildVersion(getBuildVersion());
  3699. IpAddress ipaddr = queryHostIP();
  3700. ipaddr.getIpText(EspIP);
  3701. resp.setESPIPAddress(EspIP.str());
  3702. //Get Archive
  3703. Owned<IConstWUQuery> query = cw->getQuery();
  3704. if(query)
  3705. {
  3706. SCMStringBuffer queryText;
  3707. query->getQueryText(queryText);
  3708. if (queryText.length() && isArchiveQuery(queryText.str()))
  3709. resp.setArchive(queryText.str());
  3710. }
  3711. //Get Thor IP
  3712. BoolHash uniqueProcesses;
  3713. Owned<IStringIterator> thorInstances = cw->getProcesses("Thor");
  3714. ForEach (*thorInstances)
  3715. {
  3716. SCMStringBuffer processName;
  3717. thorInstances->str(processName);
  3718. if (processName.length() < 1)
  3719. continue;
  3720. bool* found = uniqueProcesses.getValue(processName.str());
  3721. if (found && *found)
  3722. continue;
  3723. uniqueProcesses.setValue(processName.str(), true);
  3724. Owned<IStringIterator> thorLogs = cw->getLogs("Thor", processName.str());
  3725. ForEach (*thorLogs)
  3726. {
  3727. SCMStringBuffer logName;
  3728. thorLogs->str(logName);
  3729. if (!logName.length())
  3730. continue;
  3731. const char* thorIPPtr = NULL;
  3732. const char* ptr = logName.str();
  3733. while (ptr)
  3734. {
  3735. if (!thorIPPtr && (*ptr != '/'))
  3736. thorIPPtr = ptr;
  3737. else if (thorIPPtr && (*ptr == '/'))
  3738. break;
  3739. ptr++;
  3740. }
  3741. if (!thorIPPtr)
  3742. continue;
  3743. //Found a thor IP
  3744. if (ThorIP.length())
  3745. ThorIP.append(",");
  3746. if (!*ptr)
  3747. ThorIP.append(thorIPPtr);
  3748. else
  3749. ThorIP.append(ptr-thorIPPtr, thorIPPtr);
  3750. }
  3751. }
  3752. if (ThorIP.length())
  3753. resp.setThorIPAddress(ThorIP.str());
  3754. }
  3755. catch(IException* e)
  3756. {
  3757. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  3758. }
  3759. return true;
  3760. }
  3761. bool CWsWorkunitsEx::onWUCheckFeatures(IEspContext &context, IEspWUCheckFeaturesRequest &req, IEspWUCheckFeaturesResponse &resp)
  3762. {
  3763. resp.setBuildVersionMajor(BUILD_VERSION_MAJOR);
  3764. resp.setBuildVersionMinor(BUILD_VERSION_MINOR);
  3765. resp.setBuildVersionPoint(BUILD_VERSION_POINT);
  3766. resp.setMaxRequestEntityLength(maxRequestEntityLength);
  3767. resp.updateDeployment().setUseCompression(true);
  3768. return true;
  3769. }
  3770. static const char * checkGetStatsInput(const char * s)
  3771. {
  3772. if (!s || !*s)
  3773. return "*";
  3774. return s;
  3775. }
  3776. bool CWsWorkunitsEx::onWUGetStats(IEspContext &context, IEspWUGetStatsRequest &req, IEspWUGetStatsResponse &resp)
  3777. {
  3778. try
  3779. {
  3780. StringBuffer wuid = req.getWUID();
  3781. WsWuHelpers::checkAndTrimWorkunit("WUInfo", wuid);
  3782. ensureWsWorkunitAccess(context, wuid.str(), SecAccess_Read);
  3783. const char* creatorType = checkGetStatsInput(req.getCreatorType());
  3784. const char* creator = checkGetStatsInput(req.getCreator());
  3785. const char* scopeType = checkGetStatsInput(req.getScopeType());
  3786. const char* scope = checkGetStatsInput(req.getScope());
  3787. const char* kind = checkGetStatsInput(req.getKind());
  3788. const char* measure = req.getMeasure();
  3789. StatisticsFilter filter(creatorType, creator, scopeType, scope, measure, kind);
  3790. if (!req.getMinScopeDepth_isNull() && !req.getMaxScopeDepth_isNull())
  3791. filter.setScopeDepth(req.getMinScopeDepth(), req.getMaxScopeDepth());
  3792. else if (!req.getMinScopeDepth_isNull())
  3793. filter.setScopeDepth(req.getMinScopeDepth());
  3794. bool createDescriptions = false;
  3795. if (!req.getCreateDescriptions_isNull())
  3796. createDescriptions = req.getCreateDescriptions();
  3797. WsWuInfo winfo(context, wuid.str());
  3798. IArrayOf<IEspWUStatisticItem> statistics;
  3799. winfo.getStats(filter, createDescriptions, statistics);
  3800. resp.setStatistics(statistics);
  3801. resp.setWUID(wuid.str());
  3802. }
  3803. catch(IException* e)
  3804. {
  3805. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  3806. }
  3807. return true;
  3808. }