workunit.cpp 344 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #include "jlib.hpp"
  14. #include "workunit.hpp"
  15. #include "jprop.hpp"
  16. #include "jmisc.hpp"
  17. #include "jexcept.hpp"
  18. #include "jiter.ipp"
  19. #include "jptree.hpp"
  20. #include "jtime.ipp"
  21. #include "jencrypt.hpp"
  22. #include "junicode.hpp"
  23. #include "eclrtl.hpp"
  24. #include "deftype.hpp"
  25. #include <time.h>
  26. #include "mpbase.hpp"
  27. #include "daclient.hpp"
  28. #include "dadfs.hpp"
  29. #include "dafdesc.hpp"
  30. #include "dasds.hpp"
  31. #include "danqs.hpp"
  32. #include "dautils.hpp"
  33. #include "dllserver.hpp"
  34. #include "thorhelper.hpp"
  35. #include "workflow.hpp"
  36. #include "nbcd.hpp"
  37. #include "seclib.hpp"
  38. #include "wuerror.hpp"
  39. #include "wujobq.hpp"
  40. #include "environment.hpp"
  41. #define GLOBAL_WORKUNIT "global"
  42. #define SDS_LOCK_TIMEOUT (5*60*1000) // 5mins, 30s a bit short
  43. static int workUnitTraceLevel = 1;
  44. static StringBuffer &getXPath(StringBuffer &wuRoot, const char *wuid)
  45. {
  46. // MORE - can fold in the date
  47. return wuRoot.append("/WorkUnits/").append(wuid);
  48. }
  49. //To be called by eclserver, but esp etc. won't know, so we need to store it.
  50. static StringBuffer & appendLibrarySuffix(StringBuffer & suffix)
  51. {
  52. #ifdef _WIN32
  53. suffix.append("W");
  54. #else
  55. suffix.append("L");
  56. #endif
  57. #ifdef __64BIT__
  58. suffix.append("64");
  59. #else
  60. suffix.append("32");
  61. #endif
  62. return suffix;
  63. }
  64. typedef MapStringTo<bool> UniqueScopes;
  65. static void wuAccessError(const char *username, const char *action, const char *wuscope, const char *wuid, bool excpt, bool log)
  66. {
  67. StringBuffer err;
  68. err.append("Workunit Access Denied - action: ").append(action).append(" user:").append(username ? username : "<Unknown>");
  69. if (wuid)
  70. err.append(" workunit:").append(wuid);
  71. if (wuscope)
  72. err.append(" scope:").append(wuscope);
  73. //MORE - we would need more information passed in from outside if we want to make the audit message format the same as from higher level ESP calls
  74. SYSLOG(AUDIT_TYPE_ACCESS_FAILURE, err.str());
  75. if (log)
  76. LOG(MCuserError, "%s", err.str());
  77. if (excpt)
  78. throw MakeStringException(WUERR_AccessError, "%s", err.str());
  79. }
  80. static bool checkWuScopeSecAccess(const char *wuscope, ISecManager &secmgr, ISecUser *secuser, int required, const char *action, bool excpt, bool log)
  81. {
  82. bool ret=(!secuser) ? true : (secmgr.authorizeEx(RT_WORKUNIT_SCOPE, *secuser, wuscope)>=required);
  83. if (!ret && (log || excpt))
  84. wuAccessError(secuser ? secuser->getName() : NULL, action, wuscope, NULL, excpt, log);
  85. return ret;
  86. }
  87. static bool checkWuScopeListSecAccess(const char *wuscope, ISecResourceList *scopes, int required, const char *action, bool excpt, bool log)
  88. {
  89. if (!scopes)
  90. return true;
  91. bool ret=true;
  92. if (wuscope)
  93. {
  94. Owned<ISecResource> res=scopes->getResource(wuscope);
  95. if (!res || res->getAccessFlags()<required)
  96. ret=false;
  97. }
  98. else
  99. {
  100. for (int seq=0; ret && seq<scopes->count(); seq++)
  101. {
  102. ISecResource *res=scopes->queryResource(seq);
  103. if (res && res->getAccessFlags()<required)
  104. return false;
  105. }
  106. }
  107. if (!ret && (log || excpt))
  108. wuAccessError(NULL, action, wuscope, NULL, excpt, log);
  109. return ret;
  110. }
  111. static bool checkWuSecAccess(IConstWorkUnit &cw, ISecManager &secmgr, ISecUser *secuser, int required, const char *action, bool excpt, bool log)
  112. {
  113. SCMStringBuffer wuscope;
  114. bool ret=(!secuser) ? true : (secmgr.authorizeEx(RT_WORKUNIT_SCOPE, *secuser, cw.getWuScope(wuscope).str())>=required);
  115. if (!ret && (log || excpt))
  116. {
  117. SCMStringBuffer wuid;
  118. wuAccessError(secuser ? secuser->getName() : NULL, action, wuscope.str(), cw.getWuid(wuid).str(), excpt, log);
  119. }
  120. return ret;
  121. }
  122. static bool checkWuSecAccess(const char *wuid, ISecManager &secmgr, ISecUser *secuser, int required, const char *action, bool excpt, bool log)
  123. {
  124. StringBuffer wuRoot;
  125. Owned<IRemoteConnection> conn = querySDS().connect(getXPath(wuRoot, wuid).str(), myProcessSession(), 0, SDS_LOCK_TIMEOUT);
  126. if (conn)
  127. {
  128. Owned<IPropertyTree> ptree=conn->getRoot();
  129. return checkWuScopeSecAccess(ptree->queryProp("@scope"), secmgr, secuser, required, action, excpt, log);
  130. }
  131. if (log || excpt)
  132. wuAccessError(secuser ? secuser->getName() : NULL, action, "Unknown", NULL, excpt, log);
  133. return false;
  134. }
  135. void doDescheduleWorkkunit(char const * wuid)
  136. {
  137. StringBuffer xpath;
  138. xpath.append("*/*/*/");
  139. ncnameEscape(wuid, xpath);
  140. Owned<IRemoteConnection> conn = querySDS().connect("/Schedule", myProcessSession(), RTM_LOCK_WRITE, SDS_LOCK_TIMEOUT);
  141. if(!conn) return;
  142. Owned<IPropertyTree> root = conn->getRoot();
  143. bool more;
  144. do more = root->removeProp(xpath.str()); while(more);
  145. }
  146. #define PROGRESS_FORMAT_V 2
  147. class CConstGraphProgress : public CInterface, implements IConstWUGraphProgress
  148. {
  149. class CGraphProgress : public CInterface, implements IWUGraphProgress
  150. {
  151. CConstGraphProgress &parent;
  152. public:
  153. IMPLEMENT_IINTERFACE;
  154. CGraphProgress(CConstGraphProgress &_parent) : parent(_parent)
  155. {
  156. parent.lockWrite();
  157. }
  158. ~CGraphProgress()
  159. {
  160. parent.unlock();
  161. }
  162. virtual IPropertyTree * queryProgressTree() { return parent.queryProgressTree(); }
  163. virtual WUGraphState queryGraphState() { return parent.queryGraphState(); }
  164. virtual WUGraphState queryNodeState(WUGraphIDType nodeId) { return parent.queryNodeState(nodeId); }
  165. virtual IWUGraphProgress * update() { return parent.update(); }
  166. virtual unsigned queryFormatVersion() { return parent.queryFormatVersion(); }
  167. virtual IPropertyTree & updateEdge(WUGraphIDType nodeId, const char *edgeId)
  168. {
  169. return parent.updateEdge(nodeId, edgeId);
  170. }
  171. virtual IPropertyTree & updateNode(WUGraphIDType nodeId, WUNodeIDType id)
  172. {
  173. return parent.updateNode(nodeId, id);
  174. }
  175. virtual void setGraphState(WUGraphState state)
  176. {
  177. parent.setGraphState(state);
  178. }
  179. virtual void setNodeState(WUGraphIDType nodeId, WUGraphState state)
  180. {
  181. parent.setNodeState(nodeId, state);
  182. }
  183. };
  184. IPropertyTree &updateElement(WUGraphIDType nodeId, const char *elemName, const char *id)
  185. {
  186. IPropertyTree *elem = NULL;
  187. if (!connectedWrite) lockWrite();
  188. StringBuffer path;
  189. path.append("node[@id=\"").append(nodeId).append("\"]");
  190. IPropertyTree *node = progress->queryPropTree(path.str());
  191. if (!node)
  192. {
  193. node = progress->addPropTree("node", createPTree());
  194. node->setPropInt("@id", (int)nodeId);
  195. elem = node->addPropTree(elemName, createPTree());
  196. elem->setProp("@id", id);
  197. }
  198. else
  199. {
  200. path.clear().append(elemName).append("[@id=\"").append(id).append("\"]");
  201. elem = node->queryPropTree(path.str());
  202. if (!elem)
  203. {
  204. elem = node->addPropTree(elemName, createPTree());
  205. elem->setProp("@id", id);
  206. }
  207. }
  208. return *elem;
  209. }
  210. public:
  211. IMPLEMENT_IINTERFACE;
  212. static void deleteWuidProgress(const char *wuid)
  213. {
  214. StringBuffer path("/GraphProgress/");
  215. path.append(wuid);
  216. Owned<IRemoteConnection> conn = querySDS().connect(path.str(), myProcessSession(), RTM_LOCK_WRITE, SDS_LOCK_TIMEOUT);
  217. if (conn)
  218. conn->close(true);
  219. }
  220. CConstGraphProgress(const char *_wuid, const char *_graphName) : wuid(_wuid), graphName(_graphName)
  221. {
  222. rootPath.append("/GraphProgress/").append(wuid).append('/').append(graphName).append('/');
  223. connected = connectedWrite = false;
  224. formatVersion = 0;
  225. progress = NULL;
  226. }
  227. void connect()
  228. {
  229. conn.clear();
  230. packProgress(wuid,false);
  231. conn.setown(querySDS().connect(rootPath.str(), myProcessSession(), RTM_LOCK_READ|RTM_CREATE_QUERY, SDS_LOCK_TIMEOUT));
  232. progress = conn->queryRoot();
  233. formatVersion = progress->getPropInt("@format");
  234. connected = true;
  235. }
  236. void lockWrite()
  237. {
  238. if (connectedWrite) return;
  239. // JCSMORE - look at using changeMode here.
  240. if (conn)
  241. conn.clear();
  242. else
  243. packProgress(wuid,false);
  244. conn.setown(querySDS().connect(rootPath.str(), myProcessSession(), RTM_LOCK_WRITE|RTM_CREATE_QUERY, SDS_LOCK_TIMEOUT));
  245. progress = conn->queryRoot();
  246. if (!progress->hasChildren()) // i.e. blank.
  247. {
  248. formatVersion = PROGRESS_FORMAT_V;
  249. progress->setPropInt("@format", PROGRESS_FORMAT_V);
  250. }
  251. else
  252. formatVersion = progress->getPropInt("@format");
  253. connected = connectedWrite = true;
  254. }
  255. void unlock()
  256. {
  257. connected = false;
  258. connectedWrite = false;
  259. conn.clear();
  260. }
  261. IPropertyTree &updateNode(WUGraphIDType nodeId, WUNodeIDType id)
  262. {
  263. StringBuffer s;
  264. return updateElement(nodeId, "node", s.append(id).str());
  265. }
  266. IPropertyTree &updateEdge(WUGraphIDType nodeId, const char *edgeId)
  267. {
  268. return updateElement(nodeId, "edge", edgeId);
  269. }
  270. static bool getRunningGraph(const char *wuid, IStringVal &graphName, WUGraphIDType &subId)
  271. {
  272. StringBuffer path;
  273. Owned<IRemoteConnection> conn = querySDS().connect(path.append("/GraphProgress/").append(wuid).str(), myProcessSession(), RTM_LOCK_READ, SDS_LOCK_TIMEOUT);
  274. if (!conn) return false;
  275. const char *name = conn->queryRoot()->queryProp("Running/@graph");
  276. if (name)
  277. {
  278. graphName.set(name);
  279. subId = conn->queryRoot()->getPropInt64("Running/@subId");
  280. return true;
  281. }
  282. else
  283. return false;
  284. }
  285. void setGraphState(WUGraphState state)
  286. {
  287. progress->setPropInt("@_state", (unsigned)state);
  288. }
  289. void setNodeState(WUGraphIDType nodeId, WUGraphState state)
  290. {
  291. if (!connectedWrite) lockWrite();
  292. StringBuffer path;
  293. path.append("node[@id=\"").append(nodeId).append("\"]");
  294. IPropertyTree *node = progress->queryPropTree(path.str());
  295. if (!node)
  296. {
  297. node = progress->addPropTree("node", createPTree());
  298. node->setPropInt("@id", (int)nodeId);
  299. }
  300. node->setPropInt("@_state", (unsigned)state);
  301. switch (state)
  302. {
  303. case WUGraphRunning:
  304. {
  305. StringBuffer path;
  306. Owned<IRemoteConnection> conn = querySDS().connect(path.append("/GraphProgress/").append(wuid).str(), myProcessSession(), RTM_LOCK_WRITE|RTM_CREATE_QUERY, SDS_LOCK_TIMEOUT);
  307. IPropertyTree *running = conn->queryRoot()->setPropTree("Running", createPTree());
  308. running->setProp("@graph", graphName);
  309. running->setPropInt64("@subId", nodeId);
  310. break;
  311. }
  312. case WUGraphComplete:
  313. {
  314. StringBuffer path;
  315. Owned<IRemoteConnection> conn = querySDS().connect(path.append("/GraphProgress/").append(wuid).str(), myProcessSession(), RTM_LOCK_WRITE, SDS_LOCK_TIMEOUT);
  316. conn->queryRoot()->removeProp("Running"); // only one thing running at any given time and one thing with lockWrite access
  317. break;
  318. }
  319. }
  320. }
  321. virtual IPropertyTree * queryProgressTree()
  322. {
  323. if (!connected) connect();
  324. return progress;
  325. }
  326. virtual WUGraphState queryGraphState()
  327. {
  328. return (WUGraphState)queryProgressTree()->getPropInt("@_state", (unsigned)WUGraphUnknown);
  329. }
  330. virtual WUGraphState queryNodeState(WUGraphIDType nodeId)
  331. {
  332. StringBuffer path;
  333. path.append("node[@id=\"").append(nodeId).append("\"]/@_state");
  334. return (WUGraphState)queryProgressTree()->getPropInt(path.str(), (unsigned)WUGraphUnknown);
  335. }
  336. virtual IWUGraphProgress * update()
  337. {
  338. return new CGraphProgress(*this);
  339. }
  340. virtual unsigned queryFormatVersion()
  341. {
  342. if (!connected) connect();
  343. return formatVersion;
  344. }
  345. static bool packProgress(const char *wuid,bool pack)
  346. {
  347. StringBuffer path;
  348. path.append("/GraphProgress/").append(wuid);
  349. Owned<IRemoteConnection> conn(querySDS().connect(path.str(), myProcessSession(), RTM_LOCK_WRITE|RTM_CREATE_QUERY, SDS_LOCK_TIMEOUT));
  350. if (!conn)
  351. return false;
  352. Owned<IPropertyTree> newt;
  353. MemoryBuffer buf;
  354. IPropertyTree *root = conn->queryRoot();
  355. if (root->getPropBin("Packed",buf)) {
  356. if (pack)
  357. return true;
  358. newt.setown(createPTree(buf));
  359. IPropertyTree *running = root->queryPropTree("Running");
  360. if (running)
  361. newt->setPropTree("Running",createPTreeFromIPT(running));
  362. }
  363. else {
  364. if (!pack)
  365. return true;
  366. newt.setown(createPTree(wuid));
  367. IPropertyTree *running = root->queryPropTree("Running");
  368. if (running) {
  369. newt->setPropTree("Running",createPTreeFromIPT(running));
  370. root->removeTree(running);
  371. }
  372. root->serialize(buf);
  373. newt->setPropBin("Packed",buf.length(),buf.bufferBase());
  374. }
  375. root->setPropTree(NULL,newt.getClear());
  376. return true;
  377. }
  378. private:
  379. Owned<IRemoteConnection> conn;
  380. IPropertyTree* progress;
  381. StringAttr wuid, graphName;
  382. StringBuffer rootPath;
  383. bool connected, connectedWrite;
  384. unsigned formatVersion;
  385. };
  386. class CLocalWUTimeStamp : public CInterface, implements IConstWUTimeStamp
  387. {
  388. Owned<IPropertyTree> p;
  389. public:
  390. IMPLEMENT_IINTERFACE;
  391. CLocalWUTimeStamp(IPropertyTree *p);
  392. virtual IStringVal & getApplication(IStringVal & str) const;
  393. virtual IStringVal & getEvent(IStringVal & str) const;
  394. virtual IStringVal & getDate(IStringVal & dt) const;
  395. };
  396. class CLocalWUAppValue : public CInterface, implements IConstWUAppValue
  397. {
  398. Owned<IPropertyTree> p;
  399. StringBuffer prop;
  400. public:
  401. IMPLEMENT_IINTERFACE;
  402. CLocalWUAppValue(IPropertyTree *p,unsigned child);
  403. virtual IStringVal & getApplication(IStringVal & str) const;
  404. virtual IStringVal & getName(IStringVal & str) const;
  405. virtual IStringVal & getValue(IStringVal & dt) const;
  406. };
  407. class CLocalWUStatistic : public CInterface, implements IConstWUStatistic
  408. {
  409. Owned<IPropertyTree> p;
  410. public:
  411. IMPLEMENT_IINTERFACE;
  412. CLocalWUStatistic(IPropertyTree *p);
  413. virtual IStringVal & getFullName(IStringVal & str) const;
  414. virtual IStringVal & getCreator(IStringVal & str) const;
  415. virtual IStringVal & getDescription(IStringVal & str) const;
  416. virtual IStringVal & getName(IStringVal & str) const;
  417. virtual IStringVal & getScope(IStringVal & str) const;
  418. virtual StatisticMeasure getKind() const;
  419. virtual unsigned __int64 getValue() const;
  420. virtual unsigned __int64 getCount() const;
  421. virtual unsigned __int64 getMax() const;
  422. };
  423. template <typename T, typename IT> struct CachedTags
  424. {
  425. CachedTags(): cached(false) {}
  426. void load(IPropertyTree* p,const char* xpath)
  427. {
  428. if (!cached)
  429. {
  430. assertex(tags.length() == 0);
  431. Owned<IPropertyTreeIterator> r = p->getElements(xpath);
  432. for (r->first(); r->isValid(); r->next())
  433. {
  434. IPropertyTree *rp = &r->query();
  435. rp->Link();
  436. tags.append(*new T(rp));
  437. }
  438. cached = true;
  439. }
  440. }
  441. void append(IPropertyTree * p)
  442. {
  443. tags.append(*new T(p));
  444. }
  445. operator IArrayOf<IT>&() { return tags; }
  446. void kill()
  447. {
  448. cached = false;
  449. tags.kill();
  450. }
  451. bool cached;
  452. IArrayOf<IT> tags;
  453. };
  454. template <> struct CachedTags<CLocalWUAppValue, IConstWUAppValue>
  455. {
  456. CachedTags(): cached(false) {}
  457. void load(IPropertyTree* p,const char* xpath)
  458. {
  459. if (!cached)
  460. {
  461. assertex(tags.length() == 0);
  462. Owned<IPropertyTreeIterator> r = p->getElements(xpath);
  463. for (r->first(); r->isValid(); r->next())
  464. {
  465. IPropertyTree *rp = &r->query();
  466. Owned<IPropertyTreeIterator> v = rp->getElements("*");
  467. unsigned pos = 1;
  468. for (v->first(); v->isValid(); v->next())
  469. {
  470. rp->Link();
  471. tags.append(*new CLocalWUAppValue(rp,pos++));
  472. }
  473. }
  474. cached = true;
  475. }
  476. }
  477. operator IArrayOf<IConstWUAppValue>&() { return tags; }
  478. void kill()
  479. {
  480. cached = false;
  481. tags.kill();
  482. }
  483. bool cached;
  484. IArrayOf<IConstWUAppValue> tags;
  485. };
  486. class CLocalWorkUnit : public CInterface, implements IConstWorkUnit , implements ISDSSubscription, implements IExtendedWUInterface
  487. {
  488. friend StringBuffer &exportWorkUnitToXML(const IConstWorkUnit *wu, StringBuffer &str, bool decodeGraphs, bool includeProgress);
  489. friend void exportWorkUnitToXMLFile(const IConstWorkUnit *wu, const char * filename, unsigned extraXmlFlags, bool decodeGraphs, bool includeProgress);
  490. // NOTE - order is important - we need to construct connection before p and (especially) destruct after p
  491. Owned<IRemoteConnection> connection;
  492. Owned<IPropertyTree> p;
  493. bool dirty;
  494. bool connectAtRoot;
  495. mutable bool abortDirty;
  496. mutable bool abortState;
  497. mutable CriticalSection crit;
  498. mutable Owned<IWUQuery> query;
  499. mutable Owned<IWUWebServicesInfo> webServicesInfo;
  500. mutable Owned<IWURoxieQueryInfo> roxieQueryInfo;
  501. mutable Owned<IWorkflowItemIterator> workflowIterator;
  502. mutable bool workflowIteratorCached;
  503. mutable bool resultsCached;
  504. mutable bool temporariesCached;
  505. mutable bool variablesCached;
  506. mutable bool exceptionsCached;
  507. mutable bool pluginsCached;
  508. mutable bool librariesCached;
  509. mutable bool activitiesCached;
  510. mutable bool webServicesInfoCached;
  511. mutable bool roxieQueryInfoCached;
  512. mutable bool timersCached;
  513. mutable IArrayOf<IWUActivity> activities;
  514. mutable IArrayOf<IWUPlugin> plugins;
  515. mutable IArrayOf<IWULibrary> libraries;
  516. mutable IArrayOf<IWUException> exceptions;
  517. mutable IArrayOf<IWUGraph> graphs;
  518. mutable IArrayOf<IWUResult> results;
  519. mutable IArrayOf<IWUResult> temporaries;
  520. mutable IArrayOf<IWUResult> variables;
  521. mutable IArrayOf<IWUTimer> timers;
  522. mutable CachedTags<CLocalWUTimeStamp,IConstWUTimeStamp> timestamps;
  523. mutable CachedTags<CLocalWUAppValue,IConstWUAppValue> appvalues;
  524. mutable CachedTags<CLocalWUStatistic,IConstWUStatistic> statistics;
  525. mutable Owned<IUserDescriptor> userDesc;
  526. Mutex locked;
  527. Owned<ISecManager> secMgr;
  528. Owned<ISecUser> secUser;
  529. mutable Owned<IPropertyTree> cachedGraphs;
  530. public:
  531. IMPLEMENT_IINTERFACE;
  532. CLocalWorkUnit(IRemoteConnection *_conn, ISecManager *secmgr, ISecUser *secuser, const char *parentWuid = NULL);
  533. CLocalWorkUnit(IRemoteConnection *_conn, IPropertyTree* root, ISecManager *secmgr, ISecUser *secuser);
  534. ~CLocalWorkUnit();
  535. CLocalWorkUnit(const char *dummyWuid, const char *parentWuid, ISecManager *secmgr, ISecUser *secuser);
  536. IPropertyTree *getUnpackedTree(bool includeProgress) const;
  537. ISecManager *querySecMgr(){return secMgr.get();}
  538. ISecUser *querySecUser(){return secUser.get();}
  539. void setSecIfcs(ISecManager *mgr, ISecUser*usr){secMgr.set(mgr); secUser.set(usr);}
  540. virtual bool aborting() const;
  541. virtual void forceReload();
  542. virtual WUAction getAction() const;
  543. virtual IStringVal& getActionEx(IStringVal & str) const;
  544. virtual IStringVal & getApplicationValue(const char * application, const char * propname, IStringVal & str) const;
  545. virtual int getApplicationValueInt(const char * application, const char * propname, int defVal) const;
  546. virtual IConstWUAppValueIterator & getApplicationValues() const;
  547. virtual bool hasWorkflow() const;
  548. virtual unsigned queryEventScheduledCount() const;
  549. virtual IPropertyTree * queryWorkflowTree() const;
  550. virtual IConstWorkflowItemIterator * getWorkflowItems() const;
  551. virtual IWorkflowItemArray * getWorkflowClone() const;
  552. virtual IConstLocalFileUploadIterator * getLocalFileUploads() const;
  553. virtual bool requiresLocalFileUpload() const;
  554. virtual bool getIsQueryService() const;
  555. virtual IStringVal & getClusterName(IStringVal & str) const;
  556. virtual unsigned getCombineQueries() const;
  557. virtual WUCompareMode getCompareMode() const;
  558. virtual IStringVal & getCustomerId(IStringVal & str) const;
  559. virtual bool hasDebugValue(const char * propname) const;
  560. virtual IStringVal & getDebugValue(const char * propname, IStringVal & str) const;
  561. virtual IStringIterator & getDebugValues() const;
  562. virtual IStringIterator & getDebugValues(const char *prop) const;
  563. virtual int getDebugValueInt(const char * propname, int defVal) const;
  564. virtual __int64 getDebugValueInt64(const char * propname, __int64 defVal) const;
  565. virtual bool getDebugValueBool(const char * propname, bool defVal) const;
  566. virtual unsigned getExceptionCount() const;
  567. virtual IConstWUExceptionIterator & getExceptions() const;
  568. virtual IConstWUResult * getGlobalByName(const char * name) const;
  569. virtual unsigned getGraphCount() const;
  570. virtual unsigned getSourceFileCount() const;
  571. virtual unsigned getResultCount() const;
  572. virtual unsigned getVariableCount() const;
  573. virtual unsigned getTimerCount() const;
  574. virtual unsigned getApplicationValueCount() const;
  575. virtual IConstWUGraphIterator & getGraphs(WUGraphType type) const;
  576. virtual IConstWUGraph * getGraph(const char *name) const;
  577. virtual IConstWUGraphProgress * getGraphProgress(const char * name) const;
  578. virtual IStringVal & getJobName(IStringVal & str) const;
  579. virtual IStringVal & getParentWuid(IStringVal & str) const;
  580. virtual IConstWUPlugin * getPluginByName(const char * name) const;
  581. virtual IConstWUPluginIterator & getPlugins() const;
  582. virtual IConstWULibraryIterator & getLibraries() const;
  583. virtual WUPriorityClass getPriority() const;
  584. virtual int getPriorityLevel() const;
  585. virtual int getPriorityValue() const;
  586. virtual IConstWUQuery * getQuery() const;
  587. virtual bool getRescheduleFlag() const;
  588. virtual IConstWUResult * getResultByName(const char * name) const;
  589. virtual IConstWUResult * getResultBySequence(unsigned seq) const;
  590. virtual unsigned getResultLimit() const;
  591. virtual IConstWUResultIterator & getResults() const;
  592. virtual IConstWUActivityIterator& getActivities() const;
  593. virtual IConstWUActivity* getActivity(__int64 id) const;
  594. virtual IStringVal & getScope(IStringVal & str) const;
  595. virtual IStringVal & getSecurityToken(IStringVal & str) const;
  596. virtual WUState getState() const;
  597. virtual IStringVal & getStateEx(IStringVal & str) const;
  598. virtual __int64 getAgentSession() const;
  599. virtual unsigned getAgentPID() const;
  600. virtual IStringVal & getStateDesc(IStringVal & str) const;
  601. virtual IConstWUResult * getTemporaryByName(const char * name) const;
  602. virtual IConstWUResultIterator & getTemporaries() const;
  603. virtual unsigned getTimerCount(const char * timerName) const;
  604. virtual unsigned getTimerDuration(const char * timerName) const;
  605. virtual IStringVal & getTimerDescription(const char * timerName, IStringVal & str) const;
  606. virtual IStringIterator & getTimers() const;
  607. virtual IConstWUTimerIterator & getTimerIterator() const;
  608. virtual IConstWUTimeStampIterator & getTimeStamps() const;
  609. virtual IConstWUStatisticIterator & getStatistics() const;
  610. virtual IConstWUStatistic * getStatistic(const char * name) const;
  611. virtual IConstWUWebServicesInfo * getWebServicesInfo() const;
  612. virtual IConstWURoxieQueryInfo * getRoxieQueryInfo() const;
  613. virtual IStringVal & getXmlParams(IStringVal & params) const;
  614. virtual const IPropertyTree *getXmlParams() const;
  615. virtual unsigned __int64 getHash() const;
  616. virtual IStringIterator *getLogs(const char *type, const char *component) const;
  617. virtual IStringIterator *getProcesses(const char *type) const;
  618. virtual IPropertyTreeIterator* getProcesses(const char *type, const char *instance) const;
  619. virtual bool getWuDate(unsigned & year, unsigned & month, unsigned& day);
  620. virtual IStringVal & getSnapshot(IStringVal & str) const;
  621. virtual IStringVal & getTimeStamp(const char * name, const char * instance, IStringVal & str) const;
  622. virtual IStringVal & getUser(IStringVal & str) const;
  623. virtual IStringVal & getWuScope(IStringVal & str) const;
  624. virtual IConstWUResult * getVariableByName(const char * name) const;
  625. virtual IConstWUResultIterator & getVariables() const;
  626. virtual IStringVal & getWuid(IStringVal & str) const;
  627. virtual bool getRunningGraph(IStringVal &graphName, WUGraphIDType &subId) const;
  628. virtual bool isProtected() const;
  629. virtual bool isPausing() const;
  630. virtual bool isBilled() const;
  631. virtual IWorkUnit& lock();
  632. virtual bool reload();
  633. virtual void requestAbort();
  634. virtual void subscribe(WUSubscribeOptions options);
  635. virtual unsigned calculateHash(unsigned prevHash);
  636. virtual void copyWorkUnit(IConstWorkUnit *cached, bool all);
  637. virtual unsigned queryFileUsage(const char *filename) const;
  638. virtual bool getCloneable() const;
  639. virtual IUserDescriptor * queryUserDescriptor() const;
  640. virtual unsigned getCodeVersion() const;
  641. virtual unsigned getWuidVersion() const;
  642. virtual void getBuildVersion(IStringVal & buildVersion, IStringVal & eclVersion) const;
  643. virtual IPropertyTree * getDiskUsageStats();
  644. virtual IPropertyTreeIterator & getFileIterator() const;
  645. virtual bool archiveWorkUnit(const char *base,bool del,bool ignoredllerrors,bool deleteOwned);
  646. virtual void packWorkUnit(bool pack=true);
  647. virtual IJlibDateTime & getTimeScheduled(IJlibDateTime &val) const;
  648. virtual IPropertyTreeIterator & getFilesReadIterator() const;
  649. virtual void protect(bool protectMode);
  650. virtual IConstWULibrary * getLibraryByName(const char * name) const;
  651. virtual unsigned getDebugAgentListenerPort() const;
  652. virtual IStringVal & getDebugAgentListenerIP(IStringVal &ip) const;
  653. void clearExceptions();
  654. void commit();
  655. IWUException *createException();
  656. void setTimeStamp(const char *name, const char *instance, const char *event);
  657. void addTimeStamp(const char * name, const char * instance, const char *event);
  658. void addProcess(const char *type, const char *instance, unsigned pid, const char *log);
  659. void setAction(WUAction action);
  660. void setApplicationValue(const char * application, const char * propname, const char * value, bool overwrite);
  661. void setApplicationValueInt(const char * application, const char * propname, int value, bool overwrite);
  662. void incEventScheduledCount();
  663. void setIsQueryService(bool value);
  664. void setCloneable(bool value);
  665. void setIsClone(bool value);
  666. void setClusterName(const char * value);
  667. void setCodeVersion(unsigned version, const char * buildVersion, const char * eclVersion);
  668. void setCombineQueries(unsigned combine);
  669. void setCompareMode(WUCompareMode value);
  670. void setCustomerId(const char * value);
  671. void setDebugValue(const char * propname, const char * value, bool overwrite);
  672. void setDebugValueInt(const char * propname, int value, bool overwrite);
  673. void setJobName(const char * value);
  674. void setPriority(WUPriorityClass cls);
  675. void setPriorityLevel(int level);
  676. void setRescheduleFlag(bool value);
  677. void setResultLimit(unsigned value);
  678. void setState(WUState state);
  679. void setStateEx(const char * text);
  680. void setAgentSession(__int64 sessionId);
  681. void setSecurityToken(const char *value);
  682. void setStatistic(const char * creator, const char * wuScope, const char * stat, const char * description, StatisticMeasure kind, unsigned __int64 value, unsigned __int64 count, unsigned __int64 maxValue, bool merge);
  683. void setTimerInfo(const char * name, unsigned ms, unsigned count, unsigned __int64 max);
  684. void setTracingValue(const char * propname, const char * value);
  685. void setTracingValueInt(const char * propname, int value);
  686. void setUser(const char * value);
  687. void setWuScope(const char * value);
  688. void setBilled(bool billed);
  689. void setSnapshot(const char * value);
  690. void setTimeStamp(const char *application, const char *instance, const char *event, bool add);
  691. void setDebugAgentListenerPort(unsigned port);
  692. void setDebugAgentListenerIP(const char * ip);
  693. void setXmlParams(const char *params);
  694. void setXmlParams(IPropertyTree *tree);
  695. void setHash(unsigned __int64 hash);
  696. IWorkflowItem* addWorkflowItem(unsigned wfid, WFType type, WFMode mode, unsigned success, unsigned failure, unsigned recovery, unsigned retriesAllowed, unsigned contingencyFor);
  697. IWorkflowItemIterator * updateWorkflowItems();
  698. void syncRuntimeWorkflow(IWorkflowItemArray * array);
  699. void resetWorkflow();
  700. void schedule();
  701. void deschedule();
  702. unsigned addLocalFileUpload(LocalFileUploadType type, char const * source, char const * destination, char const * eventTag);
  703. IWUResult * updateGlobalByName(const char * name);
  704. IWUGraph * updateGraph(const char * name);
  705. IWUQuery * updateQuery();
  706. IWUWebServicesInfo* updateWebServicesInfo(bool create);
  707. IWURoxieQueryInfo* updateRoxieQueryInfo(const char *wuid, const char *roxieClusterName);
  708. IWUActivity* updateActivity(__int64 id);
  709. IWUPlugin * updatePluginByName(const char * name);
  710. IWULibrary * updateLibraryByName(const char * name);
  711. IWUResult * updateResultByName(const char * name);
  712. IWUResult * updateResultBySequence(unsigned seq);
  713. IWUResult * updateTemporaryByName(const char * name);
  714. IWUResult * updateVariableByName(const char * name);
  715. void addFile(const char *fileName, StringArray *clusters, unsigned usageCount, WUFileKind fileKind, const char *graphOwner);
  716. void noteFileRead(IDistributedFile *file);
  717. void releaseFile(const char *fileName);
  718. void clearGraphProgress();
  719. void resetBeforeGeneration();
  720. void deleteTempFiles(const char *graph, bool deleteOwned, bool deleteJobOwned);
  721. void deleteTemporaries();
  722. void addDiskUsageStats(__int64 avgNodeUsage, unsigned minNode, __int64 minNodeUsage, unsigned maxNode, __int64 maxNodeUsage, __int64 graphId);
  723. void setTimeScheduled(const IJlibDateTime &val);
  724. // ILocalWorkUnit - used for debugging etc
  725. void loadXML(const char *xml);
  726. void serialize(MemoryBuffer &tgt);
  727. void deserialize(MemoryBuffer &src);
  728. IWorkUnit &lockRemote(bool commit);
  729. void unlockRemote(bool closing);
  730. void notify(SubscriptionId id, const char *xpath, SDSNotifyFlags flags, unsigned valueLen=0, const void *valueData=NULL);
  731. void abort();
  732. void cleanupAndDelete(bool deldll,bool deleteOwned, const StringArray *deleteExclusions=NULL);
  733. bool switchThorQueue(const char *cluster, IQueueSwitcher *qs);
  734. void setAllowedClusters(const char *value);
  735. IStringVal & getAllowedClusters(IStringVal & str) const;
  736. void remoteCheckAccess(IUserDescriptor *user, bool writeaccess) const;
  737. void setAllowAutoQueueSwitch(bool val);
  738. bool getAllowAutoQueueSwitch() const;
  739. void setLibraryInformation(const char * name, unsigned interfaceHash, unsigned definitionHash);
  740. protected:
  741. IConstWUStatistic * getStatisticByDescription(const char * name) const;
  742. private:
  743. void init();
  744. IWUGraph *createGraph();
  745. IWUResult *createResult();
  746. void loadGraphs() const;
  747. void loadResults() const;
  748. void loadTemporaries() const;
  749. void loadVariables() const;
  750. void loadExceptions() const;
  751. void loadPlugins() const;
  752. void loadLibraries() const;
  753. void loadClusters() const;
  754. void loadActivities() const;
  755. void loadTimers() const;
  756. void unsubscribe();
  757. void checkAgentRunning(WUState & state);
  758. // MORE - the two could be a bit more similar...
  759. class CWorkUnitWatcher : public CInterface, implements ISDSSubscription
  760. {
  761. ISDSSubscription *parent; // not linked - it links me
  762. SubscriptionId change;
  763. bool sub;
  764. public:
  765. IMPLEMENT_IINTERFACE;
  766. CWorkUnitWatcher(ISDSSubscription *_parent, const char *wuid, bool _sub) : parent(_parent), sub(_sub)
  767. {
  768. StringBuffer wuRoot;
  769. getXPath(wuRoot, wuid);
  770. change = querySDS().subscribe(wuRoot.str(), *this, sub);
  771. }
  772. ~CWorkUnitWatcher()
  773. {
  774. assertex(change==0);
  775. }
  776. bool watchingChildren()
  777. {
  778. return sub;
  779. }
  780. void unsubscribe()
  781. {
  782. querySDS().unsubscribe(change);
  783. change = 0;
  784. }
  785. void notify(SubscriptionId id, const char *xpath, SDSNotifyFlags flags, unsigned valueLen, const void *valueData)
  786. {
  787. parent->notify(id, xpath, flags, valueLen, valueData);
  788. }
  789. };
  790. class CWorkUnitAbortWatcher : public CInterface, implements ISDSSubscription
  791. {
  792. CLocalWorkUnit *parent; // not linked - it links me
  793. SubscriptionId abort;
  794. public:
  795. IMPLEMENT_IINTERFACE;
  796. CWorkUnitAbortWatcher(CLocalWorkUnit *_parent, const char *wuid) : parent(_parent)
  797. {
  798. StringBuffer wuRoot;
  799. wuRoot.append("/WorkUnitAborts/").append(wuid);
  800. abort = querySDS().subscribe(wuRoot.str(), *this);
  801. }
  802. ~CWorkUnitAbortWatcher()
  803. {
  804. assertex(abort==0);
  805. }
  806. void unsubscribe()
  807. {
  808. querySDS().unsubscribe(abort);
  809. abort = 0;
  810. }
  811. void notify(SubscriptionId id, const char *xpath, SDSNotifyFlags flags, unsigned valueLen, const void *valueData)
  812. {
  813. parent->abort();
  814. }
  815. };
  816. Owned<CWorkUnitAbortWatcher> abortWatcher;
  817. Owned<CWorkUnitWatcher> changeWatcher;
  818. void ensureGraphsUnpacked ()
  819. {
  820. IPropertyTree *t = p->queryPropTree("PackedGraphs");
  821. MemoryBuffer buf;
  822. if (t&&t->getPropBin(NULL,buf)) {
  823. cachedGraphs.clear();
  824. IPropertyTree *st = createPTree(buf);
  825. if (st) {
  826. p->setPropTree("Graphs",st);
  827. p->removeTree(t);
  828. }
  829. }
  830. }
  831. };
  832. class CLockedWorkUnit : public CInterface, implements ILocalWorkUnit, implements IExtendedWUInterface
  833. {
  834. public:
  835. Owned<CLocalWorkUnit> c;
  836. IMPLEMENT_IINTERFACE;
  837. CLockedWorkUnit(CLocalWorkUnit *_c) : c(_c) {}
  838. ~CLockedWorkUnit()
  839. {
  840. if (workUnitTraceLevel > 1)
  841. {
  842. StringAttr x;
  843. StringAttrAdaptor strval(x);
  844. getWuid(strval);
  845. PrintLog("Releasing locked workunit %s", x.get());
  846. }
  847. if (c)
  848. c->unlockRemote(c->IsShared());
  849. }
  850. void setSecIfcs(ISecManager *mgr, ISecUser*usr){c->setSecIfcs(mgr, usr);}
  851. virtual IConstWorkUnit * unlock()
  852. {
  853. c->unlockRemote(c->IsShared());
  854. return c.getClear();
  855. }
  856. virtual bool aborting() const
  857. { return c->aborting(); }
  858. virtual void forceReload()
  859. { UNIMPLEMENTED; }
  860. virtual WUAction getAction() const
  861. { return c->getAction(); }
  862. virtual IStringVal& getActionEx(IStringVal & str) const
  863. { return c->getActionEx(str); }
  864. virtual IStringVal & getApplicationValue(const char * application, const char * propname, IStringVal & str) const
  865. { return c->getApplicationValue(application, propname, str); }
  866. virtual int getApplicationValueInt(const char * application, const char * propname, int defVal) const
  867. { return c->getApplicationValueInt(application, propname, defVal); }
  868. virtual IConstWUAppValueIterator & getApplicationValues() const
  869. { return c->getApplicationValues(); }
  870. virtual bool hasWorkflow() const
  871. { return c->hasWorkflow(); }
  872. virtual unsigned queryEventScheduledCount() const
  873. { return c->queryEventScheduledCount(); }
  874. virtual IPropertyTree * queryWorkflowTree() const
  875. { return c->queryWorkflowTree(); }
  876. virtual IConstWorkflowItemIterator * getWorkflowItems() const
  877. { return c->getWorkflowItems(); }
  878. virtual IWorkflowItemArray * getWorkflowClone() const
  879. { return c->getWorkflowClone(); }
  880. virtual bool requiresLocalFileUpload() const
  881. { return c->requiresLocalFileUpload(); }
  882. virtual IConstLocalFileUploadIterator * getLocalFileUploads() const
  883. { return c->getLocalFileUploads(); }
  884. virtual bool getIsQueryService() const
  885. { return c->getIsQueryService(); }
  886. virtual bool getCloneable() const
  887. { return c->getCloneable(); }
  888. virtual IUserDescriptor * queryUserDescriptor() const
  889. { return c->queryUserDescriptor(); }
  890. virtual IStringVal & getClusterName(IStringVal & str) const
  891. { return c->getClusterName(str); }
  892. virtual unsigned getCodeVersion() const
  893. { return c->getCodeVersion(); }
  894. virtual unsigned getWuidVersion() const
  895. { return c->getWuidVersion(); }
  896. virtual void getBuildVersion(IStringVal & buildVersion, IStringVal & eclVersion) const
  897. { c->getBuildVersion(buildVersion, eclVersion); }
  898. virtual unsigned getCombineQueries() const
  899. { return c->getCombineQueries(); }
  900. virtual WUCompareMode getCompareMode() const
  901. { return c->getCompareMode(); }
  902. virtual IStringVal & getCustomerId(IStringVal & str) const
  903. { return c->getCustomerId(str); }
  904. virtual bool hasDebugValue(const char * propname) const
  905. { return c->hasDebugValue(propname); }
  906. virtual IStringVal & getDebugValue(const char * propname, IStringVal & str) const
  907. { return c->getDebugValue(propname, str); }
  908. virtual int getDebugValueInt(const char * propname, int defVal) const
  909. { return c->getDebugValueInt(propname, defVal); }
  910. virtual __int64 getDebugValueInt64(const char * propname, __int64 defVal) const
  911. { return c->getDebugValueInt64(propname, defVal); }
  912. virtual bool getDebugValueBool(const char * propname, bool defVal) const
  913. { return c->getDebugValueBool(propname, defVal); }
  914. virtual IStringIterator & getDebugValues() const
  915. { return c->getDebugValues(NULL); }
  916. virtual IStringIterator & getDebugValues(const char *prop) const
  917. { return c->getDebugValues(prop); }
  918. virtual unsigned getExceptionCount() const
  919. { return c->getExceptionCount(); }
  920. virtual IConstWUExceptionIterator & getExceptions() const
  921. { return c->getExceptions(); }
  922. virtual unsigned getGraphCount() const
  923. { return c->getGraphCount(); }
  924. virtual unsigned getSourceFileCount() const
  925. { return c->getSourceFileCount(); }
  926. virtual unsigned getResultCount() const
  927. { return c->getResultCount(); }
  928. virtual unsigned getVariableCount() const
  929. { return c->getVariableCount(); }
  930. virtual unsigned getTimerCount() const
  931. { return c->getTimerCount(); }
  932. virtual unsigned getApplicationValueCount() const
  933. { return c->getApplicationValueCount(); }
  934. virtual IConstWUGraphIterator & getGraphs(WUGraphType type) const
  935. { return c->getGraphs(type); }
  936. virtual IConstWUGraph * getGraph(const char *name) const
  937. { return c->getGraph(name); }
  938. virtual IConstWUGraphProgress * getGraphProgress(const char * name) const
  939. { return c->getGraphProgress(name); }
  940. virtual IStringVal & getJobName(IStringVal & str) const
  941. { return c->getJobName(str); }
  942. virtual IStringVal & getParentWuid(IStringVal & str) const
  943. { return c->getParentWuid(str); }
  944. virtual IConstWUPlugin * getPluginByName(const char * name) const
  945. { return c->getPluginByName(name); }
  946. virtual IConstWUPluginIterator & getPlugins() const
  947. { return c->getPlugins(); }
  948. virtual IConstWULibrary* getLibraryByName(const char *name) const
  949. { return c->getLibraryByName(name); }
  950. virtual IConstWULibraryIterator & getLibraries() const
  951. { return c->getLibraries(); }
  952. virtual WUPriorityClass getPriority() const
  953. { return c->getPriority(); }
  954. virtual int getPriorityLevel() const
  955. { return c->getPriorityLevel(); }
  956. virtual int getPriorityValue() const
  957. { return c->getPriorityValue(); }
  958. virtual IConstWUQuery * getQuery() const
  959. { return c->getQuery(); }
  960. virtual IConstWUWebServicesInfo * getWebServicesInfo() const
  961. { return c->getWebServicesInfo(); }
  962. virtual IConstWURoxieQueryInfo* getRoxieQueryInfo() const
  963. { return c->getRoxieQueryInfo(); }
  964. virtual bool getRescheduleFlag() const
  965. { return c->getRescheduleFlag(); }
  966. virtual IConstWUResult * getResultByName(const char * name) const
  967. { return c->getResultByName(name); }
  968. virtual IConstWUResult * getResultBySequence(unsigned seq) const
  969. { return c->getResultBySequence(seq); }
  970. virtual unsigned getResultLimit() const
  971. { return c->getResultLimit(); }
  972. virtual IConstWUResultIterator & getResults() const
  973. { return c->getResults(); }
  974. virtual IConstWUActivityIterator & getActivities() const
  975. { return c->getActivities(); }
  976. virtual IConstWUActivity * getActivity(__int64 id) const
  977. { return c->getActivity(id); }
  978. virtual IStringVal & getScope(IStringVal & str) const
  979. { return c->getScope(str); }
  980. virtual IStringVal & getSecurityToken(IStringVal & str) const
  981. { return c->getSecurityToken(str); }
  982. virtual WUState getState() const
  983. { return c->getState(); }
  984. virtual IStringVal & getStateEx(IStringVal & str) const
  985. { return c->getStateEx(str); }
  986. virtual __int64 getAgentSession() const
  987. { return c->getAgentSession(); }
  988. virtual unsigned getAgentPID() const
  989. { return c->getAgentPID(); }
  990. virtual IStringVal & getStateDesc(IStringVal & str) const
  991. { return c->getStateDesc(str); }
  992. virtual bool getRunningGraph(IStringVal & graphName, WUGraphIDType & subId) const
  993. { return c->getRunningGraph(graphName, subId); }
  994. virtual unsigned getTimerCount(const char * timerName) const
  995. { return c->getTimerCount(timerName); }
  996. virtual unsigned getTimerDuration(const char * timerName) const
  997. { return c->getTimerDuration(timerName); }
  998. virtual IStringVal & getTimerDescription(const char * timerName, IStringVal & str) const
  999. { return c->getTimerDescription(timerName, str); }
  1000. virtual IStringVal & getTimeStamp(const char * name, const char * instance, IStringVal & str) const
  1001. { return c->getTimeStamp(name, instance, str); }
  1002. virtual IStringIterator & getTimers() const
  1003. { return c->getTimers(); }
  1004. virtual IConstWUTimerIterator & getTimerIterator() const
  1005. { return c->getTimerIterator(); }
  1006. virtual IConstWUTimeStampIterator & getTimeStamps() const
  1007. { return c->getTimeStamps(); }
  1008. virtual IConstWUStatisticIterator & getStatistics() const
  1009. { return c->getStatistics(); }
  1010. virtual IConstWUStatistic * getStatistic(const char * name) const
  1011. { return c->getStatistic(name); }
  1012. virtual bool getWuDate(unsigned & year, unsigned & month, unsigned& day)
  1013. { return c->getWuDate(year,month,day);}
  1014. virtual IStringVal & getSnapshot(IStringVal & str) const
  1015. { return c->getSnapshot(str); }
  1016. virtual IStringVal & getUser(IStringVal & str) const
  1017. { return c->getUser(str); }
  1018. virtual IStringVal & getWuScope(IStringVal & str) const
  1019. { return c->getWuScope(str); }
  1020. virtual IStringVal & getWuid(IStringVal & str) const
  1021. { return c->getWuid(str); }
  1022. virtual IConstWUResult * getGlobalByName(const char * name) const
  1023. { return c->getGlobalByName(name); }
  1024. virtual IConstWUResult * getTemporaryByName(const char * name) const
  1025. { return c->getTemporaryByName(name); }
  1026. virtual IConstWUResultIterator & getTemporaries() const
  1027. { return c->getTemporaries(); }
  1028. virtual IConstWUResult * getVariableByName(const char * name) const
  1029. { return c->getVariableByName(name); }
  1030. virtual IConstWUResultIterator & getVariables() const
  1031. { return c->getVariables(); }
  1032. virtual bool isProtected() const
  1033. { return c->isProtected(); }
  1034. virtual bool isPausing() const
  1035. { return c->isPausing(); }
  1036. virtual bool isBilled() const
  1037. { return c->isBilled(); }
  1038. virtual IWorkUnit & lock()
  1039. { ((CInterface *)this)->Link(); return (IWorkUnit &) *this; }
  1040. virtual bool reload()
  1041. { UNIMPLEMENTED; }
  1042. virtual void subscribe(WUSubscribeOptions options)
  1043. { c->subscribe(options); }
  1044. virtual void requestAbort()
  1045. { c->requestAbort(); }
  1046. virtual unsigned calculateHash(unsigned prevHash)
  1047. { return c->calculateHash(prevHash); }
  1048. virtual void copyWorkUnit(IConstWorkUnit *cached, bool all)
  1049. { c->copyWorkUnit(cached, all); }
  1050. virtual bool archiveWorkUnit(const char *base,bool del,bool deldll,bool deleteOwned)
  1051. { return c->archiveWorkUnit(base,del,deldll,deleteOwned); }
  1052. virtual void packWorkUnit(bool pack)
  1053. { c->packWorkUnit(pack); }
  1054. virtual unsigned queryFileUsage(const char *filename) const
  1055. { return c->queryFileUsage(filename); }
  1056. virtual IJlibDateTime & getTimeScheduled(IJlibDateTime &val) const
  1057. { return c->getTimeScheduled(val); }
  1058. virtual unsigned getDebugAgentListenerPort() const
  1059. { return c->getDebugAgentListenerPort(); }
  1060. virtual IStringVal & getDebugAgentListenerIP(IStringVal &ip) const
  1061. { return c->getDebugAgentListenerIP(ip); }
  1062. virtual IStringVal & getXmlParams(IStringVal & params) const
  1063. { return c->getXmlParams(params); }
  1064. virtual const IPropertyTree *getXmlParams() const
  1065. { return c->getXmlParams(); }
  1066. virtual unsigned __int64 getHash() const
  1067. { return c->getHash(); }
  1068. virtual IStringIterator *getLogs(const char *type, const char *instance) const
  1069. { return c->getLogs(type, instance); }
  1070. virtual IStringIterator *getProcesses(const char *type) const
  1071. { return c->getProcesses(type); }
  1072. virtual IPropertyTreeIterator* getProcesses(const char *type, const char *instance) const
  1073. { return c->getProcesses(type, instance); }
  1074. virtual void clearExceptions()
  1075. { c->clearExceptions(); }
  1076. virtual void commit()
  1077. { c->commit(); }
  1078. virtual IWUException * createException()
  1079. { return c->createException(); }
  1080. virtual void setTimeStamp(const char * name, const char * instance, const char *event)
  1081. { c->setTimeStamp(name, instance, event); }
  1082. virtual void addTimeStamp(const char * name, const char * instance, const char *event)
  1083. { c->addTimeStamp(name, instance, event); }
  1084. virtual void addProcess(const char *type, const char *instance, unsigned pid, const char *log)
  1085. { c->addProcess(type, instance, pid, log); }
  1086. virtual void protect(bool protectMode)
  1087. { c->protect(protectMode); }
  1088. virtual void setBilled(bool billed)
  1089. { c->setBilled(billed); }
  1090. virtual void setAction(WUAction action)
  1091. { c->setAction(action); }
  1092. virtual void setApplicationValue(const char * application, const char * propname, const char * value, bool overwrite)
  1093. { c->setApplicationValue(application, propname, value, overwrite); }
  1094. virtual void setApplicationValueInt(const char * application, const char * propname, int value, bool overwrite)
  1095. { c->setApplicationValueInt(application, propname, value, overwrite); }
  1096. virtual void incEventScheduledCount()
  1097. { c->incEventScheduledCount(); }
  1098. virtual void setIsQueryService(bool value)
  1099. { c->setIsQueryService(value); }
  1100. virtual void setCloneable(bool value)
  1101. { c->setCloneable(value); }
  1102. virtual void setIsClone(bool value)
  1103. { c->setIsClone(value); }
  1104. virtual void setClusterName(const char * value)
  1105. { c->setClusterName(value); }
  1106. virtual void setCodeVersion(unsigned version, const char * buildVersion, const char * eclVersion)
  1107. { c->setCodeVersion(version, buildVersion, eclVersion); }
  1108. virtual void setCombineQueries(unsigned combine)
  1109. { c->setCombineQueries(combine); }
  1110. virtual void setCompareMode(WUCompareMode value)
  1111. { c->setCompareMode(value); }
  1112. virtual void setCustomerId(const char * value)
  1113. { c->setCustomerId(value); }
  1114. virtual void setDebugValue(const char * propname, const char * value, bool overwrite)
  1115. { c->setDebugValue(propname, value, overwrite); }
  1116. virtual void setDebugValueInt(const char * propname, int value, bool overwrite)
  1117. { c->setDebugValueInt(propname, value, overwrite); }
  1118. virtual void setJobName(const char * value)
  1119. { c->setJobName(value); }
  1120. virtual void setPriority(WUPriorityClass cls)
  1121. { c->setPriority(cls); }
  1122. virtual void setPriorityLevel(int level)
  1123. { c->setPriorityLevel(level); }
  1124. virtual void setRescheduleFlag(bool value)
  1125. { c->setRescheduleFlag(value); }
  1126. virtual void setResultLimit(unsigned value)
  1127. { c->setResultLimit(value); }
  1128. virtual void setSecurityToken(const char *value)
  1129. { c->setSecurityToken(value); }
  1130. virtual void setState(WUState state)
  1131. { c->setState(state); }
  1132. virtual void setStateEx(const char * text)
  1133. { c->setStateEx(text); }
  1134. virtual void setAgentSession(__int64 sessionId)
  1135. { c->setAgentSession(sessionId); }
  1136. virtual void setTimerInfo(const char * name, unsigned ms, unsigned count, unsigned __int64 max)
  1137. { c->setTimerInfo(name, ms, count, max); }
  1138. virtual void setStatistic(const char * creator, const char * wuScope, const char * stat, const char * description, StatisticMeasure kind, unsigned __int64 value, unsigned __int64 count, unsigned __int64 maxValue, bool merge)
  1139. { c->setStatistic(creator, wuScope, stat, description, kind, value, count, maxValue, merge); }
  1140. virtual void setTracingValue(const char * propname, const char * value)
  1141. { c->setTracingValue(propname, value); }
  1142. virtual void setTracingValueInt(const char * propname, int value)
  1143. { c->setTracingValueInt(propname, value); }
  1144. virtual void setUser(const char * value)
  1145. { c->setUser(value); }
  1146. virtual void setWuScope(const char * value)
  1147. {
  1148. if (value && *value)
  1149. {
  1150. ISecManager *secmgr=c->querySecMgr();
  1151. ISecUser *secusr=c->querySecUser();
  1152. if (!secmgr || !secusr)
  1153. throw MakeStringException(WUERR_SecurityNotAvailable, "Trying to change workunit scope without security interfaces available");
  1154. if (checkWuScopeSecAccess(value, *secmgr, secusr, SecAccess_Write, "Change Scope", true, true))
  1155. c->setWuScope(value);
  1156. }
  1157. }
  1158. virtual IWorkflowItem* addWorkflowItem(unsigned wfid, WFType type, WFMode mode, unsigned success, unsigned failure, unsigned recovery, unsigned retriesAllowed, unsigned contingencyFor)
  1159. { return c->addWorkflowItem(wfid, type, mode, success, failure, recovery, retriesAllowed, contingencyFor); }
  1160. virtual void syncRuntimeWorkflow(IWorkflowItemArray * array)
  1161. { c->syncRuntimeWorkflow(array); }
  1162. virtual IWorkflowItemIterator * updateWorkflowItems()
  1163. { return c->updateWorkflowItems(); }
  1164. virtual void resetWorkflow()
  1165. { c->resetWorkflow(); }
  1166. virtual void schedule()
  1167. { c->schedule(); }
  1168. virtual void deschedule()
  1169. { c->deschedule(); }
  1170. virtual unsigned addLocalFileUpload(LocalFileUploadType type, char const * source, char const * destination, char const * eventTag)
  1171. { return c->addLocalFileUpload(type, source, destination, eventTag); }
  1172. virtual IWUResult * updateGlobalByName(const char * name)
  1173. { return c->updateGlobalByName(name); }
  1174. virtual IWUGraph * updateGraph(const char * name)
  1175. { return c->updateGraph(name); }
  1176. virtual IWUQuery * updateQuery()
  1177. { return c->updateQuery(); }
  1178. virtual IWUWebServicesInfo * updateWebServicesInfo(bool create)
  1179. { return c->updateWebServicesInfo(create); }
  1180. virtual IWURoxieQueryInfo * updateRoxieQueryInfo(const char *wuid, const char *roxieClusterName)
  1181. { return c->updateRoxieQueryInfo(wuid, roxieClusterName); }
  1182. virtual IWUActivity * updateActivity(__int64 id)
  1183. { return c->updateActivity(id); }
  1184. virtual IWUPlugin * updatePluginByName(const char * name)
  1185. { return c->updatePluginByName(name); }
  1186. virtual IWULibrary * updateLibraryByName(const char * name)
  1187. { return c->updateLibraryByName(name); }
  1188. virtual IWUResult * updateResultByName(const char * name)
  1189. { return c->updateResultByName(name); }
  1190. virtual IWUResult * updateResultBySequence(unsigned seq)
  1191. { return c->updateResultBySequence(seq); }
  1192. virtual IWUResult * updateTemporaryByName(const char * name)
  1193. { return c->updateTemporaryByName(name); }
  1194. virtual IWUResult * updateVariableByName(const char * name)
  1195. { return c->updateVariableByName(name); }
  1196. virtual void addFile(const char *fileName, StringArray *clusters, unsigned usageCount, WUFileKind fileKind, const char *graphOwner)
  1197. { c->addFile(fileName, clusters, usageCount, fileKind, graphOwner); }
  1198. virtual void noteFileRead(IDistributedFile *file)
  1199. { c->noteFileRead(file); }
  1200. virtual void releaseFile(const char *fileName)
  1201. { c->releaseFile(fileName); }
  1202. virtual void clearGraphProgress()
  1203. { c->clearGraphProgress(); }
  1204. virtual void resetBeforeGeneration()
  1205. { c->resetBeforeGeneration(); }
  1206. virtual void deleteTempFiles(const char *graph, bool deleteOwned, bool deleteJobOwned)
  1207. { c->deleteTempFiles(graph, deleteOwned, deleteJobOwned); }
  1208. virtual void deleteTemporaries()
  1209. { c->deleteTemporaries(); }
  1210. virtual void addDiskUsageStats(__int64 avgNodeUsage, unsigned minNode, __int64 minNodeUsage, unsigned maxNode, __int64 maxNodeUsage, __int64 graphId)
  1211. { c->addDiskUsageStats(avgNodeUsage, minNode, minNodeUsage, maxNode, maxNodeUsage, graphId); }
  1212. virtual IPropertyTree * getDiskUsageStats()
  1213. { return c->getDiskUsageStats(); }
  1214. virtual IPropertyTreeIterator & getFileIterator() const
  1215. { return c->getFileIterator(); }
  1216. virtual IPropertyTreeIterator & getFilesReadIterator() const
  1217. { return c->getFilesReadIterator(); }
  1218. virtual void setSnapshot(const char * value)
  1219. { c->setSnapshot(value); }
  1220. virtual void setTimeScheduled(const IJlibDateTime &val)
  1221. { c->setTimeScheduled(val); }
  1222. virtual void setDebugAgentListenerPort(unsigned port)
  1223. { c->setDebugAgentListenerPort(port); }
  1224. virtual void setDebugAgentListenerIP(const char * ip)
  1225. { c->setDebugAgentListenerIP(ip); }
  1226. virtual void setXmlParams(const char *params)
  1227. { c->setXmlParams(params); }
  1228. virtual void setXmlParams(IPropertyTree *tree)
  1229. { c->setXmlParams(tree); }
  1230. virtual void setHash(unsigned __int64 hash)
  1231. { c->setHash(hash); }
  1232. // ILocalWorkUnit - used for debugging etc
  1233. virtual void loadXML(const char *xml)
  1234. { c->loadXML(xml); }
  1235. virtual void serialize(MemoryBuffer &tgt)
  1236. { c->serialize(tgt); }
  1237. virtual void deserialize(MemoryBuffer &src)
  1238. { c->deserialize(src); }
  1239. virtual bool switchThorQueue(const char *cluster, IQueueSwitcher *qs)
  1240. { return c->switchThorQueue(cluster,qs); }
  1241. virtual void setAllowedClusters(const char *value)
  1242. { c->setAllowedClusters(value); }
  1243. virtual IStringVal& getAllowedClusters(IStringVal &str) const
  1244. { return c->getAllowedClusters(str); }
  1245. virtual void remoteCheckAccess(IUserDescriptor *user, bool writeaccess) const
  1246. { c->remoteCheckAccess(user,writeaccess); }
  1247. virtual void setAllowAutoQueueSwitch(bool val)
  1248. { c->setAllowAutoQueueSwitch(val); }
  1249. virtual bool getAllowAutoQueueSwitch() const
  1250. { return c->getAllowAutoQueueSwitch(); }
  1251. virtual void setLibraryInformation(const char * name, unsigned interfaceHash, unsigned definitionHash)
  1252. { c->setLibraryInformation(name, interfaceHash, definitionHash); }
  1253. virtual void setResultInt(const char * name, unsigned sequence, __int64 val)
  1254. {
  1255. Owned<IWUResult> r = updateResult(name, sequence);
  1256. if (r)
  1257. {
  1258. r->setResultInt(val);
  1259. r->setResultStatus(ResultStatusCalculated);
  1260. }
  1261. }
  1262. virtual void setResultUInt(const char * name, unsigned sequence, unsigned __int64 val)
  1263. {
  1264. Owned<IWUResult> r = updateResult(name, sequence);
  1265. if (r)
  1266. {
  1267. r->setResultUInt(val);
  1268. r->setResultStatus(ResultStatusCalculated);
  1269. }
  1270. }
  1271. virtual void setResultReal(const char *name, unsigned sequence, double val)
  1272. {
  1273. Owned<IWUResult> r = updateResult(name, sequence);
  1274. if (r)
  1275. {
  1276. r->setResultReal(val);
  1277. r->setResultStatus(ResultStatusCalculated);
  1278. }
  1279. }
  1280. virtual void setResultVarString(const char * stepname, unsigned sequence, const char *val)
  1281. {
  1282. setResultString(stepname, sequence, strlen(val), val);
  1283. }
  1284. virtual void setResultVarUnicode(const char * stepname, unsigned sequence, UChar const *val)
  1285. {
  1286. setResultUnicode(stepname, sequence, rtlUnicodeStrlen(val), val);
  1287. }
  1288. virtual void setResultString(const char * stepname, unsigned sequence, int len, const char *val)
  1289. {
  1290. doSetResultString(type_string, stepname, sequence, len, val);
  1291. }
  1292. virtual void setResultData(const char * stepname, unsigned sequence, int len, const void *val)
  1293. {
  1294. doSetResultString(type_data, stepname, sequence, len, (const char *)val);
  1295. }
  1296. virtual void setResultRaw(const char * name, unsigned sequence, int len, const void *val)
  1297. {
  1298. Owned<IWUResult> r = updateResult(name, sequence);
  1299. if (r)
  1300. {
  1301. r->setResultRaw(len, val, ResultFormatRaw);
  1302. r->setResultStatus(ResultStatusCalculated);
  1303. }
  1304. }
  1305. virtual void setResultSet(const char * name, unsigned sequence, bool isAll, size32_t len, const void *val, ISetToXmlTransformer *)
  1306. {
  1307. Owned<IWUResult> r = updateResult(name, sequence);
  1308. if (r)
  1309. {
  1310. r->setResultIsAll(isAll);
  1311. r->setResultRaw(len, val, ResultFormatRaw);
  1312. r->setResultStatus(ResultStatusCalculated);
  1313. }
  1314. }
  1315. virtual void setResultUnicode(const char * name, unsigned sequence, int len, UChar const * val)
  1316. {
  1317. Owned<IWUResult> r = updateResult(name, sequence);
  1318. if (r)
  1319. {
  1320. r->setResultUnicode((char const *)val, len);
  1321. r->setResultStatus(ResultStatusCalculated);
  1322. }
  1323. }
  1324. virtual void setResultBool(const char *name, unsigned sequence, bool val)
  1325. {
  1326. Owned<IWUResult> r = updateResult(name, sequence);
  1327. if (r)
  1328. {
  1329. r->setResultBool(val);
  1330. r->setResultStatus(ResultStatusCalculated);
  1331. }
  1332. }
  1333. virtual void setResultDecimal(const char *name, unsigned sequence, int len, int precision, bool isSigned, const void *val)
  1334. {
  1335. Owned<IWUResult> r = updateResult(name, sequence);
  1336. if (r)
  1337. {
  1338. r->setResultDecimal(val, len);
  1339. r->setResultStatus(ResultStatusCalculated);
  1340. }
  1341. }
  1342. virtual void setResultDataset(const char * name, unsigned sequence, size32_t len, const void *val, unsigned numRows, bool extend)
  1343. {
  1344. Owned<IWUResult> r = updateResult(name, sequence);
  1345. if (r)
  1346. {
  1347. __int64 totalRows = numRows;
  1348. if (extend)
  1349. {
  1350. totalRows += r->getResultRowCount();
  1351. r->addResultRaw(len, val, ResultFormatRaw);
  1352. }
  1353. else
  1354. r->setResultRaw(len, val, ResultFormatRaw);
  1355. r->setResultStatus(ResultStatusCalculated);
  1356. r->setResultRowCount(totalRows);
  1357. r->setResultTotalRowCount(totalRows);
  1358. }
  1359. }
  1360. protected:
  1361. IWUResult *updateResult(const char *name, unsigned sequence)
  1362. {
  1363. Owned <IWUResult> result = updateWorkUnitResult(this, name, sequence);
  1364. if (result)
  1365. {
  1366. SCMStringBuffer rname;
  1367. if (!result->getResultName(rname).length())
  1368. result->setResultName(name);
  1369. }
  1370. return result.getClear();
  1371. }
  1372. void doSetResultString(type_t type, const char *name, unsigned sequence, int len, const char *val)
  1373. {
  1374. Owned<IWUResult> r = updateResult(name, sequence);
  1375. if (r)
  1376. {
  1377. r->setResultString(val, len);
  1378. r->setResultStatus(ResultStatusCalculated);
  1379. }
  1380. }
  1381. };
  1382. class CLocalWUAssociated : public CInterface, implements IConstWUAssociatedFile
  1383. {
  1384. Owned<IPropertyTree> p;
  1385. public:
  1386. IMPLEMENT_IINTERFACE;
  1387. CLocalWUAssociated(IPropertyTree *p);
  1388. virtual WUFileType getType() const;
  1389. virtual IStringVal & getDescription(IStringVal & ret) const;
  1390. virtual IStringVal & getIp(IStringVal & ret) const;
  1391. virtual IStringVal & getName(IStringVal & ret) const;
  1392. virtual IStringVal & getNameTail(IStringVal & ret) const;
  1393. virtual unsigned getCrc() const;
  1394. };
  1395. class CLocalWUQuery : public CInterface, implements IWUQuery
  1396. {
  1397. Owned<IPropertyTree> p;
  1398. mutable IArrayOf<IConstWUAssociatedFile> associated;
  1399. mutable CriticalSection crit;
  1400. mutable bool associatedCached;
  1401. private:
  1402. void addSpecialCaseAssociated(WUFileType type, const char * propname, unsigned crc) const;
  1403. void loadAssociated() const;
  1404. public:
  1405. IMPLEMENT_IINTERFACE;
  1406. CLocalWUQuery(IPropertyTree *p);
  1407. virtual WUQueryType getQueryType() const;
  1408. virtual IStringVal& getQueryText(IStringVal &str) const;
  1409. virtual IStringVal& getQueryShortText(IStringVal &str) const;
  1410. virtual IStringVal& getQueryName(IStringVal &str) const;
  1411. virtual IStringVal & getQueryMainDefinition(IStringVal & str) const;
  1412. virtual IStringVal& getQueryDllName(IStringVal &str) const;
  1413. virtual unsigned getQueryDllCrc() const;
  1414. virtual IStringVal& getQueryCppName(IStringVal &str) const;
  1415. virtual IStringVal& getQueryResTxtName(IStringVal &str) const;
  1416. virtual IConstWUAssociatedFile * getAssociatedFile(WUFileType type, unsigned index) const;
  1417. virtual IConstWUAssociatedFileIterator& getAssociatedFiles() const;
  1418. virtual void setQueryType(WUQueryType qt);
  1419. virtual void setQueryText(const char *pstr);
  1420. virtual void setQueryName(const char *);
  1421. virtual void setQueryMainDefinition(const char * str);
  1422. virtual void addAssociatedFile(WUFileType type, const char * name, const char * ip, const char * desc, unsigned crc);
  1423. virtual void removeAssociatedFiles();
  1424. };
  1425. class CLocalWUWebServicesInfo : public CInterface, implements IWUWebServicesInfo
  1426. {
  1427. Owned<IPropertyTree> p;
  1428. mutable CriticalSection crit;
  1429. private:
  1430. public:
  1431. IMPLEMENT_IINTERFACE;
  1432. CLocalWUWebServicesInfo(IPropertyTree *p);
  1433. virtual IStringVal& getModuleName(IStringVal &str) const;
  1434. virtual IStringVal& getAttributeName(IStringVal &str) const;
  1435. virtual IStringVal& getDefaultName(IStringVal &str) const;
  1436. virtual IStringVal& getInfo(const char *name, IStringVal &str) const;
  1437. virtual unsigned getWebServicesCRC() const;
  1438. virtual void setModuleName(const char *);
  1439. virtual void setAttributeName(const char *);
  1440. virtual void setDefaultName(const char *);
  1441. virtual void setInfo(const char *name, const char *info);
  1442. virtual void setWebServicesCRC(unsigned);
  1443. };
  1444. class CLocalWURoxieQueryInfo : public CInterface, implements IWURoxieQueryInfo
  1445. {
  1446. Owned<IPropertyTree> p;
  1447. mutable CriticalSection crit;
  1448. private:
  1449. public:
  1450. IMPLEMENT_IINTERFACE;
  1451. CLocalWURoxieQueryInfo(IPropertyTree *p);
  1452. virtual IStringVal& getQueryInfo(IStringVal &str) const;
  1453. virtual IStringVal& getDefaultPackageInfo(IStringVal &str) const;
  1454. virtual IStringVal& getRoxieClusterName(IStringVal &str) const;
  1455. virtual IStringVal& getWuid(IStringVal &str) const;
  1456. virtual void setQueryInfo(const char *info);
  1457. virtual void setDefaultPackageInfo(const char *, int len);
  1458. virtual void setRoxieClusterName(const char *str);
  1459. virtual void setWuid(const char *str);
  1460. };
  1461. class CLocalWUResult : public CInterface, implements IWUResult
  1462. {
  1463. friend class CLocalWorkUnit;
  1464. mutable CriticalSection crit;
  1465. Owned<IPropertyTree> p;
  1466. Owned<IProperties> xmlns;
  1467. void getSchema(TypeInfoArray &types, StringAttrArray &names, IStringVal * ecl=NULL) const;
  1468. public:
  1469. IMPLEMENT_IINTERFACE;
  1470. CLocalWUResult(IPropertyTree *props);
  1471. ~CLocalWUResult() { try { p.clear(); } catch (IException *E) {E->Release();}}
  1472. virtual WUResultStatus getResultStatus() const;
  1473. virtual IStringVal& getResultName(IStringVal &str) const;
  1474. virtual int getResultSequence() const;
  1475. virtual bool isResultScalar() const;
  1476. virtual IStringVal& getResultXml(IStringVal &str) const;
  1477. virtual unsigned getResultFetchSize() const;
  1478. virtual __int64 getResultTotalRowCount() const;
  1479. virtual __int64 getResultRowCount() const;
  1480. virtual void getResultDataset(IStringVal & ecl, IStringVal & defs) const;
  1481. virtual IStringVal& getResultLogicalName(IStringVal &ecl) const;
  1482. virtual IStringVal& getResultKeyField(IStringVal& ecl) const;
  1483. virtual unsigned getResultRequestedRows() const;
  1484. virtual __int64 getResultInt() const;
  1485. virtual bool getResultBool() const;
  1486. virtual double getResultReal() const;
  1487. virtual IStringVal& getResultString(IStringVal & str) const;
  1488. virtual IDataVal& getResultRaw(IDataVal & data, IXmlToRawTransformer * xmlTransformer, ICsvToRawTransformer * csvTransformer) const;
  1489. virtual IDataVal& getResultUnicode(IDataVal & data) const;
  1490. virtual void getResultDecimal(void * val, unsigned length, unsigned precision, bool isSigned) const;
  1491. virtual IStringVal& getResultEclSchema(IStringVal & str) const;
  1492. virtual __int64 getResultRawSize(IXmlToRawTransformer * xmlTransformer, ICsvToRawTransformer * csvTransformer) const;
  1493. virtual IDataVal& getResultRaw(IDataVal & data, __int64 from, __int64 length, IXmlToRawTransformer * xmlTransformer, ICsvToRawTransformer * csvTransformer) const;
  1494. virtual IStringVal& getResultRecordSizeEntry(IStringVal & str) const;
  1495. virtual IStringVal& getResultTransformerEntry(IStringVal & str) const;
  1496. virtual __int64 getResultRowLimit() const;
  1497. virtual IStringVal& getResultFilename(IStringVal & str) const;
  1498. virtual WUResultFormat getResultFormat() const;
  1499. virtual unsigned getResultHash() const;
  1500. virtual bool getResultIsAll() const;
  1501. virtual IProperties *queryXmlns();
  1502. // interface IWUResult
  1503. virtual void setResultStatus(WUResultStatus status);
  1504. virtual void setResultName(const char *name);
  1505. virtual void setResultSequence(unsigned seq);
  1506. virtual void setResultSchemaRaw(unsigned len, const void *schema);
  1507. virtual void setResultScalar(bool isScalar);
  1508. virtual void setResultRaw(unsigned len, const void *xml, WUResultFormat format);
  1509. virtual void setResultFetchSize(unsigned rows); // 0 means file-loaded
  1510. virtual void setResultTotalRowCount(__int64 rows); // -1 means unknown
  1511. virtual void setResultRowCount(__int64 rows);
  1512. virtual void setResultDataset(const char *ecl, const char *defs);
  1513. virtual void setResultLogicalName(const char *logicalName);
  1514. virtual void setResultKeyField(const char * name);
  1515. virtual void setResultRequestedRows(unsigned req);
  1516. virtual void setResultRecordSizeEntry(const char * val);
  1517. virtual void setResultTransformerEntry(const char * val);
  1518. virtual void setResultInt(__int64 val);
  1519. virtual void setResultReal(double val);
  1520. virtual void setResultBool(bool val);
  1521. virtual void setResultString(const char * val, unsigned length);
  1522. virtual void setResultUnicode(const void * val, unsigned length);
  1523. virtual void setResultData(const void * val, unsigned length);
  1524. virtual void setResultDecimal(const void * val, unsigned length);
  1525. virtual void addResultRaw(unsigned len, const void * data, WUResultFormat format);
  1526. virtual void setResultRowLimit(__int64 value);
  1527. virtual void setResultFilename(const char * name);
  1528. virtual void setResultUInt(unsigned __int64 val);
  1529. virtual void setResultIsAll(bool value);
  1530. virtual void setResultFormat(WUResultFormat format);
  1531. virtual void setResultXML(const char *val);
  1532. virtual void setResultRow(unsigned len, const void * data);
  1533. virtual void setXmlns(const char *prefix, const char *uri);
  1534. };
  1535. class CLocalWUPlugin : public CInterface, implements IWUPlugin
  1536. {
  1537. Owned<IPropertyTree> p;
  1538. public:
  1539. IMPLEMENT_IINTERFACE;
  1540. CLocalWUPlugin(IPropertyTree *p);
  1541. virtual IStringVal& getPluginName(IStringVal &str) const;
  1542. virtual IStringVal& getPluginVersion(IStringVal &str) const;
  1543. virtual bool getPluginThor() const;
  1544. virtual bool getPluginHole() const;
  1545. virtual void setPluginName(const char *str);
  1546. virtual void setPluginVersion(const char *str);
  1547. virtual void setPluginThor(bool on);
  1548. virtual void setPluginHole(bool on);
  1549. };
  1550. class CLocalWULibrary : public CInterface, implements IWULibrary
  1551. {
  1552. Owned<IPropertyTree> p;
  1553. public:
  1554. IMPLEMENT_IINTERFACE;
  1555. CLocalWULibrary(IPropertyTree *p);
  1556. virtual IStringVal & getName(IStringVal & str) const;
  1557. virtual IConstWULibraryActivityIterator * getActivities() const;
  1558. virtual void setName(const char * str);
  1559. virtual void addActivity(unsigned id);
  1560. };
  1561. class CLocalWUGraph : public CInterface, implements IWUGraph
  1562. {
  1563. const CLocalWorkUnit &owner;
  1564. Owned<IPropertyTree> p;
  1565. mutable Owned<IPropertyTree> graph; // cached copy of graph xgmml
  1566. mutable Linked<IConstWUGraphProgress> progress;
  1567. StringAttr wuid;
  1568. unsigned wuidVersion;
  1569. void mergeProgress(IPropertyTree &tree, IPropertyTree &progressTree, const unsigned &progressV) const;
  1570. public:
  1571. IMPLEMENT_IINTERFACE;
  1572. CLocalWUGraph(const CLocalWorkUnit &owner, IPropertyTree *p);
  1573. virtual IStringVal & getXGMML(IStringVal & ret, bool mergeProgress) const;
  1574. virtual IStringVal & getDOT(IStringVal & ret) const;
  1575. virtual IStringVal & getName(IStringVal & ret) const;
  1576. virtual IStringVal & getLabel(IStringVal & ret) const;
  1577. virtual IStringVal & getTypeName(IStringVal & ret) const;
  1578. virtual WUGraphType getType() const;
  1579. virtual IPropertyTree * getXGMMLTree(bool mergeProgress) const;
  1580. virtual IPropertyTree * getXGMMLTreeRaw() const;
  1581. virtual bool isValid() const;
  1582. virtual void setName(const char *str);
  1583. virtual void setLabel(const char *str);
  1584. virtual void setType(WUGraphType type);
  1585. virtual void setXGMML(const char *str);
  1586. virtual void setXGMMLTree(IPropertyTree * tree, bool compress=true);
  1587. };
  1588. class CLocalWUActivity : public CInterface, implements IWUActivity
  1589. {
  1590. Owned<IPropertyTree> p;
  1591. public:
  1592. IMPLEMENT_IINTERFACE;
  1593. CLocalWUActivity(IPropertyTree *p, __int64 id = 0);
  1594. virtual __int64 getId() const;
  1595. virtual unsigned getKind() const;
  1596. virtual IStringVal & getHelper(IStringVal & ret) const;
  1597. virtual void setKind(unsigned id);
  1598. virtual void setHelper(const char * str);
  1599. };
  1600. class CLocalWUException : public CInterface, implements IWUException
  1601. {
  1602. Owned<IPropertyTree> p;
  1603. public:
  1604. IMPLEMENT_IINTERFACE;
  1605. CLocalWUException(IPropertyTree *p);
  1606. virtual IStringVal& getExceptionSource(IStringVal &str) const;
  1607. virtual IStringVal& getExceptionMessage(IStringVal &str) const;
  1608. virtual unsigned getExceptionCode() const;
  1609. virtual WUExceptionSeverity getSeverity() const;
  1610. virtual IStringVal & getTimeStamp(IStringVal & dt) const;
  1611. virtual IStringVal & getExceptionFileName(IStringVal & str) const;
  1612. virtual unsigned getExceptionLineNo() const;
  1613. virtual unsigned getExceptionColumn() const;
  1614. virtual void setExceptionSource(const char *str);
  1615. virtual void setExceptionMessage(const char *str);
  1616. virtual void setExceptionCode(unsigned code);
  1617. virtual void setSeverity(WUExceptionSeverity level);
  1618. virtual void setTimeStamp(const char * dt);
  1619. virtual void setExceptionFileName(const char *str);
  1620. virtual void setExceptionLineNo(unsigned r);
  1621. virtual void setExceptionColumn(unsigned c);
  1622. };
  1623. //==========================================================================================
  1624. extern WORKUNIT_API bool isSpecialResultSequence(unsigned sequence)
  1625. {
  1626. switch (sequence)
  1627. {
  1628. case ResultSequenceInternal:
  1629. case ResultSequenceOnce:
  1630. case ResultSequencePersist:
  1631. case ResultSequenceStored:
  1632. return true;
  1633. default:
  1634. assertex(sequence <= INT_MAX);
  1635. return false;
  1636. }
  1637. }
  1638. struct mapEnums { int val; const char *str; };
  1639. const char *getEnumText(int value, mapEnums *map)
  1640. {
  1641. const char *defval = map->str;
  1642. while (map->str)
  1643. {
  1644. if (value==map->val)
  1645. return map->str;
  1646. map++;
  1647. }
  1648. assertex(!"Unexpected value in setEnum");
  1649. return defval;
  1650. }
  1651. void setEnum(IPropertyTree *p, const char *propname, int value, mapEnums *map)
  1652. {
  1653. const char *defval = map->str;
  1654. while (map->str)
  1655. {
  1656. if (value==map->val)
  1657. {
  1658. p->setProp(propname, map->str);
  1659. return;
  1660. }
  1661. map++;
  1662. }
  1663. assertex(!"Unexpected value in setEnum");
  1664. p->setProp(propname, defval);
  1665. }
  1666. static int getEnum(const char *v, mapEnums *map)
  1667. {
  1668. if (v)
  1669. {
  1670. while (map->str)
  1671. {
  1672. if (stricmp(v, map->str)==0)
  1673. return map->val;
  1674. map++;
  1675. }
  1676. assertex(!"Unexpected value in getEnum");
  1677. }
  1678. return 0;
  1679. }
  1680. static int getEnum(const IPropertyTree *p, const char *propname, mapEnums *map)
  1681. {
  1682. return getEnum(p->queryProp(propname),map);
  1683. }
  1684. //==========================================================================================
  1685. class CConstWUArrayIterator : public CInterface, implements IConstWorkUnitIterator
  1686. {
  1687. IArrayOf<IPropertyTree> trees;
  1688. Owned<IConstWorkUnit> cur;
  1689. unsigned curTreeNum;
  1690. Linked<IRemoteConnection> conn;
  1691. Linked<ISecManager> secmgr;
  1692. Linked<ISecUser> secuser;
  1693. void setCurrent()
  1694. {
  1695. cur.setown(new CLocalWorkUnit(LINK(conn), LINK(&trees.item(curTreeNum)), secmgr, secuser));
  1696. }
  1697. public:
  1698. IMPLEMENT_IINTERFACE;
  1699. CConstWUArrayIterator(IRemoteConnection *_conn, IArrayOf<IPropertyTree> &_trees, ISecManager *_secmgr=NULL, ISecUser *_secuser=NULL)
  1700. : conn(_conn), secmgr(_secmgr), secuser(_secuser)
  1701. {
  1702. ForEachItemIn(t, _trees)
  1703. trees.append(*LINK(&_trees.item(t)));
  1704. curTreeNum = 0;
  1705. }
  1706. bool first()
  1707. {
  1708. curTreeNum = 0;
  1709. return next();
  1710. }
  1711. bool isValid()
  1712. {
  1713. return (NULL != cur.get());
  1714. }
  1715. bool next()
  1716. {
  1717. if (curTreeNum >= trees.ordinality())
  1718. {
  1719. cur.clear();
  1720. return false;
  1721. }
  1722. setCurrent();
  1723. ++curTreeNum;
  1724. return true;
  1725. }
  1726. IConstWorkUnit & query() { return *cur; }
  1727. };
  1728. //==========================================================================================
  1729. class CStringArrayIterator : public CInterface, implements IStringIterator
  1730. {
  1731. StringArray strings;
  1732. unsigned idx;
  1733. public:
  1734. IMPLEMENT_IINTERFACE;
  1735. CStringArrayIterator() { idx = 0; };
  1736. void append(const char *str) { strings.append(str); }
  1737. virtual bool first() { idx = 0; return strings.isItem(idx); }
  1738. virtual bool next() { idx ++; return strings.isItem(idx); }
  1739. virtual bool isValid() { return strings.isItem(idx); }
  1740. virtual IStringVal & str(IStringVal &s) { s.set(strings.item(idx)); return s; }
  1741. };
  1742. class CCachedJobNameIterator : public CInterface, implements IStringIterator
  1743. {
  1744. Owned<IPropertyTreeIterator> it;
  1745. public:
  1746. IMPLEMENT_IINTERFACE;
  1747. CCachedJobNameIterator(IPropertyTreeIterator *p) : it(p) {};
  1748. virtual bool first() { return it->first(); }
  1749. virtual bool next() { return it->next(); }
  1750. virtual bool isValid() { return it->isValid(); }
  1751. virtual IStringVal & str(IStringVal &s) { s.set(it->query().queryName()+1); return s; }
  1752. };
  1753. class CEmptyStringIterator : public CInterface, implements IStringIterator
  1754. {
  1755. public:
  1756. IMPLEMENT_IINTERFACE;
  1757. virtual bool first() { return false; }
  1758. virtual bool next() { return false; }
  1759. virtual bool isValid() { return false; }
  1760. virtual IStringVal & str(IStringVal &s) { s.clear(); return s; }
  1761. };
  1762. mapEnums workunitSortFields[] =
  1763. {
  1764. { WUSFuser, "@submitID" },
  1765. { WUSFcluster, "@clusterName" },
  1766. { WUSFjob, "@jobName" },
  1767. { WUSFstate, "@state" },
  1768. { WUSFpriority, "@priorityClass" },
  1769. { WUSFprotected, "@protected" },
  1770. { WUSFwuid, "@" },
  1771. { WUSFecl, "Query/Text" },
  1772. { WUSFfileread, "FilesRead/File/@name" },
  1773. { WUSFroxiecluster, "RoxieQueryInfo/@roxieClusterName" },
  1774. { WUSFbatchloginid, "Application/Dispatcher/FTPUserID" },
  1775. { WUSFbatchcustomername, "Application/Dispatcher/CustomerName" },
  1776. { WUSFbatchpriority, "Application/Dispatcher/JobPriority" },
  1777. { WUSFbatchinputreccount, "Application/Dispatcher/InputRecords" },
  1778. { WUSFbatchtimeuploaded, "Application/Dispatcher/TimeUploaded" },
  1779. { WUSFbatchtimecompleted, "Application/Dispatcher/TimeCompleted" },
  1780. { WUSFbatchmachine, "Application/Dispatcher/Machine" },
  1781. { WUSFbatchinputfile, "Application/Dispatcher/InputFileName" },
  1782. { WUSFbatchoutputfile, "Application/Dispatcher/OutputFileName" },
  1783. { WUSFtotalthortime, "Statistics/Statistic[@desc='Total thor time']/@value|Timings/Timing[@name='Total thor time']/@duration" },//Use Statistics first. If not found, use Timings
  1784. { WUSFterm, NULL }
  1785. };
  1786. mapEnums querySortFields[] =
  1787. {
  1788. { WUQSFId, "@id" },
  1789. { WUQSFwuid, "@wuid" },
  1790. { WUQSFname, "@name" },
  1791. { WUQSFdll, "@dll" },
  1792. { WUQSFmemoryLimit, "@memoryLimit" },
  1793. { WUQSFmemoryLimitHi, "@memoryLimit" },
  1794. { WUQSFtimeLimit, "@timeLimit" },
  1795. { WUQSFtimeLimitHi, "@timeLimit" },
  1796. { WUQSFwarnTimeLimit, "@warnTimeLimit" },
  1797. { WUQSFwarnTimeLimitHi, "@warnTimeLimit" },
  1798. { WUQSFpriority, "@priority" },
  1799. { WUQSFpriorityHi, "@priority" },
  1800. { WUQSFQuerySet, "../@id" },
  1801. { WUQSFActivited, "@activated" },
  1802. { WUQSFSuspendedByUser, "@suspended" },
  1803. { WUQSFLibrary, "Library"},
  1804. { WUQSFterm, NULL }
  1805. };
  1806. class asyncRemoveDllWorkItem: public CInterface, implements IWorkQueueItem // class only used in asyncRemoveDll
  1807. {
  1808. StringAttr name;
  1809. public:
  1810. IMPLEMENT_IINTERFACE;
  1811. asyncRemoveDllWorkItem(const char * _name) : name(_name)
  1812. {
  1813. }
  1814. void execute()
  1815. {
  1816. PROGLOG("WU removeDll %s", name.get());
  1817. queryDllServer().removeDll(name, true, true); // <name>, removeDlls=true, removeDirectory=true
  1818. }
  1819. };
  1820. class asyncRemoveRemoteFileWorkItem: public CInterface, implements IWorkQueueItem // class only used in asyncRemoveFile
  1821. {
  1822. RemoteFilename name;
  1823. public:
  1824. IMPLEMENT_IINTERFACE;
  1825. asyncRemoveRemoteFileWorkItem(const char * _ip, const char * _name)
  1826. {
  1827. SocketEndpoint ep(_ip);
  1828. name.setPath(ep, _name);
  1829. }
  1830. void execute()
  1831. {
  1832. Owned<IFile> file = createIFile(name);
  1833. PROGLOG("WU removeDll %s",file->queryFilename());
  1834. file->remove();
  1835. }
  1836. };
  1837. //==========================================================================================
  1838. class CConstQuerySetQueryIterator : public CInterface, implements IConstQuerySetQueryIterator
  1839. {
  1840. IArrayOf<IPropertyTree> trees;
  1841. unsigned index;
  1842. public:
  1843. IMPLEMENT_IINTERFACE;
  1844. CConstQuerySetQueryIterator(IArrayOf<IPropertyTree> &_trees)
  1845. {
  1846. ForEachItemIn(t, _trees)
  1847. trees.append(*LINK(&_trees.item(t)));
  1848. index = 0;
  1849. }
  1850. ~CConstQuerySetQueryIterator()
  1851. {
  1852. trees.kill();
  1853. }
  1854. bool first()
  1855. {
  1856. index = 0;
  1857. return (trees.ordinality()!=0);
  1858. }
  1859. bool next()
  1860. {
  1861. index++;
  1862. return (index<trees.ordinality());
  1863. }
  1864. bool isValid()
  1865. {
  1866. return (index<trees.ordinality());
  1867. }
  1868. IPropertyTree &query()
  1869. {
  1870. return trees.item(index);
  1871. }
  1872. };
  1873. #define WUID_VERSION 2 // recorded in each wuid created, useful for bkwd compat. checks
  1874. class CWorkUnitFactory : public CInterface, implements IWorkUnitFactory, implements IDaliClientShutdown
  1875. {
  1876. Owned<IWorkQueueThread> deletedllworkq;
  1877. public:
  1878. IMPLEMENT_IINTERFACE;
  1879. CWorkUnitFactory()
  1880. {
  1881. // Assumes dali client configuration has already been done
  1882. sdsManager = &querySDS();
  1883. session = myProcessSession();
  1884. deletedllworkq.setown(createWorkQueueThread());
  1885. addShutdownHook(*this);
  1886. }
  1887. ~CWorkUnitFactory()
  1888. {
  1889. removeShutdownHook(*this);
  1890. // deletepool->joinAll();
  1891. }
  1892. void clientShutdown();
  1893. SessionId startSession()
  1894. {
  1895. // Temporary placeholder until startSession is implemented
  1896. #ifdef _WIN32
  1897. return GetTickCount();
  1898. #else
  1899. struct timeval tm;
  1900. gettimeofday(&tm,NULL);
  1901. return tm.tv_usec;
  1902. #endif
  1903. }
  1904. IWorkUnit* ensureNamedWorkUnit(const char *name)
  1905. {
  1906. if (workUnitTraceLevel > 1)
  1907. PrintLog("ensureNamedWorkUnit created %s", name);
  1908. StringBuffer wuRoot;
  1909. getXPath(wuRoot, name);
  1910. IRemoteConnection* conn = sdsManager->connect(wuRoot.str(), session, RTM_LOCK_WRITE|RTM_CREATE_QUERY, SDS_LOCK_TIMEOUT);
  1911. conn->queryRoot()->setProp("@xmlns:xsi", "http://www.w3.org/1999/XMLSchema-instance");
  1912. Owned<CLocalWorkUnit> cw = new CLocalWorkUnit(conn, (ISecManager *)NULL, NULL, (const char *)NULL);
  1913. return &cw->lockRemote(false);
  1914. }
  1915. virtual IWorkUnit* createNamedWorkUnit(const char *wuid,const char *parentWuid, const char *app, const char *user)
  1916. {
  1917. StringBuffer wuRoot;
  1918. getXPath(wuRoot, wuid);
  1919. IRemoteConnection *conn;
  1920. if (queryDaliServerVersion().compare("2.0") >= 0)
  1921. conn = sdsManager->connect(wuRoot.str(), session, RTM_LOCK_WRITE|RTM_CREATE_UNIQUE, SDS_LOCK_TIMEOUT);
  1922. else
  1923. conn = sdsManager->connect(wuRoot.str(), session, RTM_LOCK_WRITE|RTM_CREATE, SDS_LOCK_TIMEOUT);
  1924. conn->queryRoot()->setProp("@xmlns:xsi", "http://www.w3.org/1999/XMLSchema-instance");
  1925. conn->queryRoot()->setPropInt("@wuidVersion", WUID_VERSION);
  1926. Owned<CLocalWorkUnit> cw = new CLocalWorkUnit(conn, (ISecManager*)NULL, NULL, parentWuid);
  1927. IWorkUnit* ret = &cw->lockRemote(false);
  1928. ret->setDebugValue("CREATED_BY", app, true);
  1929. ret->setDebugValue("CREATED_FOR", user, true);
  1930. if (user)
  1931. cw->setWuScope(user);
  1932. return ret;
  1933. }
  1934. virtual IWorkUnit* createWorkUnit(const char *parentWuid, const char *app, const char *user)
  1935. {
  1936. StringBuffer wuid("W");
  1937. char result[32];
  1938. time_t ltime;
  1939. time( &ltime );
  1940. tm *today = localtime( &ltime ); // MORE - this is not threadsafe. But I probably don't care that much!
  1941. strftime(result, sizeof(result), "%Y%m%d-%H%M%S", today);
  1942. wuid.append(result);
  1943. if (queryDaliServerVersion().compare("2.0") < 0)
  1944. wuid.append('-').append(startSession());
  1945. if (workUnitTraceLevel > 1)
  1946. PrintLog("createWorkUnit created %s", wuid.str());
  1947. IWorkUnit* ret = createNamedWorkUnit(wuid.str(),parentWuid, app, user);
  1948. if (workUnitTraceLevel > 1)
  1949. {
  1950. SCMStringBuffer wuidName;
  1951. ret->getWuid(wuidName);
  1952. PrintLog("createWorkUnit created %s", wuidName.str());
  1953. }
  1954. ret->addTimeStamp("workunit", NULL, "Created");
  1955. return ret;
  1956. }
  1957. bool secDeleteWorkUnit(const char * wuid, ISecManager *secmgr, ISecUser *secuser, bool raiseexceptions)
  1958. {
  1959. if (workUnitTraceLevel > 1)
  1960. PrintLog("deleteWorkUnit %s", wuid);
  1961. StringBuffer wuRoot;
  1962. getXPath(wuRoot, wuid);
  1963. IRemoteConnection *conn = sdsManager->connect(wuRoot.str(), session, RTM_LOCK_WRITE|RTM_LOCK_SUB, SDS_LOCK_TIMEOUT);
  1964. if (!conn)
  1965. {
  1966. if (workUnitTraceLevel > 0)
  1967. PrintLog("deleteWorkUnit %s not found", wuid);
  1968. return false;
  1969. }
  1970. Owned<CLocalWorkUnit> cw = new CLocalWorkUnit(conn, secmgr, secuser); // takes ownership of conn
  1971. if (secmgr && !checkWuSecAccess(*cw.get(), *secmgr, secuser, SecAccess_Full, "delete", true, true)) {
  1972. if (raiseexceptions) {
  1973. // perhaps raise exception here?
  1974. }
  1975. return false;
  1976. }
  1977. if (raiseexceptions) {
  1978. try
  1979. {
  1980. cw->cleanupAndDelete(true,true);
  1981. }
  1982. catch (IException *E)
  1983. {
  1984. StringBuffer s;
  1985. LOG(MCexception(E, MSGCLS_warning), E, s.append("Exception during deleteWorkUnit: ").append(wuid).str());
  1986. E->Release();
  1987. return false;
  1988. }
  1989. }
  1990. else
  1991. cw->cleanupAndDelete(true,true);
  1992. removeWorkUnitFromAllQueues(wuid); //known active workunits wouldn't make it this far
  1993. return true;
  1994. }
  1995. virtual bool deleteWorkUnitEx(const char * wuid)
  1996. {
  1997. return secDeleteWorkUnit(wuid,NULL,NULL,true);
  1998. }
  1999. virtual bool deleteWorkUnit(const char * wuid)
  2000. {
  2001. return secDeleteWorkUnit(wuid,NULL,NULL,false);
  2002. }
  2003. virtual IConstWorkUnitIterator * getWorkUnitsByOwner(const char * owner)
  2004. {
  2005. // Not sure what to do about customerID vs user etc
  2006. StringBuffer path("*");
  2007. if (owner && *owner)
  2008. path.append("[@submitID=\"").append(owner).append("\"]");
  2009. return getWorkUnitsByXPath(path.str());
  2010. }
  2011. virtual IConstWorkUnitIterator * getWorkUnitsByState(WUState state);
  2012. virtual IConstWorkUnitIterator * getWorkUnitsByECL(const char* ecl)
  2013. {
  2014. StringBuffer path("*");
  2015. if (ecl && *ecl)
  2016. path.append("[Query/Text=~\"*").append(ecl).append("*\"]");
  2017. return getWorkUnitsByXPath(path.str());
  2018. }
  2019. virtual IConstWorkUnitIterator * getWorkUnitsByCluster(const char* cluster)
  2020. {
  2021. StringBuffer path("*");
  2022. if (cluster && *cluster)
  2023. path.append("[@clusterName=\"").append(cluster).append("\"]");
  2024. return getWorkUnitsByXPath(path.str());
  2025. }
  2026. virtual IConstWorkUnitIterator * getChildWorkUnits(const char *parent)
  2027. {
  2028. StringBuffer path("*[@parent=\"");
  2029. path.append(parent).append("\"]");
  2030. return getWorkUnitsByXPath(path.str());
  2031. }
  2032. virtual IConstWorkUnit* secOpenWorkUnit(const char *wuid, bool lock, ISecManager *secmgr=NULL, ISecUser *secuser=NULL)
  2033. {
  2034. StringBuffer wuidStr(wuid);
  2035. wuidStr.trim();
  2036. if (!wuidStr.length())
  2037. return NULL;
  2038. if (workUnitTraceLevel > 1)
  2039. PrintLog("openWorkUnit %s", wuidStr.str());
  2040. StringBuffer wuRoot;
  2041. getXPath(wuRoot, wuidStr.str());
  2042. IRemoteConnection* conn = sdsManager->connect(wuRoot.str(), session, lock ? RTM_LOCK_READ|RTM_LOCK_SUB : 0, SDS_LOCK_TIMEOUT);
  2043. if (conn)
  2044. {
  2045. CLocalWorkUnit *wu = new CLocalWorkUnit(conn, secmgr, secuser);
  2046. if (secmgr && wu)
  2047. {
  2048. if (!checkWuSecAccess(*wu, *secmgr, secuser, SecAccess_Read, "opening", true, true))
  2049. {
  2050. delete wu;
  2051. return NULL;
  2052. }
  2053. }
  2054. return wu;
  2055. }
  2056. else
  2057. {
  2058. if (workUnitTraceLevel > 0)
  2059. PrintLog("openWorkUnit %s not found", wuidStr.str());
  2060. return NULL;
  2061. }
  2062. }
  2063. virtual IConstWorkUnit* openWorkUnit(const char *wuid, bool lock)
  2064. {
  2065. return secOpenWorkUnit(wuid, lock);
  2066. }
  2067. virtual IWorkUnit* secUpdateWorkUnit(const char *wuid, ISecManager *secmgr=NULL, ISecUser *secuser=NULL)
  2068. {
  2069. if (workUnitTraceLevel > 1)
  2070. PrintLog("updateWorkUnit %s", wuid);
  2071. StringBuffer wuRoot;
  2072. getXPath(wuRoot, wuid);
  2073. IRemoteConnection* conn = sdsManager->connect(wuRoot.str(), session, RTM_LOCK_WRITE|RTM_LOCK_SUB, SDS_LOCK_TIMEOUT);
  2074. if (conn)
  2075. {
  2076. Owned<CLocalWorkUnit> cw = new CLocalWorkUnit(conn, secmgr, secuser);
  2077. if (secmgr && cw)
  2078. {
  2079. if (!checkWuSecAccess(*cw.get(), *secmgr, secuser, SecAccess_Write, "updating", true, true))
  2080. return NULL;
  2081. }
  2082. return &cw->lockRemote(false);
  2083. }
  2084. else
  2085. {
  2086. if (workUnitTraceLevel > 0)
  2087. PrintLog("updateWorkUnit %s not found", wuid);
  2088. return NULL;
  2089. }
  2090. }
  2091. virtual IWorkUnit* updateWorkUnit(const char *wuid)
  2092. {
  2093. return secUpdateWorkUnit(wuid);
  2094. }
  2095. virtual int setTracingLevel(int newLevel)
  2096. {
  2097. if (newLevel)
  2098. PrintLog("Setting workunit trace level to %d", newLevel);
  2099. int level = workUnitTraceLevel;
  2100. workUnitTraceLevel = newLevel;
  2101. return level;
  2102. }
  2103. IConstWorkUnitIterator * getWorkUnitsByXPath(const char *xpath)
  2104. {
  2105. return getWorkUnitsByXPath(xpath,NULL,NULL);
  2106. }
  2107. void descheduleAllWorkUnits()
  2108. {
  2109. Owned<IRemoteConnection> conn = querySDS().connect("/Schedule", myProcessSession(), RTM_LOCK_WRITE, SDS_LOCK_TIMEOUT);
  2110. if(!conn) return;
  2111. Owned<IPropertyTree> root(conn->queryRoot()->getBranch("."));
  2112. KeptAtomTable entries;
  2113. Owned<IPropertyTreeIterator> iter(root->getElements("*/*/*/*"));
  2114. StringBuffer wuid;
  2115. for(iter->first(); iter->isValid(); iter->next())
  2116. {
  2117. char const * entry = iter->query().queryName();
  2118. if(!entries.find(entry))
  2119. {
  2120. entries.addAtom(entry);
  2121. ncnameUnescape(entry, wuid.clear());
  2122. Owned<IWorkUnit> wu = updateWorkUnit(wuid);
  2123. if(wu && (wu->getState() == WUStateWait))
  2124. wu->setState(WUStateCompleted);
  2125. }
  2126. }
  2127. bool more;
  2128. do more = root->removeProp("*"); while(more);
  2129. }
  2130. IConstWorkUnitIterator * getWorkUnitsByXPath(const char *xpath, ISecManager *secmgr, ISecUser *secuser)
  2131. {
  2132. Owned<IRemoteConnection> conn = sdsManager->connect("/WorkUnits", session, 0, SDS_LOCK_TIMEOUT);
  2133. if (conn)
  2134. {
  2135. CDaliVersion serverVersionNeeded("3.2");
  2136. Owned<IPropertyTreeIterator> iter(queryDaliServerVersion().compare(serverVersionNeeded) < 0 ?
  2137. conn->queryRoot()->getElements(xpath) :
  2138. conn->getElements(xpath));
  2139. return new CConstWUIterator(conn, iter, secmgr, secuser);
  2140. }
  2141. else
  2142. return NULL;
  2143. }
  2144. IConstWorkUnitIterator* getWorkUnitsSorted( WUSortField *sortorder, // list of fields to sort by (terminated by WUSFterm)
  2145. WUSortField *filters, // NULL or list of fields to folteron (terminated by WUSFterm)
  2146. const void *filterbuf, // (appended) string values for filters
  2147. unsigned startoffset,
  2148. unsigned maxnum,
  2149. const char *queryowner,
  2150. __int64 *cachehint,
  2151. ISecManager *secmgr,
  2152. ISecUser *secuser,
  2153. unsigned *total)
  2154. {
  2155. class CWorkUnitsPager : public CSimpleInterface, implements IElementsPager
  2156. {
  2157. StringAttr xPath;
  2158. StringAttr sortOrder;
  2159. StringAttr nameFilterLo;
  2160. StringAttr nameFilterHi;
  2161. StringArray unknownAttributes;
  2162. public:
  2163. IMPLEMENT_IINTERFACE_USING(CSimpleInterface);
  2164. CWorkUnitsPager(const char* _xPath, const char *_sortOrder, const char* _nameFilterLo, const char* _nameFilterHi, StringArray& _unknownAttributes)
  2165. : xPath(_xPath), sortOrder(_sortOrder), nameFilterLo(_nameFilterLo), nameFilterHi(_nameFilterHi)
  2166. {
  2167. ForEachItemIn(x, _unknownAttributes)
  2168. unknownAttributes.append(_unknownAttributes.item(x));
  2169. }
  2170. virtual IRemoteConnection* getElements(IArrayOf<IPropertyTree> &elements)
  2171. {
  2172. Owned<IRemoteConnection> conn = querySDS().connect("WorkUnits", myProcessSession(), 0, SDS_LOCK_TIMEOUT);
  2173. if (!conn)
  2174. return NULL;
  2175. Owned<IPropertyTreeIterator> iter = conn->getElements(xPath);
  2176. if (!iter)
  2177. return NULL;
  2178. sortElements(iter, sortOrder.get(), nameFilterLo.get(), nameFilterHi.get(), unknownAttributes, elements);
  2179. return conn.getClear();
  2180. }
  2181. };
  2182. class CScopeChecker : public CSimpleInterface, implements ISortedElementsTreeFilter
  2183. {
  2184. UniqueScopes done;
  2185. ISecManager *secmgr;
  2186. ISecUser *secuser;
  2187. CriticalSection crit;
  2188. public:
  2189. IMPLEMENT_IINTERFACE_USING(CSimpleInterface);
  2190. CScopeChecker(ISecManager *_secmgr,ISecUser *_secuser)
  2191. {
  2192. secmgr = _secmgr;
  2193. secuser = _secuser;
  2194. }
  2195. bool isOK(IPropertyTree &tree)
  2196. {
  2197. const char *scopename = tree.queryProp("@scope");
  2198. if (!scopename||!*scopename)
  2199. return true;
  2200. {
  2201. CriticalBlock block(crit);
  2202. const bool *b = done.getValue(scopename);
  2203. if (b)
  2204. return *b;
  2205. }
  2206. bool ret = checkWuScopeSecAccess(scopename,*secmgr,secuser,SecAccess_Read,"iterating",false,false);
  2207. {
  2208. // conceivably could have already been checked and added, but ok.
  2209. CriticalBlock block(crit);
  2210. done.setValue(scopename,ret);
  2211. }
  2212. return ret;
  2213. }
  2214. };
  2215. Owned<ISortedElementsTreeFilter> sc = new CScopeChecker(secmgr,secuser);
  2216. StringBuffer query;
  2217. StringBuffer so;
  2218. StringAttr namefilter("*");
  2219. StringAttr namefilterlo;
  2220. StringAttr namefilterhi;
  2221. StringArray unknownAttributes;
  2222. if (filters) {
  2223. const char *fv = (const char *)filterbuf;
  2224. for (unsigned i=0;filters[i]!=WUSFterm;i++) {
  2225. int fmt = filters[i];
  2226. int subfmt = (fmt&0xff);
  2227. if (subfmt==WUSFwuid)
  2228. namefilterlo.set(fv);
  2229. else if (subfmt==WUSFwuidhigh)
  2230. namefilterhi.set(fv);
  2231. else if (subfmt==WUSFwildwuid)
  2232. namefilter.set(fv);
  2233. else if (subfmt==WUSFcustom)
  2234. query.append("[").append(fv).append("]");
  2235. else if (!fv || !*fv)
  2236. unknownAttributes.append(getEnumText(subfmt,workunitSortFields));
  2237. else {
  2238. query.append('[').append(getEnumText(subfmt,workunitSortFields)).append('=');
  2239. if (fmt&WUSFnocase)
  2240. query.append('?');
  2241. if (fmt&WUSFwild)
  2242. query.append('~');
  2243. query.append('"').append(fv).append("\"]");
  2244. }
  2245. fv = fv + strlen(fv)+1;
  2246. }
  2247. }
  2248. query.insert(0, namefilter.get());
  2249. if (sortorder) {
  2250. for (unsigned i=0;sortorder[i]!=WUSFterm;i++) {
  2251. if (so.length())
  2252. so.append(',');
  2253. int fmt = sortorder[i];
  2254. if (fmt&WUSFreverse)
  2255. so.append('-');
  2256. if (fmt&WUSFnocase)
  2257. so.append('?');
  2258. if (fmt&WUSFnumeric)
  2259. so.append('#');
  2260. so.append(getEnumText(fmt&0xff,workunitSortFields));
  2261. }
  2262. }
  2263. IArrayOf<IPropertyTree> results;
  2264. Owned<IElementsPager> elementsPager = new CWorkUnitsPager(query.str(), so.length()?so.str():NULL, namefilterlo.get(), namefilterhi.get(), unknownAttributes);
  2265. Owned<IRemoteConnection> conn=getElementsPaged(elementsPager,startoffset,maxnum,secmgr?sc:NULL,queryowner,cachehint,results,total);
  2266. return new CConstWUArrayIterator(conn, results, secmgr, secuser);
  2267. }
  2268. IConstWorkUnitIterator* getWorkUnitsSorted( WUSortField *sortorder, // list of fields to sort by (terminated by WUSFterm)
  2269. WUSortField *filters, // NULL or list of fields to filter on (terminated by WUSFterm)
  2270. const void *filterbuf, // (appended) string values for filters
  2271. unsigned startoffset,
  2272. unsigned maxnum,
  2273. const char *queryowner,
  2274. __int64 *cachehint,
  2275. unsigned *total)
  2276. {
  2277. return getWorkUnitsSorted(sortorder,filters,filterbuf,startoffset,maxnum,queryowner,cachehint, NULL, NULL, total);
  2278. }
  2279. IConstQuerySetQueryIterator* getQuerySetQueriesSorted( WUQuerySortField *sortorder, // list of fields to sort by (terminated by WUSFterm)
  2280. WUQuerySortField *filters, // NULL or list of fields to filter on (terminated by WUSFterm)
  2281. const void *filterbuf, // (appended) string values for filters
  2282. unsigned startoffset,
  2283. unsigned maxnum,
  2284. __int64 *cachehint,
  2285. unsigned *total,
  2286. const MapStringTo<bool> *_subset)
  2287. {
  2288. struct PostFilters
  2289. {
  2290. WUQueryFilterBoolean activatedFilter;
  2291. WUQueryFilterBoolean suspendedByUserFilter;
  2292. PostFilters()
  2293. {
  2294. activatedFilter = WUQFSAll;
  2295. suspendedByUserFilter = WUQFSAll;
  2296. };
  2297. } postFilters;
  2298. class CQuerySetQueriesPager : public CSimpleInterface, implements IElementsPager
  2299. {
  2300. StringAttr querySet;
  2301. StringAttr xPath;
  2302. StringAttr sortOrder;
  2303. PostFilters postFilters;
  2304. StringArray unknownAttributes;
  2305. const MapStringTo<bool> *subset;
  2306. void populateQueryTree(IPropertyTree* queryRegistry, const char* querySetId, IPropertyTree* querySetTree, const char *xPath, IPropertyTree* queryTree)
  2307. {
  2308. Owned<IPropertyTreeIterator> iter = querySetTree->getElements(xPath);
  2309. ForEach(*iter)
  2310. {
  2311. IPropertyTree &query = iter->query();
  2312. bool activated = false;
  2313. const char* queryId = query.queryProp("@id");
  2314. if (queryId && *queryId)
  2315. {
  2316. if (subset)
  2317. {
  2318. VStringBuffer match("%s/%s", querySetId, queryId);
  2319. if (!subset->getValue(match))
  2320. continue;
  2321. }
  2322. VStringBuffer xPath("Alias[@id='%s']", queryId);
  2323. IPropertyTree *alias = queryRegistry->queryPropTree(xPath.str());
  2324. if (alias)
  2325. activated = true;
  2326. }
  2327. if (activated && (postFilters.activatedFilter == WUQFSNo))
  2328. continue;
  2329. if (!activated && (postFilters.activatedFilter == WUQFSYes))
  2330. continue;
  2331. if ((postFilters.suspendedByUserFilter == WUQFSNo) && query.hasProp(getEnumText(WUQSFSuspendedByUser,querySortFields)))
  2332. continue;
  2333. if ((postFilters.suspendedByUserFilter == WUQFSYes) && !query.hasProp(getEnumText(WUQSFSuspendedByUser,querySortFields)))
  2334. continue;
  2335. IPropertyTree *queryWithSetId = queryTree->addPropTree("Query", LINK(&query));
  2336. queryWithSetId->addProp("@querySetId", querySetId);
  2337. queryWithSetId->addPropBool("@activated", activated);
  2338. }
  2339. }
  2340. IPropertyTree* getAllQuerySetQueries(IRemoteConnection* conn, const char *querySet, const char *xPath)
  2341. {
  2342. Owned<IPropertyTree> queryTree = createPTree("Queries");
  2343. IPropertyTree* root = conn->queryRoot();
  2344. if (querySet && *querySet)
  2345. {
  2346. Owned<IPropertyTree> queryRegistry = getQueryRegistry(querySet, false);
  2347. VStringBuffer path("QuerySet[@id='%s']/Query%s", querySet, xPath);
  2348. populateQueryTree(queryRegistry, querySet, root, path.str(), queryTree);
  2349. }
  2350. else
  2351. {
  2352. Owned<IPropertyTreeIterator> iter = root->getElements("QuerySet");
  2353. ForEach(*iter)
  2354. {
  2355. IPropertyTree &querySetTree = iter->query();
  2356. const char* id = querySetTree.queryProp("@id");
  2357. if (id && *id)
  2358. {
  2359. Owned<IPropertyTree> queryRegistry = getQueryRegistry(id, false);
  2360. VStringBuffer path("Query%s", xPath);
  2361. populateQueryTree(queryRegistry, id, &querySetTree, path.str(), queryTree);
  2362. }
  2363. }
  2364. }
  2365. return queryTree.getClear();
  2366. }
  2367. public:
  2368. IMPLEMENT_IINTERFACE_USING(CSimpleInterface);
  2369. CQuerySetQueriesPager(const char* _querySet, const char* _xPath, const char *_sortOrder, PostFilters& _postFilters, StringArray& _unknownAttributes, const MapStringTo<bool> *_subset)
  2370. : querySet(_querySet), xPath(_xPath), sortOrder(_sortOrder), subset(_subset)
  2371. {
  2372. postFilters.activatedFilter = _postFilters.activatedFilter;
  2373. postFilters.suspendedByUserFilter = _postFilters.suspendedByUserFilter;
  2374. ForEachItemIn(x, _unknownAttributes)
  2375. unknownAttributes.append(_unknownAttributes.item(x));
  2376. }
  2377. virtual IRemoteConnection* getElements(IArrayOf<IPropertyTree> &elements)
  2378. {
  2379. Owned<IRemoteConnection> conn = querySDS().connect("QuerySets", myProcessSession(), 0, SDS_LOCK_TIMEOUT);
  2380. if (!conn)
  2381. return NULL;
  2382. Owned<IPropertyTree> elementTree = getAllQuerySetQueries(conn, querySet.get(), xPath.get());
  2383. if (!elementTree)
  2384. return NULL;
  2385. Owned<IPropertyTreeIterator> iter = elementTree->getElements("*");
  2386. if (!iter)
  2387. return NULL;
  2388. sortElements(iter, sortOrder.get(), NULL, NULL, unknownAttributes, elements);
  2389. return conn.getClear();
  2390. }
  2391. };
  2392. StringAttr querySet;
  2393. StringBuffer xPath;
  2394. StringBuffer so;
  2395. StringArray unknownAttributes;
  2396. if (filters)
  2397. {
  2398. const char *fv = (const char *)filterbuf;
  2399. for (unsigned i=0;filters[i]!=WUQSFterm;i++) {
  2400. int fmt = filters[i];
  2401. int subfmt = (fmt&0xff);
  2402. if (subfmt==WUQSFQuerySet)
  2403. querySet.set(fv);
  2404. else if ((subfmt==WUQSFmemoryLimit) || (subfmt==WUQSFtimeLimit) || (subfmt==WUQSFwarnTimeLimit) || (subfmt==WUQSFpriority))
  2405. xPath.append('[').append(getEnumText(subfmt,querySortFields)).append(">=").append(fv).append("]");
  2406. else if ((subfmt==WUQSFmemoryLimitHi) || (subfmt==WUQSFtimeLimitHi) || (subfmt==WUQSFwarnTimeLimitHi) || (subfmt==WUQSFpriorityHi))
  2407. xPath.append('[').append(getEnumText(subfmt,querySortFields)).append("<=").append(fv).append("]");
  2408. else if (subfmt==WUQSFActivited)
  2409. postFilters.activatedFilter = (WUQueryFilterBoolean) atoi(fv);
  2410. else if (subfmt==WUQSFSuspendedByUser)
  2411. postFilters.suspendedByUserFilter = (WUQueryFilterBoolean) atoi(fv);
  2412. else if (!fv || !*fv)
  2413. unknownAttributes.append(getEnumText(subfmt,querySortFields));
  2414. else {
  2415. xPath.append('[').append(getEnumText(subfmt,querySortFields)).append('=');
  2416. if (fmt&WUQSFnocase)
  2417. xPath.append('?');
  2418. if (fmt&WUQSFnumeric)
  2419. xPath.append('#');
  2420. if (fmt&WUQSFwild)
  2421. xPath.append('~');
  2422. xPath.append('"').append(fv).append("\"]");
  2423. }
  2424. fv = fv + strlen(fv)+1;
  2425. }
  2426. }
  2427. if (sortorder) {
  2428. for (unsigned i=0;sortorder[i]!=WUQSFterm;i++) {
  2429. if (so.length())
  2430. so.append(',');
  2431. int fmt = sortorder[i];
  2432. if (fmt&WUQSFreverse)
  2433. so.append('-');
  2434. if (fmt&WUQSFnocase)
  2435. so.append('?');
  2436. if (fmt&WUQSFnumeric)
  2437. so.append('#');
  2438. so.append(getEnumText(fmt&0xff,querySortFields));
  2439. }
  2440. }
  2441. IArrayOf<IPropertyTree> results;
  2442. Owned<IElementsPager> elementsPager = new CQuerySetQueriesPager(querySet.get(), xPath.str(), so.length()?so.str():NULL, postFilters, unknownAttributes, _subset);
  2443. Owned<IRemoteConnection> conn=getElementsPaged(elementsPager,startoffset,maxnum,NULL,"",cachehint,results,total);
  2444. return new CConstQuerySetQueryIterator(results);
  2445. }
  2446. virtual unsigned numWorkUnits()
  2447. {
  2448. Owned<IRemoteConnection> conn = sdsManager->connect("/WorkUnits", session, 0, SDS_LOCK_TIMEOUT);
  2449. if (!conn)
  2450. return 0;
  2451. IPropertyTree *root = conn->queryRoot();
  2452. return root->numChildren();
  2453. }
  2454. virtual unsigned numWorkUnitsFiltered(WUSortField *filters,
  2455. const void *filterbuf,
  2456. ISecManager *secmgr,
  2457. ISecUser *secuser)
  2458. {
  2459. unsigned total;
  2460. Owned<IConstWorkUnitIterator> iter = getWorkUnitsSorted( NULL,filters,filterbuf,0,0x7fffffff,NULL,NULL,secmgr,secuser,&total);
  2461. return total;
  2462. }
  2463. virtual unsigned numWorkUnitsFiltered(WUSortField *filters,const void *filterbuf)
  2464. {
  2465. if (!filters)
  2466. return numWorkUnits();
  2467. return numWorkUnitsFiltered(filters,filterbuf,NULL,NULL);
  2468. }
  2469. void asyncRemoveDll(const char * name)
  2470. {
  2471. deletedllworkq->post(new asyncRemoveDllWorkItem(name));
  2472. }
  2473. void asyncRemoveFile(const char * ip, const char * name)
  2474. {
  2475. deletedllworkq->post(new asyncRemoveRemoteFileWorkItem(ip, name));
  2476. }
  2477. ISDSManager *sdsManager;
  2478. SessionId session;
  2479. ISecManager *secMgr;
  2480. private:
  2481. void deleteChildren(IPropertyTree *root, const char *wuid)
  2482. {
  2483. StringBuffer kids("*[@parent=\"");
  2484. kids.append(wuid).append("\"]");
  2485. Owned<IPropertyTreeIterator> it = root->getElements(kids.str());
  2486. ForEach (*it)
  2487. {
  2488. deleteChildren(root, it->query().queryName());
  2489. }
  2490. root->removeProp(wuid);
  2491. }
  2492. class CConstWUIterator : public CInterface, implements IConstWorkUnitIterator
  2493. {
  2494. Owned<IConstWorkUnit> cur;
  2495. Linked<IRemoteConnection> conn;
  2496. Linked<IPropertyTreeIterator> ptreeIter;
  2497. Linked<ISecManager> secmgr;
  2498. Linked<ISecUser> secuser;
  2499. Owned<ISecResourceList> scopes;
  2500. void setCurrent()
  2501. {
  2502. cur.setown(new CLocalWorkUnit(LINK(conn), LINK(&ptreeIter->query()), secmgr, secuser));
  2503. }
  2504. bool getNext() // scan for a workunit with permissions
  2505. {
  2506. if (!scopes)
  2507. {
  2508. setCurrent();
  2509. return true;
  2510. }
  2511. do
  2512. {
  2513. const char *scopeName = ptreeIter->query().queryProp("@scope");
  2514. if (!scopeName || !*scopeName || checkWuScopeListSecAccess(scopeName, scopes, SecAccess_Read, "iterating", false, false))
  2515. {
  2516. setCurrent();
  2517. return true;
  2518. }
  2519. }
  2520. while (ptreeIter->next());
  2521. cur.clear();
  2522. return false;
  2523. }
  2524. public:
  2525. IMPLEMENT_IINTERFACE;
  2526. CConstWUIterator(IRemoteConnection *_conn, IPropertyTreeIterator *_ptreeIter, ISecManager *_secmgr=NULL, ISecUser *_secuser=NULL)
  2527. : conn(_conn), ptreeIter(_ptreeIter), secmgr(_secmgr), secuser(_secuser)
  2528. {
  2529. UniqueScopes us;
  2530. if (secmgr /* && secmgr->authTypeRequired(RT_WORKUNIT_SCOPE) tbd */)
  2531. {
  2532. scopes.setown(secmgr->createResourceList("wuscopes"));
  2533. ForEach(*ptreeIter)
  2534. {
  2535. const char *scopeName = ptreeIter->query().queryProp("@scope");
  2536. if (scopeName && *scopeName && !us.getValue(scopeName))
  2537. {
  2538. scopes->addResource(scopeName);
  2539. us.setValue(scopeName, true);
  2540. }
  2541. }
  2542. if (scopes->count())
  2543. secmgr->authorizeEx(RT_WORKUNIT_SCOPE, *secuser, scopes);
  2544. else
  2545. scopes.clear();
  2546. }
  2547. }
  2548. bool first()
  2549. {
  2550. if (!ptreeIter->first())
  2551. {
  2552. cur.clear();
  2553. return false;
  2554. }
  2555. return getNext();
  2556. }
  2557. bool isValid()
  2558. {
  2559. return (NULL != cur.get());
  2560. }
  2561. bool next()
  2562. {
  2563. if (!ptreeIter->next())
  2564. {
  2565. cur.clear();
  2566. return false;
  2567. }
  2568. return getNext();
  2569. }
  2570. IConstWorkUnit & query() { return *cur; }
  2571. };
  2572. IRemoteConnection* connect(const char *xpath, unsigned flags)
  2573. {
  2574. return sdsManager->connect(xpath, session, flags, SDS_LOCK_TIMEOUT);
  2575. }
  2576. };
  2577. static Owned<CWorkUnitFactory> factory;
  2578. void CWorkUnitFactory::clientShutdown()
  2579. {
  2580. factory.clear();
  2581. }
  2582. void clientShutdownWorkUnit()
  2583. {
  2584. factory.clear();
  2585. }
  2586. extern WORKUNIT_API IWorkUnitFactory * getWorkUnitFactory()
  2587. {
  2588. if (!factory)
  2589. factory.setown(new CWorkUnitFactory());
  2590. return factory.getLink();
  2591. }
  2592. class CSecureWorkUnitFactory : public CInterface, implements IWorkUnitFactory
  2593. {
  2594. public:
  2595. IMPLEMENT_IINTERFACE;
  2596. CSecureWorkUnitFactory(ISecManager &secmgr, ISecUser &secuser)
  2597. {
  2598. if (!factory)
  2599. factory.setown(new CWorkUnitFactory());
  2600. secMgr.set(&secmgr);
  2601. secUser.set(&secuser);
  2602. }
  2603. virtual IWorkUnit* createNamedWorkUnit(const char *wuid,const char *parentWuid, const char *app, const char *user)
  2604. {
  2605. checkWuScopeSecAccess(user, *secMgr.get(), secUser.get(), SecAccess_Write, "Create", true, true);
  2606. IWorkUnit *wu=factory->createNamedWorkUnit(wuid, parentWuid, app, user);
  2607. if (wu)
  2608. {
  2609. CLockedWorkUnit* lw = dynamic_cast<CLockedWorkUnit*>(wu);
  2610. if (lw)
  2611. lw->setSecIfcs(secMgr.get(), secUser.get());
  2612. }
  2613. return wu;
  2614. }
  2615. virtual IWorkUnit* createWorkUnit(const char *parentWuid, const char *app, const char *user)
  2616. {
  2617. checkWuScopeSecAccess(user, *secMgr.get(), secUser.get(), SecAccess_Write, "Create", true, true);
  2618. IWorkUnit *wu=factory->createWorkUnit(parentWuid, app, user);
  2619. if (wu)
  2620. {
  2621. CLockedWorkUnit* lw = dynamic_cast<CLockedWorkUnit*>(wu);
  2622. if (lw)
  2623. lw->setSecIfcs(secMgr.get(), secUser.get());
  2624. }
  2625. return wu;
  2626. }
  2627. virtual bool deleteWorkUnitEx(const char * wuid)
  2628. {
  2629. return factory->secDeleteWorkUnit(wuid, secMgr.get(), secUser.get(), true);
  2630. }
  2631. virtual bool deleteWorkUnit(const char * wuid)
  2632. {
  2633. return factory->secDeleteWorkUnit(wuid, secMgr.get(), secUser.get(), false);
  2634. }
  2635. virtual IConstWorkUnit* openWorkUnit(const char *wuid, bool lock)
  2636. {
  2637. return factory->secOpenWorkUnit(wuid, lock, secMgr.get(), secUser.get());
  2638. }
  2639. virtual IWorkUnit* updateWorkUnit(const char *wuid)
  2640. {
  2641. return factory->secUpdateWorkUnit(wuid, secMgr.get(), secUser.get());
  2642. }
  2643. //make cached workunits a non secure pass through for now.
  2644. virtual IConstWorkUnitIterator * getWorkUnitsByOwner(const char * owner)
  2645. {
  2646. // Not sure what to do about customerID vs user etc
  2647. StringBuffer path("*");
  2648. if (owner && *owner)
  2649. path.append("[@submitID=\"").append(owner).append("\"]");
  2650. return factory->getWorkUnitsByXPath(path.str(), secMgr.get(), secUser.get());
  2651. }
  2652. virtual IConstWorkUnitIterator * getWorkUnitsByState(WUState state);
  2653. virtual IConstWorkUnitIterator * getWorkUnitsByECL(const char* ecl)
  2654. {
  2655. return factory->getWorkUnitsByECL(ecl);
  2656. }
  2657. virtual IConstWorkUnitIterator * getWorkUnitsByCluster(const char* cluster)
  2658. {
  2659. return factory->getWorkUnitsByCluster(cluster);
  2660. }
  2661. virtual IConstWorkUnitIterator * getWorkUnitsByXPath(const char * xpath)
  2662. {
  2663. return factory->getWorkUnitsByXPath(xpath, secMgr.get(), secUser.get());
  2664. }
  2665. virtual void descheduleAllWorkUnits()
  2666. {
  2667. factory->descheduleAllWorkUnits();
  2668. }
  2669. virtual IConstWorkUnitIterator * getChildWorkUnits(const char *parent)
  2670. {
  2671. StringBuffer path("*[@parent=\"");
  2672. path.append(parent).append("\"]");
  2673. return factory->getWorkUnitsByXPath(path.str(), secMgr.get(), secUser.get());
  2674. }
  2675. virtual int setTracingLevel(int newLevel)
  2676. {
  2677. return factory->setTracingLevel(newLevel);
  2678. }
  2679. virtual IConstWorkUnitIterator* getWorkUnitsSorted( WUSortField *sortorder, // list of fields to sort by (terminated by WUSFterm)
  2680. WUSortField *filters, // NULL or list of fields to filter on (terminated by WUSFterm)
  2681. const void *filterbuf, // (appended) string values for filters
  2682. unsigned startoffset,
  2683. unsigned maxnum,
  2684. const char *queryowner,
  2685. __int64 *cachehint,
  2686. unsigned *total)
  2687. {
  2688. return factory->getWorkUnitsSorted(sortorder,filters,filterbuf,startoffset,maxnum,queryowner,cachehint, secMgr.get(), secUser.get(), total);
  2689. }
  2690. virtual IConstQuerySetQueryIterator* getQuerySetQueriesSorted( WUQuerySortField *sortorder,
  2691. WUQuerySortField *filters,
  2692. const void *filterbuf,
  2693. unsigned startoffset,
  2694. unsigned maxnum,
  2695. __int64 *cachehint,
  2696. unsigned *total,
  2697. const MapStringTo<bool> *subset)
  2698. {
  2699. return factory->getQuerySetQueriesSorted(sortorder,filters,filterbuf,startoffset,maxnum,cachehint,total, subset);
  2700. }
  2701. virtual unsigned numWorkUnits()
  2702. {
  2703. return factory->numWorkUnits();
  2704. }
  2705. virtual unsigned numWorkUnitsFiltered(WUSortField *filters,
  2706. const void *filterbuf)
  2707. {
  2708. return factory->numWorkUnitsFiltered(filters,filterbuf,secMgr.get(), secUser.get());
  2709. }
  2710. private:
  2711. Owned<CWorkUnitFactory> base_factory;
  2712. Owned<ISecManager> secMgr;
  2713. Owned<ISecUser> secUser;
  2714. };
  2715. extern WORKUNIT_API IWorkUnitFactory * getSecWorkUnitFactory(ISecManager &secmgr, ISecUser &secuser)
  2716. {
  2717. return new CSecureWorkUnitFactory(secmgr, secuser);
  2718. }
  2719. extern WORKUNIT_API IWorkUnitFactory * getWorkUnitFactory(ISecManager *secmgr, ISecUser *secuser)
  2720. {
  2721. if (secmgr && secuser)
  2722. return getSecWorkUnitFactory(*secmgr, *secuser);
  2723. else
  2724. return getWorkUnitFactory();
  2725. }
  2726. //==========================================================================================
  2727. class CStringPTreeIterator : public CInterface, implements IStringIterator
  2728. {
  2729. Owned<IPropertyTreeIterator> it;
  2730. public:
  2731. IMPLEMENT_IINTERFACE;
  2732. CStringPTreeIterator(IPropertyTreeIterator *p) : it(p) {};
  2733. virtual bool first() { return it->first(); }
  2734. virtual bool next() { return it->next(); }
  2735. virtual bool isValid() { return it->isValid(); }
  2736. virtual IStringVal & str(IStringVal &s) { s.set(it->query().queryProp(NULL)); return s; }
  2737. };
  2738. class CStringPTreeTagIterator : public CInterface, implements IStringIterator
  2739. {
  2740. Owned<IPropertyTreeIterator> it;
  2741. public:
  2742. IMPLEMENT_IINTERFACE;
  2743. CStringPTreeTagIterator(IPropertyTreeIterator *p) : it(p) {};
  2744. virtual bool first() { return it->first(); }
  2745. virtual bool next() { return it->next(); }
  2746. virtual bool isValid() { return it->isValid(); }
  2747. virtual IStringVal & str(IStringVal &s) { s.set(it->query().queryName()); return s; }
  2748. };
  2749. class CStringPTreeAttrIterator : public CInterface, implements IStringIterator
  2750. {
  2751. Owned<IPropertyTreeIterator> it;
  2752. StringAttr name;
  2753. public:
  2754. IMPLEMENT_IINTERFACE;
  2755. CStringPTreeAttrIterator(IPropertyTreeIterator *p, const char *_name) : it(p), name(_name) {};
  2756. virtual bool first() { return it->first(); }
  2757. virtual bool next() { return it->next(); }
  2758. virtual bool isValid() { return it->isValid(); }
  2759. virtual IStringVal & str(IStringVal &s) { s.set(it->query().queryProp(name)); return s; }
  2760. };
  2761. //==========================================================================================
  2762. CLocalWorkUnit::CLocalWorkUnit(IRemoteConnection *_conn, ISecManager *secmgr, ISecUser *secuser, const char *parentWuid) : connection(_conn)
  2763. {
  2764. connectAtRoot = true;
  2765. init();
  2766. p.setown(connection->getRoot());
  2767. if (parentWuid)
  2768. p->setProp("@parent", parentWuid);
  2769. secMgr.set(secmgr);
  2770. secUser.set(secuser);
  2771. }
  2772. CLocalWorkUnit::CLocalWorkUnit(IRemoteConnection *_conn, IPropertyTree* root, ISecManager *secmgr, ISecUser *secuser) : connection(_conn)
  2773. {
  2774. connectAtRoot = false;
  2775. init();
  2776. p.setown(root);
  2777. secMgr.set(secmgr);
  2778. secUser.set(secuser);
  2779. }
  2780. void CLocalWorkUnit::init()
  2781. {
  2782. p.clear();
  2783. cachedGraphs.clear();
  2784. workflowIterator.clear();
  2785. query.clear();
  2786. graphs.kill();
  2787. results.kill();
  2788. variables.kill();
  2789. plugins.kill();
  2790. libraries.kill();
  2791. activities.kill();
  2792. exceptions.kill();
  2793. temporaries.kill();
  2794. timers.kill();
  2795. roxieQueryInfo.clear();
  2796. webServicesInfo.clear();
  2797. workflowIteratorCached = false;
  2798. resultsCached = false;
  2799. temporariesCached = false;
  2800. variablesCached = false;
  2801. exceptionsCached = false;
  2802. pluginsCached = false;
  2803. librariesCached = false;
  2804. activitiesCached = false;
  2805. webServicesInfoCached = false;
  2806. roxieQueryInfoCached = false;
  2807. timersCached = false;
  2808. dirty = false;
  2809. abortDirty = true;
  2810. abortState = false;
  2811. }
  2812. // Dummy workunit support
  2813. CLocalWorkUnit::CLocalWorkUnit(const char *_wuid, const char *parentWuid, ISecManager *secmgr, ISecUser *secuser)
  2814. {
  2815. connectAtRoot = true;
  2816. init();
  2817. p.setown(createPTree(_wuid));
  2818. p->setProp("@xmlns:xsi", "http://www.w3.org/1999/XMLSchema-instance");
  2819. if (parentWuid)
  2820. p->setProp("@parentWuid", parentWuid);
  2821. secMgr.set(secmgr);
  2822. secUser.set(secuser);
  2823. }
  2824. CLocalWorkUnit::~CLocalWorkUnit()
  2825. {
  2826. if (workUnitTraceLevel > 1)
  2827. {
  2828. PrintLog("Releasing workunit %s mode %x", p->queryName(), connection ? connection->queryMode() :0);
  2829. }
  2830. try
  2831. {
  2832. unsubscribe();
  2833. query.clear();
  2834. webServicesInfo.clear();
  2835. roxieQueryInfo.clear();
  2836. workflowIterator.clear();
  2837. activities.kill();
  2838. plugins.kill();
  2839. libraries.kill();
  2840. exceptions.kill();
  2841. graphs.kill();
  2842. results.kill();
  2843. temporaries.kill();
  2844. variables.kill();
  2845. timestamps.kill();
  2846. appvalues.kill();
  2847. statistics.kill();
  2848. userDesc.clear();
  2849. secMgr.clear();
  2850. secUser.clear();
  2851. cachedGraphs.clear();
  2852. p.clear();
  2853. connection.clear();
  2854. }
  2855. catch (IException *E) { LOG(MCexception(E, MSGCLS_warning), E, "Exception during ~CLocalWorkUnit"); E->Release(); }
  2856. }
  2857. void CLocalWorkUnit::cleanupAndDelete(bool deldll, bool deleteOwned, const StringArray *deleteExclusions)
  2858. {
  2859. TIME_SECTION("WUDELETE cleanupAndDelete total");
  2860. // Delete any related things in SDS etc that might otherwise be forgotten
  2861. assertex(connectAtRoot); // make sure we don't delete entire workunit tree!
  2862. if (p->getPropBool("@protected", false))
  2863. throw MakeStringException(WUERR_WorkunitProtected, "%s: Workunit is protected",p->queryName());
  2864. switch (getState())
  2865. {
  2866. case WUStateAborted:
  2867. case WUStateCompleted:
  2868. case WUStateFailed:
  2869. case WUStateArchived:
  2870. break;
  2871. case WUStateCompiled:
  2872. if (getAction()==WUActionRun || getAction()==WUActionUnknown)
  2873. throw MakeStringException(WUERR_WorkunitActive, "%s: Workunit is active",p->queryName());
  2874. break;
  2875. case WUStateWait:
  2876. throw MakeStringException(WUERR_WorkunitScheduled, "%s: Workunit is scheduled",p->queryName());
  2877. default:
  2878. throw MakeStringException(WUERR_WorkunitActive, "%s: Workunit is active",p->queryName());
  2879. break;
  2880. }
  2881. if (getIsQueryService())
  2882. {
  2883. Owned<IPropertyTree> registry = getQueryRegistryRoot();
  2884. if (registry)
  2885. {
  2886. VStringBuffer xpath("QuerySet/Query[@wuid='%s']", p->queryName());
  2887. if (registry->hasProp(xpath.str()))
  2888. throw MakeStringException(WUERR_WorkunitPublished, "%s: Workunit is published",p->queryName());
  2889. }
  2890. }
  2891. try
  2892. {
  2893. if (deldll && !p->getPropBool("@isClone", false))
  2894. {
  2895. Owned<IConstWUQuery> q = getQuery();
  2896. if (q)
  2897. {
  2898. Owned<IConstWUAssociatedFileIterator> iter = &q->getAssociatedFiles();
  2899. SCMStringBuffer name;
  2900. ForEach(*iter)
  2901. {
  2902. IConstWUAssociatedFile & cur = iter->query();
  2903. cur.getNameTail(name);
  2904. if (!deleteExclusions || (NotFound == deleteExclusions->find(name.str())))
  2905. {
  2906. Owned<IDllEntry> entry = queryDllServer().getEntry(name.str());
  2907. if (entry.get())
  2908. factory->asyncRemoveDll(name.str());
  2909. else
  2910. {
  2911. SCMStringBuffer ip, localPath;
  2912. cur.getName(localPath);
  2913. cur.getIp(ip);
  2914. factory->asyncRemoveFile(ip.str(), localPath.str());
  2915. }
  2916. }
  2917. }
  2918. }
  2919. }
  2920. StringBuffer apath;
  2921. // PROGLOG("wuid dll files removed");
  2922. {
  2923. apath.append("/WorkUnitAborts/").append(p->queryName());
  2924. Owned<IRemoteConnection> acon = factory->sdsManager->connect(apath.str(), factory->session, RTM_LOCK_WRITE | RTM_DELETE_ON_DISCONNECT, SDS_LOCK_TIMEOUT);
  2925. acon.clear();
  2926. }
  2927. // PROGLOG("wuid WorkUnitAborts entry removed");
  2928. deleteTempFiles(NULL, deleteOwned, true); // all, any remaining.
  2929. }
  2930. catch(IException *E)
  2931. {
  2932. StringBuffer s;
  2933. LOG(MCexception(E, MSGCLS_warning), E, s.append("Exception during cleanupAndDelete: ").append(p->queryName()).str());
  2934. E->Release();
  2935. }
  2936. catch (...)
  2937. {
  2938. WARNLOG("Unknown exception during cleanupAndDelete: %s", p->queryName());
  2939. }
  2940. CConstGraphProgress::deleteWuidProgress(p->queryName());
  2941. connection->close(true);
  2942. PROGLOG("WUID %s removed",p->queryName());
  2943. connection.clear();
  2944. }
  2945. void CLocalWorkUnit::setTimeScheduled(const IJlibDateTime &val)
  2946. {
  2947. SCMStringBuffer strval;
  2948. val.getGmtString(strval);
  2949. p->setProp("@timescheduled",strval.str());
  2950. }
  2951. IJlibDateTime & CLocalWorkUnit::getTimeScheduled(IJlibDateTime &val) const
  2952. {
  2953. StringBuffer str;
  2954. p->getProp("@timescheduled",str);
  2955. if(str.length())
  2956. val.setGmtString(str.str());
  2957. return val;
  2958. }
  2959. bool modifyAndWriteWorkUnitXML(char const * wuid, StringBuffer & buf, StringBuffer & extra, IFileIO * fileio)
  2960. {
  2961. // kludge in extra chunks of XML such as GraphProgress and GeneratedDlls
  2962. if(extra.length())
  2963. {
  2964. size32_t l = (size32_t)strlen(wuid);
  2965. size32_t p = buf.length()-l-4; // bit of a kludge
  2966. assertex(memcmp(buf.str()+p+2,wuid,l)==0);
  2967. StringAttr tail(buf.str()+p);
  2968. buf.setLength(p);
  2969. buf.append(extra);
  2970. buf.append(tail);
  2971. }
  2972. return (fileio->write(0,buf.length(),buf.str()) == buf.length());
  2973. }
  2974. bool CLocalWorkUnit::archiveWorkUnit(const char *base,bool del,bool ignoredllerrors,bool deleteOwned)
  2975. {
  2976. CriticalBlock block(crit);
  2977. StringBuffer path(base);
  2978. if (!p)
  2979. return false;
  2980. const char *wuid = p->queryName();
  2981. if (!wuid||!*wuid)
  2982. return false;
  2983. addPathSepChar(path).append(wuid).append(".xml");
  2984. Owned<IFile> file = createIFile(path.str());
  2985. if (!file)
  2986. return false;
  2987. Owned<IFileIO> fileio = file->open(IFOcreate);
  2988. if (!fileio)
  2989. return false;
  2990. StringBuffer buf;
  2991. exportWorkUnitToXML(this, buf, false, false);
  2992. StringBuffer extraWorkUnitXML;
  2993. StringBuffer xpath("/GraphProgress/");
  2994. xpath.append(wuid);
  2995. Owned<IRemoteConnection> conn = querySDS().connect(xpath.str(), myProcessSession(), RTM_LOCK_WRITE, SDS_LOCK_TIMEOUT);
  2996. if (conn)
  2997. {
  2998. Owned<IPropertyTree> tmp = createPTree("GraphProgress");
  2999. mergePTree(tmp,conn->queryRoot());
  3000. toXML(tmp,extraWorkUnitXML,1,XML_Format);
  3001. conn->close();
  3002. }
  3003. Owned<IConstWUQuery> q = getQuery();
  3004. if (!q)
  3005. {
  3006. if (!modifyAndWriteWorkUnitXML(wuid, buf, extraWorkUnitXML, fileio))
  3007. return false;
  3008. if (del)
  3009. {
  3010. if (getState()==WUStateUnknown)
  3011. setState(WUStateArchived); // to allow delete
  3012. cleanupAndDelete(false,deleteOwned); // no query, may as well delete
  3013. }
  3014. return false;
  3015. }
  3016. StringArray deleteExclusions; // associated files not to delete, added if failure to copy
  3017. Owned<IConstWUAssociatedFileIterator> iter = &q->getAssociatedFiles();
  3018. Owned<IPropertyTree> generatedDlls = createPTree("GeneratedDlls");
  3019. ForEach(*iter)
  3020. {
  3021. IConstWUAssociatedFile & cur = iter->query();
  3022. SCMStringBuffer name;
  3023. cur.getNameTail(name);
  3024. if (name.length())
  3025. {
  3026. Owned<IDllEntry> entry = queryDllServer().getEntry(name.str());
  3027. SCMStringBuffer curPath, curIp;
  3028. cur.getName(curPath);
  3029. cur.getIp(curIp);
  3030. SocketEndpoint curEp(curIp.str());
  3031. RemoteFilename curRfn;
  3032. curRfn.setPath(curEp, curPath.str());
  3033. StringBuffer dst(base);
  3034. addPathSepChar(dst);
  3035. curRfn.getTail(dst);
  3036. Owned<IFile> dstFile = createIFile(dst.str());
  3037. if (entry.get())
  3038. {
  3039. Owned<IException> exception;
  3040. Owned<IDllLocation> loc;
  3041. Owned<IPropertyTree> generatedDllBranch = createPTree();
  3042. generatedDllBranch->setProp("@name", entry->queryName());
  3043. generatedDllBranch->setProp("@kind", entry->queryKind());
  3044. try
  3045. {
  3046. loc.setown(entry->getBestLocation()); //throws exception if no readable locations
  3047. }
  3048. catch(IException * e)
  3049. {
  3050. exception.setown(e);
  3051. loc.setown(entry->getBestLocationCandidate()); //this will be closest of the unreadable locations
  3052. }
  3053. RemoteFilename filename;
  3054. loc->getDllFilename(filename);
  3055. if (!exception)
  3056. {
  3057. Owned<IFile> srcfile = createIFile(filename);
  3058. try
  3059. {
  3060. if (dstFile->exists())
  3061. {
  3062. if (streq(srcfile->queryFilename(), dstFile->queryFilename()))
  3063. deleteExclusions.append(name.str()); // restored workunit, referencing archive location for query dll (no longer true post HPCC-11191 fix)
  3064. // still want to delete if already archived but there are source file copies
  3065. }
  3066. else
  3067. copyFile(dstFile, srcfile);
  3068. }
  3069. catch(IException * e)
  3070. {
  3071. exception.setown(e);
  3072. }
  3073. }
  3074. if (exception)
  3075. {
  3076. if (ignoredllerrors)
  3077. {
  3078. EXCLOG(exception.get(), "archiveWorkUnit (copying associated file)");
  3079. //copy failed, so don't delete the registred dll files
  3080. deleteExclusions.append(name.str());
  3081. }
  3082. else
  3083. throw exception.getClear();
  3084. }
  3085. // Record Associated path to restore back to
  3086. StringBuffer restorePath;
  3087. curRfn.getRemotePath(restorePath);
  3088. generatedDllBranch->setProp("@location", restorePath.str());
  3089. generatedDlls->addPropTree("GeneratedDll", generatedDllBranch.getClear());
  3090. }
  3091. else // no generated dll entry
  3092. {
  3093. Owned<IFile> srcFile = createIFile(curRfn);
  3094. try
  3095. {
  3096. copyFile(dstFile, srcFile);
  3097. }
  3098. catch (IException *e)
  3099. {
  3100. VStringBuffer msg("Failed to archive associated file '%s' to destination '%s'", srcFile->queryFilename(), dstFile->queryFilename());
  3101. EXCLOG(e, msg.str());
  3102. e->Release();
  3103. deleteExclusions.append(name.str());
  3104. }
  3105. }
  3106. }
  3107. }
  3108. iter.clear();
  3109. if (generatedDlls->numChildren())
  3110. toXML(generatedDlls, extraWorkUnitXML, 1, XML_Format);
  3111. if (!modifyAndWriteWorkUnitXML(wuid, buf, extraWorkUnitXML, fileio))
  3112. return false;
  3113. if (del)
  3114. {
  3115. //setState(WUStateArchived); // this isn't useful as about to delete it!
  3116. q.clear();
  3117. cleanupAndDelete(true, deleteOwned, &deleteExclusions);
  3118. }
  3119. return true;
  3120. }
  3121. void CLocalWorkUnit::packWorkUnit(bool pack)
  3122. {
  3123. // only packs Graph info currently
  3124. CriticalBlock block(crit);
  3125. if (!p)
  3126. return;
  3127. const char *wuid = p->queryName();
  3128. if (!wuid||!*wuid)
  3129. return;
  3130. if (pack) {
  3131. if (!p->hasProp("PackedGraphs")) {
  3132. cachedGraphs.clear();
  3133. IPropertyTree *t = p->queryPropTree("Graphs");
  3134. if (t) {
  3135. MemoryBuffer buf;
  3136. t->serialize(buf);
  3137. p->setPropBin("PackedGraphs",buf.length(),buf.bufferBase());
  3138. p->removeTree(t);
  3139. }
  3140. }
  3141. }
  3142. else {
  3143. ensureGraphsUnpacked();
  3144. }
  3145. CConstGraphProgress::packProgress(wuid,pack);
  3146. }
  3147. IPropertyTree * pruneBranch(IPropertyTree * from, char const * xpath)
  3148. {
  3149. Owned<IPropertyTree> ret;
  3150. IPropertyTree * branch = from->queryPropTree(xpath);
  3151. if(branch) {
  3152. ret.setown(createPTreeFromIPT(branch));
  3153. from->removeTree(branch);
  3154. }
  3155. return ret.getClear();
  3156. }
  3157. bool restoreWorkUnit(const char *base,const char *wuid)
  3158. {
  3159. StringBuffer path(base);
  3160. if (!wuid||!*wuid)
  3161. return false;
  3162. addPathSepChar(path).append(wuid).append(".xml");
  3163. Owned<IFile> file = createIFile(path.str());
  3164. if (!file)
  3165. return false;
  3166. Owned<IFileIO> fileio = file->open(IFOread);
  3167. if (!fileio)
  3168. return false;
  3169. Owned<IPropertyTree> pt = createPTree(*fileio);
  3170. if (!pt)
  3171. return false;
  3172. CDateTime dt;
  3173. dt.setNow();
  3174. StringBuffer dts;
  3175. dt.getString(dts);
  3176. pt->setProp("@restoredDate", dts.str());
  3177. VStringBuffer xpath("/WorkUnits/%s", wuid);
  3178. Owned<IRemoteConnection> conn = querySDS().connect(xpath.str(), myProcessSession(), RTM_LOCK_WRITE|RTM_CREATE_QUERY, SDS_LOCK_TIMEOUT);
  3179. if (!conn)
  3180. {
  3181. ERRLOG("restoreWorkUnit could not create to %s", xpath.str());
  3182. return false;
  3183. }
  3184. IPropertyTree *root = conn->queryRoot();
  3185. if (root->hasChildren())
  3186. {
  3187. ERRLOG("restoreWorkUnit WUID %s already exists", wuid);
  3188. return false;
  3189. }
  3190. Owned<IPropertyTree> gprogress = pruneBranch(pt, "GraphProgress[1]");
  3191. Owned<IPropertyTree> generatedDlls = pruneBranch(pt, "GeneratedDlls[1]");
  3192. Owned<IPropertyTree> associatedFiles;
  3193. IPropertyTree *srcAssociated = pt->queryPropTree("Query/Associated");
  3194. if (srcAssociated)
  3195. associatedFiles.setown(createPTreeFromIPT(srcAssociated));
  3196. root->setPropTree(NULL, pt.getClear());
  3197. conn.clear();
  3198. // now kludge back GraphProgress and GeneratedDlls
  3199. if (gprogress)
  3200. {
  3201. VStringBuffer xpath("/GraphProgress/%s", wuid);
  3202. conn.setown(querySDS().connect(xpath, myProcessSession(), RTM_LOCK_WRITE|RTM_CREATE_QUERY, SDS_LOCK_TIMEOUT));
  3203. if (conn)
  3204. {
  3205. IPropertyTree *groot = conn->queryRoot();
  3206. if (groot->hasChildren())
  3207. WARNLOG("restoreWorkUnit WUID %s graphprogress already exists, replacing",wuid);
  3208. groot->setPropTree(NULL, gprogress.getClear());
  3209. }
  3210. }
  3211. if (generatedDlls)
  3212. {
  3213. Owned<IPropertyTreeIterator> dlls = generatedDlls->getElements("GeneratedDll");
  3214. for(dlls->first(); dlls->isValid(); dlls->next())
  3215. {
  3216. IPropertyTree & dll = dlls->query();
  3217. char const * name = dll.queryProp("@name");
  3218. char const * kind = dll.queryProp("@kind");
  3219. char const * location = dll.queryProp("@location");
  3220. Owned<IDllEntry> got = queryDllServer().getEntry(name);
  3221. if (!got)
  3222. {
  3223. RemoteFilename dstRfn;
  3224. dstRfn.setRemotePath(location);
  3225. StringBuffer srcPath(base);
  3226. addPathSepChar(srcPath);
  3227. dstRfn.getTail(srcPath);
  3228. OwnedIFile srcFile = createIFile(srcPath);
  3229. OwnedIFile dstFile = createIFile(dstRfn);
  3230. copyFile(dstFile, srcFile);
  3231. queryDllServer().registerDll(name, kind, location);
  3232. }
  3233. }
  3234. }
  3235. if (associatedFiles)
  3236. {
  3237. Owned<IPropertyTreeIterator> associated = associatedFiles->getElements("*");
  3238. ForEach(*associated)
  3239. {
  3240. IPropertyTree &file = associated->query();
  3241. const char *filename = file.queryProp("@filename");
  3242. SocketEndpoint ep(file.queryProp("@ip"));
  3243. RemoteFilename rfn;
  3244. rfn.setPath(ep, filename);
  3245. OwnedIFile dstFile = createIFile(rfn);
  3246. StringBuffer srcPath(base), name;
  3247. addPathSepChar(srcPath);
  3248. rfn.getTail(name);
  3249. srcPath.append(name);
  3250. if (generatedDlls)
  3251. {
  3252. VStringBuffer gDllPath("GeneratedDll[@name=\"%s\"]", name.str());
  3253. if (generatedDlls->hasProp(gDllPath))
  3254. continue; // generated dlls handled separately - see above
  3255. }
  3256. OwnedIFile srcFile = createIFile(srcPath);
  3257. if (srcFile->exists())
  3258. {
  3259. try
  3260. {
  3261. copyFile(dstFile, srcFile);
  3262. }
  3263. catch (IException *e)
  3264. {
  3265. VStringBuffer msg("Failed to restore associated file '%s' to destination '%s'", srcFile->queryFilename(), dstFile->queryFilename());
  3266. EXCLOG(e, msg.str());
  3267. e->Release();
  3268. }
  3269. }
  3270. }
  3271. }
  3272. return true;
  3273. }
  3274. void CLocalWorkUnit::loadXML(const char *xml)
  3275. {
  3276. CriticalBlock block(crit);
  3277. init();
  3278. assertex(xml);
  3279. p.setown(createPTreeFromXMLString(xml));
  3280. }
  3281. void CLocalWorkUnit::serialize(MemoryBuffer &tgt)
  3282. {
  3283. CriticalBlock block(crit);
  3284. StringBuffer x;
  3285. tgt.append(exportWorkUnitToXML(this, x, false, false).str());
  3286. }
  3287. void CLocalWorkUnit::deserialize(MemoryBuffer &src)
  3288. {
  3289. CriticalBlock block(crit);
  3290. StringAttr value;
  3291. src.read(value);
  3292. loadXML(value);
  3293. }
  3294. void CLocalWorkUnit::notify(SubscriptionId id, const char *xpath, SDSNotifyFlags flags, unsigned valueLen, const void *valueData)
  3295. {
  3296. dirty = true;
  3297. }
  3298. void CLocalWorkUnit::abort()
  3299. {
  3300. abortDirty = true;
  3301. }
  3302. void CLocalWorkUnit::requestAbort()
  3303. {
  3304. CriticalBlock block(crit);
  3305. abortWorkUnit(p->queryName());
  3306. }
  3307. void CLocalWorkUnit::subscribe(WUSubscribeOptions options)
  3308. {
  3309. CriticalBlock block(crit);
  3310. bool subscribeAbort = false;
  3311. bool subscribeChange = false;
  3312. bool needChildren = true;
  3313. switch (options)
  3314. {
  3315. case SubscribeOptionAbort:
  3316. subscribeAbort = true;
  3317. break;
  3318. case SubscribeOptionRunningState:
  3319. needChildren = false;
  3320. case SubscribeOptionAnyState:
  3321. subscribeAbort = true;
  3322. subscribeChange = true;
  3323. break;
  3324. case SubscribeOptionProgress:
  3325. case SubscribeOptionAll:
  3326. subscribeChange = true;
  3327. break;
  3328. }
  3329. if (subscribeChange)
  3330. {
  3331. if (changeWatcher && changeWatcher->watchingChildren() != needChildren)
  3332. {
  3333. changeWatcher->unsubscribe();
  3334. changeWatcher.clear();
  3335. }
  3336. if (!changeWatcher)
  3337. {
  3338. changeWatcher.setown(new CWorkUnitWatcher(this, p->queryName(), needChildren));
  3339. dirty = true;
  3340. }
  3341. }
  3342. if (subscribeAbort && !abortWatcher)
  3343. {
  3344. abortWatcher.setown(new CWorkUnitAbortWatcher(this, p->queryName()));
  3345. abortDirty = true;
  3346. }
  3347. }
  3348. void CLocalWorkUnit::forceReload()
  3349. {
  3350. dirty = true;
  3351. reload();
  3352. }
  3353. bool CLocalWorkUnit::reload()
  3354. {
  3355. CriticalBlock block(crit);
  3356. if (dirty)
  3357. {
  3358. if (!connectAtRoot)
  3359. {
  3360. StringBuffer wuRoot;
  3361. getXPath(wuRoot, p->queryName());
  3362. IRemoteConnection *newconn = factory->sdsManager->connect(wuRoot.str(), factory->session, 0, SDS_LOCK_TIMEOUT);
  3363. if (!newconn)
  3364. throw MakeStringException(WUERR_ConnectFailed, "Could not connect to workunit %s (deleted?)",p->queryName());
  3365. connection.setown(newconn);
  3366. connectAtRoot = true;
  3367. }
  3368. else
  3369. connection->reload();
  3370. init();
  3371. p.setown(connection->getRoot());
  3372. return true;
  3373. }
  3374. return false;
  3375. }
  3376. void CLocalWorkUnit::unsubscribe()
  3377. {
  3378. CriticalBlock block(crit);
  3379. if (abortWatcher)
  3380. {
  3381. abortWatcher->unsubscribe();
  3382. abortWatcher.clear();
  3383. }
  3384. if (changeWatcher)
  3385. {
  3386. changeWatcher->unsubscribe();
  3387. changeWatcher.clear();
  3388. }
  3389. }
  3390. void CLocalWorkUnit::unlockRemote(bool commit)
  3391. {
  3392. CriticalBlock block(crit);
  3393. locked.unlock();
  3394. if (commit)
  3395. {
  3396. try
  3397. {
  3398. assertex(connectAtRoot);
  3399. setTimeStamp("workunit", NULL, "Modified",false);
  3400. try { connection->commit(); }
  3401. catch (IException *e)
  3402. {
  3403. EXCLOG(e, "Error during workunit commit");
  3404. connection->rollback();
  3405. connection->changeMode(0, SDS_LOCK_TIMEOUT);
  3406. throw;
  3407. }
  3408. connection->changeMode(0, SDS_LOCK_TIMEOUT);
  3409. }
  3410. catch (IException *E)
  3411. {
  3412. StringBuffer s;
  3413. PrintLog("Failed to release write lock on workunit: %s", E->errorMessage(s).str());
  3414. throw;
  3415. }
  3416. }
  3417. }
  3418. IWorkUnit &CLocalWorkUnit::lockRemote(bool commit)
  3419. {
  3420. if (secMgr)
  3421. checkWuSecAccess(*this, *secMgr.get(), secUser.get(), SecAccess_Write, "write lock", true, true);
  3422. locked.lock();
  3423. CriticalBlock block(crit);
  3424. if (commit)
  3425. {
  3426. try
  3427. {
  3428. StringBuffer wuRoot;
  3429. getXPath(wuRoot, p->queryName());
  3430. if (connection&&connectAtRoot)
  3431. connection->changeMode(RTM_LOCK_WRITE,SDS_LOCK_TIMEOUT);
  3432. else
  3433. connection.setown(factory->sdsManager->connect(wuRoot.str(), factory->session, RTM_LOCK_WRITE, SDS_LOCK_TIMEOUT));
  3434. if (!connection)
  3435. throw MakeStringException(WUERR_LockFailed, "Failed to get connection for xpath %s", wuRoot.str());
  3436. connectAtRoot = true;
  3437. init();
  3438. p.setown(connection->getRoot());
  3439. }
  3440. catch (IException *E)
  3441. {
  3442. StringBuffer s;
  3443. PrintLog("Failed to get write lock on workunit: %s", E->errorMessage(s).str());
  3444. locked.unlock();
  3445. throw;
  3446. }
  3447. }
  3448. return *new CLockedWorkUnit(LINK(this));
  3449. }
  3450. void CLocalWorkUnit::commit()
  3451. {
  3452. CriticalBlock block(crit);
  3453. assertex(connectAtRoot);
  3454. if (connection)
  3455. connection->commit();
  3456. }
  3457. IWorkUnit& CLocalWorkUnit::lock()
  3458. {
  3459. return lockRemote(true);
  3460. }
  3461. IStringVal& CLocalWorkUnit::getWuid(IStringVal &str) const
  3462. {
  3463. CriticalBlock block(crit);
  3464. str.set(p->queryName());
  3465. return str;
  3466. }
  3467. unsigned CLocalWorkUnit::getDebugAgentListenerPort() const
  3468. {
  3469. CriticalBlock block(crit);
  3470. return p->getPropInt("@DebugListenerPort", 0);
  3471. }
  3472. void CLocalWorkUnit::setDebugAgentListenerPort(unsigned port)
  3473. {
  3474. CriticalBlock block(crit);
  3475. p->setPropInt("@DebugListenerPort", port);
  3476. }
  3477. IStringVal& CLocalWorkUnit::getDebugAgentListenerIP(IStringVal &ip) const
  3478. {
  3479. CriticalBlock block(crit);
  3480. ip.set(p->queryProp("@DebugListenerIP"));
  3481. return ip;
  3482. }
  3483. void CLocalWorkUnit::setDebugAgentListenerIP(const char * ip)
  3484. {
  3485. CriticalBlock block(crit);
  3486. p->setProp("@DebugListenerIP", ip);
  3487. }
  3488. IStringVal& CLocalWorkUnit::getSecurityToken(IStringVal &str) const
  3489. {
  3490. CriticalBlock block(crit);
  3491. str.set(p->queryProp("@token"));
  3492. return str;
  3493. }
  3494. void CLocalWorkUnit::setSecurityToken(const char *value)
  3495. {
  3496. CriticalBlock block(crit);
  3497. p->setProp("@token", value);
  3498. }
  3499. bool CLocalWorkUnit::getRunningGraph(IStringVal &graphName, WUGraphIDType &subId) const
  3500. {
  3501. return CConstGraphProgress::getRunningGraph(p->queryName(), graphName, subId);
  3502. }
  3503. void CLocalWorkUnit::setJobName(const char *value)
  3504. {
  3505. CriticalBlock block(crit);
  3506. p->setProp("@jobName", value);
  3507. }
  3508. IStringVal& CLocalWorkUnit::getJobName(IStringVal &str) const
  3509. {
  3510. CriticalBlock block(crit);
  3511. str.set(p->queryProp("@jobName"));
  3512. return str;
  3513. }
  3514. void CLocalWorkUnit::setClusterName(const char *value)
  3515. {
  3516. CriticalBlock block(crit);
  3517. p->setProp("@clusterName", value);
  3518. }
  3519. IStringVal& CLocalWorkUnit::getClusterName(IStringVal &str) const
  3520. {
  3521. CriticalBlock block(crit);
  3522. str.set(p->queryProp("@clusterName"));
  3523. return str;
  3524. }
  3525. void CLocalWorkUnit::setAllowedClusters(const char *value)
  3526. {
  3527. setDebugValue("allowedclusters",value, true);
  3528. }
  3529. IStringVal& CLocalWorkUnit::getAllowedClusters(IStringVal &str) const
  3530. {
  3531. CriticalBlock block(crit);
  3532. getDebugValue("allowedclusters",str);
  3533. if (str.length()!=0)
  3534. return str;
  3535. str.set(p->queryProp("@clusterName"));
  3536. return str;
  3537. }
  3538. void CLocalWorkUnit::setAllowAutoQueueSwitch(bool val)
  3539. {
  3540. setDebugValueInt("allowautoqueueswitch",val?1:0,true);
  3541. }
  3542. bool CLocalWorkUnit::getAllowAutoQueueSwitch() const
  3543. {
  3544. CriticalBlock block(crit);
  3545. return getDebugValueBool("allowautoqueueswitch",false);
  3546. }
  3547. void CLocalWorkUnit::setLibraryInformation(const char * name, unsigned interfaceHash, unsigned definitionHash)
  3548. {
  3549. StringBuffer suffix;
  3550. if (name && *name)
  3551. setApplicationValue("LibraryModule", "name", name, true);
  3552. setApplicationValueInt("LibraryModule", "interfaceHash", interfaceHash, true);
  3553. setApplicationValueInt("LibraryModule", "definitionHash", definitionHash, true);
  3554. setApplicationValue("LibraryModule", "platform", appendLibrarySuffix(suffix).str(), true);
  3555. }
  3556. void CLocalWorkUnit::remoteCheckAccess(IUserDescriptor *user, bool writeaccess) const
  3557. {
  3558. unsigned auditflags = DALI_LDAP_AUDIT_REPORT|DALI_LDAP_READ_WANTED;
  3559. if (writeaccess)
  3560. auditflags |= DALI_LDAP_WRITE_WANTED;
  3561. int perm = 255;
  3562. const char *scopename = p->queryProp("@scope");
  3563. if (scopename&&*scopename) {
  3564. if (!user)
  3565. user = queryUserDescriptor();
  3566. perm = querySessionManager().getPermissionsLDAP("workunit",scopename,user,auditflags);
  3567. if (perm<0) {
  3568. if (perm==-1)
  3569. perm = 255;
  3570. else
  3571. perm = 0;
  3572. }
  3573. }
  3574. if (!HASREADPERMISSION(perm)) {
  3575. SCMStringBuffer wuid;
  3576. getWuid(wuid);
  3577. throw MakeStringException(WUERR_WorkunitAccessDenied, "Read access denied for workunit %s",wuid.s.str());
  3578. }
  3579. if (writeaccess&&!HASWRITEPERMISSION(perm)) {
  3580. SCMStringBuffer wuid;
  3581. getWuid(wuid);
  3582. throw MakeStringException(WUERR_WorkunitAccessDenied, "Write access denied for workunit %s",wuid.s.str());
  3583. }
  3584. }
  3585. IStringVal& CLocalWorkUnit::getParentWuid(IStringVal &str) const
  3586. {
  3587. CriticalBlock block(crit);
  3588. str.set(p->queryProp("@parent"));
  3589. return str;
  3590. }
  3591. void CLocalWorkUnit::setUser(const char * value)
  3592. {
  3593. CriticalBlock block(crit);
  3594. p->setProp("@submitID", value);
  3595. }
  3596. IStringVal& CLocalWorkUnit::getUser(IStringVal &str) const
  3597. {
  3598. CriticalBlock block(crit);
  3599. str.set(p->queryProp("@submitID"));
  3600. return str;
  3601. }
  3602. void CLocalWorkUnit::setWuScope(const char * value)
  3603. {
  3604. CriticalBlock block(crit);
  3605. p->setProp("@scope", value);
  3606. }
  3607. IStringVal& CLocalWorkUnit::getWuScope(IStringVal &str) const
  3608. {
  3609. CriticalBlock block(crit);
  3610. str.set(p->queryProp("@scope"));
  3611. return str;
  3612. }
  3613. void CLocalWorkUnit::setCustomerId(const char * value)
  3614. {
  3615. CriticalBlock block(crit);
  3616. p->setProp("CustomerID", value);
  3617. }
  3618. IStringVal& CLocalWorkUnit::getCustomerId(IStringVal &str) const
  3619. {
  3620. CriticalBlock block(crit);
  3621. str.set(p->queryProp("CustomerID"));
  3622. return str;
  3623. }
  3624. mapEnums priorityClasses[] = {
  3625. { PriorityClassUnknown, "unknown" },
  3626. { PriorityClassLow, "low" },
  3627. { PriorityClassNormal, "normal" },
  3628. { PriorityClassHigh, "high" },
  3629. { PriorityClassSize, NULL },
  3630. };
  3631. void CLocalWorkUnit::setPriority(WUPriorityClass cls)
  3632. {
  3633. CriticalBlock block(crit);
  3634. setEnum(p, "@priorityClass", cls, priorityClasses);
  3635. }
  3636. WUPriorityClass CLocalWorkUnit::getPriority() const
  3637. {
  3638. CriticalBlock block(crit);
  3639. return (WUPriorityClass) getEnum(p, "@priorityClass", priorityClasses);
  3640. }
  3641. mapEnums states[] = {
  3642. { WUStateUnknown, "unknown" },
  3643. { WUStateCompiled, "compiled" },
  3644. { WUStateRunning, "running" },
  3645. { WUStateCompleted, "completed" },
  3646. { WUStateFailed, "failed" },
  3647. { WUStateArchived, "archived" },
  3648. { WUStateAborting, "aborting" },
  3649. { WUStateAborted, "aborted" },
  3650. { WUStateBlocked, "blocked" },
  3651. { WUStateSubmitted, "submitted" },
  3652. { WUStateScheduled, "scheduled" },
  3653. { WUStateCompiling, "compiling" },
  3654. { WUStateWait, "wait" },
  3655. { WUStateUploadingFiles, "uploading_files" },
  3656. { WUStateDebugPaused, "debugging" },
  3657. { WUStateDebugRunning, "debug_running" },
  3658. { WUStatePaused, "paused" },
  3659. { WUStateSize, NULL }
  3660. };
  3661. const char * getWorkunitStateStr(WUState state)
  3662. {
  3663. return states[state].str;
  3664. }
  3665. IConstWorkUnitIterator * CWorkUnitFactory::getWorkUnitsByState(WUState state)
  3666. {
  3667. StringBuffer path("*");
  3668. path.append("[@state=\"").append(getEnumText(state, states)).append("\"]");
  3669. return getWorkUnitsByXPath(path.str());
  3670. }
  3671. IConstWorkUnitIterator * CSecureWorkUnitFactory::getWorkUnitsByState(WUState state)
  3672. {
  3673. StringBuffer path("*");
  3674. path.append("[@state=\"").append(getEnumText(state, states)).append("\"]");
  3675. return factory->getWorkUnitsByXPath(path.str(), secMgr.get(), secUser.get());
  3676. }
  3677. void CLocalWorkUnit::setState(WUState value)
  3678. {
  3679. CriticalBlock block(crit);
  3680. if (value==WUStateAborted || value==WUStatePaused || value==WUStateCompleted || value==WUStateFailed || value==WUStateSubmitted || value==WUStateWait)
  3681. {
  3682. if (abortWatcher)
  3683. {
  3684. abortWatcher->unsubscribe();
  3685. abortWatcher.clear();
  3686. }
  3687. StringBuffer apath;
  3688. apath.append("/WorkUnitAborts/").append(p->queryName());
  3689. if(factory)
  3690. {
  3691. Owned<IRemoteConnection> acon = factory->sdsManager->connect(apath.str(), factory->session, RTM_LOCK_WRITE|RTM_LOCK_SUB, SDS_LOCK_TIMEOUT);
  3692. if (acon)
  3693. acon->close(true);
  3694. }
  3695. }
  3696. setEnum(p, "@state", value, states);
  3697. if (getDebugValueBool("monitorWorkunit", false))
  3698. {
  3699. switch(value)
  3700. {
  3701. case WUStateAborted:
  3702. FLLOG(MCoperatorWarning, "Workunit %s aborted", p->queryName());
  3703. break;
  3704. case WUStateCompleted:
  3705. FLLOG(MCoperatorProgress, "Workunit %s completed", p->queryName());
  3706. break;
  3707. case WUStateFailed:
  3708. FLLOG(MCoperatorProgress, "Workunit %s failed", p->queryName());
  3709. break;
  3710. }
  3711. }
  3712. p->removeProp("@stateEx");
  3713. }
  3714. void CLocalWorkUnit::setStateEx(const char * text)
  3715. {
  3716. CriticalBlock block(crit);
  3717. p->setProp("@stateEx", text);
  3718. }
  3719. void CLocalWorkUnit::setAgentSession(__int64 sessionId)
  3720. {
  3721. CriticalBlock block(crit);
  3722. p->setPropInt64("@agentSession", sessionId);
  3723. }
  3724. bool CLocalWorkUnit::aborting() const
  3725. {
  3726. CriticalBlock block(crit);
  3727. if (abortDirty)
  3728. {
  3729. if (factory)
  3730. {
  3731. StringBuffer apath;
  3732. apath.append("/WorkUnitAborts/").append(p->queryName());
  3733. Owned<IRemoteConnection> acon = factory->sdsManager->connect(apath.str(), factory->session, 0, SDS_LOCK_TIMEOUT);
  3734. if (acon)
  3735. abortState = acon->queryRoot()->getPropInt(NULL)!=0;
  3736. else
  3737. abortState = false;
  3738. }
  3739. abortDirty = false;
  3740. }
  3741. return abortState;
  3742. }
  3743. bool CLocalWorkUnit::getIsQueryService() const
  3744. {
  3745. CriticalBlock block(crit);
  3746. return p->getPropBool("@isQueryService", false);
  3747. }
  3748. void CLocalWorkUnit::setIsQueryService(bool value)
  3749. {
  3750. CriticalBlock block(crit);
  3751. p->setPropBool("@isQueryService", value);
  3752. }
  3753. void CLocalWorkUnit::checkAgentRunning(WUState & state)
  3754. {
  3755. if (queryDaliServerVersion().compare("2.1")<0)
  3756. return;
  3757. switch(state)
  3758. {
  3759. case WUStateRunning:
  3760. case WUStateDebugPaused:
  3761. case WUStateDebugRunning:
  3762. case WUStateBlocked:
  3763. case WUStateAborting:
  3764. case WUStateCompiling:
  3765. case WUStatePaused:
  3766. {
  3767. SessionId agent = getAgentSession();
  3768. if((agent>0) && querySessionManager().sessionStopped(agent, 0))
  3769. {
  3770. forceReload();
  3771. state = (WUState) getEnum(p, "@state", states);
  3772. bool isecl=state==WUStateCompiling;
  3773. if (aborting())
  3774. state = WUStateAborted;
  3775. else if (state==WUStateRunning || state==WUStatePaused || state==WUStateDebugPaused || state==WUStateDebugRunning || state==WUStateBlocked || state==WUStateCompiling)
  3776. state = WUStateFailed;
  3777. else
  3778. return;
  3779. WARNLOG("checkAgentRunning terminated: %"I64F"d state = %d",(__int64)agent,(int)state);
  3780. Owned<IWorkUnit> w = &lock();
  3781. w->setState(state);
  3782. Owned<IWUException> e = w->createException();
  3783. WUAction action = w->getAction();
  3784. switch (action)
  3785. {
  3786. case WUActionPause:
  3787. case WUActionPauseNow:
  3788. case WUActionResume:
  3789. w->setAction(WUActionUnknown);
  3790. }
  3791. if(isecl)
  3792. {
  3793. e->setExceptionCode(1001);
  3794. e->setExceptionMessage("EclServer terminated unexpectedly");
  3795. }
  3796. else
  3797. {
  3798. e->setExceptionCode(1000);
  3799. e->setExceptionMessage("Workunit terminated unexpectedly");
  3800. }
  3801. }
  3802. }
  3803. }
  3804. }
  3805. WUState CLocalWorkUnit::getState() const
  3806. {
  3807. CriticalBlock block(crit);
  3808. WUState state = (WUState) getEnum(p, "@state", states);
  3809. switch (state)
  3810. {
  3811. case WUStateRunning:
  3812. case WUStateDebugPaused:
  3813. case WUStateDebugRunning:
  3814. case WUStateBlocked:
  3815. case WUStateCompiling:
  3816. if (aborting())
  3817. state = WUStateAborting;
  3818. break;
  3819. case WUStateSubmitted:
  3820. if (aborting())
  3821. state = WUStateAborted;
  3822. break;
  3823. }
  3824. const_cast<CLocalWorkUnit *>(this)->checkAgentRunning(state); //need const_cast as will change state if agent has died
  3825. return state;
  3826. }
  3827. IStringVal& CLocalWorkUnit::getStateEx(IStringVal & str) const
  3828. {
  3829. CriticalBlock block(crit);
  3830. str.set(p->queryProp("@stateEx"));
  3831. return str;
  3832. }
  3833. __int64 CLocalWorkUnit::getAgentSession() const
  3834. {
  3835. CriticalBlock block(crit);
  3836. return p->getPropInt64("@agentSession", -1);
  3837. }
  3838. unsigned CLocalWorkUnit::getAgentPID() const
  3839. {
  3840. CriticalBlock block(crit);
  3841. return p->getPropInt("@agentPID", -1);
  3842. }
  3843. IStringVal& CLocalWorkUnit::getStateDesc(IStringVal &str) const
  3844. {
  3845. // MORE - not sure about this - may prefer a separate interface
  3846. CriticalBlock block(crit);
  3847. try
  3848. {
  3849. str.set(getEnumText(getState(), states));
  3850. }
  3851. catch (...)
  3852. {
  3853. str.set("???");
  3854. }
  3855. return str;
  3856. }
  3857. mapEnums actions[] = {
  3858. { WUActionUnknown, "unknown" },
  3859. { WUActionCompile, "compile" },
  3860. { WUActionCheck, "check" },
  3861. { WUActionRun, "run" },
  3862. { WUActionExecuteExisting, "execute" },
  3863. { WUActionPause, "pause" },
  3864. { WUActionPauseNow, "pausenow" },
  3865. { WUActionResume, "resume" },
  3866. { WUActionSize, NULL },
  3867. };
  3868. void CLocalWorkUnit::setAction(WUAction value)
  3869. {
  3870. CriticalBlock block(crit);
  3871. setEnum(p, "Action", value, actions);
  3872. }
  3873. WUAction CLocalWorkUnit::getAction() const
  3874. {
  3875. CriticalBlock block(crit);
  3876. return (WUAction) getEnum(p, "Action", actions);
  3877. }
  3878. IStringVal& CLocalWorkUnit::getActionEx(IStringVal & str) const
  3879. {
  3880. CriticalBlock block(crit);
  3881. str.set(p->queryProp("Action"));
  3882. return str;
  3883. }
  3884. IStringVal& CLocalWorkUnit::getApplicationValue(const char *app, const char *propname, IStringVal &str) const
  3885. {
  3886. CriticalBlock block(crit);
  3887. StringBuffer prop("Application/");
  3888. prop.append(app).append('/').append(propname);
  3889. str.set(p->queryProp(prop.str()));
  3890. return str;
  3891. }
  3892. int CLocalWorkUnit::getApplicationValueInt(const char *app, const char *propname, int defVal) const
  3893. {
  3894. CriticalBlock block(crit);
  3895. StringBuffer prop("Application/");
  3896. prop.append(app).append('/').append(propname);
  3897. return p->getPropInt(prop.str(), defVal);
  3898. }
  3899. IConstWUAppValueIterator& CLocalWorkUnit::getApplicationValues() const
  3900. {
  3901. CriticalBlock block(crit);
  3902. appvalues.load(p,"Application/*");
  3903. return *new CArrayIteratorOf<IConstWUAppValue,IConstWUAppValueIterator> (appvalues, 0, (IConstWorkUnit *) this);
  3904. }
  3905. void CLocalWorkUnit::setApplicationValue(const char *app, const char *propname, const char *value, bool overwrite)
  3906. {
  3907. CriticalBlock block(crit);
  3908. StringBuffer prop("Application/");
  3909. prop.append(app).append('/').append(propname);
  3910. if (overwrite || !p->hasProp(prop.str()))
  3911. {
  3912. // MORE - not sure these lines should be needed....
  3913. StringBuffer sp;
  3914. p->setProp(sp.append("Application").str(), "");
  3915. p->setProp(sp.append('/').append(app).str(), "");
  3916. p->setProp(prop.str(), value);
  3917. }
  3918. }
  3919. void CLocalWorkUnit::setApplicationValueInt(const char *app, const char *propname, int value, bool overwrite)
  3920. {
  3921. CriticalBlock block(crit);
  3922. StringBuffer prop("Application/");
  3923. prop.append(app).append('/').append(propname);
  3924. if (overwrite || !p->hasProp(prop.str()))
  3925. {
  3926. // MORE - not sure these lines should be needed....
  3927. StringBuffer sp;
  3928. p->setProp(sp.append("Application").str(), "");
  3929. p->setProp(sp.append('/').append(app).str(), "");
  3930. p->setPropInt(prop.str(), value);
  3931. }
  3932. }
  3933. void CLocalWorkUnit::setPriorityLevel(int level)
  3934. {
  3935. CriticalBlock block(crit);
  3936. p->setPropInt("PriorityFlag", level);
  3937. }
  3938. int CLocalWorkUnit::getPriorityLevel() const
  3939. {
  3940. CriticalBlock block(crit);
  3941. return p->getPropInt("PriorityFlag");
  3942. }
  3943. int calcPriorityValue(const IPropertyTree * p)
  3944. {
  3945. int priority = p->getPropInt("PriorityFlag");
  3946. switch((WUPriorityClass) getEnum(p, "@priorityClass", priorityClasses))
  3947. {
  3948. case PriorityClassLow:
  3949. priority -= 100;
  3950. break;
  3951. case PriorityClassHigh:
  3952. priority += 100;
  3953. break;
  3954. }
  3955. return priority;
  3956. }
  3957. int CLocalWorkUnit::getPriorityValue() const
  3958. {
  3959. CriticalBlock block(crit);
  3960. return calcPriorityValue(p);
  3961. }
  3962. void CLocalWorkUnit::setRescheduleFlag(bool value)
  3963. {
  3964. CriticalBlock block(crit);
  3965. p->setPropInt("RescheduleFlag", (int) value);
  3966. }
  3967. bool CLocalWorkUnit::getRescheduleFlag() const
  3968. {
  3969. CriticalBlock block(crit);
  3970. return p->getPropInt("RescheduleFlag") != 0;
  3971. }
  3972. class NullIStringIterator : public CInterface, extends IStringIterator
  3973. {
  3974. public:
  3975. IMPLEMENT_IINTERFACE;
  3976. bool first() { return false; }
  3977. bool next() { return false; }
  3978. bool isValid() { return false; }
  3979. IStringVal & str(IStringVal & str) { return str; }
  3980. };
  3981. ClusterType getClusterType(const char * platform, ClusterType dft)
  3982. {
  3983. if (stricmp(platform, "thor") == 0)
  3984. return ThorLCRCluster;
  3985. if (stricmp(platform, "thorlcr") == 0)
  3986. return ThorLCRCluster;
  3987. if (stricmp(platform, "hthor") == 0)
  3988. return HThorCluster;
  3989. if (stricmp(platform, "roxie") == 0)
  3990. return RoxieCluster;
  3991. return dft;
  3992. }
  3993. const char *clusterTypeString(ClusterType clusterType, bool lcrSensitive)
  3994. {
  3995. switch (clusterType)
  3996. {
  3997. case ThorLCRCluster:
  3998. if (lcrSensitive)
  3999. return "thorlcr";
  4000. return "thor";
  4001. case RoxieCluster:
  4002. return "roxie";
  4003. case HThorCluster:
  4004. return "hthor";
  4005. }
  4006. throwUnexpected();
  4007. }
  4008. IPropertyTree *queryRoxieProcessTree(IPropertyTree *environment, const char *process)
  4009. {
  4010. if (!process || !*process)
  4011. return NULL;
  4012. VStringBuffer xpath("Software/RoxieCluster[@name=\"%s\"]", process);
  4013. return environment->queryPropTree(xpath.str());
  4014. }
  4015. void getRoxieProcessServers(IPropertyTree *roxie, SocketEndpointArray &endpoints)
  4016. {
  4017. if (!roxie)
  4018. return;
  4019. Owned<IPropertyTreeIterator> servers = roxie->getElements("RoxieServerProcess");
  4020. ForEach(*servers)
  4021. {
  4022. IPropertyTree &server = servers->query();
  4023. const char *netAddress = server.queryProp("@netAddress");
  4024. if (netAddress && *netAddress)
  4025. {
  4026. SocketEndpoint ep(netAddress, server.getPropInt("@port", 9876));
  4027. endpoints.append(ep);
  4028. }
  4029. }
  4030. }
  4031. void getRoxieProcessServers(const char *process, SocketEndpointArray &servers)
  4032. {
  4033. Owned<IEnvironmentFactory> factory = getEnvironmentFactory();
  4034. Owned<IConstEnvironment> env = factory->openEnvironment();
  4035. if (!env)
  4036. return;
  4037. Owned<IPropertyTree> root = &env->getPTree();
  4038. getRoxieProcessServers(queryRoxieProcessTree(root, process), servers);
  4039. }
  4040. class CEnvironmentClusterInfo: public CInterface, implements IConstWUClusterInfo
  4041. {
  4042. StringAttr name;
  4043. StringAttr serverQueue;
  4044. StringAttr agentQueue;
  4045. StringAttr roxieProcess;
  4046. SocketEndpointArray roxieServers;
  4047. StringAttr thorQueue;
  4048. StringArray thorProcesses;
  4049. StringArray primaryThorProcesses;
  4050. StringAttr prefix;
  4051. StringAttr ldapUser;
  4052. StringBuffer ldapPassword;
  4053. ClusterType platform;
  4054. unsigned clusterWidth;
  4055. public:
  4056. IMPLEMENT_IINTERFACE;
  4057. CEnvironmentClusterInfo(const char *_name, const char *_prefix, IPropertyTree *agent, IArrayOf<IPropertyTree> &thors, IPropertyTree *roxie)
  4058. : name(_name), prefix(_prefix)
  4059. {
  4060. StringBuffer queue;
  4061. if (thors.ordinality())
  4062. {
  4063. thorQueue.set(getClusterThorQueueName(queue.clear(), name));
  4064. clusterWidth = 0;
  4065. bool isMultiThor = (thors.length() > 1);
  4066. ForEachItemIn(i,thors)
  4067. {
  4068. IPropertyTree &thor = thors.item(i);
  4069. const char* thorName = thor.queryProp("@name");
  4070. thorProcesses.append(thorName);
  4071. if (!isMultiThor)
  4072. primaryThorProcesses.append(thorName);
  4073. else
  4074. {
  4075. const char *nodeGroup = thor.queryProp("@nodeGroup");
  4076. if (!nodeGroup || strieq(nodeGroup, thorName))
  4077. primaryThorProcesses.append(thorName);
  4078. }
  4079. unsigned nodes = thor.getCount("ThorSlaveProcess");
  4080. if (!nodes)
  4081. throw MakeStringException(WUERR_MismatchClusterSize,"CEnvironmentClusterInfo: Thor cluster can not have 0 slave processes");
  4082. unsigned ts = nodes * thor.getPropInt("@slavesPerNode", 1);
  4083. if (clusterWidth && (ts!=clusterWidth))
  4084. throw MakeStringException(WUERR_MismatchClusterSize,"CEnvironmentClusterInfo: mismatched thor sizes in cluster");
  4085. clusterWidth = ts;
  4086. bool islcr = !thor.getPropBool("@Legacy");
  4087. if (!islcr)
  4088. throw MakeStringException(WUERR_MismatchThorType,"CEnvironmentClusterInfo: Legacy Thor no longer supported");
  4089. }
  4090. platform = ThorLCRCluster;
  4091. }
  4092. else if (roxie)
  4093. {
  4094. roxieProcess.set(roxie->queryProp("@name"));
  4095. platform = RoxieCluster;
  4096. getRoxieProcessServers(roxie, roxieServers);
  4097. clusterWidth = roxieServers.length();
  4098. ldapUser.set(roxie->queryProp("@ldapUser"));
  4099. StringBuffer encPassword = roxie->queryProp("@ldapPassword");
  4100. if (encPassword.length())
  4101. decrypt(ldapPassword, encPassword);
  4102. }
  4103. else
  4104. {
  4105. clusterWidth = 1;
  4106. platform = HThorCluster;
  4107. }
  4108. if (agent)
  4109. {
  4110. assertex(!roxie);
  4111. agentQueue.set(getClusterEclAgentQueueName(queue.clear(), name));
  4112. }
  4113. else if (roxie)
  4114. agentQueue.set(getClusterRoxieQueueName(queue.clear(), name));
  4115. // MORE - does this need to be conditional?
  4116. serverQueue.set(getClusterEclCCServerQueueName(queue.clear(), name));
  4117. }
  4118. IStringVal & getName(IStringVal & str) const
  4119. {
  4120. str.set(name.get());
  4121. return str;
  4122. }
  4123. IStringVal & getScope(IStringVal & str) const
  4124. {
  4125. str.set(prefix.get());
  4126. return str;
  4127. }
  4128. IStringVal & getAgentQueue(IStringVal & str) const
  4129. {
  4130. str.set(agentQueue);
  4131. return str;
  4132. }
  4133. virtual IStringVal & getServerQueue(IStringVal & str) const
  4134. {
  4135. str.set(serverQueue);
  4136. return str;
  4137. }
  4138. IStringVal & getThorQueue(IStringVal & str) const
  4139. {
  4140. str.set(thorQueue);
  4141. return str;
  4142. }
  4143. unsigned getSize() const
  4144. {
  4145. return clusterWidth;
  4146. }
  4147. virtual ClusterType getPlatform() const
  4148. {
  4149. return platform;
  4150. }
  4151. IStringVal & getRoxieProcess(IStringVal & str) const
  4152. {
  4153. str.set(roxieProcess.get());
  4154. return str;
  4155. }
  4156. const StringArray & getThorProcesses() const
  4157. {
  4158. return thorProcesses;
  4159. }
  4160. const StringArray & getPrimaryThorProcesses() const
  4161. {
  4162. return primaryThorProcesses;
  4163. }
  4164. const SocketEndpointArray & getRoxieServers() const
  4165. {
  4166. return roxieServers;
  4167. }
  4168. const char *getLdapUser() const
  4169. {
  4170. return ldapUser.get();
  4171. }
  4172. virtual const char *getLdapPassword() const
  4173. {
  4174. return ldapPassword.str();
  4175. }
  4176. };
  4177. IStringVal &getProcessQueueNames(IStringVal &ret, const char *process, const char *type, const char *suffix)
  4178. {
  4179. if (process)
  4180. {
  4181. Owned<IEnvironmentFactory> factory = getEnvironmentFactory();
  4182. Owned<IConstEnvironment> env = factory->openEnvironment();
  4183. if (env)
  4184. {
  4185. Owned<IPropertyTree> root = &env->getPTree();
  4186. StringBuffer queueNames;
  4187. StringBuffer xpath;
  4188. xpath.appendf("%s[@process=\"%s\"]", type, process);
  4189. Owned<IPropertyTreeIterator> targets = root->getElements("Software/Topology/Cluster");
  4190. ForEach(*targets)
  4191. {
  4192. IPropertyTree &target = targets->query();
  4193. if (target.hasProp(xpath))
  4194. {
  4195. if (queueNames.length())
  4196. queueNames.append(',');
  4197. queueNames.append(target.queryProp("@name")).append(suffix);
  4198. }
  4199. }
  4200. ret.set(queueNames);
  4201. }
  4202. }
  4203. return ret;
  4204. }
  4205. #define ROXIE_QUEUE_EXT ".roxie"
  4206. #define THOR_QUEUE_EXT ".thor"
  4207. #define ECLCCSERVER_QUEUE_EXT ".eclserver"
  4208. #define ECLSERVER_QUEUE_EXT ECLCCSERVER_QUEUE_EXT
  4209. #define ECLSCHEDULER_QUEUE_EXT ".eclscheduler"
  4210. #define ECLAGENT_QUEUE_EXT ".agent"
  4211. extern WORKUNIT_API IStringVal &getEclCCServerQueueNames(IStringVal &ret, const char *process)
  4212. {
  4213. return getProcessQueueNames(ret, process, "EclCCServerProcess", ECLCCSERVER_QUEUE_EXT);
  4214. }
  4215. extern WORKUNIT_API IStringVal &getEclServerQueueNames(IStringVal &ret, const char *process)
  4216. {
  4217. return getProcessQueueNames(ret, process, "EclServerProcess", ECLSERVER_QUEUE_EXT); // shares queue name with EclCCServer
  4218. }
  4219. extern WORKUNIT_API IStringVal &getEclSchedulerQueueNames(IStringVal &ret, const char *process)
  4220. {
  4221. return getProcessQueueNames(ret, process, "EclSchedulerProcess", ECLSCHEDULER_QUEUE_EXT); // Shares deployment/config with EclCCServer
  4222. }
  4223. extern WORKUNIT_API IStringVal &getAgentQueueNames(IStringVal &ret, const char *process)
  4224. {
  4225. return getProcessQueueNames(ret, process, "EclAgentProcess", ECLAGENT_QUEUE_EXT);
  4226. }
  4227. extern WORKUNIT_API IStringVal &getRoxieQueueNames(IStringVal &ret, const char *process)
  4228. {
  4229. return getProcessQueueNames(ret, process, "RoxieCluster", ROXIE_QUEUE_EXT);
  4230. }
  4231. extern WORKUNIT_API IStringVal &getThorQueueNames(IStringVal &ret, const char *process)
  4232. {
  4233. return getProcessQueueNames(ret, process, "ThorCluster", THOR_QUEUE_EXT);
  4234. }
  4235. extern WORKUNIT_API StringBuffer &getClusterThorQueueName(StringBuffer &ret, const char *cluster)
  4236. {
  4237. return ret.append(cluster).append(THOR_QUEUE_EXT);
  4238. }
  4239. extern WORKUNIT_API StringBuffer &getClusterThorGroupName(StringBuffer &ret, const char *cluster)
  4240. {
  4241. Owned<IEnvironmentFactory> factory = getEnvironmentFactory();
  4242. Owned<IConstEnvironment> env = factory->openEnvironment();
  4243. if (env)
  4244. {
  4245. Owned<IPropertyTree> root = &env->getPTree();
  4246. StringBuffer path;
  4247. path.append("Software/ThorCluster[@name=\"").append(cluster).append("\"]");
  4248. IPropertyTree * child = root->queryPropTree(path);
  4249. if (child)
  4250. getClusterGroupName(*child, ret);
  4251. }
  4252. return ret;
  4253. }
  4254. extern WORKUNIT_API StringBuffer &getClusterRoxieQueueName(StringBuffer &ret, const char *cluster)
  4255. {
  4256. return ret.append(cluster).append(ROXIE_QUEUE_EXT);
  4257. }
  4258. extern WORKUNIT_API StringBuffer &getClusterEclCCServerQueueName(StringBuffer &ret, const char *cluster)
  4259. {
  4260. return ret.append(cluster).append(ECLCCSERVER_QUEUE_EXT);
  4261. }
  4262. extern WORKUNIT_API StringBuffer &getClusterEclServerQueueName(StringBuffer &ret, const char *cluster)
  4263. {
  4264. return ret.append(cluster).append(ECLSERVER_QUEUE_EXT);
  4265. }
  4266. extern WORKUNIT_API StringBuffer &getClusterEclAgentQueueName(StringBuffer &ret, const char *cluster)
  4267. {
  4268. return ret.append(cluster).append(ECLAGENT_QUEUE_EXT);
  4269. }
  4270. extern WORKUNIT_API IStringIterator *getTargetClusters(const char *processType, const char *processName)
  4271. {
  4272. Owned<CStringArrayIterator> ret = new CStringArrayIterator;
  4273. Owned<IEnvironmentFactory> factory = getEnvironmentFactory();
  4274. Owned<IConstEnvironment> env = factory->openEnvironment();
  4275. if (env)
  4276. {
  4277. Owned<IPropertyTree> root = &env->getPTree();
  4278. StringBuffer xpath;
  4279. xpath.appendf("%s", processType ? processType : "*");
  4280. if (processName && *processName)
  4281. xpath.appendf("[@process=\"%s\"]", processName);
  4282. Owned<IPropertyTreeIterator> targets = root->getElements("Software/Topology/Cluster");
  4283. ForEach(*targets)
  4284. {
  4285. IPropertyTree &target = targets->query();
  4286. if (target.hasProp(xpath))
  4287. {
  4288. ret->append(target.queryProp("@name"));
  4289. }
  4290. }
  4291. }
  4292. return ret.getClear();
  4293. }
  4294. extern WORKUNIT_API bool isProcessCluster(const char *process)
  4295. {
  4296. if (!process || !*process)
  4297. return false;
  4298. Owned<IEnvironmentFactory> factory = getEnvironmentFactory();
  4299. Owned<IConstEnvironment> env = factory->openEnvironment();
  4300. if (!env)
  4301. return false;
  4302. Owned<IPropertyTree> root = &env->getPTree();
  4303. VStringBuffer xpath("Software/*Cluster[@name=\"%s\"]", process);
  4304. return root->hasProp(xpath.str());
  4305. }
  4306. extern WORKUNIT_API bool isProcessCluster(const char *remoteDali, const char *process)
  4307. {
  4308. if (!remoteDali || !*remoteDali)
  4309. return isProcessCluster(process);
  4310. if (!process || !*process)
  4311. return false;
  4312. Owned<INode> remote = createINode(remoteDali, 7070);
  4313. if (!remote)
  4314. return false;
  4315. //Cannot use getEnvironmentFactory() since it is using a remotedali
  4316. VStringBuffer xpath("Environment/Software/*Cluster[@name=\"%s\"]/@name", process);
  4317. try
  4318. {
  4319. Owned<IPropertyTreeIterator> clusters = querySDS().getElementsRaw(xpath, remote, 1000*60*1);
  4320. return clusters->first();
  4321. }
  4322. catch (IException *E)
  4323. {
  4324. StringBuffer msg;
  4325. E->errorMessage(msg);
  4326. DBGLOG("Exception validating cluster %s/%s: %s", remoteDali, xpath.str(), msg.str());
  4327. E->Release();
  4328. }
  4329. return true;
  4330. }
  4331. IConstWUClusterInfo* getTargetClusterInfo(IPropertyTree *environment, IPropertyTree *cluster)
  4332. {
  4333. const char *clustname = cluster->queryProp("@name");
  4334. // MORE - at the moment configenf specifies eclagent and thor queues by (in effect) placing an 'example' thor or eclagent in the topology
  4335. // that uses the queue that will be used.
  4336. // We should and I hope will change that, at which point the code below gets simpler
  4337. StringBuffer prefix(cluster->queryProp("@prefix"));
  4338. prefix.toLowerCase();
  4339. StringBuffer xpath;
  4340. StringBuffer querySetName;
  4341. IPropertyTree *agent = NULL;
  4342. const char *agentName = cluster->queryProp("EclAgentProcess/@process");
  4343. if (agentName)
  4344. {
  4345. xpath.clear().appendf("Software/EclAgentProcess[@name=\"%s\"]", agentName);
  4346. agent = environment->queryPropTree(xpath.str());
  4347. }
  4348. Owned<IPropertyTreeIterator> ti = cluster->getElements("ThorCluster");
  4349. IArrayOf<IPropertyTree> thors;
  4350. ForEach(*ti)
  4351. {
  4352. const char *thorName = ti->query().queryProp("@process");
  4353. if (thorName)
  4354. {
  4355. xpath.clear().appendf("Software/ThorCluster[@name=\"%s\"]", thorName);
  4356. thors.append(*environment->getPropTree(xpath.str()));
  4357. }
  4358. }
  4359. const char *roxieName = cluster->queryProp("RoxieCluster/@process");
  4360. return new CEnvironmentClusterInfo(clustname, prefix, agent, thors, queryRoxieProcessTree(environment, roxieName));
  4361. }
  4362. IPropertyTree* getTopologyCluster(Owned<IPropertyTree> &envRoot, const char *clustname)
  4363. {
  4364. if (!clustname || !*clustname)
  4365. return NULL;
  4366. Owned<IEnvironmentFactory> factory = getEnvironmentFactory();
  4367. Owned<IConstEnvironment> env = factory->openEnvironment();
  4368. if (!env)
  4369. return NULL;
  4370. envRoot.setown(&env->getPTree());
  4371. StringBuffer xpath;
  4372. xpath.appendf("Software/Topology/Cluster[@name=\"%s\"]", clustname);
  4373. return envRoot->getPropTree(xpath.str());
  4374. }
  4375. bool validateTargetClusterName(const char *clustname)
  4376. {
  4377. Owned<IPropertyTree> envRoot;
  4378. Owned<IPropertyTree> cluster = getTopologyCluster(envRoot, clustname);
  4379. return (cluster.get()!=NULL);
  4380. }
  4381. IConstWUClusterInfo* getTargetClusterInfo(const char *clustname)
  4382. {
  4383. Owned<IPropertyTree> envRoot;
  4384. Owned<IPropertyTree> cluster = getTopologyCluster(envRoot, clustname);
  4385. if (!cluster)
  4386. return NULL;
  4387. return getTargetClusterInfo(envRoot, cluster);
  4388. }
  4389. unsigned getEnvironmentClusterInfo(CConstWUClusterInfoArray &clusters)
  4390. {
  4391. Owned<IEnvironmentFactory> factory = getEnvironmentFactory();
  4392. Owned<IConstEnvironment> env = factory->openEnvironment();
  4393. if (!env)
  4394. return 0;
  4395. Owned<IPropertyTree> root = &env->getPTree();
  4396. return getEnvironmentClusterInfo(root, clusters);
  4397. }
  4398. unsigned getEnvironmentClusterInfo(IPropertyTree* environmentRoot, CConstWUClusterInfoArray &clusters)
  4399. {
  4400. if (!environmentRoot)
  4401. return 0;
  4402. Owned<IPropertyTreeIterator> clusterIter = environmentRoot->getElements("Software/Topology/Cluster");
  4403. ForEach(*clusterIter)
  4404. {
  4405. IPropertyTree &node = clusterIter->query();
  4406. Owned<IConstWUClusterInfo> cluster = getTargetClusterInfo(environmentRoot, &node);
  4407. clusters.append(*cluster.getClear());
  4408. }
  4409. return clusters.ordinality();
  4410. }
  4411. const char *getTargetClusterComponentName(const char *clustname, const char *processType, StringBuffer &name)
  4412. {
  4413. if (!clustname)
  4414. return NULL;
  4415. Owned<IEnvironmentFactory> factory = getEnvironmentFactory();
  4416. Owned<IConstEnvironment> env = factory->openEnvironment();
  4417. if (!env)
  4418. return NULL;
  4419. Owned<IPropertyTree> root = &env->getPTree();
  4420. StringBuffer xpath;
  4421. xpath.appendf("Software/Topology/Cluster[@name=\"%s\"]", clustname);
  4422. Owned<IPropertyTree> cluster = root->getPropTree(xpath.str());
  4423. if (!cluster)
  4424. return NULL;
  4425. StringBuffer xpath1;
  4426. xpath1.appendf("%s/@process", processType);
  4427. name.append(cluster->queryProp(xpath1.str()));
  4428. return name.str();
  4429. }
  4430. unsigned getEnvironmentThorClusterNames(StringArray &thorNames, StringArray &groupNames, StringArray &targetNames, StringArray &queueNames)
  4431. {
  4432. Owned<IEnvironmentFactory> factory = getEnvironmentFactory();
  4433. Owned<IConstEnvironment> env = factory->openEnvironment();
  4434. if (!env)
  4435. return 0;
  4436. Owned<IPropertyTree> root = &env->getPTree();
  4437. Owned<IPropertyTreeIterator> allTargets = root->getElements("Software/Topology/Cluster");
  4438. ForEach(*allTargets)
  4439. {
  4440. IPropertyTree &target = allTargets->query();
  4441. const char *targetName = target.queryProp("@name");
  4442. if (targetName && *targetName)
  4443. {
  4444. Owned<IPropertyTreeIterator> thorClusters = target.getElements("ThorCluster");
  4445. ForEach(*thorClusters)
  4446. {
  4447. const char *thorName = thorClusters->query().queryProp("@process");
  4448. VStringBuffer query("Software/ThorCluster[@name=\"%s\"]",thorName);
  4449. IPropertyTree *thorCluster = root->queryPropTree(query.str());
  4450. if (thorCluster)
  4451. {
  4452. const char *groupName = thorCluster->queryProp("@nodeGroup");
  4453. if (!groupName||!*groupName)
  4454. groupName = thorName;
  4455. thorNames.append(thorName);
  4456. groupNames.append(groupName);
  4457. targetNames.append(targetName);
  4458. StringBuffer queueName(targetName);
  4459. queueNames.append(queueName.append(THOR_QUEUE_EXT));
  4460. }
  4461. }
  4462. }
  4463. }
  4464. return thorNames.ordinality();
  4465. }
  4466. unsigned getEnvironmentHThorClusterNames(StringArray &eclAgentNames, StringArray &groupNames, StringArray &targetNames)
  4467. {
  4468. Owned<IEnvironmentFactory> factory = getEnvironmentFactory();
  4469. Owned<IConstEnvironment> env = factory->openEnvironment();
  4470. if (!env)
  4471. return 0;
  4472. Owned<IPropertyTree> root = &env->getPTree();
  4473. Owned<IPropertyTreeIterator> allEclAgents = root->getElements("Software/EclAgentProcess");
  4474. ForEach(*allEclAgents)
  4475. {
  4476. IPropertyTree &eclAgent = allEclAgents->query();
  4477. const char *eclAgentName = eclAgent.queryProp("@name");
  4478. if (eclAgentName && *eclAgentName)
  4479. {
  4480. Owned<IPropertyTreeIterator> allTargets = root->getElements("Software/Topology/Cluster");
  4481. ForEach(*allTargets)
  4482. {
  4483. IPropertyTree &target = allTargets->query();
  4484. const char *targetName = target.queryProp("@name");
  4485. if (targetName && *targetName)
  4486. {
  4487. StringBuffer xpath;
  4488. xpath.appendf("EclAgentProcess[@process=\"%s\"]", eclAgentName);
  4489. if (target.hasProp(xpath) && !target.hasProp("ThorCluster"))
  4490. {
  4491. StringBuffer groupName("hthor__");
  4492. groupName.append(eclAgentName);
  4493. groupNames.append(groupName);
  4494. eclAgentNames.append(eclAgentName);
  4495. targetNames.append(targetName);
  4496. }
  4497. }
  4498. }
  4499. }
  4500. }
  4501. return eclAgentNames.ordinality();
  4502. }
  4503. IStringVal& CLocalWorkUnit::getScope(IStringVal &str) const
  4504. {
  4505. CriticalBlock block(crit);
  4506. if (p->hasProp("Debug/ForceScope"))
  4507. {
  4508. StringBuffer prefix(p->queryProp("Debug/ForceScope"));
  4509. str.set(prefix.toLowerCase().str());
  4510. }
  4511. else
  4512. {
  4513. Owned <IConstWUClusterInfo> ci = getTargetClusterInfo(p->queryProp("@clusterName"));
  4514. if (ci)
  4515. ci->getScope(str);
  4516. else
  4517. str.clear();
  4518. }
  4519. return str;
  4520. }
  4521. //Queries
  4522. void CLocalWorkUnit::setCodeVersion(unsigned codeVersion, const char * buildVersion, const char * eclVersion)
  4523. {
  4524. CriticalBlock block(crit);
  4525. p->setPropInt("@codeVersion", codeVersion);
  4526. p->setProp("@buildVersion", buildVersion);
  4527. p->setProp("@eclVersion", eclVersion);
  4528. }
  4529. unsigned CLocalWorkUnit::getCodeVersion() const
  4530. {
  4531. CriticalBlock block(crit);
  4532. return p->getPropInt("@codeVersion");
  4533. }
  4534. unsigned CLocalWorkUnit::getWuidVersion() const
  4535. {
  4536. CriticalBlock block(crit);
  4537. return p->getPropInt("@wuidVersion");
  4538. }
  4539. void CLocalWorkUnit::getBuildVersion(IStringVal & buildVersion, IStringVal & eclVersion) const
  4540. {
  4541. CriticalBlock block(crit);
  4542. buildVersion.set(p->queryProp("@buildVersion"));
  4543. eclVersion.set(p->queryProp("@eclVersion"));
  4544. }
  4545. void CLocalWorkUnit::setCloneable(bool value)
  4546. {
  4547. CriticalBlock block(crit);
  4548. p->setPropInt("@cloneable", value);
  4549. }
  4550. void CLocalWorkUnit::setIsClone(bool value)
  4551. {
  4552. CriticalBlock block(crit);
  4553. p->setPropInt("@isClone", value);
  4554. }
  4555. bool CLocalWorkUnit::getCloneable() const
  4556. {
  4557. CriticalBlock block(crit);
  4558. return p->getPropBool("@cloneable", false);
  4559. }
  4560. IUserDescriptor *CLocalWorkUnit::queryUserDescriptor() const
  4561. {
  4562. CriticalBlock block(crit);
  4563. if (!userDesc)
  4564. {
  4565. SCMStringBuffer token, user, password;
  4566. getSecurityToken(token);
  4567. SCMStringBuffer wuid;
  4568. getWuid(wuid);
  4569. extractToken(token.str(), wuid.str(), user, password);
  4570. userDesc.setown(createUserDescriptor());
  4571. userDesc->set(user.str(), password.str());
  4572. }
  4573. return userDesc;
  4574. }
  4575. void CLocalWorkUnit::setCombineQueries(unsigned combine)
  4576. {
  4577. CriticalBlock block(crit);
  4578. p->setPropInt("COMBINE_QUERIES", combine);
  4579. }
  4580. unsigned CLocalWorkUnit::getCombineQueries() const
  4581. {
  4582. CriticalBlock block(crit);
  4583. return p->getPropInt("COMBINE_QUERIES");
  4584. }
  4585. bool CLocalWorkUnit::isProtected() const
  4586. {
  4587. CriticalBlock block(crit);
  4588. return p->getPropBool("@protected", false);
  4589. }
  4590. bool CLocalWorkUnit::isPausing() const
  4591. {
  4592. CriticalBlock block(crit);
  4593. if (WUActionPause == getAction())
  4594. {
  4595. switch (getState())
  4596. {
  4597. case WUStateRunning:
  4598. case WUStateAborting:
  4599. return true;
  4600. }
  4601. }
  4602. return false;
  4603. }
  4604. void CLocalWorkUnit::protect(bool protectMode)
  4605. {
  4606. CriticalBlock block(crit);
  4607. p->setPropBool("@protected", protectMode);
  4608. }
  4609. bool CLocalWorkUnit::isBilled() const
  4610. {
  4611. CriticalBlock block(crit);
  4612. return p->getPropBool("@billed", false);
  4613. }
  4614. void CLocalWorkUnit::setBilled(bool value)
  4615. {
  4616. CriticalBlock block(crit);
  4617. p->setPropBool("@billed", value);
  4618. }
  4619. void CLocalWorkUnit::setResultLimit(unsigned value)
  4620. {
  4621. CriticalBlock block(crit);
  4622. p->setPropInt("resultLimit", value);
  4623. }
  4624. unsigned CLocalWorkUnit::getResultLimit() const
  4625. {
  4626. CriticalBlock block(crit);
  4627. return p->getPropInt("resultLimit");
  4628. }
  4629. void CLocalWorkUnit::setCompareMode(WUCompareMode value)
  4630. {
  4631. CriticalBlock block(crit);
  4632. p->setPropInt("comparemode", (int)value);
  4633. }
  4634. WUCompareMode CLocalWorkUnit::getCompareMode() const
  4635. {
  4636. CriticalBlock block(crit);
  4637. return (WUCompareMode) p->getPropInt("comparemode");
  4638. }
  4639. IStringVal & CLocalWorkUnit::getSnapshot(IStringVal & str) const
  4640. {
  4641. CriticalBlock block(crit);
  4642. str.set(p->queryProp("SNAPSHOT"));
  4643. return str;
  4644. }
  4645. void CLocalWorkUnit::setSnapshot(const char * val)
  4646. {
  4647. CriticalBlock block(crit);
  4648. p->setProp("SNAPSHOT", val);
  4649. }
  4650. static int comparePropTrees(IInterface **ll, IInterface **rr)
  4651. {
  4652. IPropertyTree *l = (IPropertyTree *) *ll;
  4653. IPropertyTree *r = (IPropertyTree *) *rr;
  4654. return stricmp(l->queryName(), r->queryName());
  4655. };
  4656. unsigned CLocalWorkUnit::calculateHash(unsigned crc)
  4657. {
  4658. // Any other values in the WU that could affect generated code should be crc'ed here
  4659. IPropertyTree *tree = p->queryBranch("Debug");
  4660. if (tree)
  4661. {
  4662. Owned<IPropertyTreeIterator> sub = tree->getElements("*");
  4663. ICopyArrayOf<IPropertyTree> subs;
  4664. for(sub->first(); sub->isValid(); sub->next())
  4665. subs.append(sub->query());
  4666. subs.sort(comparePropTrees);
  4667. ForEachItemIn(idx, subs)
  4668. {
  4669. const char *name = subs.item(idx).queryName();
  4670. const char *val = subs.item(idx).queryProp(NULL);
  4671. crc = crc32(name, (size32_t)strlen(name), crc);
  4672. if (val)
  4673. crc = crc32(val, (size32_t)strlen(val), crc);
  4674. }
  4675. }
  4676. Owned<IConstWUPluginIterator> plugins = &getPlugins();
  4677. for (plugins->first();plugins->isValid();plugins->next())
  4678. {
  4679. IConstWUPlugin &thisplugin = plugins->query();
  4680. SCMStringBuffer version;
  4681. thisplugin.getPluginVersion(version);
  4682. crc = crc32(version.str(), version.length(), crc);
  4683. }
  4684. return crc;
  4685. }
  4686. static void updateProp(IPropertyTree * to, const IPropertyTree * from, const char * xpath)
  4687. {
  4688. if (!to->hasProp(xpath) && from->hasProp(xpath))
  4689. to->setProp(xpath, from->queryProp(xpath));
  4690. }
  4691. static void setProp(IPropertyTree * to, const IPropertyTree * from, const char * xpath)
  4692. {
  4693. if (from->hasProp(xpath))
  4694. to->setProp(xpath, from->queryProp(xpath));
  4695. }
  4696. static void copyTree(IPropertyTree * to, const IPropertyTree * from, const char * xpath)
  4697. {
  4698. IPropertyTree * match = from->getBranch(xpath);
  4699. if (match)
  4700. to->setPropTree(xpath, match);
  4701. }
  4702. void CLocalWorkUnit::copyWorkUnit(IConstWorkUnit *cached, bool all)
  4703. {
  4704. CLocalWorkUnit *from = QUERYINTERFACE(cached, CLocalWorkUnit);
  4705. if (!from)
  4706. {
  4707. CLockedWorkUnit *fl = QUERYINTERFACE(cached, CLockedWorkUnit);
  4708. if (!fl)
  4709. throw MakeStringException(WUERR_InternalUnknownImplementation, "Cached workunit not created using workunit dll");
  4710. from = fl->c;
  4711. }
  4712. // Need to copy the query, the results, and the graphs from the cached query.
  4713. // The cache is made before the query is executed so there is no need to clear them.
  4714. if (!cached->getCloneable())
  4715. throw MakeStringException(WUERR_CannotCloneWorkunit, "Source work unit not marked as clonable");
  4716. const IPropertyTree * fromP = from->p;
  4717. IPropertyTree *pt;
  4718. CriticalBlock block(crit);
  4719. query.clear();
  4720. updateProp(p, fromP, "@jobName");
  4721. copyTree(p, fromP, "Query");
  4722. pt = fromP->getBranch("Application/LibraryModule");
  4723. if (pt)
  4724. {
  4725. ensurePTree(p, "Application");
  4726. p->setPropTree("Application/LibraryModule", pt);
  4727. }
  4728. pt = fromP->queryBranch("Debug");
  4729. if (pt)
  4730. {
  4731. IPropertyTree *curDebug = p->queryPropTree("Debug");
  4732. if (curDebug)
  4733. {
  4734. Owned<IPropertyTreeIterator> elems = pt->getElements("*");
  4735. ForEach(*elems)
  4736. {
  4737. IPropertyTree *elem = &elems->query();
  4738. if (!curDebug->hasProp(elem->queryName()))
  4739. curDebug->setPropTree(elem->queryName(),LINK(elem));
  4740. }
  4741. }
  4742. else
  4743. p->setPropTree("Debug", LINK(pt));
  4744. }
  4745. copyTree(p, fromP, "Plugins");
  4746. copyTree(p, fromP, "Libraries");
  4747. copyTree(p, fromP, "Results");
  4748. copyTree(p, fromP, "Graphs");
  4749. copyTree(p, fromP, "Workflow");
  4750. if (all)
  4751. {
  4752. // 'all' mode is used when setting up a dali WU from the embedded wu in a workunit dll
  4753. // Merge timing info from both branches
  4754. pt = fromP->getBranch("Timings");
  4755. if (pt)
  4756. {
  4757. IPropertyTree *tgtTimings = ensurePTree(p, "Timings");
  4758. mergePTree(tgtTimings, pt);
  4759. pt->Release();
  4760. }
  4761. pt = fromP->getBranch("Statistics");
  4762. if (pt)
  4763. {
  4764. IPropertyTree *tgtStatistics = ensurePTree(p, "Statistics");
  4765. mergePTree(tgtStatistics, pt);
  4766. pt->Release();
  4767. }
  4768. }
  4769. updateProp(p, fromP, "@clusterName");
  4770. updateProp(p, fromP, "allowedclusters");
  4771. updateProp(p, fromP, "@submitID");
  4772. updateProp(p, fromP, "CustomerID");
  4773. updateProp(p, fromP, "SNAPSHOT");
  4774. //MORE: This is very adhoc. All options that should be cloned should really be in a common branch
  4775. if (all)
  4776. {
  4777. setProp(p, fromP, "PriorityFlag");
  4778. setProp(p, fromP, "@priorityClass");
  4779. setProp(p, fromP, "@protected");
  4780. setProp(p, fromP, "@clusterName");
  4781. updateProp(p, fromP, "@scope");
  4782. }
  4783. //Variables may have been set up as parameters to the query - so need to preserve any values that were supplied.
  4784. pt = fromP->getBranch("Variables");
  4785. if (pt)
  4786. {
  4787. IPropertyTree *ptTgtVariables = ensurePTree(p, "Variables");
  4788. Owned<IPropertyTreeIterator> ptiVariable = pt->getElements("Variable");
  4789. for (ptiVariable->first(); ptiVariable->isValid(); ptiVariable->next())
  4790. {
  4791. IPropertyTree *ptSrcVariable = &ptiVariable->query();
  4792. const char *name = ptSrcVariable->queryProp("@name");
  4793. assertex(name);
  4794. StringBuffer xpath;
  4795. xpath.append("Variable[@name='").append(name).append("']");
  4796. IPropertyTree *ptTgtVariable = ptTgtVariables->queryPropTree(xpath.str());
  4797. IPropertyTree *merged = createPTreeFromIPT(ptSrcVariable); // clone entire source info...
  4798. merged->removeProp("Value"); // except value and status
  4799. merged->setProp("@status", "undefined");
  4800. if (!merged->getPropBool("@isScalar"))
  4801. merged->removeProp("totalRowCount");
  4802. merged->removeProp("rowCount");
  4803. // If there are any other fields that get set ONLY by eclagent, strip them out here...
  4804. if (ptTgtVariable)
  4805. {
  4806. // copy status and Value from what is already set in target
  4807. merged->setProp("@status", ptTgtVariable->queryProp("@status"));
  4808. MemoryBuffer value;
  4809. if (ptTgtVariable->getPropBin("Value", value))
  4810. merged->setPropBin("Value", value.length(), value.toByteArray());
  4811. ptTgtVariable->removeProp(xpath.str());
  4812. // If there are any other fields in a variable that get set by ws_ecl before submitting, copy them across here...
  4813. }
  4814. ptTgtVariables->addPropTree("Variable", merged);
  4815. }
  4816. pt->Release();
  4817. }
  4818. p->setProp("@codeVersion", fromP->queryProp("@codeVersion"));
  4819. p->setPropBool("@cloneable", true);
  4820. p->setPropBool("@isClone", true);
  4821. resetWorkflow(); // the source Workflow section may have had some parts already executed...
  4822. // resetResults(); // probably should be resetting the results as well... rather than waiting for the rerun to overwrite them
  4823. }
  4824. bool CLocalWorkUnit::hasDebugValue(const char *propname) const
  4825. {
  4826. StringBuffer lower;
  4827. lower.append(propname).toLowerCase();
  4828. CriticalBlock block(crit);
  4829. StringBuffer prop("Debug/");
  4830. return p->hasProp(prop.append(lower));
  4831. }
  4832. IStringVal& CLocalWorkUnit::getDebugValue(const char *propname, IStringVal &str) const
  4833. {
  4834. StringBuffer lower;
  4835. lower.append(propname).toLowerCase();
  4836. CriticalBlock block(crit);
  4837. StringBuffer prop("Debug/");
  4838. str.set(p->queryProp(prop.append(lower).str()));
  4839. return str;
  4840. }
  4841. IStringIterator& CLocalWorkUnit::getDebugValues() const
  4842. {
  4843. return getDebugValues(NULL);
  4844. }
  4845. IStringIterator& CLocalWorkUnit::getDebugValues(const char *prop) const
  4846. {
  4847. CriticalBlock block(crit);
  4848. StringBuffer path("Debug/");
  4849. if (prop)
  4850. {
  4851. StringBuffer lower;
  4852. lower.append(prop).toLowerCase();
  4853. path.append(lower);
  4854. }
  4855. else
  4856. path.append("*");
  4857. return *new CStringPTreeTagIterator(p->getElements(path.str()));
  4858. }
  4859. int CLocalWorkUnit::getDebugValueInt(const char *propname, int defVal) const
  4860. {
  4861. StringBuffer lower;
  4862. lower.append(propname).toLowerCase();
  4863. CriticalBlock block(crit);
  4864. StringBuffer prop("Debug/");
  4865. prop.append(lower);
  4866. return p->getPropInt(prop.str(), defVal);
  4867. }
  4868. __int64 CLocalWorkUnit::getDebugValueInt64(const char *propname, __int64 defVal) const
  4869. {
  4870. StringBuffer lower;
  4871. lower.append(propname).toLowerCase();
  4872. CriticalBlock block(crit);
  4873. StringBuffer prop("Debug/");
  4874. prop.append(lower);
  4875. return p->getPropInt64(prop.str(), defVal);
  4876. }
  4877. bool CLocalWorkUnit::getDebugValueBool(const char * propname, bool defVal) const
  4878. {
  4879. StringBuffer lower;
  4880. lower.append(propname).toLowerCase();
  4881. CriticalBlock block(crit);
  4882. StringBuffer prop("Debug/");
  4883. prop.append(lower);
  4884. return p->getPropBool(prop.str(), defVal);
  4885. }
  4886. IStringIterator *CLocalWorkUnit::getLogs(const char *type, const char *instance) const
  4887. {
  4888. VStringBuffer xpath("Process/%s/", type);
  4889. if (instance)
  4890. xpath.append(instance);
  4891. else
  4892. xpath.append("*");
  4893. CriticalBlock block(crit);
  4894. if (p->getPropInt("@wuidVersion") < 1) // legacy wuid
  4895. {
  4896. // NB: instance unused
  4897. if (streq("EclAgent", type))
  4898. return new CStringPTreeIterator(p->getElements("Debug/eclagentlog"));
  4899. else if (streq("Thor", type))
  4900. return new CStringPTreeIterator(p->getElements("Debug/thorlog*"));
  4901. VStringBuffer xpath("Debug/%s", type);
  4902. return new CStringPTreeIterator(p->getElements(xpath.str()));
  4903. }
  4904. else
  4905. return new CStringPTreeAttrIterator(p->getElements(xpath.str()), "@log");
  4906. }
  4907. IPropertyTreeIterator* CLocalWorkUnit::getProcesses(const char *type, const char *instance) const
  4908. {
  4909. VStringBuffer xpath("Process/%s/", type);
  4910. if (instance)
  4911. xpath.append(instance);
  4912. else
  4913. xpath.append("*");
  4914. CriticalBlock block(crit);
  4915. return p->getElements(xpath.str());
  4916. }
  4917. IStringIterator *CLocalWorkUnit::getProcesses(const char *type) const
  4918. {
  4919. VStringBuffer xpath("Process/%s/*", type);
  4920. CriticalBlock block(crit);
  4921. return new CStringPTreeTagIterator(p->getElements(xpath.str()));
  4922. }
  4923. void CLocalWorkUnit::addProcess(const char *type, const char *instance, unsigned pid, const char *log)
  4924. {
  4925. VStringBuffer processType("Process/%s", type);
  4926. VStringBuffer xpath("%s/%s", processType.str(), instance);
  4927. if (log)
  4928. xpath.appendf("[@log=\"%s\"]", log);
  4929. CriticalBlock block(crit);
  4930. if (!p->hasProp(xpath))
  4931. {
  4932. IPropertyTree *node = ensurePTree(p, processType.str());
  4933. node = node->addPropTree(instance, createPTree());
  4934. node->setProp("@log", log);
  4935. node->setPropInt("@pid", pid);
  4936. }
  4937. }
  4938. void CLocalWorkUnit::setDebugValue(const char *propname, const char *value, bool overwrite)
  4939. {
  4940. StringBuffer lower;
  4941. lower.append(propname).toLowerCase();
  4942. CriticalBlock block(crit);
  4943. StringBuffer prop("Debug/");
  4944. prop.append(lower);
  4945. if (overwrite || !p->hasProp(prop.str()))
  4946. {
  4947. // MORE - not sure this line should be needed....
  4948. p->setProp("Debug", "");
  4949. p->setProp(prop.str(), value);
  4950. }
  4951. }
  4952. void CLocalWorkUnit::setDebugValueInt(const char *propname, int value, bool overwrite)
  4953. {
  4954. StringBuffer lower;
  4955. lower.append(propname).toLowerCase();
  4956. CriticalBlock block(crit);
  4957. StringBuffer prop("Debug/");
  4958. prop.append(lower);
  4959. if (overwrite || !p->hasProp(prop.str()))
  4960. {
  4961. // MORE - not sure this line should be needed....
  4962. p->setProp("Debug", "");
  4963. p->setPropInt(prop.str(), value);
  4964. }
  4965. }
  4966. void CLocalWorkUnit::setTracingValue(const char *propname, const char *value)
  4967. {
  4968. CriticalBlock block(crit);
  4969. // MORE - not sure this line should be needed....
  4970. p->setProp("Tracing", "");
  4971. StringBuffer prop("Tracing/");
  4972. p->setProp(prop.append(propname).str(), value);
  4973. }
  4974. void CLocalWorkUnit::setTracingValueInt(const char *propname, int value)
  4975. {
  4976. CriticalBlock block(crit);
  4977. StringBuffer prop("Tracing/");
  4978. p->setPropInt(prop.append(propname).str(), value);
  4979. }
  4980. IConstWUQuery* CLocalWorkUnit::getQuery() const
  4981. {
  4982. // For this to be legally called, we must have the read-able interface. So we are already locked for (at least) read.
  4983. CriticalBlock block(crit);
  4984. if (!query)
  4985. {
  4986. IPropertyTree *s = p->getPropTree("Query");
  4987. if (s)
  4988. query.setown(new CLocalWUQuery(s)); // NB takes ownership of 's'
  4989. }
  4990. return query.getLink();
  4991. }
  4992. IWUQuery* CLocalWorkUnit::updateQuery()
  4993. {
  4994. // For this to be legally called, we must have the write-able interface. So we are already locked for write.
  4995. CriticalBlock block(crit);
  4996. if (!query)
  4997. {
  4998. IPropertyTree *s = p->queryPropTree("Query");
  4999. if (!s)
  5000. s = p->addPropTree("Query", createPTreeFromXMLString("<Query fetchEntire='1'/>"));
  5001. s->Link();
  5002. query.setown(new CLocalWUQuery(s));
  5003. }
  5004. return query.getLink();
  5005. }
  5006. void CLocalWorkUnit::loadPlugins() const
  5007. {
  5008. CriticalBlock block(crit);
  5009. if (!pluginsCached)
  5010. {
  5011. assertex(plugins.length() == 0);
  5012. Owned<IPropertyTreeIterator> r = p->getElements("Plugins/Plugin");
  5013. for (r->first(); r->isValid(); r->next())
  5014. {
  5015. IPropertyTree *rp = &r->query();
  5016. rp->Link();
  5017. plugins.append(*new CLocalWUPlugin(rp));
  5018. }
  5019. pluginsCached = true;
  5020. }
  5021. }
  5022. IConstWUPluginIterator& CLocalWorkUnit::getPlugins() const
  5023. {
  5024. CriticalBlock block(crit);
  5025. loadPlugins();
  5026. return *new CArrayIteratorOf<IConstWUPlugin,IConstWUPluginIterator> (plugins, 0, (IConstWorkUnit *) this);
  5027. }
  5028. void CLocalWorkUnit::loadLibraries() const
  5029. {
  5030. CriticalBlock block(crit);
  5031. if (!librariesCached)
  5032. {
  5033. assertex(libraries.length() == 0);
  5034. Owned<IPropertyTreeIterator> r = p->getElements("Libraries/Library");
  5035. ForEach(*r)
  5036. {
  5037. IPropertyTree *rp = &r->query();
  5038. rp->Link();
  5039. libraries.append(*new CLocalWULibrary(rp));
  5040. }
  5041. librariesCached = true;
  5042. }
  5043. }
  5044. IConstWULibraryIterator& CLocalWorkUnit::getLibraries() const
  5045. {
  5046. CriticalBlock block(crit);
  5047. loadLibraries();
  5048. return *new CArrayIteratorOf<IConstWULibrary,IConstWULibraryIterator> (libraries, 0, (IConstWorkUnit *) this);
  5049. }
  5050. IConstWULibrary * CLocalWorkUnit::getLibraryByName(const char * search) const
  5051. {
  5052. CriticalBlock block(crit);
  5053. loadLibraries();
  5054. ForEachItemIn(idx, libraries)
  5055. {
  5056. SCMStringBuffer name;
  5057. IConstWULibrary &cur = libraries.item(idx);
  5058. cur.getName(name);
  5059. if (stricmp(name.str(), search)==0)
  5060. return &OLINK(cur);
  5061. }
  5062. return NULL;
  5063. }
  5064. unsigned CLocalWorkUnit::getTimerDuration(const char *name) const
  5065. {
  5066. Owned<IConstWUStatistic> stat = getStatisticByDescription(name);
  5067. if (stat)
  5068. {
  5069. unsigned __int64 time = stat->getValue();
  5070. return (unsigned)(time / 1000000);
  5071. }
  5072. //Backward compatibility - but only use it if no statistics
  5073. CriticalBlock block(crit);
  5074. if (p->hasProp("Statistics"))
  5075. return 0;
  5076. StringBuffer pname;
  5077. pname.appendf("Timings/Timing[@name=\"%s\"]/@duration", name);
  5078. return p->getPropInt(pname.str(), 0);
  5079. }
  5080. IStringVal & CLocalWorkUnit::getTimerDescription(const char * name, IStringVal & str) const
  5081. {
  5082. Owned<IConstWUStatistic> stat = getStatisticByDescription(name);
  5083. if (stat)
  5084. return stat->getDescription(str);
  5085. //Backward compatibility - but only use it if no statistics
  5086. CriticalBlock block(crit);
  5087. if (p->hasProp("Statistics"))
  5088. {
  5089. str.clear();
  5090. return str;
  5091. }
  5092. str.set(name);
  5093. return str;
  5094. }
  5095. unsigned CLocalWorkUnit::getTimerCount(const char *name) const
  5096. {
  5097. Owned<IConstWUStatistic> stat = getStatisticByDescription(name);
  5098. if (stat)
  5099. return (unsigned)stat->getCount();
  5100. //Backward compatibility - but only use it if no statistics
  5101. CriticalBlock block(crit);
  5102. if (p->hasProp("Statistics"))
  5103. return 0;
  5104. StringBuffer pname;
  5105. pname.appendf("Timings/Timing[@name=\"%s\"]/@count", name);
  5106. return p->getPropInt(pname.str(), 0);
  5107. }
  5108. IStringIterator& CLocalWorkUnit::getTimers() const
  5109. {
  5110. CriticalBlock block(crit);
  5111. if (p->hasProp("Statistics"))
  5112. return *new CStringPTreeAttrIterator(p->getElements("Statistics/Statistic[@unit=\"ns\"]"), "@desc");
  5113. //Backward compatibility - but only use it if no statistics
  5114. return *new CStringPTreeAttrIterator(p->getElements("Timings/Timing"), "@name");
  5115. }
  5116. IConstWUTimerIterator& CLocalWorkUnit::getTimerIterator() const
  5117. {
  5118. CriticalBlock block(crit);
  5119. loadTimers();
  5120. return *new CArrayIteratorOf<IConstWUTimer,IConstWUTimerIterator> (timers, 0, (IConstWorkUnit *) this);
  5121. }
  5122. class CLocalWUTimer : public CInterface, implements IWUTimer
  5123. {
  5124. StringAttr name;
  5125. unsigned count;
  5126. unsigned duration;
  5127. public:
  5128. IMPLEMENT_IINTERFACE;
  5129. CLocalWUTimer(const char* _name, unsigned _count, unsigned _duration) : name(_name), count(_count), duration(_duration) { };
  5130. virtual IStringVal & getName(IStringVal & str) const { str.set(name.get()); return str; } ;
  5131. virtual unsigned getCount() const { return count; };
  5132. virtual unsigned getDuration() const { return duration; };
  5133. virtual void setName(const char * str) { name.set(str); };
  5134. virtual void setCount(unsigned c) { count = c; };
  5135. virtual void setDuration(unsigned d) { duration = d; };
  5136. };
  5137. void CLocalWorkUnit::loadTimers() const
  5138. {
  5139. CriticalBlock block(crit);
  5140. if (timersCached)
  5141. return;
  5142. assertex(timers.length() == 0);
  5143. Owned<IPropertyTreeIterator> r = p->getElements("Timings/Timing");
  5144. ForEach(*r)
  5145. {
  5146. IPropertyTree *rp = &r->query();
  5147. timers.append(*new CLocalWUTimer(rp->queryProp("@name"), rp->getPropInt("@count"), rp->getPropInt("@duration")));
  5148. }
  5149. timersCached = true;
  5150. }
  5151. StringBuffer &formatGraphTimerLabel(StringBuffer &str, const char *graphName, unsigned subGraphNum, unsigned __int64 subId)
  5152. {
  5153. str.append("Graph ").append(graphName);
  5154. if (subGraphNum) str.append(" - ").append(subGraphNum).append(" (").append(subId).append(")");
  5155. else if (subId) str.append(" - id(").append(subId).append(")");
  5156. return str;
  5157. }
  5158. StringBuffer &formatGraphTimerScope(StringBuffer &str, const char *graphName, unsigned subGraphNum, unsigned __int64 subId)
  5159. {
  5160. str.append(graphName);
  5161. if (subId) str.append(":").append(subId);
  5162. return str;
  5163. }
  5164. bool parseGraphTimerLabel(const char *label, StringAttr &graphName, unsigned & graphNum, unsigned &subGraphNum, unsigned &subId)
  5165. {
  5166. // expects format: "Graph <graphname>[ - <subgraphnum> (<subgraphid>)]"
  5167. unsigned len = (size32_t)strlen(label);
  5168. if (len < 6 || (0 != memcmp(label, "Graph ", 6)))
  5169. return false;
  5170. graphNum = 0;
  5171. subGraphNum = 0;
  5172. subId = 0;
  5173. const char *finger = label+6;
  5174. const char *finger2 = strchr(finger, '-');
  5175. if (NULL == finger2) // just graphName
  5176. graphName.set(finger);
  5177. else
  5178. {
  5179. graphName.set(finger, (size32_t)((finger2-1)-finger));
  5180. finger = finger2+2; // skip '-' and space
  5181. finger2 = strchr(finger, ' ');
  5182. if (finger2)
  5183. {
  5184. subGraphNum = atoi_l(finger, (size32_t)(finger2-finger));
  5185. finger = finger2+2; // skip space and '('
  5186. finger2 = strchr(finger, ')');
  5187. if (finger2)
  5188. subId = atoi_l(finger, (size32_t)(finger2-finger));
  5189. }
  5190. else if (((len-(finger-label))>3) && 0 == memcmp(finger, "id(", 3)) // subgraph id only, new format.
  5191. {
  5192. finger += 3;
  5193. finger2 = strchr(finger, ')');
  5194. if (finger2)
  5195. subId = atoi_l(finger, (size32_t)(finger2-finger));
  5196. }
  5197. }
  5198. if (graphName && !memicmp(graphName, "graph", 5))
  5199. graphNum = atoi(graphName + 5);
  5200. return true;
  5201. }
  5202. void CLocalWorkUnit::setTimerInfo(const char *name, unsigned ms, unsigned count, unsigned __int64 max)
  5203. {
  5204. CriticalBlock block(crit);
  5205. IPropertyTree *timings = p->queryPropTree("Timings");
  5206. if (!timings)
  5207. timings = p->addPropTree("Timings", createPTree("Timings"));
  5208. StringBuffer xpath;
  5209. xpath.append("Timing[@name=\"").append(name).append("\"]");
  5210. IPropertyTree *timing = timings->queryPropTree(xpath.str());
  5211. if (!timing)
  5212. {
  5213. timing = timings->addPropTree("Timing", createPTree("Timing"));
  5214. timing->setProp("@name", name);
  5215. }
  5216. timing->setPropInt("@count", count);
  5217. timing->setPropInt("@duration", ms);
  5218. if (!max && 1==count) max = milliToNano(ms); // max is in nanoseconds
  5219. if (max)
  5220. timing->setPropInt64("@max", max);
  5221. }
  5222. void CLocalWorkUnit::setTimeStamp(const char *application, const char *instance, const char *event, bool add)
  5223. {
  5224. CriticalBlock block(crit);
  5225. char timeStamp[64];
  5226. time_t tNow;
  5227. time(&tNow);
  5228. #ifdef _WIN32
  5229. struct tm *gmtNow;
  5230. gmtNow = gmtime(&tNow);
  5231. strftime(timeStamp, 64, "%Y-%m-%dT%H:%M:%SZ", gmtNow);
  5232. #else
  5233. struct tm gmtNow;
  5234. gmtime_r(&tNow, &gmtNow);
  5235. strftime(timeStamp, 64, "%Y-%m-%dT%H:%M:%SZ", &gmtNow);
  5236. #endif //_WIN32
  5237. IPropertyTree *ts = p->queryPropTree("TimeStamps");
  5238. if (!ts) {
  5239. ts = p->addPropTree("TimeStamps", createPTree("TimeStamps"));
  5240. add = true;
  5241. }
  5242. IPropertyTree *t=NULL;
  5243. if (!add) {
  5244. StringBuffer path;
  5245. path.appendf("TimeStamp[@application=\"%s\"]",application);
  5246. t = ts->queryBranch(path.str());
  5247. }
  5248. if (!t) {
  5249. t = createPTree("TimeStamp");
  5250. t->setProp("@application", application);
  5251. add = true;
  5252. }
  5253. if (instance)
  5254. t->setProp("@instance", instance);
  5255. t->setProp(event, timeStamp);
  5256. IPropertyTree *et = t->queryPropTree(event);
  5257. if(et)
  5258. et->setPropInt("@ts",(int)tNow);
  5259. if (add)
  5260. ts->addPropTree("TimeStamp", t);
  5261. }
  5262. mapEnums queryStatMeasure[] =
  5263. {
  5264. { SMEASURE_TIME_NS, "ns" },
  5265. { SMEASURE_COUNT, "cnt" },
  5266. { SMEASURE_MEM_KB, "kb" },
  5267. { SMEASURE_MAX, NULL},
  5268. };
  5269. void CLocalWorkUnit::setStatistic(const char * creator, const char * wuScope, const char * stat, const char * description, StatisticMeasure kind, unsigned __int64 value, unsigned __int64 count, unsigned __int64 maxValue, bool merge)
  5270. {
  5271. if (!wuScope) wuScope = "workunit";
  5272. //creator. scope and name must all be present, and must not contain semi colons.
  5273. assertex(creator && wuScope && stat);
  5274. dbgassertex(!strchr(creator, ';') && !strchr(wuScope, ';') && !strchr(stat, ';'));
  5275. if (count == 1 && maxValue < value)
  5276. maxValue = value;
  5277. StringBuffer fullname;
  5278. fullname.append(creator).append(";").append(wuScope).append(";").append(stat);
  5279. StringBuffer xpath;
  5280. xpath.append("Statistic[@name=\"").append(fullname).append("\"]");
  5281. CriticalBlock block(crit);
  5282. IPropertyTree * stats = p->queryPropTree("Statistics");
  5283. if (!stats)
  5284. stats = p->addPropTree("Statistics", createPTree("Statistics"));
  5285. IPropertyTree * statTree = stats->queryPropTree(xpath.str());
  5286. if (!statTree)
  5287. {
  5288. //MORE: When getTimings is removed the default description could be dynamically calculated
  5289. StringBuffer descriptionText;
  5290. if (!description || !*description)
  5291. {
  5292. bool isDefaultName = streq(stat, "time");
  5293. bool isDefaultScope = streq(wuScope, "workunit");
  5294. descriptionText.append(creator);
  5295. if (isDefaultName || !isDefaultScope)
  5296. descriptionText.append(": ").append(wuScope);
  5297. if (!isDefaultName)
  5298. descriptionText.append(": ").append(stat);
  5299. description = descriptionText;
  5300. }
  5301. statTree = stats->addPropTree("Statistic", createPTree("Statistic"));
  5302. statTree->setProp("@name", fullname.str());
  5303. if (description)
  5304. statTree->setProp("@desc", description);
  5305. setEnum(statTree, "@unit", kind, queryStatMeasure);
  5306. statTree->setPropInt64("@value", value);
  5307. statTree->setPropInt64("@count", count);
  5308. if (maxValue)
  5309. statTree->setPropInt64("@max", maxValue);
  5310. if (statistics.cached)
  5311. statistics.append(LINK(statTree));
  5312. }
  5313. else
  5314. {
  5315. if (merge)
  5316. {
  5317. unsigned __int64 oldValue = statTree->getPropInt64("@value", 0);
  5318. unsigned __int64 oldCount = statTree->getPropInt64("@count", 0);
  5319. unsigned __int64 oldMax = statTree->getPropInt64("@max", 0);
  5320. statTree->setPropInt64("@value", value + oldValue);
  5321. statTree->setPropInt64("@count", count + oldCount);
  5322. if (maxValue > oldMax)
  5323. statTree->setPropInt64("@max", maxValue);
  5324. }
  5325. else
  5326. {
  5327. statTree->setPropInt64("@value", value);
  5328. statTree->setPropInt64("@count", count);
  5329. if (maxValue)
  5330. statTree->setPropInt64("@max", maxValue);
  5331. }
  5332. }
  5333. }
  5334. void CLocalWorkUnit::setTimeStamp(const char *application, const char *instance, const char *event)
  5335. {
  5336. setTimeStamp(application,instance,event,false);
  5337. }
  5338. void CLocalWorkUnit::addTimeStamp(const char *application, const char *instance, const char *event)
  5339. {
  5340. setTimeStamp(application,instance,event,true);
  5341. }
  5342. IStringVal &CLocalWorkUnit::getTimeStamp(const char *name, const char *application, IStringVal &str) const
  5343. {
  5344. CriticalBlock block(crit);
  5345. str.clear();
  5346. StringBuffer pname("TimeStamps/TimeStamp");
  5347. if (application)
  5348. pname.appendf("[@application=\"%s\"]", application);
  5349. pname.appendf("/%s", name);
  5350. Owned<IPropertyTreeIterator> stamps = p->getElements(pname.str());
  5351. if (stamps && stamps->first())
  5352. str.set(stamps->query().queryProp(NULL));
  5353. return str;
  5354. }
  5355. IConstWUTimeStampIterator& CLocalWorkUnit::getTimeStamps() const
  5356. {
  5357. CriticalBlock block(crit);
  5358. timestamps.load(p,"TimeStamps/*");
  5359. return *new CArrayIteratorOf<IConstWUTimeStamp,IConstWUTimeStampIterator> (timestamps, 0, (IConstWorkUnit *) this);
  5360. }
  5361. IConstWUStatisticIterator& CLocalWorkUnit::getStatistics() const
  5362. {
  5363. CriticalBlock block(crit);
  5364. statistics.load(p,"Statistics/*");
  5365. return *new CArrayIteratorOf<IConstWUStatistic,IConstWUStatisticIterator> (statistics, 0, (IConstWorkUnit *) this);
  5366. }
  5367. IConstWUStatistic * CLocalWorkUnit::getStatisticByDescription(const char * desc) const
  5368. {
  5369. StringBuffer xpath;
  5370. xpath.appendf("Statistics/Statistic[@desc=\"%s\"]", desc);
  5371. CriticalBlock block(crit);
  5372. IPropertyTree * match = p->queryPropTree(xpath);
  5373. if (!match)
  5374. return NULL;
  5375. return new CLocalWUStatistic(LINK(match));
  5376. }
  5377. IConstWUStatistic * CLocalWorkUnit::getStatistic(const char * name) const
  5378. {
  5379. StringBuffer xpath;
  5380. xpath.appendf("Statistics/Statistic[@name=\"%s\"]", name);
  5381. CriticalBlock block(crit);
  5382. IPropertyTree * match = p->queryPropTree(xpath);
  5383. if (!match)
  5384. return NULL;
  5385. return new CLocalWUStatistic(LINK(match));
  5386. }
  5387. bool CLocalWorkUnit::getWuDate(unsigned & year, unsigned & month, unsigned& day)
  5388. {
  5389. CriticalBlock block(crit);
  5390. SCMStringBuffer wuidstr;
  5391. const char *wuid = getWuid(wuidstr).str();
  5392. if (sscanf(wuid, "W%4u%2u%2u", &year, &month, &day)==3)
  5393. {
  5394. }
  5395. return false;
  5396. }
  5397. IWUPlugin* CLocalWorkUnit::updatePluginByName(const char *qname)
  5398. {
  5399. CriticalBlock block(crit);
  5400. IConstWUPlugin *existing = getPluginByName(qname);
  5401. if (existing)
  5402. return (IWUPlugin *) existing;
  5403. if (!plugins.length())
  5404. p->addPropTree("Plugins", createPTree("Plugins"));
  5405. IPropertyTree *pl = p->queryPropTree("Plugins");
  5406. IPropertyTree *s = pl->addPropTree("Plugin", createPTree("Plugin"));
  5407. s->Link();
  5408. IWUPlugin* q = new CLocalWUPlugin(s);
  5409. q->Link();
  5410. plugins.append(*q);
  5411. q->setPluginName(qname);
  5412. return q;
  5413. }
  5414. IConstWUPlugin* CLocalWorkUnit::getPluginByName(const char *qname) const
  5415. {
  5416. CriticalBlock block(crit);
  5417. loadPlugins();
  5418. ForEachItemIn(idx, plugins)
  5419. {
  5420. SCMStringBuffer name;
  5421. IConstWUPlugin &cur = plugins.item(idx);
  5422. cur.getPluginName(name);
  5423. if (stricmp(name.str(), qname)==0)
  5424. {
  5425. cur.Link();
  5426. return &cur;
  5427. }
  5428. }
  5429. return NULL;
  5430. }
  5431. IWULibrary* CLocalWorkUnit::updateLibraryByName(const char *qname)
  5432. {
  5433. CriticalBlock block(crit);
  5434. IConstWULibrary *existing = getLibraryByName(qname);
  5435. if (existing)
  5436. return (IWULibrary *) existing;
  5437. if (!libraries.length())
  5438. p->addPropTree("Libraries", createPTree("Libraries"));
  5439. IPropertyTree *pl = p->queryPropTree("Libraries");
  5440. IPropertyTree *s = pl->addPropTree("Library", createPTree("Library"));
  5441. s->Link();
  5442. IWULibrary* q = new CLocalWULibrary(s);
  5443. q->Link();
  5444. libraries.append(*q);
  5445. q->setName(qname);
  5446. return q;
  5447. }
  5448. void CLocalWorkUnit::loadExceptions() const
  5449. {
  5450. CriticalBlock block(crit);
  5451. if (!exceptionsCached)
  5452. {
  5453. assertex(exceptions.length() == 0);
  5454. Owned<IPropertyTreeIterator> r = p->getElements("Exceptions/Exception");
  5455. for (r->first(); r->isValid(); r->next())
  5456. {
  5457. IPropertyTree *rp = &r->query();
  5458. rp->Link();
  5459. exceptions.append(*new CLocalWUException(rp));
  5460. }
  5461. exceptionsCached = true;
  5462. }
  5463. }
  5464. IConstWUExceptionIterator& CLocalWorkUnit::getExceptions() const
  5465. {
  5466. CriticalBlock block(crit);
  5467. loadExceptions();
  5468. return *new CArrayIteratorOf<IConstWUException,IConstWUExceptionIterator> (exceptions, 0, (IConstWorkUnit *) this);
  5469. }
  5470. unsigned CLocalWorkUnit::getExceptionCount() const
  5471. {
  5472. CriticalBlock block(crit);
  5473. loadExceptions();
  5474. return exceptions.length();
  5475. }
  5476. void CLocalWorkUnit::clearExceptions()
  5477. {
  5478. CriticalBlock block(crit);
  5479. // For this to be legally called, we must have the write-able interface. So we are already locked for write.
  5480. exceptions.kill();
  5481. exceptionsCached = true;
  5482. p->removeProp("Exceptions");
  5483. }
  5484. IWUException* CLocalWorkUnit::createException()
  5485. {
  5486. CriticalBlock block(crit);
  5487. // For this to be legally called, we must have the write-able interface. So we are already locked for write.
  5488. loadExceptions();
  5489. if (!exceptions.length())
  5490. p->addPropTree("Exceptions", createPTree("Exceptions"));
  5491. IPropertyTree *r = p->queryPropTree("Exceptions");
  5492. IPropertyTree *s = r->addPropTree("Exception", createPTree("Exception"));
  5493. IWUException* q = new CLocalWUException(LINK(s));
  5494. exceptions.append(*LINK(q));
  5495. Owned<IJlibDateTime> now = createDateTimeNow();
  5496. SCMStringBuffer temp;
  5497. now->getString(temp);
  5498. q->setTimeStamp(temp.str());
  5499. return q;
  5500. }
  5501. IConstWUWebServicesInfo* CLocalWorkUnit::getWebServicesInfo() const
  5502. {
  5503. // For this to be legally called, we must have the read-able interface. So we are already locked for (at least) read.
  5504. CriticalBlock block(crit);
  5505. if (!webServicesInfoCached)
  5506. {
  5507. assertex(!webServicesInfo);
  5508. IPropertyTree *s = p->getPropTree("WebServicesInfo");
  5509. if (s)
  5510. webServicesInfo.setown(new CLocalWUWebServicesInfo(s)); // NB takes ownership of 's'
  5511. webServicesInfoCached = true;
  5512. }
  5513. return webServicesInfo.getLink();
  5514. }
  5515. IWUWebServicesInfo* CLocalWorkUnit::updateWebServicesInfo(bool create)
  5516. {
  5517. // For this to be legally called, we must have the write-able interface. So we are already locked for write.
  5518. CriticalBlock block(crit);
  5519. if (!webServicesInfoCached)
  5520. {
  5521. IPropertyTree *s = p->queryPropTree("WebServicesInfo");
  5522. if (!s)
  5523. {
  5524. if (create)
  5525. s = p->addPropTree("WebServicesInfo", createPTreeFromXMLString("<WebServicesInfo />"));
  5526. else
  5527. return NULL;
  5528. }
  5529. s->Link();
  5530. webServicesInfo.setown(new CLocalWUWebServicesInfo(s));
  5531. webServicesInfoCached = true;
  5532. }
  5533. return webServicesInfo.getLink();
  5534. }
  5535. IConstWURoxieQueryInfo* CLocalWorkUnit::getRoxieQueryInfo() const
  5536. {
  5537. // For this to be legally called, we must have the read-able interface. So we are already locked for (at least) read.
  5538. CriticalBlock block(crit);
  5539. if (!roxieQueryInfoCached)
  5540. {
  5541. assertex(!roxieQueryInfo);
  5542. IPropertyTree *s = p->getPropTree("RoxieQueryInfo");
  5543. if (s)
  5544. roxieQueryInfo.setown(new CLocalWURoxieQueryInfo(s)); // NB takes ownership of 's'
  5545. roxieQueryInfoCached = true;
  5546. }
  5547. return roxieQueryInfo.getLink();
  5548. }
  5549. IWURoxieQueryInfo* CLocalWorkUnit::updateRoxieQueryInfo(const char *wuid, const char *roxieClusterName)
  5550. {
  5551. // For this to be legally called, we must have the write-able interface. So we are already locked for write.
  5552. CriticalBlock block(crit);
  5553. if (!roxieQueryInfoCached)
  5554. {
  5555. IPropertyTree *s = p->queryPropTree("RoxieQueryInfo");
  5556. if (!s)
  5557. s = p->addPropTree("RoxieQueryInfo", createPTreeFromXMLString("<RoxieQueryInfo />"));
  5558. if (wuid && *wuid)
  5559. s->addProp("@wuid", wuid);
  5560. if (roxieClusterName && *roxieClusterName)
  5561. s->addProp("@roxieClusterName", roxieClusterName);
  5562. s->Link();
  5563. roxieQueryInfo.setown(new CLocalWURoxieQueryInfo(s));
  5564. roxieQueryInfoCached = true;
  5565. }
  5566. return roxieQueryInfo.getLink();
  5567. }
  5568. static int compareResults(IInterface **ll, IInterface **rr)
  5569. {
  5570. CLocalWUResult *l = (CLocalWUResult *) *ll;
  5571. CLocalWUResult *r = (CLocalWUResult *) *rr;
  5572. return l->getResultSequence() - r->getResultSequence();
  5573. }
  5574. void CLocalWorkUnit::loadResults() const
  5575. {
  5576. CriticalBlock block(crit);
  5577. if (!resultsCached)
  5578. {
  5579. assertex(results.length() == 0);
  5580. Owned<IPropertyTreeIterator> r = p->getElements("Results/Result");
  5581. for (r->first(); r->isValid(); r->next())
  5582. {
  5583. IPropertyTree *rp = &r->query();
  5584. rp->Link();
  5585. results.append(*new CLocalWUResult(rp));
  5586. }
  5587. results.sort(compareResults);
  5588. resultsCached = true;
  5589. }
  5590. }
  5591. void CLocalWorkUnit::loadVariables() const
  5592. {
  5593. CriticalBlock block(crit);
  5594. if (!variablesCached)
  5595. {
  5596. assertex(variables.length() == 0);
  5597. Owned<IPropertyTreeIterator> r = p->getElements("Variables/Variable");
  5598. for (r->first(); r->isValid(); r->next())
  5599. {
  5600. IPropertyTree *rp = &r->query();
  5601. rp->Link();
  5602. variables.append(*new CLocalWUResult(rp));
  5603. }
  5604. variablesCached = true;
  5605. }
  5606. }
  5607. void CLocalWorkUnit::loadTemporaries() const
  5608. {
  5609. CriticalBlock block(crit);
  5610. if (!temporariesCached)
  5611. {
  5612. assertex(temporaries.length() == 0);
  5613. Owned<IPropertyTreeIterator> r = p->getElements("Temporaries/Variable");
  5614. for (r->first(); r->isValid(); r->next())
  5615. {
  5616. IPropertyTree *rp = &r->query();
  5617. rp->Link();
  5618. temporaries.append(*new CLocalWUResult(rp));
  5619. }
  5620. temporariesCached = true;
  5621. }
  5622. }
  5623. void CLocalWorkUnit::deleteTemporaries()
  5624. {
  5625. CriticalBlock block(crit);
  5626. if (temporariesCached)
  5627. {
  5628. temporaries.kill();
  5629. temporariesCached = false;
  5630. }
  5631. p->removeProp("Temporaries");
  5632. }
  5633. IWUResult* CLocalWorkUnit::createResult()
  5634. {
  5635. CriticalBlock block(crit);
  5636. // For this to be legally called, we must have the write-able interface. So we are already locked for write.
  5637. loadResults();
  5638. if (!results.length())
  5639. p->addPropTree("Results", createPTree("Results"));
  5640. IPropertyTree *r = p->queryPropTree("Results");
  5641. IPropertyTree *s = r->addPropTree("Result", createPTree());
  5642. s->Link();
  5643. IWUResult* q = new CLocalWUResult(s);
  5644. q->Link();
  5645. results.append(*q);
  5646. return q;
  5647. }
  5648. IWUResult* CLocalWorkUnit::updateResultByName(const char *qname)
  5649. {
  5650. CriticalBlock block(crit);
  5651. IConstWUResult *existing = getResultByName(qname);
  5652. if (existing)
  5653. return (IWUResult *) existing;
  5654. IWUResult* q = createResult();
  5655. q->setResultName(qname);
  5656. return q;
  5657. }
  5658. IWUResult* CLocalWorkUnit::updateResultBySequence(unsigned seq)
  5659. {
  5660. CriticalBlock block(crit);
  5661. IConstWUResult *existing = getResultBySequence(seq);
  5662. if (existing)
  5663. return (IWUResult *) existing;
  5664. IWUResult* q = createResult();
  5665. q->setResultSequence(seq);
  5666. return q;
  5667. }
  5668. IConstWUResultIterator& CLocalWorkUnit::getResults() const
  5669. {
  5670. CriticalBlock block(crit);
  5671. loadResults();
  5672. return *new CArrayIteratorOf<IConstWUResult,IConstWUResultIterator> (results, 0, (IConstWorkUnit *) this);
  5673. }
  5674. IConstWUResult* CLocalWorkUnit::getResultByName(const char *qname) const
  5675. {
  5676. CriticalBlock block(crit);
  5677. loadResults();
  5678. ForEachItemIn(idx, results)
  5679. {
  5680. SCMStringBuffer name;
  5681. IConstWUResult &cur = results.item(idx);
  5682. cur.getResultName(name);
  5683. if (stricmp(name.str(), qname)==0)
  5684. {
  5685. cur.Link();
  5686. return &cur;
  5687. }
  5688. }
  5689. return NULL;
  5690. }
  5691. IConstWUResult* CLocalWorkUnit::getResultBySequence(unsigned seq) const
  5692. {
  5693. CriticalBlock block(crit);
  5694. loadResults();
  5695. ForEachItemIn(idx, results)
  5696. {
  5697. IConstWUResult &cur = results.item(idx);
  5698. if (cur.getResultSequence() == seq)
  5699. {
  5700. cur.Link();
  5701. return &cur;
  5702. }
  5703. }
  5704. return NULL;
  5705. }
  5706. IConstWUResultIterator& CLocalWorkUnit::getVariables() const
  5707. {
  5708. CriticalBlock block(crit);
  5709. loadVariables();
  5710. return *new CArrayIteratorOf<IConstWUResult,IConstWUResultIterator> (variables, 0, (IConstWorkUnit *) this);
  5711. }
  5712. IConstWUResult* CLocalWorkUnit::getGlobalByName(const char *qname) const
  5713. {
  5714. CriticalBlock block(crit);
  5715. if (strcmp(p->queryName(), GLOBAL_WORKUNIT)==0)
  5716. return getVariableByName(qname);
  5717. Owned <IWorkUnit> global = factory->ensureNamedWorkUnit(GLOBAL_WORKUNIT);
  5718. return global->getVariableByName(qname);
  5719. }
  5720. IWUResult* CLocalWorkUnit::updateGlobalByName(const char *qname)
  5721. {
  5722. CriticalBlock block(crit);
  5723. if (strcmp(p->queryName(), GLOBAL_WORKUNIT)==0)
  5724. return updateVariableByName(qname);
  5725. Owned <IWorkUnit> global = factory->ensureNamedWorkUnit(GLOBAL_WORKUNIT);
  5726. return global->updateVariableByName(qname);
  5727. }
  5728. IConstWUResult* CLocalWorkUnit::getVariableByName(const char *qname) const
  5729. {
  5730. CriticalBlock block(crit);
  5731. loadVariables();
  5732. ForEachItemIn(idx, variables)
  5733. {
  5734. SCMStringBuffer name;
  5735. IConstWUResult &cur = variables.item(idx);
  5736. cur.getResultName(name);
  5737. if (stricmp(name.str(), qname)==0)
  5738. {
  5739. cur.Link();
  5740. return &cur;
  5741. }
  5742. }
  5743. return NULL;
  5744. }
  5745. IConstWUResult* CLocalWorkUnit::getTemporaryByName(const char *qname) const
  5746. {
  5747. CriticalBlock block(crit);
  5748. loadTemporaries();
  5749. ForEachItemIn(idx, temporaries)
  5750. {
  5751. SCMStringBuffer name;
  5752. IConstWUResult &cur = temporaries.item(idx);
  5753. cur.getResultName(name);
  5754. if (stricmp(name.str(), qname)==0)
  5755. {
  5756. cur.Link();
  5757. return &cur;
  5758. }
  5759. }
  5760. return NULL;
  5761. }
  5762. IConstWUResultIterator& CLocalWorkUnit::getTemporaries() const
  5763. {
  5764. CriticalBlock block(crit);
  5765. loadTemporaries();
  5766. return *new CArrayIteratorOf<IConstWUResult,IConstWUResultIterator> (temporaries, 0, (IConstWorkUnit *) this);
  5767. }
  5768. IWUResult* CLocalWorkUnit::updateTemporaryByName(const char *qname)
  5769. {
  5770. CriticalBlock block(crit);
  5771. IConstWUResult *existing = getTemporaryByName(qname);
  5772. if (existing)
  5773. return (IWUResult *) existing;
  5774. if (!temporaries.length())
  5775. p->addPropTree("Temporaries", createPTree("Temporaries"));
  5776. IPropertyTree *vars = p->queryPropTree("Temporaries");
  5777. IPropertyTree *s = vars->addPropTree("Variable", createPTree("Variable"));
  5778. s->Link();
  5779. IWUResult* q = new CLocalWUResult(s);
  5780. q->Link();
  5781. temporaries.append(*q);
  5782. q->setResultName(qname);
  5783. return q;
  5784. }
  5785. IWUResult* CLocalWorkUnit::updateVariableByName(const char *qname)
  5786. {
  5787. CriticalBlock block(crit);
  5788. IConstWUResult *existing = getVariableByName(qname);
  5789. if (existing)
  5790. return (IWUResult *) existing;
  5791. if (!variables.length())
  5792. p->addPropTree("Variables", createPTree("Variables"));
  5793. IPropertyTree *vars = p->queryPropTree("Variables");
  5794. IPropertyTree *s = vars->addPropTree("Variable", createPTree("Variable"));
  5795. s->Link();
  5796. IWUResult* q = new CLocalWUResult(s);
  5797. q->Link();
  5798. variables.append(*q);
  5799. q->setResultName(qname);
  5800. return q;
  5801. }
  5802. void CLocalWorkUnit::deleteTempFiles(const char *graph, bool deleteOwned, bool deleteJobOwned)
  5803. {
  5804. CriticalBlock block(crit);
  5805. IPropertyTree *files = p->queryPropTree("Files");
  5806. if (!files) return;
  5807. Owned<IPropertyTreeIterator> iter = files->getElements("File");
  5808. ICopyArrayOf<IPropertyTree> toRemove;
  5809. ForEach (*iter)
  5810. {
  5811. IPropertyTree &file = iter->query();
  5812. WUFileKind fileKind = (WUFileKind) file.getPropInt("@kind", WUFileStandard);
  5813. if(file.getPropBool("@temporary")) fileKind = WUFileTemporary; // @temporary, legacy check
  5814. bool needDelete;
  5815. switch(fileKind)
  5816. {
  5817. case WUFileTemporary:
  5818. if(graph==NULL)
  5819. needDelete = true;
  5820. else
  5821. {
  5822. const char *graphOwner = file.queryProp("@graph");
  5823. needDelete = ((graphOwner==NULL) || (strcmp(graph, graphOwner)==0));
  5824. }
  5825. break;
  5826. case WUFileJobOwned:
  5827. needDelete = ((graph==NULL) && deleteJobOwned);
  5828. break;
  5829. case WUFileOwned:
  5830. needDelete = ((graph==NULL) && deleteOwned);
  5831. break;
  5832. default:
  5833. needDelete = false;
  5834. }
  5835. if(needDelete)
  5836. {
  5837. const char *name = file.queryProp("@name");
  5838. LOG(MCdebugProgress, unknownJob, "Removing workunit file %s from DFS", name);
  5839. queryDistributedFileDirectory().removeEntry(name, queryUserDescriptor());
  5840. toRemove.append(file);
  5841. }
  5842. }
  5843. ForEachItemIn(r, toRemove) files->removeTree(&toRemove.item(r));
  5844. }
  5845. static void _noteFileRead(IDistributedFile *file, IPropertyTree *filesRead)
  5846. {
  5847. IDistributedSuperFile *super = file->querySuperFile();
  5848. StringBuffer fname;
  5849. file->getLogicalName(fname);
  5850. StringBuffer path("File[@name=\"");
  5851. path.append(fname).append("\"]");
  5852. IPropertyTree *fileTree = filesRead->queryPropTree(path.str());
  5853. if (fileTree)
  5854. fileTree->setPropInt("@useCount", fileTree->getPropInt("@useCount")+1);
  5855. else
  5856. {
  5857. StringBuffer cluster;
  5858. file->getClusterName(0,cluster);
  5859. fileTree = createPTree();
  5860. fileTree->setProp("@name", fname.str());
  5861. fileTree->setProp("@cluster", cluster.str());
  5862. fileTree->setPropInt("@useCount", 1);
  5863. fileTree = filesRead->addPropTree("File", fileTree);
  5864. }
  5865. if (super)
  5866. {
  5867. Owned<IDistributedFileIterator> iter = super->getSubFileIterator(false);
  5868. ForEach (*iter)
  5869. {
  5870. IDistributedFile &file = iter->query();
  5871. StringBuffer fname;
  5872. file.getLogicalName(fname);
  5873. Owned<IPropertyTree> subfile = createPTree();
  5874. subfile->setProp("@name", fname.str());
  5875. fileTree->addPropTree("Subfile", subfile.getClear());
  5876. _noteFileRead(&file, filesRead);
  5877. }
  5878. }
  5879. }
  5880. void CLocalWorkUnit::noteFileRead(IDistributedFile *file)
  5881. {
  5882. CriticalBlock block(crit);
  5883. IPropertyTree *files = p->queryPropTree("FilesRead");
  5884. if (!files)
  5885. files = p->addPropTree("FilesRead", createPTree());
  5886. _noteFileRead(file, files);
  5887. }
  5888. static void addFile(IPropertyTree *files, const char *fileName, const char *cluster, unsigned usageCount, WUFileKind fileKind, const char *graphOwner)
  5889. {
  5890. StringBuffer path("File[@name=\"");
  5891. path.append(fileName).append("\"]");
  5892. if (cluster)
  5893. path.append("[@cluster=\"").append(cluster).append("\"]");
  5894. IPropertyTree *file = files->queryPropTree(path.str());
  5895. if (file) files->removeTree(file);
  5896. file = createPTree();
  5897. file->setProp("@name", fileName);
  5898. if (cluster)
  5899. file->setProp("@cluster", cluster);
  5900. if (graphOwner)
  5901. file->setProp("@graph", graphOwner);
  5902. file->setPropInt("@kind", (unsigned)fileKind);
  5903. if (WUFileTemporary == fileKind)
  5904. file->setPropInt("@usageCount", usageCount);
  5905. files->addPropTree("File", file);
  5906. }
  5907. void CLocalWorkUnit::addFile(const char *fileName, StringArray *clusters, unsigned usageCount, WUFileKind fileKind, const char *graphOwner)
  5908. {
  5909. CriticalBlock block(crit);
  5910. IPropertyTree *files = p->queryPropTree("Files");
  5911. if (!files)
  5912. files = p->addPropTree("Files", createPTree());
  5913. if (!clusters)
  5914. addFile(fileName, NULL, usageCount, fileKind, graphOwner);
  5915. else
  5916. {
  5917. ForEachItemIn(c, *clusters)
  5918. ::addFile(files, fileName, clusters->item(c), usageCount, fileKind, graphOwner);
  5919. }
  5920. }
  5921. void CLocalWorkUnit::releaseFile(const char *fileName)
  5922. {
  5923. StringBuffer path("File[@name=\"");
  5924. path.append(fileName).append("\"]");
  5925. CriticalBlock block(crit);
  5926. IPropertyTree *files = p->queryPropTree("Files");
  5927. if (!files) return;
  5928. Owned<IPropertyTreeIterator> fiter = files->getElements(path.str());
  5929. ForEach (*fiter)
  5930. {
  5931. IPropertyTree *file = &fiter->query();
  5932. unsigned usageCount = file->getPropInt("@usageCount");
  5933. if (usageCount > 1)
  5934. file->setPropInt("@usageCount", usageCount-1);
  5935. else
  5936. {
  5937. StringAttr name(file->queryProp("@name"));
  5938. files->removeTree(file);
  5939. if (!name.isEmpty()&&(1 == usageCount))
  5940. {
  5941. if (queryDistributedFileDirectory().removeEntry(fileName, queryUserDescriptor()))
  5942. LOG(MCdebugProgress, unknownJob, "Removed (released) file %s from DFS", name.get());
  5943. }
  5944. }
  5945. }
  5946. }
  5947. void CLocalWorkUnit::clearGraphProgress()
  5948. {
  5949. CConstGraphProgress::deleteWuidProgress(p->queryName());
  5950. }
  5951. void CLocalWorkUnit::resetBeforeGeneration()
  5952. {
  5953. CriticalBlock block(crit);
  5954. //Remove all associated files
  5955. Owned<IWUQuery> q = updateQuery();
  5956. q->removeAssociatedFiles();
  5957. //Remove any pre-existing workflow information
  5958. workflowIterator.clear();
  5959. p->removeProp("Workflow");
  5960. }
  5961. unsigned CLocalWorkUnit::queryFileUsage(const char *fileName) const
  5962. {
  5963. StringBuffer path("Files/File[@name=\"");
  5964. path.append(fileName).append("\"]/@usageCount");
  5965. CriticalBlock block(crit);
  5966. return p->getPropInt(path.str());
  5967. }
  5968. IPropertyTree *CLocalWorkUnit::getDiskUsageStats()
  5969. {
  5970. return p->getPropTree("DiskUsageStats");
  5971. }
  5972. void CLocalWorkUnit::addDiskUsageStats(__int64 _avgNodeUsage, unsigned _minNode, __int64 _minNodeUsage, unsigned _maxNode, __int64 _maxNodeUsage, __int64 _graphId)
  5973. {
  5974. IPropertyTree *stats = p->queryPropTree("DiskUsageStats");
  5975. offset_t maxNodeUsage;
  5976. if (stats)
  5977. maxNodeUsage = stats->getPropInt64("@maxNodeUsage");
  5978. else
  5979. {
  5980. stats = p->addPropTree("DiskUsageStats", createPTree());
  5981. maxNodeUsage = 0;
  5982. }
  5983. if ((offset_t)_maxNodeUsage > maxNodeUsage)
  5984. {
  5985. // record all details at time of max node usage.
  5986. stats->setPropInt("@minNode", _minNode);
  5987. stats->setPropInt("@maxNode", _maxNode);
  5988. stats->setPropInt64("@minNodeUsage", _minNodeUsage);
  5989. stats->setPropInt64("@maxNodeUsage", _maxNodeUsage);
  5990. stats->setPropInt64("@graphId", _graphId);
  5991. if (_avgNodeUsage)
  5992. {
  5993. unsigned _skewHi = (unsigned)((100 * (_maxNodeUsage-_avgNodeUsage))/_avgNodeUsage);
  5994. unsigned _skewLo = (unsigned)((100 * (_avgNodeUsage-_minNodeUsage))/_avgNodeUsage);
  5995. stats->setPropInt("@skewHi", _skewHi);
  5996. stats->setPropInt("@skewLo", _skewLo);
  5997. }
  5998. }
  5999. }
  6000. IPropertyTreeIterator & CLocalWorkUnit::getFileIterator() const
  6001. {
  6002. CriticalBlock block(crit);
  6003. return * p->getElements("Files/File");
  6004. }
  6005. IPropertyTreeIterator & CLocalWorkUnit::getFilesReadIterator() const
  6006. {
  6007. CriticalBlock block(crit);
  6008. return * p->getElements("FilesRead/File");
  6009. }
  6010. //=================================================================================================
  6011. IWUActivity * CLocalWorkUnit::updateActivity(__int64 id)
  6012. {
  6013. CriticalBlock block(crit);
  6014. IConstWUActivity *existing = getActivity(id);
  6015. if (existing)
  6016. return (IWUActivity *) existing;
  6017. if (!activities.length())
  6018. p->addPropTree("Activities", createPTree("Activities"));
  6019. IPropertyTree *pl = p->queryPropTree("Activities");
  6020. IPropertyTree *s = pl->addPropTree("Activity", createPTree("Activity"));
  6021. IWUActivity * q = new CLocalWUActivity(LINK(s), id);
  6022. activities.append(*LINK(q));
  6023. return q;
  6024. }
  6025. IConstWUActivity * CLocalWorkUnit::getActivity(__int64 id) const
  6026. {
  6027. CriticalBlock block(crit);
  6028. loadActivities();
  6029. ForEachItemIn(idx, activities)
  6030. {
  6031. IConstWUActivity &cur = activities.item(idx);
  6032. if (cur.getId() == id)
  6033. return &OLINK(cur);
  6034. }
  6035. return NULL;
  6036. }
  6037. void CLocalWorkUnit::loadActivities() const
  6038. {
  6039. CriticalBlock block(crit);
  6040. if (!activitiesCached)
  6041. {
  6042. assertex(activities.length() == 0);
  6043. Owned<IPropertyTreeIterator> r = p->getElements("Activities/Activity");
  6044. for (r->first(); r->isValid(); r->next())
  6045. {
  6046. IPropertyTree *rp = &r->query();
  6047. rp->Link();
  6048. activities.append(*new CLocalWUActivity(rp));
  6049. }
  6050. activitiesCached = true;
  6051. }
  6052. }
  6053. IConstWUActivityIterator& CLocalWorkUnit::getActivities() const
  6054. {
  6055. CriticalBlock block(crit);
  6056. loadActivities();
  6057. return *new CArrayIteratorOf<IConstWUActivity,IConstWUActivityIterator> (activities, 0, (IConstWorkUnit *) this);
  6058. }
  6059. //=================================================================================================
  6060. bool CLocalWorkUnit::switchThorQueue(const char *cluster, IQueueSwitcher *qs)
  6061. {
  6062. CriticalBlock block(crit);
  6063. if (qs->isAuto()&&!getAllowAutoQueueSwitch())
  6064. return false;
  6065. Owned<IConstWUClusterInfo> newci = getTargetClusterInfo(cluster);
  6066. if (!newci)
  6067. return false;
  6068. StringBuffer currentcluster;
  6069. if (!p->getProp("@clusterName",currentcluster))
  6070. return false;
  6071. Owned<IConstWUClusterInfo> curci = getTargetClusterInfo(currentcluster.str());
  6072. if (!curci)
  6073. return false;
  6074. SCMStringBuffer curqname;
  6075. curci->getThorQueue(curqname);
  6076. const char *wuid = p->queryName();
  6077. void *qi = qs->getQ(curqname.str(),wuid);
  6078. if (!qi)
  6079. return false;
  6080. setClusterName(cluster);
  6081. SCMStringBuffer newqname;
  6082. newci->getThorQueue(newqname);
  6083. qs->putQ(newqname.str(),wuid,qi);
  6084. return true;
  6085. }
  6086. //=================================================================================================
  6087. IPropertyTree *CLocalWorkUnit::getUnpackedTree(bool includeProgress) const
  6088. {
  6089. Owned<IPropertyTree> ret = createPTreeFromIPT(p);
  6090. Owned<IConstWUGraphIterator> graphIter = &getGraphs(GraphTypeAny);
  6091. ForEach(*graphIter)
  6092. {
  6093. IConstWUGraph &graph = graphIter->query();
  6094. Owned<IPropertyTree> graphTree = graph.getXGMMLTree(includeProgress);
  6095. SCMStringBuffer gName;
  6096. graph.getName(gName);
  6097. StringBuffer xpath("Graphs/Graph[@name=\"");
  6098. xpath.append(gName.s).append("\"]/xgmml");
  6099. IPropertyTree *xgmml = ret->queryPropTree(xpath.str());
  6100. if (xgmml) // don't know of any reason it shouldn't exist
  6101. {
  6102. xgmml->removeProp("graphBin");
  6103. xgmml->setPropTree("graph", graphTree.getClear());
  6104. }
  6105. }
  6106. return ret.getClear();
  6107. }
  6108. void CLocalWorkUnit::loadGraphs() const
  6109. {
  6110. CriticalBlock block(crit);
  6111. if (!cachedGraphs.get())
  6112. {
  6113. MemoryBuffer buf;
  6114. IPropertyTree *t = p->queryPropTree("PackedGraphs");
  6115. if (t&&t->getPropBin(NULL,buf)) {
  6116. cachedGraphs.setown(createPTree(buf));
  6117. }
  6118. else
  6119. cachedGraphs.set(p->queryPropTree("Graphs"));
  6120. if (cachedGraphs.get())
  6121. {
  6122. Owned<IPropertyTreeIterator> iter = cachedGraphs->getElements("Graph");
  6123. ForEach(*iter)
  6124. {
  6125. IPropertyTree &graph = iter->query();
  6126. graphs.append(*new CLocalWUGraph(*this, LINK(&graph)));
  6127. }
  6128. }
  6129. }
  6130. }
  6131. mapEnums graphTypes[] = {
  6132. { GraphTypeAny, "unknown" },
  6133. { GraphTypeProgress, "progress" },
  6134. { GraphTypeEcl, "ECL" },
  6135. { GraphTypeActivities, "activities" },
  6136. { GraphTypeSubProgress, "subgraph" },
  6137. { GraphTypeSize, NULL },
  6138. };
  6139. CLocalWUGraph::CLocalWUGraph(const CLocalWorkUnit &_owner, IPropertyTree *props) : p(props), owner(_owner)
  6140. {
  6141. SCMStringBuffer str;
  6142. owner.getWuid(str);
  6143. wuid.set(str.s.str());
  6144. wuidVersion = owner.getWuidVersion();
  6145. }
  6146. IStringVal& CLocalWUGraph::getName(IStringVal &str) const
  6147. {
  6148. str.set(p->queryProp("@name"));
  6149. return str;
  6150. }
  6151. IStringVal& CLocalWUGraph::getLabel(IStringVal &str) const
  6152. {
  6153. if (wuidVersion >= 2)
  6154. {
  6155. str.set(p->queryProp("@label"));
  6156. return str;
  6157. }
  6158. else
  6159. {
  6160. Owned<IPropertyTree> xgmml = getXGMMLTree(false);
  6161. str.set(xgmml->queryProp("@label"));
  6162. return str;
  6163. }
  6164. }
  6165. IStringVal& CLocalWUGraph::getXGMML(IStringVal &str, bool mergeProgress) const
  6166. {
  6167. Owned<IPropertyTree> xgmml = getXGMMLTree(mergeProgress);
  6168. if (xgmml)
  6169. {
  6170. StringBuffer x;
  6171. toXML(xgmml, x);
  6172. str.set(x.str());
  6173. }
  6174. return str;
  6175. }
  6176. unsigned CLocalWorkUnit::getGraphCount() const
  6177. {
  6178. CriticalBlock block(crit);
  6179. if (p->hasProp("Graphs"))
  6180. {
  6181. return p->queryPropTree("Graphs")->numChildren();
  6182. }
  6183. return 0;
  6184. }
  6185. unsigned CLocalWorkUnit::getSourceFileCount() const
  6186. {
  6187. CriticalBlock block(crit);
  6188. if (p->hasProp("FilesRead"))
  6189. {
  6190. return p->queryPropTree("FilesRead")->numChildren();
  6191. }
  6192. return 0;
  6193. }
  6194. unsigned CLocalWorkUnit::getResultCount() const
  6195. {
  6196. CriticalBlock block(crit);
  6197. if (p->hasProp("Results"))
  6198. {
  6199. return p->queryPropTree("Results")->numChildren();
  6200. }
  6201. return 0;
  6202. }
  6203. unsigned CLocalWorkUnit::getVariableCount() const
  6204. {
  6205. CriticalBlock block(crit);
  6206. if (p->hasProp("Variables"))
  6207. {
  6208. return p->queryPropTree("Variables")->numChildren();
  6209. }
  6210. return 0;
  6211. }
  6212. unsigned CLocalWorkUnit::getTimerCount() const
  6213. {
  6214. CriticalBlock block(crit);
  6215. if (p->hasProp("Statistics"))
  6216. {
  6217. Owned<IPropertyTreeIterator> iter = p->getElements("Statistics/Statistic[@unit=\"ns\"]");
  6218. unsigned cnt =0;
  6219. if (iter)
  6220. {
  6221. ForEach(*iter)
  6222. cnt++;
  6223. }
  6224. return cnt;
  6225. }
  6226. if (p->hasProp("Timings"))
  6227. return p->queryPropTree("Timings")->numChildren();
  6228. return 0;
  6229. }
  6230. unsigned CLocalWorkUnit::getApplicationValueCount() const
  6231. {
  6232. CriticalBlock block(crit);
  6233. if (p->hasProp("Application"))
  6234. {
  6235. return p->queryPropTree("Application")->numChildren();
  6236. }
  6237. return 0;
  6238. }
  6239. IStringVal &CLocalWorkUnit::getXmlParams(IStringVal &str) const
  6240. {
  6241. CriticalBlock block(crit);
  6242. IPropertyTree *paramTree = p->queryPropTree("Parameters");
  6243. if (paramTree)
  6244. {
  6245. StringBuffer temp;
  6246. toXML(paramTree, temp);
  6247. str.set(temp.str());
  6248. }
  6249. return str;
  6250. }
  6251. const IPropertyTree *CLocalWorkUnit::getXmlParams() const
  6252. {
  6253. CriticalBlock block(crit);
  6254. return p->getPropTree("Parameters");
  6255. }
  6256. void CLocalWorkUnit::setXmlParams(const char *params)
  6257. {
  6258. CriticalBlock block(crit);
  6259. p->setPropTree("Parameters", createPTreeFromXMLString(params));
  6260. }
  6261. void CLocalWorkUnit::setXmlParams(IPropertyTree *tree)
  6262. {
  6263. CriticalBlock block(crit);
  6264. p->setPropTree("Parameters", tree);
  6265. }
  6266. unsigned __int64 CLocalWorkUnit::getHash() const
  6267. {
  6268. CriticalBlock block(crit);
  6269. return p->getPropInt64("@hash");
  6270. }
  6271. void CLocalWorkUnit::setHash(unsigned __int64 hash)
  6272. {
  6273. CriticalBlock block(crit);
  6274. p->setPropInt64("@hash", hash);
  6275. }
  6276. IConstWUGraphIterator& CLocalWorkUnit::getGraphs(WUGraphType type) const
  6277. {
  6278. CriticalBlock block(crit);
  6279. loadGraphs();
  6280. IConstWUGraphIterator *giter = new CArrayIteratorOf<IConstWUGraph,IConstWUGraphIterator> (graphs, 0, (IConstWorkUnit *) this);
  6281. if (type!=GraphTypeAny) {
  6282. class CConstWUGraphIterator: public CInterface, implements IConstWUGraphIterator
  6283. {
  6284. WUGraphType type;
  6285. Owned<IConstWUGraphIterator> base;
  6286. bool match()
  6287. {
  6288. return base->query().getType()==type;
  6289. }
  6290. public:
  6291. IMPLEMENT_IINTERFACE;
  6292. CConstWUGraphIterator(IConstWUGraphIterator *_base,WUGraphType _type)
  6293. : base(_base)
  6294. {
  6295. type = _type;
  6296. }
  6297. bool first()
  6298. {
  6299. if (!base->first())
  6300. return false;
  6301. if (match())
  6302. return true;
  6303. return next();
  6304. }
  6305. bool next()
  6306. {
  6307. while (base->next())
  6308. if (match())
  6309. return true;
  6310. return false;
  6311. }
  6312. virtual bool isValid()
  6313. {
  6314. return base->isValid();
  6315. }
  6316. IConstWUGraph & query()
  6317. {
  6318. return base->query();
  6319. }
  6320. };
  6321. giter = new CConstWUGraphIterator(giter,type);
  6322. }
  6323. return *giter;
  6324. }
  6325. IConstWUGraph* CLocalWorkUnit::getGraph(const char *qname) const
  6326. {
  6327. CriticalBlock block(crit);
  6328. loadGraphs();
  6329. ForEachItemIn(idx, graphs)
  6330. {
  6331. SCMStringBuffer name;
  6332. IConstWUGraph &cur = graphs.item(idx);
  6333. cur.getName(name);
  6334. if (stricmp(name.str(), qname)==0)
  6335. {
  6336. cur.Link();
  6337. return &cur;
  6338. }
  6339. }
  6340. return NULL;
  6341. }
  6342. IWUGraph* CLocalWorkUnit::createGraph()
  6343. {
  6344. // For this to be legally called, we must have the write-able interface. So we are already locked for write.
  6345. CriticalBlock block(crit);
  6346. ensureGraphsUnpacked();
  6347. loadGraphs();
  6348. if (!graphs.length())
  6349. p->addPropTree("Graphs", createPTree("Graphs"));
  6350. IPropertyTree *r = p->queryPropTree("Graphs");
  6351. IPropertyTree *s = r->addPropTree("Graph", createPTree());
  6352. s->Link();
  6353. IWUGraph* q = new CLocalWUGraph(*this, s);
  6354. q->Link();
  6355. graphs.append(*q);
  6356. return q;
  6357. }
  6358. IWUGraph * CLocalWorkUnit::updateGraph(const char * name)
  6359. {
  6360. CriticalBlock block(crit);
  6361. ensureGraphsUnpacked();
  6362. IConstWUGraph *existing = getGraph(name);
  6363. if (existing)
  6364. return (IWUGraph *) existing;
  6365. IWUGraph * q = createGraph();
  6366. q->setName(name);
  6367. return q;
  6368. }
  6369. IConstWUGraphProgress *CLocalWorkUnit::getGraphProgress(const char *name) const
  6370. {
  6371. CriticalBlock block(crit);
  6372. return new CConstGraphProgress(p->queryName(), name);
  6373. }
  6374. IStringVal& CLocalWUGraph::getDOT(IStringVal &str) const
  6375. {
  6376. UNIMPLEMENTED;
  6377. }
  6378. void CLocalWUGraph::setName(const char *str)
  6379. {
  6380. p->setProp("@name", str);
  6381. progress.clear();
  6382. progress.setown(new CConstGraphProgress(wuid, str));
  6383. }
  6384. void CLocalWUGraph::setLabel(const char *str)
  6385. {
  6386. p->setProp("@label", str);
  6387. }
  6388. void CLocalWUGraph::setXGMML(const char *str)
  6389. {
  6390. setXGMMLTree(createPTreeFromXMLString(str));
  6391. }
  6392. void CLocalWUGraph::setXGMMLTree(IPropertyTree *_graph, bool compress)
  6393. {
  6394. assertex(strcmp(_graph->queryName(), "graph")==0);
  6395. IPropertyTree *xgmml = p->setPropTree("xgmml", createPTree());
  6396. if (compress)
  6397. {
  6398. MemoryBuffer mb;
  6399. _graph->serialize(mb);
  6400. xgmml->setPropBin("graphBin", mb.length(), mb.toByteArray());
  6401. graph.setown(_graph);
  6402. }
  6403. else
  6404. xgmml->setPropTree("graph", _graph);
  6405. }
  6406. void CLocalWUGraph::mergeProgress(IPropertyTree &rootNode, IPropertyTree &progressTree, const unsigned &progressV) const
  6407. {
  6408. IPropertyTree *graphNode = rootNode.queryPropTree("att/graph");
  6409. if (!graphNode) return;
  6410. unsigned nodeId = rootNode.getPropInt("@id");
  6411. StringBuffer progressNodePath("node[@id=\"");
  6412. progressNodePath.append(nodeId).append("\"]");
  6413. IPropertyTree *progressNode = progressTree.queryPropTree(progressNodePath.str());
  6414. if (progressNode)
  6415. {
  6416. Owned<IPropertyTreeIterator> edges = progressNode->getElements("edge");
  6417. ForEach (*edges)
  6418. {
  6419. IPropertyTree &edge = edges->query();
  6420. StringBuffer edgePath("edge[@id=\"");
  6421. edgePath.append(edge.queryProp("@id")).append("\"]");
  6422. IPropertyTree *graphEdge = graphNode->queryPropTree(edgePath.str());
  6423. if (graphEdge)
  6424. {
  6425. if (progressV < 1)
  6426. mergePTree(graphEdge, &edge);
  6427. else
  6428. { // must translate to XGMML format
  6429. Owned<IAttributeIterator> aIter = edge.getAttributes();
  6430. ForEach (*aIter)
  6431. {
  6432. const char *aName = aIter->queryName()+1;
  6433. if (0 != stricmp("id", aName)) // "id" reserved.
  6434. {
  6435. IPropertyTree *att = graphEdge->addPropTree("att", createPTree());
  6436. att->setProp("@name", aName);
  6437. att->setProp("@value", aIter->queryValue());
  6438. }
  6439. }
  6440. // This is really only here, so that our progress format can use non-attribute values, which have different efficiency qualifies (e.g. can be external by dali)
  6441. Owned<IPropertyTreeIterator> iter = edge.getElements("*");
  6442. ForEach (*iter)
  6443. {
  6444. IPropertyTree &t = iter->query();
  6445. IPropertyTree *att = graphEdge->addPropTree("att", createPTree());
  6446. att->setProp("@name", t.queryName());
  6447. att->setProp("@value", t.queryProp(NULL));
  6448. }
  6449. }
  6450. }
  6451. }
  6452. Owned<IPropertyTreeIterator> nodes = progressNode->getElements("node");
  6453. ForEach (*nodes)
  6454. {
  6455. IPropertyTree &node = nodes->query();
  6456. StringBuffer nodePath("node[@id=\"");
  6457. nodePath.append(node.queryProp("@id")).append("\"]");
  6458. IPropertyTree *_node = graphNode->queryPropTree(nodePath.str());
  6459. if (_node)
  6460. {
  6461. if (progressV < 1)
  6462. mergePTree(_node, &node);
  6463. else
  6464. { // must translate to XGMML format
  6465. Owned<IAttributeIterator> aIter = node.getAttributes();
  6466. ForEach (*aIter)
  6467. {
  6468. const char *aName = aIter->queryName()+1;
  6469. if (0 != stricmp("id", aName)) // "id" reserved.
  6470. {
  6471. IPropertyTree *att = _node->addPropTree("att", createPTree());
  6472. att->setProp("@name", aName);
  6473. att->setProp("@value", aIter->queryValue());
  6474. }
  6475. }
  6476. }
  6477. }
  6478. }
  6479. }
  6480. Owned<IPropertyTreeIterator> iter = graphNode->getElements("node");
  6481. ForEach (*iter)
  6482. mergeProgress(iter->query(), progressTree, progressV);
  6483. }
  6484. IPropertyTree * CLocalWUGraph::getXGMMLTreeRaw() const
  6485. {
  6486. return p->getPropTree("xgmml");
  6487. }
  6488. IPropertyTree * CLocalWUGraph::getXGMMLTree(bool doMergeProgress) const
  6489. {
  6490. if (!graph)
  6491. {
  6492. // NB: although graphBin introduced in wuidVersion==2,
  6493. // daliadmin can retrospectively compress existing graphs, so need to check for all versions
  6494. MemoryBuffer mb;
  6495. if (p->getPropBin("xgmml/graphBin", mb))
  6496. graph.setown(createPTree(mb));
  6497. else
  6498. graph.setown(p->getBranch("xgmml/graph"));
  6499. if (!graph)
  6500. return NULL;
  6501. }
  6502. if (!doMergeProgress)
  6503. return graph.getLink();
  6504. else
  6505. {
  6506. Owned<IPropertyTree> copy = createPTreeFromIPT(graph);
  6507. Owned<IConstWUGraphProgress> _progress;
  6508. if (progress) _progress.set(progress);
  6509. else
  6510. _progress.setown(new CConstGraphProgress(wuid, p->queryProp("@name")));
  6511. unsigned progressV = _progress->queryFormatVersion();
  6512. IPropertyTree *progressTree = _progress->queryProgressTree();
  6513. Owned<IPropertyTreeIterator> nodeIterator = copy->getElements("node");
  6514. ForEach (*nodeIterator)
  6515. mergeProgress(nodeIterator->query(), *progressTree, progressV);
  6516. return copy.getClear();
  6517. }
  6518. }
  6519. bool CLocalWUGraph::isValid() const
  6520. {
  6521. // JCSMORE - I can't really see why this is necessary, a graph cannot be empty.
  6522. return p->hasProp("xgmml/graph/node") || p->hasProp("xgmml/graphBin");
  6523. }
  6524. WUGraphType CLocalWUGraph::getType() const
  6525. {
  6526. return (WUGraphType) getEnum(p, "@type", graphTypes);
  6527. }
  6528. IStringVal & CLocalWUGraph::getTypeName(IStringVal &str) const
  6529. {
  6530. str.set(p->queryProp("@type"));
  6531. if (!str.length())
  6532. str.set("unknown");
  6533. return str;
  6534. }
  6535. void CLocalWUGraph::setType(WUGraphType _type)
  6536. {
  6537. setEnum(p, "@type", _type, graphTypes);
  6538. }
  6539. //=================================================================================================
  6540. mapEnums queryFileTypes[] = {
  6541. { FileTypeCpp, "cpp" },
  6542. { FileTypeDll, "dll" },
  6543. { FileTypeResText, "res" },
  6544. { FileTypeHintXml, "hint" },
  6545. { FileTypeXml, "xml" },
  6546. { FileTypeSize, NULL },
  6547. };
  6548. CLocalWUAssociated::CLocalWUAssociated(IPropertyTree *props) : p(props)
  6549. {
  6550. }
  6551. WUFileType CLocalWUAssociated::getType() const
  6552. {
  6553. return (WUFileType)getEnum(p, "@type", queryFileTypes);
  6554. }
  6555. IStringVal & CLocalWUAssociated::getDescription(IStringVal & str) const
  6556. {
  6557. str.set(p->queryProp("@desc"));
  6558. return str;
  6559. }
  6560. IStringVal & CLocalWUAssociated::getIp(IStringVal & str) const
  6561. {
  6562. str.set(p->queryProp("@ip"));
  6563. return str;
  6564. }
  6565. IStringVal & CLocalWUAssociated::getName(IStringVal & str) const
  6566. {
  6567. str.set(p->queryProp("@filename"));
  6568. return str;
  6569. }
  6570. IStringVal & CLocalWUAssociated::getNameTail(IStringVal & str) const
  6571. {
  6572. str.set(pathTail(p->queryProp("@filename")));
  6573. return str;
  6574. }
  6575. unsigned CLocalWUAssociated::getCrc() const
  6576. {
  6577. return p->getPropInt("@crc", 0);
  6578. }
  6579. //=================================================================================================
  6580. CLocalWUQuery::CLocalWUQuery(IPropertyTree *props) : p(props)
  6581. {
  6582. associatedCached = false;
  6583. }
  6584. mapEnums queryTypes[] = {
  6585. { QueryTypeUnknown, "unknown" },
  6586. { QueryTypeEcl, "ECL" },
  6587. { QueryTypeSql, "SQL" },
  6588. { QueryTypeXml, "XML" },
  6589. { QueryTypeAttribute, "Attribute" },
  6590. { QueryTypeSize, NULL },
  6591. };
  6592. WUQueryType CLocalWUQuery::getQueryType() const
  6593. {
  6594. return (WUQueryType) getEnum(p, "@type", queryTypes);
  6595. }
  6596. void CLocalWUQuery::setQueryType(WUQueryType qt)
  6597. {
  6598. setEnum(p, "@type", qt, queryTypes);
  6599. }
  6600. IStringVal& CLocalWUQuery::getQueryText(IStringVal &str) const
  6601. {
  6602. str.set(p->queryProp("Text"));
  6603. return str;
  6604. }
  6605. IStringVal& CLocalWUQuery::getQueryShortText(IStringVal &str) const
  6606. {
  6607. const char * text = p->queryProp("Text");
  6608. if (isArchiveQuery(text))
  6609. {
  6610. Owned<IPropertyTree> xml = createPTreeFromXMLString(text, ipt_caseInsensitive);
  6611. const char * path = xml->queryProp("Query/@attributePath");
  6612. if (path)
  6613. {
  6614. IPropertyTree * resolved = resolveDefinitionInArchive(xml, path);
  6615. if (resolved)
  6616. str.set(resolved->queryProp(NULL));
  6617. }
  6618. else
  6619. str.set(xml->queryProp("Query"));
  6620. }
  6621. else
  6622. str.set(text);
  6623. return str;
  6624. }
  6625. IStringVal& CLocalWUQuery::getQueryName(IStringVal &str) const
  6626. {
  6627. str.set(p->queryProp("@name"));
  6628. return str;
  6629. }
  6630. IStringVal & CLocalWUQuery::getQueryMainDefinition(IStringVal & str) const
  6631. {
  6632. str.set(p->queryProp("@main"));
  6633. return str;
  6634. }
  6635. IStringVal& CLocalWUQuery::getQueryDllName(IStringVal &str) const
  6636. {
  6637. Owned<IConstWUAssociatedFile> entry = getAssociatedFile(FileTypeDll, 0);
  6638. if (entry)
  6639. entry->getNameTail(str);
  6640. return str;
  6641. }
  6642. IStringVal& CLocalWUQuery::getQueryCppName(IStringVal &str) const
  6643. {
  6644. Owned<IConstWUAssociatedFile> entry = getAssociatedFile(FileTypeCpp, 0);
  6645. if (entry)
  6646. entry->getName(str);
  6647. return str;
  6648. }
  6649. IStringVal& CLocalWUQuery::getQueryResTxtName(IStringVal &str) const
  6650. {
  6651. Owned<IConstWUAssociatedFile> entry = getAssociatedFile(FileTypeResText, 0);
  6652. if (entry)
  6653. entry->getName(str);
  6654. return str;
  6655. }
  6656. unsigned CLocalWUQuery::getQueryDllCrc() const
  6657. {
  6658. Owned<IConstWUAssociatedFile> entry = getAssociatedFile(FileTypeDll, 0);
  6659. if (entry)
  6660. return entry->getCrc();
  6661. return 0;
  6662. }
  6663. void CLocalWUQuery::setQueryText(const char *text)
  6664. {
  6665. p->setProp("Text", text);
  6666. }
  6667. void CLocalWUQuery::setQueryName(const char *qname)
  6668. {
  6669. p->setProp("@name", qname);
  6670. }
  6671. void CLocalWUQuery::setQueryMainDefinition(const char * str)
  6672. {
  6673. p->setProp("@main", str);
  6674. }
  6675. void CLocalWUQuery::addAssociatedFile(WUFileType type, const char * name, const char * ip, const char * desc, unsigned crc)
  6676. {
  6677. CriticalBlock block(crit);
  6678. loadAssociated();
  6679. if (!associated.length())
  6680. p->addPropTree("Associated", createPTree("Associated"));
  6681. IPropertyTree *pl = p->queryPropTree("Associated");
  6682. IPropertyTree *s = pl->addPropTree("File", createPTree("File"));
  6683. setEnum(s, "@type", type, queryFileTypes);
  6684. s->setProp("@filename", name);
  6685. s->setProp("@ip", ip);
  6686. s->setProp("@desc", desc);
  6687. if (crc)
  6688. s->setPropInt("@crc", crc);
  6689. IConstWUAssociatedFile * q = new CLocalWUAssociated(LINK(s));
  6690. associated.append(*q);
  6691. }
  6692. void CLocalWUQuery::removeAssociatedFiles()
  6693. {
  6694. associatedCached = false;
  6695. associated.kill();
  6696. p->removeProp("Associated");
  6697. }
  6698. IConstWUAssociatedFile * CLocalWUQuery::getAssociatedFile(WUFileType type, unsigned index) const
  6699. {
  6700. CriticalBlock block(crit);
  6701. loadAssociated();
  6702. ForEachItemIn(idx, associated)
  6703. {
  6704. CLocalWUAssociated &cur = static_cast<CLocalWUAssociated &>(associated.item(idx));
  6705. if (cur.getType() == type)
  6706. {
  6707. if (index-- == 0)
  6708. return &OLINK(cur);
  6709. }
  6710. }
  6711. return NULL;
  6712. }
  6713. void CLocalWUQuery::addSpecialCaseAssociated(WUFileType type, const char * propname, unsigned crc) const
  6714. {
  6715. const char * name = p->queryProp(propname);
  6716. if (name)
  6717. {
  6718. IPropertyTree *s = createPTree("File");
  6719. setEnum(s, "@type", type, queryFileTypes);
  6720. s->setProp("@filename", name);
  6721. if (crc)
  6722. s->setPropInt("@crc", crc);
  6723. associated.append(*new CLocalWUAssociated(s));
  6724. }
  6725. }
  6726. void CLocalWUQuery::loadAssociated() const
  6727. {
  6728. CriticalBlock block(crit);
  6729. if (!associatedCached)
  6730. {
  6731. assertex(associated.length() == 0);
  6732. addSpecialCaseAssociated(FileTypeDll, "DllName", p->getPropInt("DllCrc", 0));
  6733. addSpecialCaseAssociated(FileTypeCpp, "CppName", 0);
  6734. addSpecialCaseAssociated(FileTypeResText, "ResTxtName", 0);
  6735. Owned<IPropertyTreeIterator> r = p->getElements("Associated/File");
  6736. for (r->first(); r->isValid(); r->next())
  6737. {
  6738. IPropertyTree *rp = &r->query();
  6739. rp->Link();
  6740. associated.append(*new CLocalWUAssociated(rp));
  6741. }
  6742. associatedCached = true;
  6743. }
  6744. }
  6745. IConstWUAssociatedFileIterator& CLocalWUQuery::getAssociatedFiles() const
  6746. {
  6747. CriticalBlock block(crit);
  6748. loadAssociated();
  6749. return *new CArrayIteratorOf<IConstWUAssociatedFile,IConstWUAssociatedFileIterator> (associated, 0, (IConstWUQuery *) this);
  6750. }
  6751. //========================================================================================
  6752. CLocalWUWebServicesInfo::CLocalWUWebServicesInfo(IPropertyTree *props) : p(props)
  6753. {
  6754. }
  6755. IStringVal& CLocalWUWebServicesInfo::getModuleName(IStringVal &str) const
  6756. {
  6757. str.set(p->queryProp("@module"));
  6758. return str;
  6759. }
  6760. IStringVal& CLocalWUWebServicesInfo::getAttributeName(IStringVal &str) const
  6761. {
  6762. str.set(p->queryProp("@attribute"));
  6763. return str;
  6764. }
  6765. IStringVal& CLocalWUWebServicesInfo::getDefaultName(IStringVal &str) const
  6766. {
  6767. str.set(p->queryProp("@defaultName"));
  6768. return str;
  6769. }
  6770. unsigned CLocalWUWebServicesInfo::getWebServicesCRC() const
  6771. {
  6772. return (unsigned) p->getPropInt("@crc");
  6773. }
  6774. IStringVal& CLocalWUWebServicesInfo::getInfo(const char *name, IStringVal &str) const
  6775. {
  6776. if (!name)
  6777. {
  6778. StringBuffer ws_info;
  6779. ws_info.appendf("<%s ", p->queryName());
  6780. Owned<IAttributeIterator> attrs = p->getAttributes();
  6781. for(attrs->first(); attrs->isValid(); attrs->next())
  6782. {
  6783. const char *name = attrs->queryName()+1;
  6784. const char *value = attrs->queryValue();
  6785. ws_info.appendf("%s='%s' ", name, value);
  6786. }
  6787. ws_info.append("> \n");
  6788. Owned<IPropertyTreeIterator> info = p->getElements("*");
  6789. ForEach(*info)
  6790. {
  6791. IPropertyTree &item = info->query();
  6792. const char *name = item.queryName();
  6793. if (name)
  6794. {
  6795. MemoryBuffer mb;
  6796. bool isbin = p->isBinary(name);
  6797. if (isbin)
  6798. {
  6799. p->getPropBin(name,mb);
  6800. if (mb.length())
  6801. {
  6802. unsigned len = 0;
  6803. mb.read(len);
  6804. StringBuffer encodedString;
  6805. StringBuffer val(len, (const char *) mb.readDirect(len));
  6806. encodeXML(val, encodedString);
  6807. ws_info.appendf("<%s>%s</%s>", name, encodedString.str(), name);
  6808. }
  6809. }
  6810. else
  6811. {
  6812. StringBuffer tmp;
  6813. toXML(&item, tmp);
  6814. ws_info.append(tmp.str());
  6815. }
  6816. }
  6817. }
  6818. ws_info.appendf("</%s>", p->queryName());
  6819. str.setLen(ws_info.str(), ws_info.length());
  6820. }
  6821. else
  6822. {
  6823. MemoryBuffer mb;
  6824. p->getPropBin(name,mb);
  6825. if (mb.length())
  6826. {
  6827. unsigned len;
  6828. mb.read(len);
  6829. str.setLen((const char *) mb.readDirect(len), len);
  6830. }
  6831. }
  6832. return str;
  6833. }
  6834. void CLocalWUWebServicesInfo::setModuleName(const char *mname)
  6835. {
  6836. p->setProp("@module", mname);
  6837. }
  6838. void CLocalWUWebServicesInfo::setAttributeName(const char *aname)
  6839. {
  6840. p->setProp("@attribute", aname);
  6841. }
  6842. void CLocalWUWebServicesInfo::setDefaultName(const char *dname)
  6843. {
  6844. p->setProp("@defaultName", dname);
  6845. }
  6846. void CLocalWUWebServicesInfo::setWebServicesCRC(unsigned crc)
  6847. {
  6848. p->setPropInt("@crc", crc);
  6849. }
  6850. void CLocalWUWebServicesInfo::setInfo(const char *name, const char *info)
  6851. {
  6852. MemoryBuffer m;
  6853. unsigned len = (size32_t)strlen(info);
  6854. serializeLPString(len, info, m);
  6855. p->setPropBin(name, m.length(), m.toByteArray());
  6856. }
  6857. //========================================================================================
  6858. CLocalWURoxieQueryInfo::CLocalWURoxieQueryInfo(IPropertyTree *props) : p(props)
  6859. {
  6860. }
  6861. IStringVal& CLocalWURoxieQueryInfo::getQueryInfo(IStringVal &str) const
  6862. {
  6863. IPropertyTree *queryTree = p->queryPropTree("query");
  6864. if (queryTree)
  6865. {
  6866. StringBuffer temp;
  6867. toXML(queryTree, temp);
  6868. str.set(temp.str());
  6869. }
  6870. return str;
  6871. }
  6872. IStringVal& CLocalWURoxieQueryInfo::getDefaultPackageInfo(IStringVal &str) const
  6873. {
  6874. MemoryBuffer mb;
  6875. p->getPropBin("RoxiePackages",mb);
  6876. if (mb.length())
  6877. {
  6878. unsigned len;
  6879. mb.read(len);
  6880. str.setLen((const char *) mb.readDirect(len), len);
  6881. }
  6882. return str;
  6883. }
  6884. IStringVal& CLocalWURoxieQueryInfo::getRoxieClusterName(IStringVal &str) const
  6885. {
  6886. const char *val = p->queryProp("@roxieClusterName");
  6887. if (val)
  6888. str.set(val);
  6889. return str;
  6890. }
  6891. IStringVal& CLocalWURoxieQueryInfo::getWuid(IStringVal &str) const
  6892. {
  6893. const char *val = p->queryProp("@wuid");
  6894. if (val)
  6895. str.set(val);
  6896. return str;
  6897. }
  6898. void CLocalWURoxieQueryInfo::setQueryInfo(const char *info)
  6899. {
  6900. IPropertyTree *queryTree = p->queryPropTree("query");
  6901. if (queryTree)
  6902. p->removeTree(queryTree);
  6903. IPropertyTree * tempTree = p->addPropTree("query", createPTreeFromXMLString(info));
  6904. if (!p->hasProp("@roxieClusterName"))
  6905. {
  6906. const char *roxieClusterName = tempTree->queryProp("@roxieName");
  6907. if (roxieClusterName && *roxieClusterName)
  6908. p->addProp("@roxieClusterName", roxieClusterName);
  6909. }
  6910. if (!p->hasProp("@wuid"))
  6911. {
  6912. const char *wuid = tempTree->queryProp("Query/@wuid");
  6913. if (wuid && *wuid)
  6914. p->addProp("@wuid", wuid);
  6915. }
  6916. }
  6917. void CLocalWURoxieQueryInfo::setDefaultPackageInfo(const char *info, int len)
  6918. {
  6919. MemoryBuffer m;
  6920. serializeLPString(len, info, m);
  6921. p->setPropBin("RoxiePackages", m.length(), m.toByteArray());
  6922. }
  6923. void CLocalWURoxieQueryInfo::setRoxieClusterName(const char *info)
  6924. {
  6925. p->setProp("@roxieClusterName", info);
  6926. }
  6927. void CLocalWURoxieQueryInfo::setWuid(const char *info)
  6928. {
  6929. p->setProp("@wuid", info);
  6930. }
  6931. //========================================================================================
  6932. CLocalWUResult::CLocalWUResult(IPropertyTree *props) : p(props)
  6933. {
  6934. }
  6935. mapEnums resultStatuses[] = {
  6936. { ResultStatusUndefined, "undefined" },
  6937. { ResultStatusCalculated, "calculated" },
  6938. { ResultStatusSupplied, "supplied" },
  6939. { ResultStatusFailed, "failed" },
  6940. { ResultStatusPartial, "partial" },
  6941. { ResultStatusSize, NULL }
  6942. };
  6943. WUResultStatus CLocalWUResult::getResultStatus() const
  6944. {
  6945. return (WUResultStatus ) getEnum(p, "@status", resultStatuses);
  6946. }
  6947. IStringVal& CLocalWUResult::getResultName(IStringVal &str) const
  6948. {
  6949. str.set(p->queryProp("@name"));
  6950. return str;
  6951. }
  6952. int CLocalWUResult::getResultSequence() const
  6953. {
  6954. return p->getPropInt("@sequence", -1);
  6955. }
  6956. bool CLocalWUResult::isResultScalar() const
  6957. {
  6958. return p->getPropInt("@isScalar", 1) != 0;
  6959. }
  6960. bool findSize(int size, IntArray &sizes)
  6961. {
  6962. ForEachItemIn(idx, sizes)
  6963. {
  6964. if (sizes.item(idx)==size)
  6965. return true;
  6966. }
  6967. return false;
  6968. }
  6969. void CLocalWUResult::getSchema(TypeInfoArray &types, StringAttrArray &names, IStringVal * eclText) const
  6970. {
  6971. MemoryBuffer schema;
  6972. p->getPropBin("SchemaRaw", schema);
  6973. if (schema.length())
  6974. {
  6975. for (;;)
  6976. {
  6977. StringAttr name;
  6978. schema.read(name);
  6979. if (*schema.readDirect(0)==type_void)
  6980. break;
  6981. names.append(*new StringAttrItem(name));
  6982. types.append(*deserializeType(schema)); // MORE - nested records!
  6983. }
  6984. schema.skip(1);
  6985. if (schema.length() != schema.getPos())
  6986. {
  6987. unsigned eclLen;
  6988. schema.read(eclLen);
  6989. const char * schemaData = (const char *)schema.readDirect(eclLen);
  6990. if (eclText)
  6991. {
  6992. eclText->setLen(schemaData, eclLen);
  6993. if ((eclLen == 0) && names.ordinality())
  6994. {
  6995. const char * firstName = names.item(0).text;
  6996. StringBuffer temp;
  6997. temp.append("RECORD ");
  6998. types.item(0).getECLType(temp);
  6999. temp.append(" value{NAMED('").append(firstName).append("')}").append("; END;");
  7000. eclText->set(temp.str());
  7001. }
  7002. }
  7003. }
  7004. }
  7005. }
  7006. void readRow(StringBuffer &out, MemoryBuffer &in, TypeInfoArray &types, StringAttrArray &names)
  7007. {
  7008. ForEachItemIn(idx, types)
  7009. {
  7010. StringAttrItem &name = names.item(idx);
  7011. ITypeInfo &type = types.item(idx);
  7012. unsigned size = type.getSize();
  7013. switch(type.getTypeCode())
  7014. {
  7015. case type_data:
  7016. if (size==UNKNOWN_LENGTH)
  7017. {
  7018. if (in.remaining() < sizeof(int))
  7019. throw MakeStringException(WUERR_CorruptResult, "corrupt workunit information");
  7020. in.read(size);
  7021. }
  7022. outputXmlData(size, in.readDirect(size), name.text, out);
  7023. break;
  7024. case type_string:
  7025. if (size==UNKNOWN_LENGTH)
  7026. {
  7027. if (in.remaining() < sizeof(int))
  7028. throw MakeStringException(WUERR_CorruptResult, "corrupt workunit information");
  7029. in.read(size);
  7030. }
  7031. outputXmlString(size, (const char *) in.readDirect(size), name.text, out);
  7032. break;
  7033. case type_varstring:
  7034. {
  7035. if (size == UNKNOWN_LENGTH)
  7036. size = (size32_t)strlen((const char *) in.readDirect(0))+1;
  7037. const char * text = (const char *) in.readDirect(size);
  7038. outputXmlString((size32_t)strlen(text), text, name.text, out);
  7039. break;
  7040. }
  7041. case type_unicode:
  7042. {
  7043. unsigned len = type.getStringLen();
  7044. if (size==UNKNOWN_LENGTH)
  7045. in.read(len);
  7046. outputXmlUnicode(len, (UChar const *) in.readDirect(len*2), name.text, out);
  7047. }
  7048. break;
  7049. case type_utf8:
  7050. {
  7051. unsigned len = type.getStringLen();
  7052. if (size==UNKNOWN_LENGTH)
  7053. {
  7054. in.read(len);
  7055. size = rtlUtf8Size(len, in.readDirect(0));
  7056. }
  7057. outputXmlUtf8(len, (const char *) in.readDirect(size), name.text, out);
  7058. }
  7059. break;
  7060. case type_qstring:
  7061. {
  7062. unsigned len = type.getStringLen();
  7063. if (size==UNKNOWN_LENGTH)
  7064. in.read(len);
  7065. unsigned outlen;
  7066. char *outstr;
  7067. rtlQStrToStrX(outlen, outstr, len, (const char *) in.readDirect(rtlQStrSize(len)));
  7068. outputXmlString(outlen, outstr, name.text, out);
  7069. free(outstr);
  7070. break;
  7071. }
  7072. case type_int:
  7073. case type_swapint:
  7074. if (type.isSigned())
  7075. {
  7076. const unsigned char *raw = (const unsigned char *) in.readDirect(size);
  7077. unsigned __int64 cval8 = 0;
  7078. //MORE: I think this is wrong - swapped doesn't mean little/big/
  7079. if (type.isSwappedEndian())
  7080. {
  7081. unsigned idx = 0;
  7082. if (raw[idx] & 0x80)
  7083. cval8 = (__int64)-1;
  7084. while (size--)
  7085. cval8 = (cval8 << 8) | raw[idx++];
  7086. }
  7087. else
  7088. {
  7089. if (raw[size-1] & 0x80)
  7090. cval8 = (__int64)-1;
  7091. while (size--)
  7092. cval8 = (cval8 << 8) | raw[size];
  7093. }
  7094. outputXmlInt((__int64) cval8, name.text, out);
  7095. }
  7096. else
  7097. {
  7098. const unsigned char *raw = (const unsigned char *) in.readDirect(size);
  7099. unsigned __int64 cval8 = 0;
  7100. if (type.isSwappedEndian())
  7101. {
  7102. unsigned idx = 0;
  7103. while (size--)
  7104. cval8 = (cval8 << 8) | raw[idx++];
  7105. }
  7106. else
  7107. {
  7108. while (size--)
  7109. cval8 = (cval8 << 8) | raw[size];
  7110. }
  7111. outputXmlUInt(cval8, name.text, out);
  7112. }
  7113. break;
  7114. case type_boolean:
  7115. bool cvalb;
  7116. in.read(cvalb);
  7117. outputXmlBool(cvalb, name.text, out);
  7118. break;
  7119. case type_decimal:
  7120. if (type.isSigned())
  7121. outputXmlDecimal(in.readDirect(size), size, type.getPrecision(), name.text, out);
  7122. else
  7123. outputXmlUDecimal(in.readDirect(size), size, type.getPrecision(), name.text, out);
  7124. break;
  7125. case type_real:
  7126. double cvald;
  7127. switch(size)
  7128. {
  7129. case 4:
  7130. float cvalf;
  7131. in.read(cvalf);
  7132. cvald = cvalf;
  7133. break;
  7134. case 8:
  7135. in.read(cvald);
  7136. break;
  7137. }
  7138. outputXmlReal(cvald, name.text, out);
  7139. break;
  7140. default:
  7141. assertex(!"unexpected type in raw record");
  7142. break;
  7143. }
  7144. }
  7145. }
  7146. IStringVal& CLocalWUResult::getResultXml(IStringVal &str) const
  7147. {
  7148. TypeInfoArray types;
  7149. StringAttrArray names;
  7150. getSchema(types, names);
  7151. StringBuffer xml;
  7152. const char * name = p->queryProp("@name");
  7153. if (name)
  7154. xml.appendf("<Dataset name=\'%s\'>\n", name);
  7155. else
  7156. xml.append("<Dataset>\n");
  7157. if (p->hasProp("Value"))
  7158. {
  7159. MemoryBuffer raw;
  7160. p->getPropBin("Value", raw);
  7161. unsigned __int64 numrows = getResultRowCount();
  7162. while (numrows--)
  7163. {
  7164. xml.append(" <Row>");
  7165. readRow(xml, raw, types, names);
  7166. xml.append("</Row>\n");
  7167. }
  7168. }
  7169. else if (p->hasProp("xmlValue"))
  7170. {
  7171. xml.append(" <Row>");
  7172. appendXMLTag(xml, name, p->queryProp("xmlValue"));
  7173. xml.append("</Row>\n");
  7174. }
  7175. xml.append("</Dataset>\n");
  7176. str.set(xml.str());
  7177. return str;
  7178. }
  7179. IProperties *CLocalWUResult::queryXmlns()
  7180. {
  7181. CriticalBlock block(crit);
  7182. if (xmlns)
  7183. return xmlns;
  7184. xmlns.setown(createProperties());
  7185. Owned<IAttributeIterator> it = p->getAttributes();
  7186. unsigned prefixLen = strlen("@xmlns");
  7187. ForEach(*it)
  7188. {
  7189. const char *name = it->queryName();
  7190. if (!strncmp("@xmlns", name, prefixLen))
  7191. {
  7192. if (name[prefixLen]==':') //normal case
  7193. xmlns->setProp(name+prefixLen+1, it->queryValue());
  7194. else if (!name[prefixLen]) //special case, unprefixed namespace
  7195. xmlns->setProp("xmlns", it->queryValue());
  7196. }
  7197. }
  7198. return xmlns;
  7199. }
  7200. unsigned CLocalWUResult::getResultFetchSize() const
  7201. {
  7202. return p->getPropInt("fetchSize", 100);
  7203. }
  7204. __int64 CLocalWUResult::getResultTotalRowCount() const
  7205. {
  7206. return p->getPropInt64("totalRowCount", -1);
  7207. }
  7208. __int64 CLocalWUResult::getResultRowCount() const
  7209. {
  7210. return p->getPropInt64("rowCount", 0);
  7211. }
  7212. void CLocalWUResult::getResultDataset(IStringVal & ecl, IStringVal & defs) const
  7213. {
  7214. ecl.set(p->queryProp("datasetEcl"));
  7215. defs.set(p->queryProp("datasetEclDefs"));
  7216. }
  7217. IStringVal& CLocalWUResult::getResultLogicalName(IStringVal & val) const
  7218. {
  7219. val.set(p->queryProp("logicalName"));
  7220. return val;
  7221. }
  7222. IStringVal& CLocalWUResult::getResultKeyField(IStringVal & ecl) const
  7223. {
  7224. ecl.set(p->queryProp("keyField"));
  7225. return ecl;
  7226. }
  7227. unsigned CLocalWUResult::getResultRequestedRows() const
  7228. {
  7229. return p->getPropInt("requestedRows", 1);
  7230. }
  7231. IStringVal& CLocalWUResult::getResultEclSchema(IStringVal & str) const
  7232. {
  7233. TypeInfoArray types;
  7234. StringAttrArray names;
  7235. getSchema(types, names, &str);
  7236. return str;
  7237. }
  7238. IStringVal& CLocalWUResult::getResultRecordSizeEntry(IStringVal & str) const
  7239. {
  7240. str.set(p->queryProp("@recordSizeEntry"));
  7241. return str;
  7242. }
  7243. IStringVal& CLocalWUResult::getResultTransformerEntry(IStringVal & str) const
  7244. {
  7245. str.set(p->queryProp("@transformerEntry"));
  7246. return str;
  7247. }
  7248. __int64 CLocalWUResult::getResultRowLimit() const
  7249. {
  7250. return p->getPropInt64("@rowLimit");
  7251. }
  7252. IStringVal& CLocalWUResult::getResultFilename(IStringVal & str) const
  7253. {
  7254. str.set(p->queryProp("@tempFilename"));
  7255. return str;
  7256. }
  7257. void CLocalWUResult::setResultStatus(WUResultStatus status)
  7258. {
  7259. setEnum(p, "@status", status, resultStatuses);
  7260. if (status==ResultStatusUndefined)
  7261. p->removeProp("Value");
  7262. }
  7263. void CLocalWUResult::setResultName(const char *s)
  7264. {
  7265. p->setProp("@name", s);
  7266. }
  7267. void CLocalWUResult::setResultSequence(unsigned seq)
  7268. {
  7269. p->setPropInt("@sequence", seq);
  7270. }
  7271. void CLocalWUResult::setResultSchemaRaw(unsigned size, const void *schema)
  7272. {
  7273. p->setPropBin("SchemaRaw", size, schema);
  7274. }
  7275. void CLocalWUResult::setXmlns(const char *prefix, const char *uri)
  7276. {
  7277. StringBuffer xpath("@xmlns");
  7278. if (prefix && *prefix)
  7279. xpath.append(':').append(prefix);
  7280. p->setProp(xpath, uri);
  7281. }
  7282. void CLocalWUResult::setResultScalar(bool isScalar)
  7283. {
  7284. p->setPropInt("@isScalar", (int) isScalar);
  7285. if (isScalar)
  7286. setResultTotalRowCount(1);
  7287. }
  7288. void CLocalWUResult::setResultRaw(unsigned len, const void *data, WUResultFormat format)
  7289. {
  7290. p->setPropBin("Value", len, data);
  7291. setResultStatus(ResultStatusSupplied);
  7292. setResultFormat(format);
  7293. }
  7294. void CLocalWUResult::setResultFormat(WUResultFormat format)
  7295. {
  7296. switch (format)
  7297. {
  7298. case ResultFormatXml:
  7299. p->setProp("@format","xml");
  7300. break;
  7301. case ResultFormatXmlSet:
  7302. p->setProp("@format","xmlSet");
  7303. break;
  7304. case ResultFormatCsv:
  7305. p->setProp("@format","csv");
  7306. break;
  7307. default:
  7308. p->removeProp("@format");
  7309. break;
  7310. }
  7311. }
  7312. void CLocalWUResult::setResultXML(const char *val)
  7313. {
  7314. p->setProp("xmlValue", val);
  7315. }
  7316. void CLocalWUResult::addResultRaw(unsigned len, const void *data, WUResultFormat format)
  7317. {
  7318. p->appendPropBin("Value", len, data);
  7319. setResultStatus(ResultStatusPartial);
  7320. const char *existingFormat = p->queryProp("@format");
  7321. const char *formatStr = NULL;
  7322. switch (format)
  7323. {
  7324. case ResultFormatXml:
  7325. formatStr = "xml";
  7326. break;
  7327. case ResultFormatXmlSet:
  7328. formatStr = "xmlSet";
  7329. break;
  7330. case ResultFormatCsv:
  7331. formatStr = "csv";
  7332. break;
  7333. default:
  7334. p->removeProp("@format");
  7335. break;
  7336. }
  7337. if (format)
  7338. {
  7339. if (existingFormat)
  7340. {
  7341. if (0 != stricmp(formatStr, existingFormat))
  7342. throw MakeStringException(WUERR_ResultFormatMismatch, "addResult format %s, does not match existing format %s", formatStr, existingFormat);
  7343. }
  7344. else
  7345. p->setProp("@format", formatStr);
  7346. }
  7347. }
  7348. void CLocalWUResult::setResultFetchSize(unsigned rows)
  7349. {
  7350. p->setPropInt("fetchSize", rows);
  7351. }
  7352. void CLocalWUResult::setResultTotalRowCount(__int64 rows)
  7353. {
  7354. p->setPropInt64("totalRowCount", rows);
  7355. }
  7356. void CLocalWUResult::setResultRowCount(__int64 rows)
  7357. {
  7358. p->setPropInt64("rowCount", rows);
  7359. }
  7360. void CLocalWUResult::setResultDataset(const char *ecl, const char *defs)
  7361. {
  7362. p->setProp("datasetEcl", ecl);
  7363. p->setProp("datasetEclDefs", defs);
  7364. }
  7365. void CLocalWUResult::setResultLogicalName(const char *logicalName)
  7366. {
  7367. p->setProp("logicalName", logicalName);
  7368. }
  7369. void CLocalWUResult::setResultKeyField(const char *ecl)
  7370. {
  7371. p->setProp("keyField", ecl);
  7372. }
  7373. void CLocalWUResult::setResultRequestedRows(unsigned rows)
  7374. {
  7375. p->setPropInt("requestedRows", rows);
  7376. }
  7377. void CLocalWUResult::setResultRecordSizeEntry(const char * entry)
  7378. {
  7379. p->setProp("@recordSizeEntry", entry);
  7380. }
  7381. void CLocalWUResult::setResultTransformerEntry(const char * entry)
  7382. {
  7383. p->setProp("@transformerEntry", entry);
  7384. }
  7385. void CLocalWUResult::setResultRowLimit(__int64 value)
  7386. {
  7387. p->setPropInt64("@rowLimit", value);
  7388. }
  7389. void CLocalWUResult::setResultFilename(const char * name)
  7390. {
  7391. p->setProp("@tempFilename", name);
  7392. }
  7393. // MORE - it's an undetected error if we call getResult... of a type that does not match schema
  7394. __int64 CLocalWUResult::getResultInt() const
  7395. {
  7396. __int64 result = 0;
  7397. MemoryBuffer s;
  7398. p->getPropBin("Value", s);
  7399. if (s.length())
  7400. s.read(result);
  7401. else
  7402. result = p->getPropInt64("xmlValue");
  7403. return result;
  7404. }
  7405. bool CLocalWUResult::getResultBool() const
  7406. {
  7407. bool result = false;
  7408. MemoryBuffer s;
  7409. p->getPropBin("Value", s);
  7410. if (s.length())
  7411. s.read(result);
  7412. else
  7413. result = p->getPropBool("xmlValue");
  7414. return result;
  7415. }
  7416. double CLocalWUResult::getResultReal() const
  7417. {
  7418. double result = 0;
  7419. MemoryBuffer s;
  7420. p->getPropBin("Value", s);
  7421. if (s.length())
  7422. s.read(result);
  7423. else
  7424. {
  7425. const char *xmlVal = p->queryProp("xmlValue");
  7426. if (xmlVal)
  7427. result = atof(xmlVal);
  7428. }
  7429. return result;
  7430. }
  7431. void CLocalWUResult::getResultDecimal(void * val, unsigned len, unsigned precision, bool isSigned) const
  7432. {
  7433. MemoryBuffer s;
  7434. p->getPropBin("Value", s);
  7435. if (s.length())
  7436. {
  7437. assertex(s.length() == len);
  7438. s.read(len, val);
  7439. }
  7440. else
  7441. {
  7442. const char *xmlVal = p->queryProp("xmlValue");
  7443. if (xmlVal)
  7444. {
  7445. Decimal d;
  7446. d.setString(strlen(xmlVal), xmlVal);
  7447. if (isSigned)
  7448. d.getDecimal(len, precision, val);
  7449. else
  7450. d.getUDecimal(len, precision, val);
  7451. }
  7452. else
  7453. memset(val, 0, len);
  7454. }
  7455. }
  7456. IStringVal& CLocalWUResult::getResultString(IStringVal & str) const
  7457. {
  7458. MemoryBuffer s;
  7459. p->getPropBin("Value", s);
  7460. if (s.length())
  7461. {
  7462. unsigned len;
  7463. s.read(len);
  7464. str.setLen((const char *) s.readDirect(len), len);
  7465. }
  7466. else
  7467. {
  7468. p->getPropBin("xmlValue", s);
  7469. if (p->isBinary("xmlValue"))
  7470. str.setLen(s.toByteArray(), s.length());
  7471. else
  7472. {
  7473. char *ascii = rtlUtf8ToVStr(rtlUtf8Length(s.length(), s.toByteArray()), s.toByteArray());
  7474. str.set(ascii);
  7475. rtlFree(ascii);
  7476. }
  7477. }
  7478. return str;
  7479. }
  7480. WUResultFormat CLocalWUResult::getResultFormat() const
  7481. {
  7482. const char * format = p->queryProp("@format");
  7483. if (!format)
  7484. return ResultFormatRaw;
  7485. else if (strcmp(format, "xml") == 0)
  7486. return ResultFormatXml;
  7487. else if (strcmp(format, "xmlSet") == 0)
  7488. return ResultFormatXmlSet;
  7489. else if (strcmp(format, "csv") == 0)
  7490. return ResultFormatCsv;
  7491. else
  7492. throw MakeStringException(WUERR_InvalidResultFormat, "Unrecognised result format %s", format);
  7493. }
  7494. IDataVal& CLocalWUResult::getResultRaw(IDataVal & data, IXmlToRawTransformer * xmlTransformer, ICsvToRawTransformer * csvTransformer) const
  7495. {
  7496. MemoryBuffer s;
  7497. p->getPropBin("Value", s);
  7498. unsigned len = s.length();
  7499. if (len)
  7500. {
  7501. WUResultFormat format = getResultFormat();
  7502. if (format == ResultFormatXml || format == ResultFormatXmlSet)
  7503. {
  7504. if (!xmlTransformer)
  7505. throw MakeStringException(WUERR_MissingFormatTranslator, "No transformer supplied to translate XML format result");
  7506. xmlTransformer->transform(data, len, s.readDirect(len), format == ResultFormatXml);
  7507. }
  7508. else if (format == ResultFormatCsv)
  7509. {
  7510. if (!csvTransformer)
  7511. throw MakeStringException(WUERR_MissingFormatTranslator, "No transformer supplied to translate Csv format result");
  7512. csvTransformer->transform(data, len, s.readDirect(len), true);
  7513. }
  7514. else
  7515. data.setLen(s.readDirect(len), len);
  7516. }
  7517. else
  7518. data.clear();
  7519. return data;
  7520. }
  7521. unsigned CLocalWUResult::getResultHash() const
  7522. {
  7523. MemoryBuffer s;
  7524. p->getPropBin("Value", s);
  7525. unsigned len = s.length();
  7526. const byte * data = (const byte *)s.toByteArray();
  7527. return ~hashc(data, len, ~0);
  7528. }
  7529. IDataVal& CLocalWUResult::getResultUnicode(IDataVal & data) const
  7530. {
  7531. MemoryBuffer s;
  7532. p->getPropBin("Value", s);
  7533. if (s.length())
  7534. {
  7535. unsigned len;
  7536. s.read(len);
  7537. data.setLen(s.readDirect(len*2), len*2);
  7538. }
  7539. else
  7540. {
  7541. StringBuffer utf8;
  7542. if (p->getProp("xmlValue", utf8))
  7543. {
  7544. unsigned outlen;
  7545. UChar *out;
  7546. rtlUtf8ToUnicodeX(outlen, out, utf8.length(), utf8.str());
  7547. data.setLen(out, outlen*2);
  7548. rtlFree(out);
  7549. }
  7550. else
  7551. data.clear();
  7552. }
  7553. return data;
  7554. }
  7555. __int64 CLocalWUResult::getResultRawSize(IXmlToRawTransformer * xmlTransformer, ICsvToRawTransformer * csvTransformer) const
  7556. {
  7557. WUResultFormat format = getResultFormat();
  7558. if (format == ResultFormatRaw)
  7559. {
  7560. //MORE: This should not load the whole property...
  7561. MemoryBuffer s;
  7562. p->getPropBin("Value", s);
  7563. return s.length();
  7564. }
  7565. else
  7566. {
  7567. MemoryBuffer temp;
  7568. MemoryBuffer2IDataVal adaptor(temp);
  7569. getResultRaw(adaptor, xmlTransformer, csvTransformer);
  7570. return temp.length();
  7571. }
  7572. }
  7573. IDataVal& CLocalWUResult::getResultRaw(IDataVal & data, __int64 from, __int64 length, IXmlToRawTransformer * xmlTransformer, ICsvToRawTransformer * csvTransformer) const
  7574. {
  7575. WUResultFormat format = getResultFormat();
  7576. if (format != ResultFormatRaw)
  7577. {
  7578. MemoryBuffer temp;
  7579. MemoryBuffer2IDataVal adaptor(temp);
  7580. getResultRaw(adaptor, xmlTransformer, csvTransformer);
  7581. unsigned len = temp.length();
  7582. if (from > len) from = len;
  7583. if (from + length > len) length = len - from;
  7584. data.setLen(temp.readDirect(len) + from, (size32_t)length);
  7585. return data;
  7586. }
  7587. else
  7588. {
  7589. //MORE: This should not load the whole property, and should be different from the code above...
  7590. MemoryBuffer s;
  7591. p->getPropBin("Value", s);
  7592. unsigned len = s.length();
  7593. if (from > len) from = len;
  7594. if (from + length > len) length = len - from;
  7595. data.setLen(s.readDirect(len) + from, (size32_t)length);
  7596. return data;
  7597. }
  7598. }
  7599. bool CLocalWUResult::getResultIsAll() const
  7600. {
  7601. return p->getPropBool("@isAll", false);
  7602. }
  7603. // MORE - it's an undetected error if we call setResult... of a type that does not match schema
  7604. void CLocalWUResult::setResultInt(__int64 val)
  7605. {
  7606. // Note: we always serialize scalar integer results as int8, and schema must reflect this
  7607. MemoryBuffer m;
  7608. serializeInt8(val, m);
  7609. p->setPropBin("Value", m.length(), m.toByteArray());
  7610. setResultRowCount(1);
  7611. setResultTotalRowCount(1);
  7612. }
  7613. void CLocalWUResult::setResultUInt(unsigned __int64 val)
  7614. {
  7615. setResultInt((__int64) val);
  7616. }
  7617. void CLocalWUResult::setResultReal(double val)
  7618. {
  7619. // Note: we always serialize scalar real results as real8, and schema must reflect this
  7620. MemoryBuffer m;
  7621. serializeReal8(val, m);
  7622. p->setPropBin("Value", m.length(), m.toByteArray());
  7623. setResultRowCount(1);
  7624. setResultTotalRowCount(1);
  7625. }
  7626. void CLocalWUResult::setResultBool(bool val)
  7627. {
  7628. MemoryBuffer m;
  7629. serializeBool(val, m);
  7630. p->setPropBin("Value", m.length(), m.toByteArray());
  7631. setResultRowCount(1);
  7632. setResultTotalRowCount(1);
  7633. }
  7634. void CLocalWUResult::setResultString(const char *val, unsigned len)
  7635. {
  7636. // Note: we always serialize scalar strings with length prefix, and schema must reflect this
  7637. MemoryBuffer m;
  7638. serializeLPString(len, val, m);
  7639. p->setPropBin("Value", m.length(), m.toByteArray());
  7640. setResultRowCount(1);
  7641. setResultTotalRowCount(1);
  7642. }
  7643. void CLocalWUResult::setResultUnicode(const void *val, unsigned len)
  7644. {
  7645. // Note: we always serialize scalar strings with length prefix, and schema must reflect this
  7646. MemoryBuffer m;
  7647. m.append(len).append(len*2, val);
  7648. p->setPropBin("Value", m.length(), m.toByteArray());
  7649. setResultRowCount(1);
  7650. setResultTotalRowCount(1);
  7651. }
  7652. void CLocalWUResult::setResultData(const void *val, unsigned len)
  7653. {
  7654. // Note: we always serialize scalar data with length prefix, and schema must reflect this
  7655. MemoryBuffer m;
  7656. serializeLPString(len, (const char *)val, m);
  7657. p->setPropBin("Value", m.length(), m.toByteArray());
  7658. setResultRowCount(1);
  7659. setResultTotalRowCount(1);
  7660. }
  7661. void CLocalWUResult::setResultDecimal(const void *val, unsigned len)
  7662. {
  7663. // Note: serialized as data but with length known from schema
  7664. MemoryBuffer m;
  7665. serializeFixedData(len, val, m);
  7666. p->setPropBin("Value", m.length(), m.toByteArray());
  7667. setResultRowCount(1);
  7668. setResultTotalRowCount(1);
  7669. }
  7670. void CLocalWUResult::setResultRow(unsigned len, const void * data)
  7671. {
  7672. p->setPropBin("Value", len, data);
  7673. setResultRowCount(1);
  7674. setResultTotalRowCount(1);
  7675. setResultFormat(ResultFormatRaw);
  7676. }
  7677. void CLocalWUResult::setResultIsAll(bool value)
  7678. {
  7679. p->setPropBool("@isAll", value);
  7680. }
  7681. //==========================================================================================
  7682. CLocalWUPlugin::CLocalWUPlugin(IPropertyTree *props) : p(props)
  7683. {
  7684. }
  7685. IStringVal& CLocalWUPlugin::getPluginName(IStringVal &str) const
  7686. {
  7687. str.set(p->queryProp("@dllname"));
  7688. return str;
  7689. }
  7690. IStringVal& CLocalWUPlugin::getPluginVersion(IStringVal &str) const
  7691. {
  7692. str.set(p->queryProp("@version"));
  7693. return str;
  7694. }
  7695. bool CLocalWUPlugin::getPluginThor() const
  7696. {
  7697. return p->getPropInt("@thor") != 0;
  7698. }
  7699. bool CLocalWUPlugin::getPluginHole() const
  7700. {
  7701. return p->getPropInt("@hole") != 0;
  7702. }
  7703. void CLocalWUPlugin::setPluginName(const char *str)
  7704. {
  7705. p->setProp("@dllname", str);
  7706. }
  7707. void CLocalWUPlugin::setPluginVersion(const char *str)
  7708. {
  7709. p->setProp("@version", str);
  7710. }
  7711. void CLocalWUPlugin::setPluginThor(bool on)
  7712. {
  7713. p->setPropInt("@thor", (int) on);
  7714. }
  7715. void CLocalWUPlugin::setPluginHole(bool on)
  7716. {
  7717. p->setPropInt("@hole", (int) on);
  7718. }
  7719. //==========================================================================================
  7720. class WULibraryActivityIterator : public CInterface, implements IConstWULibraryActivityIterator
  7721. {
  7722. public:
  7723. WULibraryActivityIterator(IPropertyTree * tree) { iter.setown(tree->getElements("activity")); }
  7724. IMPLEMENT_IINTERFACE;
  7725. bool first() { return iter->first(); }
  7726. bool isValid() { return iter->isValid(); }
  7727. bool next() { return iter->next(); }
  7728. unsigned query() const { return iter->query().getPropInt("@id"); }
  7729. private:
  7730. Owned<IPropertyTreeIterator> iter;
  7731. };
  7732. CLocalWULibrary::CLocalWULibrary(IPropertyTree *props) : p(props)
  7733. {
  7734. }
  7735. IStringVal& CLocalWULibrary::getName(IStringVal &str) const
  7736. {
  7737. str.set(p->queryProp("@name"));
  7738. return str;
  7739. }
  7740. IConstWULibraryActivityIterator * CLocalWULibrary::getActivities() const
  7741. {
  7742. return new WULibraryActivityIterator(p);
  7743. }
  7744. void CLocalWULibrary::setName(const char *str)
  7745. {
  7746. p->setProp("@name", str);
  7747. }
  7748. void CLocalWULibrary::addActivity(unsigned id)
  7749. {
  7750. StringBuffer s;
  7751. s.append("activity[@id=\"").append(id).append("\"]");
  7752. if (!p->hasProp(s.str()))
  7753. p->addPropTree("activity", createPTree())->setPropInt("@id", id);
  7754. }
  7755. //==========================================================================================
  7756. CLocalWUActivity::CLocalWUActivity(IPropertyTree *props, __int64 id) : p(props)
  7757. {
  7758. if (id)
  7759. p->setPropInt64("@id", id);
  7760. }
  7761. __int64 CLocalWUActivity::getId() const
  7762. {
  7763. return p->getPropInt64("@id");
  7764. }
  7765. unsigned CLocalWUActivity::getKind() const
  7766. {
  7767. return (unsigned)p->getPropInt("@kind");
  7768. }
  7769. IStringVal & CLocalWUActivity::getHelper(IStringVal & str) const
  7770. {
  7771. str.set(p->queryProp("@helper"));
  7772. return str;
  7773. }
  7774. void CLocalWUActivity::setKind(unsigned kind)
  7775. {
  7776. p->setPropInt64("@kind", kind);
  7777. }
  7778. void CLocalWUActivity::setHelper(const char * str)
  7779. {
  7780. p->setProp("@helper", str);
  7781. }
  7782. //==========================================================================================
  7783. CLocalWUException::CLocalWUException(IPropertyTree *props) : p(props)
  7784. {
  7785. }
  7786. IStringVal& CLocalWUException::getExceptionSource(IStringVal &str) const
  7787. {
  7788. str.set(p->queryProp("@source"));
  7789. return str;
  7790. }
  7791. IStringVal& CLocalWUException::getExceptionMessage(IStringVal &str) const
  7792. {
  7793. str.set(p->queryProp(NULL));
  7794. return str;
  7795. }
  7796. unsigned CLocalWUException::getExceptionCode() const
  7797. {
  7798. return p->getPropInt("@code", 0);
  7799. }
  7800. WUExceptionSeverity CLocalWUException::getSeverity() const
  7801. {
  7802. return (WUExceptionSeverity)p->getPropInt("@severity", ExceptionSeverityError);
  7803. }
  7804. IStringVal & CLocalWUException::getTimeStamp(IStringVal & dt) const
  7805. {
  7806. dt.set(p->queryProp("@time"));
  7807. return dt;
  7808. }
  7809. IStringVal & CLocalWUException::getExceptionFileName(IStringVal & str) const
  7810. {
  7811. str.set(p->queryProp("@filename"));
  7812. return str;
  7813. }
  7814. unsigned CLocalWUException::getExceptionLineNo() const
  7815. {
  7816. return p->getPropInt("@row", 0);
  7817. }
  7818. unsigned CLocalWUException::getExceptionColumn() const
  7819. {
  7820. return p->getPropInt("@col", 0);
  7821. }
  7822. void CLocalWUException::setExceptionSource(const char *str)
  7823. {
  7824. p->setProp("@source", str);
  7825. }
  7826. void CLocalWUException::setExceptionMessage(const char *str)
  7827. {
  7828. p->setProp(NULL, str);
  7829. }
  7830. void CLocalWUException::setExceptionCode(unsigned code)
  7831. {
  7832. p->setPropInt("@code", code);
  7833. }
  7834. void CLocalWUException::setSeverity(WUExceptionSeverity level)
  7835. {
  7836. p->setPropInt("@severity", level);
  7837. }
  7838. void CLocalWUException::setTimeStamp(const char *str)
  7839. {
  7840. p->setProp("@time", str);
  7841. }
  7842. void CLocalWUException::setExceptionFileName(const char *str)
  7843. {
  7844. p->setProp("@filename", str);
  7845. }
  7846. void CLocalWUException::setExceptionLineNo(unsigned r)
  7847. {
  7848. p->setPropInt("@row", r);
  7849. }
  7850. void CLocalWUException::setExceptionColumn(unsigned c)
  7851. {
  7852. p->setPropInt("@col", c);
  7853. }
  7854. //==========================================================================================
  7855. CLocalWUTimeStamp::CLocalWUTimeStamp(IPropertyTree *props) : p(props)
  7856. {
  7857. }
  7858. IStringVal & CLocalWUTimeStamp::getApplication(IStringVal & str) const
  7859. {
  7860. str.set(p->queryProp("@application"));
  7861. return str;
  7862. }
  7863. IStringVal & CLocalWUTimeStamp::getEvent(IStringVal & str) const
  7864. {
  7865. IPropertyTree* evt=p->queryPropTree("*[1]");
  7866. if(evt)
  7867. str.set(evt->queryName());
  7868. return str;
  7869. }
  7870. IStringVal & CLocalWUTimeStamp::getDate(IStringVal & str) const
  7871. {
  7872. str.set(p->queryProp("*[1]"));
  7873. return str;
  7874. }
  7875. //==========================================================================================
  7876. CLocalWUAppValue::CLocalWUAppValue(IPropertyTree *props,unsigned child): p(props)
  7877. {
  7878. prop.append("*[").append(child).append("]");
  7879. }
  7880. IStringVal & CLocalWUAppValue::getApplication(IStringVal & str) const
  7881. {
  7882. str.set(p->queryName());
  7883. return str;
  7884. }
  7885. IStringVal & CLocalWUAppValue::getName(IStringVal & str) const
  7886. {
  7887. IPropertyTree* val=p->queryPropTree(prop.str());
  7888. if(val)
  7889. str.set(val->queryName());
  7890. return str;
  7891. }
  7892. IStringVal & CLocalWUAppValue::getValue(IStringVal & str) const
  7893. {
  7894. str.set(p->queryProp(prop.str()));
  7895. return str;
  7896. }
  7897. //==========================================================================================
  7898. CLocalWUStatistic::CLocalWUStatistic(IPropertyTree *props) : p(props)
  7899. {
  7900. }
  7901. IStringVal & CLocalWUStatistic::getFullName(IStringVal & str) const
  7902. {
  7903. str.set(p->queryProp("@name"));
  7904. return str;
  7905. }
  7906. IStringVal & CLocalWUStatistic::getCreator(IStringVal & str) const
  7907. {
  7908. const char * name = p->queryProp("@name");
  7909. const char * sep1 = strchr(name, ';');
  7910. assertex(sep1);
  7911. str.setLen(name, sep1-name);
  7912. return str;
  7913. }
  7914. IStringVal & CLocalWUStatistic::getDescription(IStringVal & str) const
  7915. {
  7916. str.set(p->queryProp("@desc"));
  7917. return str;
  7918. }
  7919. IStringVal & CLocalWUStatistic::getName(IStringVal & str) const
  7920. {
  7921. const char * name = p->queryProp("@name");
  7922. const char * sep1 = strchr(name, ';');
  7923. assertex(sep1);
  7924. const char * scope = sep1+1;
  7925. const char * sep2 = strchr(scope, ';');
  7926. assertex(sep2);
  7927. str.set(sep2+1);
  7928. return str;
  7929. }
  7930. IStringVal & CLocalWUStatistic::getScope(IStringVal & str) const
  7931. {
  7932. const char * name = p->queryProp("@name");
  7933. const char * sep1 = strchr(name, ';');
  7934. assertex(sep1);
  7935. const char * scope = sep1+1;
  7936. const char * sep2 = strchr(scope, ';');
  7937. assertex(sep2);
  7938. str.setLen(scope, sep2-scope);
  7939. return str;
  7940. }
  7941. StatisticMeasure CLocalWUStatistic::getKind() const
  7942. {
  7943. return (StatisticMeasure)getEnum(p, "@unit", queryStatMeasure);
  7944. }
  7945. unsigned __int64 CLocalWUStatistic::getValue() const
  7946. {
  7947. return p->getPropInt64("@value", 0);
  7948. }
  7949. unsigned __int64 CLocalWUStatistic::getCount() const
  7950. {
  7951. return p->getPropInt64("@count", 0);
  7952. }
  7953. unsigned __int64 CLocalWUStatistic::getMax() const
  7954. {
  7955. return p->getPropInt64("@max", 0);
  7956. }
  7957. //==========================================================================================
  7958. extern WORKUNIT_API ILocalWorkUnit * createLocalWorkUnit()
  7959. {
  7960. Owned<CLocalWorkUnit> cw = new CLocalWorkUnit("W_LOCAL", NULL, (ISecManager*)NULL, NULL);
  7961. ILocalWorkUnit* ret = QUERYINTERFACE(&cw->lockRemote(false), ILocalWorkUnit);
  7962. return ret;
  7963. }
  7964. extern WORKUNIT_API StringBuffer &exportWorkUnitToXML(const IConstWorkUnit *wu, StringBuffer &str, bool unpack, bool includeProgress)
  7965. {
  7966. const CLocalWorkUnit *w = QUERYINTERFACE(wu, const CLocalWorkUnit);
  7967. if (!w)
  7968. {
  7969. const CLockedWorkUnit *wl = QUERYINTERFACE(wu, const CLockedWorkUnit);
  7970. if (wl)
  7971. w = wl->c;
  7972. }
  7973. if (w)
  7974. {
  7975. Linked<IPropertyTree> p;
  7976. if (unpack||includeProgress)
  7977. p.setown(w->getUnpackedTree(includeProgress));
  7978. else
  7979. p.set(w->p);
  7980. toXML(p, str, 0, XML_Format|XML_SortTags);
  7981. }
  7982. else
  7983. str.append("Unrecognized workunit format");
  7984. return str;
  7985. }
  7986. extern WORKUNIT_API IStringVal& exportWorkUnitToXML(const IConstWorkUnit *wu, IStringVal &str, bool unpack, bool includeProgress)
  7987. {
  7988. StringBuffer x;
  7989. str.set(exportWorkUnitToXML(wu,x,unpack, includeProgress).str());
  7990. return str;
  7991. }
  7992. extern WORKUNIT_API void exportWorkUnitToXMLFile(const IConstWorkUnit *wu, const char * filename, unsigned extraXmlFlags, bool unpack, bool includeProgress)
  7993. {
  7994. const CLocalWorkUnit *w = QUERYINTERFACE(wu, const CLocalWorkUnit);
  7995. if (!w)
  7996. {
  7997. const CLockedWorkUnit *wl = QUERYINTERFACE(wu, const CLockedWorkUnit);
  7998. if (wl)
  7999. w = wl->c;
  8000. }
  8001. if (w)
  8002. {
  8003. Linked<IPropertyTree> p;
  8004. if (unpack||includeProgress)
  8005. p.setown(w->getUnpackedTree(includeProgress));
  8006. else
  8007. p.set(w->p);
  8008. saveXML(filename, p, 0, XML_Format|XML_SortTags|extraXmlFlags);
  8009. }
  8010. }
  8011. extern WORKUNIT_API void submitWorkUnit(const char *wuid, const char *username, const char *password)
  8012. {
  8013. MemoryBuffer buffer;
  8014. Owned<INamedQueueConnection> conn = createNamedQueueConnection(0); // MORE - security token?
  8015. Owned<IWorkUnitFactory> factory = getWorkUnitFactory();
  8016. Owned<IWorkUnit> workunit = factory->updateWorkUnit(wuid);
  8017. assertex(workunit);
  8018. SCMStringBuffer token;
  8019. createToken(wuid, username, password, token);
  8020. workunit->setSecurityToken(token.str());
  8021. SCMStringBuffer clusterName;
  8022. workunit->getClusterName(clusterName);
  8023. if (!clusterName.length())
  8024. throw MakeStringException(WUERR_InvalidCluster, "No target cluster specified");
  8025. workunit->commit();
  8026. workunit.clear();
  8027. Owned<IConstWUClusterInfo> clusterInfo = getTargetClusterInfo(clusterName.str());
  8028. if (!clusterInfo)
  8029. throw MakeStringException(WUERR_InvalidCluster, "Unknown cluster %s", clusterName.str());
  8030. SCMStringBuffer serverQueue;
  8031. clusterInfo->getServerQueue(serverQueue);
  8032. assertex(serverQueue.length());
  8033. Owned<IJobQueue> queue = createJobQueue(serverQueue.str());
  8034. if (!queue.get())
  8035. throw MakeStringException(WUERR_InvalidQueue, "Could not create workunit queue");
  8036. IJobQueueItem *item = createJobQueueItem(wuid);
  8037. queue->enqueue(item);
  8038. }
  8039. extern WORKUNIT_API void abortWorkUnit(const char *wuid)
  8040. {
  8041. StringBuffer xpath("/WorkUnitAborts/");
  8042. xpath.append(wuid);
  8043. Owned<IRemoteConnection> acon = querySDS().connect(xpath.str(), myProcessSession(), RTM_LOCK_WRITE|RTM_CREATE, SDS_LOCK_TIMEOUT);
  8044. acon->queryRoot()->setPropInt(NULL, 1);
  8045. }
  8046. extern WORKUNIT_API void secSubmitWorkUnit(const char *wuid, ISecManager &secmgr, ISecUser &secuser)
  8047. {
  8048. if (checkWuSecAccess(wuid, secmgr, &secuser, SecAccess_Write, "Submit", true, true))
  8049. submitWorkUnit(wuid, secuser.getName(), secuser.credentials().getPassword());
  8050. }
  8051. extern WORKUNIT_API void secAbortWorkUnit(const char *wuid, ISecManager &secmgr, ISecUser &secuser)
  8052. {
  8053. if (checkWuSecAccess(wuid, secmgr, &secuser, SecAccess_Write, "Submit", true, true))
  8054. abortWorkUnit(wuid);
  8055. }
  8056. extern WORKUNIT_API void submitWorkUnit(const char *wuid, ISecManager *secmgr, ISecUser *secuser)
  8057. {
  8058. if (secmgr && secuser)
  8059. return secSubmitWorkUnit(wuid, *secmgr, *secuser);
  8060. if (secuser)
  8061. return submitWorkUnit(wuid, secuser->getName(), secuser->credentials().getPassword());
  8062. submitWorkUnit(wuid, "", "");
  8063. }
  8064. extern WORKUNIT_API void abortWorkUnit(const char *wuid, ISecManager *secmgr, ISecUser *secuser)
  8065. {
  8066. if (secmgr && secuser)
  8067. return secAbortWorkUnit(wuid, *secmgr, *secuser);
  8068. abortWorkUnit(wuid);
  8069. }
  8070. bool CLocalWorkUnit::hasWorkflow() const
  8071. {
  8072. return p->hasProp("Workflow");
  8073. }
  8074. unsigned CLocalWorkUnit::queryEventScheduledCount() const
  8075. {
  8076. CriticalBlock block(crit);
  8077. return p->getPropInt("Workflow/@eventScheduledCount", 0);
  8078. }
  8079. void CLocalWorkUnit::incEventScheduledCount()
  8080. {
  8081. CriticalBlock block(crit);
  8082. p->setPropInt("Workflow/@eventScheduledCount", p->getPropInt("Workflow/@eventScheduledCount", 0)+1);
  8083. }
  8084. IPropertyTree * CLocalWorkUnit::queryWorkflowTree() const
  8085. {
  8086. CriticalBlock block(crit);
  8087. return p->queryPropTree("Workflow");
  8088. }
  8089. IConstWorkflowItemIterator* CLocalWorkUnit::getWorkflowItems() const
  8090. {
  8091. // For this to be legally called, we must have the read-able interface. So we are already locked for (at least) read.
  8092. CriticalBlock block(crit);
  8093. if(!workflowIteratorCached)
  8094. {
  8095. assertex(!workflowIterator);
  8096. Owned<IPropertyTree> s = p->getPropTree("Workflow");
  8097. if(s)
  8098. workflowIterator.setown(createWorkflowItemIterator(s));
  8099. workflowIteratorCached = true;
  8100. }
  8101. return workflowIterator.getLink();
  8102. }
  8103. IWorkflowItemArray * CLocalWorkUnit::getWorkflowClone() const
  8104. {
  8105. unsigned count = 0;
  8106. Owned<IConstWorkflowItemIterator> iter = getWorkflowItems();
  8107. for(iter->first(); iter->isValid(); iter->next())
  8108. count++;
  8109. Owned<IWorkflowItemArray> array = createWorkflowItemArray(count);
  8110. for(iter->first(); iter->isValid(); iter->next())
  8111. array->addClone(iter->query());
  8112. return array.getLink();
  8113. }
  8114. IWorkflowItem * CLocalWorkUnit::addWorkflowItem(unsigned wfid, WFType type, WFMode mode, unsigned success, unsigned failure, unsigned recovery, unsigned retriesAllowed, unsigned contingencyFor)
  8115. {
  8116. // For this to be legally called, we must have the write-able interface. So we are already locked for write.
  8117. CriticalBlock block(crit);
  8118. workflowIterator.clear();
  8119. workflowIteratorCached = false;
  8120. IPropertyTree * s = p->queryPropTree("Workflow");
  8121. if(!s)
  8122. s = p->addPropTree("Workflow", createPTree("Workflow"));
  8123. return createWorkflowItem(s, wfid, type, mode, success, failure, recovery, retriesAllowed, contingencyFor);
  8124. }
  8125. IWorkflowItemIterator * CLocalWorkUnit::updateWorkflowItems()
  8126. {
  8127. // For this to be legally called, we must have the write-able interface. So we are already locked for write.
  8128. CriticalBlock block(crit);
  8129. if(!workflowIterator)
  8130. {
  8131. IPropertyTree * s = p->queryPropTree("Workflow");
  8132. if(!s)
  8133. s = p->addPropTree("Workflow", createPTree("Workflow"));
  8134. workflowIterator.setown(createWorkflowItemIterator(s));
  8135. workflowIteratorCached = true;
  8136. }
  8137. return workflowIterator.getLink();
  8138. }
  8139. void CLocalWorkUnit::syncRuntimeWorkflow(IWorkflowItemArray * array)
  8140. {
  8141. Owned<IWorkflowItemIterator> iter = updateWorkflowItems();
  8142. Owned<IWorkflowItem> item;
  8143. for(iter->first(); iter->isValid(); iter->next())
  8144. {
  8145. item.setown(iter->get());
  8146. item->syncRuntimeData(array->queryWfid(item->queryWfid()));
  8147. }
  8148. workflowIterator.clear();
  8149. workflowIteratorCached = false;
  8150. }
  8151. void CLocalWorkUnit::resetWorkflow()
  8152. {
  8153. if (hasWorkflow())
  8154. {
  8155. Owned<IWorkflowItemIterator> iter = updateWorkflowItems();
  8156. Owned<IWorkflowItem> wf;
  8157. for(iter->first(); iter->isValid(); iter->next())
  8158. {
  8159. wf.setown(iter->get());
  8160. wf->reset();
  8161. }
  8162. workflowIterator.clear();
  8163. workflowIteratorCached = false;
  8164. }
  8165. }
  8166. void CLocalWorkUnit::schedule()
  8167. {
  8168. CriticalBlock block(crit);
  8169. if(queryEventScheduledCount() == 0) return;
  8170. switch(getState())
  8171. {
  8172. case WUStateCompleted:
  8173. setState(WUStateWait);
  8174. break;
  8175. case WUStateFailed:
  8176. case WUStateArchived:
  8177. case WUStateAborting:
  8178. case WUStateAborted:
  8179. case WUStateScheduled:
  8180. throw MakeStringException(WUERR_CannotSchedule, "Cannot schedule workunit in this state");
  8181. }
  8182. StringBuffer rootPath;
  8183. SCMStringBuffer clusterName;
  8184. getClusterName(clusterName);
  8185. rootPath.append("/Schedule/").append(clusterName.str());
  8186. Owned<IRemoteConnection> conn = querySDS().connect(rootPath.str(), myProcessSession(), RTM_LOCK_WRITE | RTM_CREATE_QUERY, SDS_LOCK_TIMEOUT);
  8187. Owned<IPropertyTree> root = conn->getRoot();
  8188. if(!root->hasChildren())
  8189. {
  8190. StringBuffer addPath;
  8191. addPath.append("/Schedulers/").append(clusterName.str());
  8192. Owned<IRemoteConnection> addConn = querySDS().connect(addPath.str(), myProcessSession(), RTM_LOCK_WRITE | RTM_CREATE_QUERY, SDS_LOCK_TIMEOUT);
  8193. }
  8194. char const * wuid = p->queryName();
  8195. StringBuffer xpath("*/*/");
  8196. ncnameEscape(wuid, xpath);
  8197. bool more;
  8198. do more = root->removeProp(xpath.str()); while(more);
  8199. Owned<IConstWorkflowItemIterator> iter = getWorkflowItems();
  8200. Owned<IWorkflowEvent> event;
  8201. Owned<IPropertyTree> branch1, branch2;
  8202. for(iter->first(); iter->isValid(); iter->next())
  8203. {
  8204. event.setown(iter->query()->getScheduleEvent());
  8205. if(!event) continue;
  8206. ncnameEscape(event->queryName(), xpath.clear());
  8207. ensurePTree(root, xpath.str());
  8208. branch1.setown(root->getPropTree(xpath.str()));
  8209. ncnameEscape(event->queryText(), xpath.clear());
  8210. ensurePTree(branch1, xpath.str());
  8211. branch2.setown(branch1->getPropTree(xpath.str()));
  8212. ncnameEscape(wuid, xpath.clear());
  8213. ensurePTree(branch2, xpath.str());
  8214. }
  8215. }
  8216. void CLocalWorkUnit::deschedule()
  8217. {
  8218. if(queryEventScheduledCount() == 0) return;
  8219. if(getState() == WUStateWait)
  8220. setState(WUStateCompleted);
  8221. doDescheduleWorkkunit(p->queryName());
  8222. }
  8223. mapEnums localFileUploadTypes[] = {
  8224. { UploadTypeFileSpray, "FileSpray" },
  8225. { UploadTypeWUResult, "WUResult" },
  8226. { UploadTypeWUResultCsv, "WUResultCsv" },
  8227. { UploadTypeWUResultXml, "WUResultXml" },
  8228. { UploadTypeSize, NULL }
  8229. };
  8230. class CLocalFileUpload : public CInterface, implements IConstLocalFileUpload
  8231. {
  8232. public:
  8233. CLocalFileUpload(IPropertyTree * _tree) : tree(_tree) {}
  8234. CLocalFileUpload(unsigned id, LocalFileUploadType type, char const * source, char const * destination, char const * eventTag)
  8235. {
  8236. tree.setown(createPTree());
  8237. tree->setPropInt("@id", id);
  8238. setEnum(tree, "@type", type, localFileUploadTypes);
  8239. tree->setProp("@source", source);
  8240. tree->setProp("@destination", destination);
  8241. if (eventTag)
  8242. tree->setProp("@eventTag", eventTag);
  8243. }
  8244. IMPLEMENT_IINTERFACE;
  8245. IPropertyTree * getTree() { return tree.getLink(); }
  8246. virtual unsigned queryID() const { return tree->getPropInt("@id"); }
  8247. virtual LocalFileUploadType queryType() const { return (LocalFileUploadType)getEnum(tree, "@type", localFileUploadTypes); }
  8248. virtual IStringVal & getSource(IStringVal & ret) const { ret.set(tree->queryProp("@source")); return ret; }
  8249. virtual IStringVal & getDestination(IStringVal & ret) const { ret.set(tree->queryProp("@destination")); return ret; }
  8250. virtual IStringVal & getEventTag(IStringVal & ret) const { if(tree->hasProp("@eventTag")) ret.set(tree->queryProp("@eventTag")); else ret.clear(); return ret; }
  8251. private:
  8252. Owned<IPropertyTree> tree;
  8253. };
  8254. class CLocalFileUploadIterator : public CInterface, implements IConstLocalFileUploadIterator
  8255. {
  8256. public:
  8257. CLocalFileUploadIterator(IPropertyTree * _tree) : tree(_tree), iter(tree->getElements("LocalFileUpload")) {}
  8258. IMPLEMENT_IINTERFACE;
  8259. bool first() { return iter->first(); }
  8260. bool isValid() { return iter->isValid(); }
  8261. bool next() { return iter->next(); }
  8262. IConstLocalFileUpload * get() { return new CLocalFileUpload(&iter->get()); }
  8263. private:
  8264. Owned<IPropertyTree> tree;
  8265. Owned<IPropertyTreeIterator> iter;
  8266. };
  8267. IConstLocalFileUploadIterator * CLocalWorkUnit::getLocalFileUploads() const
  8268. {
  8269. // For this to be legally called, we must have the read-able interface. So we are already locked for (at least) read.
  8270. CriticalBlock block(crit);
  8271. Owned<IPropertyTree> s = p->getPropTree("LocalFileUploads");
  8272. if(s)
  8273. return new CLocalFileUploadIterator(s.getClear());
  8274. else
  8275. return NULL;
  8276. }
  8277. bool CLocalWorkUnit::requiresLocalFileUpload() const
  8278. {
  8279. SCMStringBuffer dest;
  8280. Owned<IConstWUResult> result;
  8281. Owned<IConstLocalFileUploadIterator> iter(getLocalFileUploads());
  8282. if(!iter)
  8283. return false;
  8284. for(iter->first(); iter->isValid(); iter->next())
  8285. {
  8286. Owned<IConstLocalFileUpload> upload(iter->get());
  8287. switch(upload->queryType())
  8288. {
  8289. case UploadTypeWUResult:
  8290. case UploadTypeWUResultCsv:
  8291. case UploadTypeWUResultXml:
  8292. upload->getDestination(dest);
  8293. result.setown(getResultByName(dest.str()));
  8294. if(!result)
  8295. return true;
  8296. break;
  8297. default:
  8298. throw MakeStringException(WUERR_InvalidUploadFormat, "Unsupported local file upload type %s", getEnumText(upload->queryType(), localFileUploadTypes));
  8299. }
  8300. }
  8301. return false;
  8302. }
  8303. unsigned CLocalWorkUnit::addLocalFileUpload(LocalFileUploadType type, char const * source, char const * destination, char const * eventTag)
  8304. {
  8305. // For this to be legally called, we must have the write-able interface. So we are already locked for write.
  8306. CriticalBlock block(crit);
  8307. IPropertyTree * s = p->queryPropTree("LocalFileUploads");
  8308. if(!s)
  8309. s = p->addPropTree("LocalFileUploads", createPTree());
  8310. unsigned id = s->numChildren();
  8311. Owned<CLocalFileUpload> upload = new CLocalFileUpload(id, type, source, destination, eventTag);
  8312. s->addPropTree("LocalFileUpload", upload->getTree());
  8313. return id;
  8314. }
  8315. #if 0
  8316. void testConstWorkflow(IConstWorkflowItem * cwf, bool * okay, bool * dep)
  8317. {
  8318. DBGLOG("Test workflow const iface %u", cwf->queryWfid());
  8319. unsigned deps = 0;
  8320. Owned<IWorkflowDependencyIterator> diter;
  8321. switch(cwf->queryWfid())
  8322. {
  8323. case 1:
  8324. assertex(!cwf->isScheduled());
  8325. assertex(cwf->queryType() == WFTypeNormal);
  8326. assertex(cwf->queryState() == WFStateNull);
  8327. diter.setown(cwf->getDependencies());
  8328. for(diter->first(); diter->isValid(); diter->next())
  8329. deps++;
  8330. assertex(deps==0);
  8331. okay[0] = true;
  8332. break;
  8333. case 2:
  8334. assertex(!cwf->isScheduled());
  8335. assertex(cwf->queryType() == WFTypeRecovery);
  8336. assertex(cwf->queryState() == WFStateSkip);
  8337. okay[1] = true;
  8338. break;
  8339. case 3:
  8340. assertex(cwf->queryContingencyFor() == 4);
  8341. okay[2] = true;
  8342. break;
  8343. case 4:
  8344. assertex(cwf->isScheduled());
  8345. assertex(cwf->queryType() == WFTypeNormal);
  8346. assertex(cwf->queryState() == WFStateReqd);
  8347. assertex(cwf->querySuccess() == 0);
  8348. assertex(cwf->queryFailure() == 3);
  8349. assertex(cwf->queryRecovery() == 2);
  8350. assertex(cwf->queryRetriesAllowed() == 10);
  8351. assertex(cwf->queryRetriesRemaining() == 10);
  8352. diter.setown(cwf->getDependencies());
  8353. for(diter->first(); diter->isValid(); diter->next())
  8354. {
  8355. dep[diter->query()-1] = true;
  8356. deps++;
  8357. }
  8358. assertex(deps==2);
  8359. assertex(dep[0]);
  8360. assertex(dep[1]);
  8361. okay[3] = true;
  8362. break;
  8363. case 5:
  8364. assertex(cwf->isScheduled());
  8365. assertex(!cwf->isScheduledNow());
  8366. assertex(cwf->querySchedulePriority() == 75);
  8367. assertex(cwf->queryScheduleCount() == 5);
  8368. assertex(cwf->queryScheduleCountRemaining() == 5);
  8369. okay[4] = true;
  8370. break;
  8371. case 6:
  8372. assertex(cwf->isScheduled());
  8373. assertex(!cwf->isScheduledNow());
  8374. assertex(cwf->querySchedulePriority() == 25);
  8375. assertex(!cwf->hasScheduleCount());
  8376. okay[5] = true;
  8377. break;
  8378. default:
  8379. assertex(!"unknown wfid in test");
  8380. }
  8381. }
  8382. void testRuntimeWorkflow(IRuntimeWorkflowItem * rwf, bool * okay)
  8383. {
  8384. DBGLOG("Test workflow runtime iface %u", rwf->queryWfid());
  8385. switch(rwf->queryWfid())
  8386. {
  8387. case 1:
  8388. case 2:
  8389. case 3:
  8390. okay[rwf->queryWfid()-1] = true;
  8391. break;
  8392. case 4:
  8393. {
  8394. unsigned tries = 0;
  8395. while(rwf->testAndDecRetries())
  8396. tries++;
  8397. assertex(tries == 10);
  8398. assertex(rwf->queryRetriesRemaining() == 0);
  8399. rwf->setState(WFStateFail);
  8400. assertex(rwf->queryState() == WFStateFail);
  8401. rwf->reset();
  8402. assertex(rwf->queryRetriesRemaining() == 10);
  8403. assertex(rwf->queryState() == WFStateReqd);
  8404. }
  8405. okay[3] = true;
  8406. break;
  8407. case 5:
  8408. {
  8409. assertex(rwf->queryScheduleCountRemaining() == 5);
  8410. unsigned count = 0;
  8411. do count++; while(rwf->decAndTestScheduleCountRemaining());
  8412. assertex(count == 5);
  8413. assertex(rwf->queryScheduleCountRemaining() == 0);
  8414. rwf->reset();
  8415. assertex(rwf->queryScheduleCountRemaining() == 5);
  8416. }
  8417. okay[4] = true;
  8418. break;
  8419. case 6:
  8420. {
  8421. assertex(!rwf->hasScheduleCount());
  8422. unsigned count;
  8423. for(count=0; count<20; count++)
  8424. assertex(rwf->decAndTestScheduleCountRemaining());
  8425. }
  8426. okay[5] = true;
  8427. break;
  8428. default:
  8429. assertex(!"unknown wfid in test");
  8430. }
  8431. }
  8432. void testWorkflow()
  8433. {
  8434. DBGLOG("workunit.cpp : testWorkflow");
  8435. CLocalWorkUnit wu("W-WF-TEST", 0, 0, 0);
  8436. Owned<IWorkflowItem> wf;
  8437. wf.setown(wu.addWorkflowItem(1, WFTypeNormal, 0, 0, 0, 0, 0));
  8438. wf.setown(wu.addWorkflowItem(2, WFTypeRecovery, 0, 0, 0, 0, 0));
  8439. wf.setown(wu.addWorkflowItem(3, WFTypeFailure, 0, 0, 0, 0, 4));
  8440. wf.setown(wu.addWorkflowItem(4, WFTypeNormal, 0, 3, 2, 10, 0));
  8441. wf->setScheduledNow();
  8442. wf->addDependency(1);
  8443. wf.setown(wu.addWorkflowItem(5, WFTypeNormal, 0, 0, 0, 0, 0));
  8444. wf->setScheduledOn("test", "foo*");
  8445. wf->setSchedulePriority(75);
  8446. wf->setScheduleCount(5);
  8447. wf.setown(wu.addWorkflowItem(6, WFTypeNormal, 0, 0, 0, 0, 0));
  8448. wf->setScheduledOn("test", "bar*");
  8449. wf->setSchedulePriority(25);
  8450. unsigned const n = 6;
  8451. bool okay[n];
  8452. bool dep[n];
  8453. unsigned i;
  8454. for(i=0; i<n; i++)
  8455. okay[i] = dep[i] = 0;
  8456. Owned<IConstWorkflowItemIterator> citer(wu.getWorkflowItems());
  8457. for(citer->first(); citer->isValid(); citer->next())
  8458. testConstWorkflow(citer->query(), okay, dep);
  8459. for(i=0; i<n; i++)
  8460. {
  8461. assertex(okay[i]);
  8462. okay[i] = false;
  8463. }
  8464. Owned<IWorkflowItemIterator> miter(wu.updateWorkflowItems());
  8465. for(miter->first(); miter->isValid(); miter->next())
  8466. {
  8467. Owned<IRuntimeWorkflowItem> rwf(miter->get());
  8468. testRuntimeWorkflow(rwf, okay);
  8469. }
  8470. for(i=0; i<n; i++)
  8471. {
  8472. assertex(okay[i]);
  8473. okay[i] = dep[i] = false;
  8474. }
  8475. Owned<IWorkflowItemArray> array(wu.getWorkflowClone());
  8476. unsigned wfid;
  8477. for(wfid = 1; array->isValid(wfid); wfid++)
  8478. testConstWorkflow(&array->queryWfid(wfid), okay, dep);
  8479. for(i=0; i<n; i++)
  8480. {
  8481. assertex(okay[i]);
  8482. okay[i] = false;
  8483. }
  8484. for(wfid = 1; array->isValid(wfid); wfid++)
  8485. testRuntimeWorkflow(&array->queryWfid(wfid), okay);
  8486. for(i=0; i<n; i++)
  8487. {
  8488. assertex(okay[i]);
  8489. okay[i] = false;
  8490. }
  8491. }
  8492. #endif
  8493. //------------------------------------------------------------------------------------------
  8494. class WorkUnitWaiter : public CInterface, implements ISDSSubscription, implements IAbortHandler
  8495. {
  8496. Semaphore changed;
  8497. SubscriptionId change;
  8498. public:
  8499. IMPLEMENT_IINTERFACE;
  8500. WorkUnitWaiter(const char *xpath)
  8501. {
  8502. change = querySDS().subscribe(xpath, *this, false);
  8503. aborted = false;
  8504. }
  8505. ~WorkUnitWaiter()
  8506. {
  8507. assertex(change==0);
  8508. }
  8509. void notify(SubscriptionId id, const char *xpath, SDSNotifyFlags flags, unsigned valueLen, const void *valueData)
  8510. {
  8511. changed.signal();
  8512. }
  8513. bool wait(unsigned timeout)
  8514. {
  8515. return changed.wait(timeout) && !aborted;
  8516. }
  8517. bool onAbort()
  8518. {
  8519. aborted = true;
  8520. changed.signal();
  8521. return false;
  8522. }
  8523. void unsubscribe()
  8524. {
  8525. querySDS().unsubscribe(change);
  8526. change = 0;
  8527. }
  8528. bool aborted;
  8529. };
  8530. static WUState _waitForWorkUnit(const char * wuid, unsigned timeout, bool compiled, bool returnOnWaitState)
  8531. {
  8532. StringBuffer wuRoot;
  8533. getXPath(wuRoot, wuid);
  8534. Owned<WorkUnitWaiter> waiter = new WorkUnitWaiter(wuRoot.str());
  8535. LocalIAbortHandler abortHandler(*waiter);
  8536. WUState ret = WUStateUnknown;
  8537. Owned<IRemoteConnection> conn = querySDS().connect(wuRoot.str(), myProcessSession(), 0, SDS_LOCK_TIMEOUT);
  8538. if (conn)
  8539. {
  8540. unsigned start = msTick();
  8541. loop
  8542. {
  8543. ret = (WUState) getEnum(conn->queryRoot(), "@state", states);
  8544. switch (ret)
  8545. {
  8546. case WUStateCompiled:
  8547. case WUStateUploadingFiles:
  8548. if (!compiled)
  8549. break;
  8550. // fall into
  8551. case WUStateCompleted:
  8552. case WUStateFailed:
  8553. case WUStateAborted:
  8554. waiter->unsubscribe();
  8555. return ret;
  8556. case WUStateWait:
  8557. if(returnOnWaitState)
  8558. {
  8559. waiter->unsubscribe();
  8560. return ret;
  8561. }
  8562. break;
  8563. case WUStateCompiling:
  8564. case WUStateRunning:
  8565. case WUStateDebugPaused:
  8566. case WUStateDebugRunning:
  8567. case WUStateBlocked:
  8568. case WUStateAborting:
  8569. if (queryDaliServerVersion().compare("2.1")>=0)
  8570. {
  8571. SessionId agent = conn->queryRoot()->getPropInt64("@agentSession", -1);
  8572. if((agent>0) && querySessionManager().sessionStopped(agent, 0))
  8573. {
  8574. waiter->unsubscribe();
  8575. conn->reload();
  8576. ret = (WUState) getEnum(conn->queryRoot(), "@state", states);
  8577. bool isEcl = false;
  8578. switch (ret)
  8579. {
  8580. case WUStateCompiling:
  8581. isEcl = true;
  8582. // drop into
  8583. case WUStateRunning:
  8584. case WUStateBlocked:
  8585. ret = WUStateFailed;
  8586. break;
  8587. case WUStateAborting:
  8588. ret = WUStateAborted;
  8589. break;
  8590. default:
  8591. return ret;
  8592. }
  8593. WARNLOG("_waitForWorkUnit terminated: %"I64F"d state = %d",(__int64)agent,(int)ret);
  8594. Owned<IWorkUnitFactory> factory = getWorkUnitFactory();
  8595. Owned<IWorkUnit> wu = factory->updateWorkUnit(wuid);
  8596. wu->setState(ret);
  8597. Owned<IWUException> e = wu->createException();
  8598. e->setExceptionCode(isEcl ? 1001 : 1000);
  8599. e->setExceptionMessage(isEcl ? "EclServer terminated unexpectedly" : "Workunit terminated unexpectedly");
  8600. return ret;
  8601. }
  8602. }
  8603. break;
  8604. }
  8605. unsigned waited = msTick() - start;
  8606. if (timeout==-1)
  8607. {
  8608. waiter->wait(20000); // recheck state every 20 seconds even if no timeout, in case eclagent has crashed.
  8609. if (waiter->aborted)
  8610. {
  8611. ret = WUStateUnknown; // MORE - throw an exception?
  8612. break;
  8613. }
  8614. }
  8615. else if (waited > timeout || !waiter->wait(timeout-waited))
  8616. {
  8617. ret = WUStateUnknown; // MORE - throw an exception?
  8618. break;
  8619. }
  8620. conn->reload();
  8621. }
  8622. }
  8623. waiter->unsubscribe();
  8624. return ret;
  8625. }
  8626. extern WUState waitForWorkUnitToComplete(const char * wuid, int timeout, bool returnOnWaitState)
  8627. {
  8628. return _waitForWorkUnit(wuid, (unsigned)timeout, false, returnOnWaitState);
  8629. }
  8630. extern WORKUNIT_API WUState secWaitForWorkUnitToComplete(const char * wuid, ISecManager &secmgr, ISecUser &secuser, int timeout, bool returnOnWaitState)
  8631. {
  8632. if (checkWuSecAccess(wuid, secmgr, &secuser, SecAccess_Read, "Wait for Complete", false, true))
  8633. return waitForWorkUnitToComplete(wuid, timeout, returnOnWaitState);
  8634. return WUStateUnknown;
  8635. }
  8636. extern bool waitForWorkUnitToCompile(const char * wuid, int timeout)
  8637. {
  8638. switch(_waitForWorkUnit(wuid, (unsigned)timeout, true, true))
  8639. {
  8640. case WUStateCompiled:
  8641. case WUStateCompleted:
  8642. case WUStateWait:
  8643. case WUStateUploadingFiles:
  8644. return true;
  8645. default:
  8646. return false;
  8647. }
  8648. }
  8649. extern WORKUNIT_API bool secWaitForWorkUnitToCompile(const char * wuid, ISecManager &secmgr, ISecUser &secuser, int timeout)
  8650. {
  8651. if (checkWuSecAccess(wuid, secmgr, &secuser, SecAccess_Read, "Wait for Compile", false, true))
  8652. return waitForWorkUnitToCompile(wuid, timeout);
  8653. return false;
  8654. }
  8655. extern WORKUNIT_API bool secDebugWorkunit(const char * wuid, ISecManager &secmgr, ISecUser &secuser, const char *command, StringBuffer &response)
  8656. {
  8657. if (strnicmp(command, "<debug:", 7) == 0 && checkWuSecAccess(wuid, secmgr, &secuser, SecAccess_Read, "Debug", false, true))
  8658. {
  8659. Owned<IConstWorkUnit> wu = factory->secOpenWorkUnit(wuid, false, &secmgr, &secuser);
  8660. SCMStringBuffer ip;
  8661. unsigned port;
  8662. port = wu->getDebugAgentListenerPort();
  8663. wu->getDebugAgentListenerIP(ip);
  8664. SocketEndpoint debugEP(ip.str(), port);
  8665. Owned<ISocket> socket = ISocket::connect_timeout(debugEP, 1000);
  8666. unsigned len = (size32_t)strlen(command);
  8667. unsigned revlen = len;
  8668. _WINREV(revlen);
  8669. socket->write(&revlen, sizeof(revlen));
  8670. socket->write(command, len);
  8671. for (;;)
  8672. {
  8673. socket->read(&len, sizeof(len));
  8674. _WINREV(len);
  8675. if (len == 0)
  8676. break;
  8677. if (len & 0x80000000)
  8678. {
  8679. throwUnexpected();
  8680. }
  8681. char * mem = (char*) response.reserve(len);
  8682. socket->read(mem, len);
  8683. }
  8684. return true;
  8685. }
  8686. return false;
  8687. }
  8688. void updateSuppliedXmlParams(IWorkUnit * w)
  8689. {
  8690. Owned<const IPropertyTree> params = w->getXmlParams();
  8691. if (!params)
  8692. return;
  8693. Owned<IPropertyTreeIterator> elems = params->getElements("*");
  8694. ForEach(*elems)
  8695. {
  8696. IPropertyTree & curVal = elems->query();
  8697. const char *name = curVal.queryName();
  8698. Owned<IWUResult> r = updateWorkUnitResult(w, name, -1);
  8699. if (r)
  8700. {
  8701. StringBuffer s;
  8702. if (r->isResultScalar() && !curVal.hasChildren())
  8703. {
  8704. curVal.getProp(".", s);
  8705. r->setResultXML(s);
  8706. r->setResultStatus(ResultStatusSupplied);
  8707. }
  8708. else
  8709. {
  8710. toXML(&curVal, s);
  8711. bool isSet = (curVal.hasProp("Item") || curVal.hasProp("string"));
  8712. r->setResultRaw(s.length(), s.str(), isSet ? ResultFormatXmlSet : ResultFormatXml);
  8713. }
  8714. }
  8715. else
  8716. DBGLOG("WARNING: no matching variable in workunit for input parameter %s", name);
  8717. }
  8718. }
  8719. IWUResult * updateWorkUnitResult(IWorkUnit * w, const char *name, unsigned sequence)
  8720. {
  8721. switch ((int)sequence)
  8722. {
  8723. case ResultSequenceStored:
  8724. return w->updateVariableByName(name);
  8725. case ResultSequencePersist:
  8726. return w->updateGlobalByName(name);
  8727. case ResultSequenceInternal:
  8728. case ResultSequenceOnce:
  8729. return w->updateTemporaryByName(name);
  8730. default:
  8731. return w->updateResultBySequence(sequence);
  8732. }
  8733. }
  8734. IConstWUResult * getWorkUnitResult(IConstWorkUnit * w, const char *name, unsigned sequence)
  8735. {
  8736. switch ((int)sequence)
  8737. {
  8738. case ResultSequenceStored:
  8739. return w->getVariableByName(name);
  8740. case ResultSequencePersist:
  8741. return w->getGlobalByName(name);
  8742. case ResultSequenceInternal:
  8743. case ResultSequenceOnce:
  8744. return w->getTemporaryByName(name);
  8745. default:
  8746. if (name && name[0])
  8747. return w->getResultByName(name);//name takes precedence over sequence
  8748. else
  8749. return w->getResultBySequence(sequence);
  8750. }
  8751. }
  8752. extern WORKUNIT_API bool getWorkUnitCreateTime(const char *wuid,CDateTime &time)
  8753. {
  8754. if (wuid) {
  8755. char prefchar;
  8756. unsigned year,month,day,hour,min,sec;
  8757. if (sscanf(wuid, "%c%4u%2u%2u-%2u%2u%2u", &prefchar, &year, &month, &day, &hour, &min, &sec)==7) {
  8758. time.set(year, month, day, hour, min, sec, 0, true);
  8759. // time.setDate(year, month, day);
  8760. // time.setTime(hour, min, sec, 0, true); // for some reason time is local
  8761. return true;
  8762. }
  8763. }
  8764. return false;
  8765. }
  8766. extern WORKUNIT_API IStringVal& createToken(const char *wuid, const char *user, const char *password, IStringVal &str)
  8767. {
  8768. StringBuffer wu, token("X");
  8769. wu.append(wuid).append(';').append(user).append(';').append(password);
  8770. encrypt(token,wu.str());
  8771. str.set(token.str());
  8772. return str;
  8773. }
  8774. // This will be replaced by something more secure!
  8775. extern WORKUNIT_API void extractToken(const char *token, const char *wuid, IStringVal &user, IStringVal &password)
  8776. {
  8777. if (token && *token)
  8778. {
  8779. StringBuffer wu;
  8780. decrypt(wu, token+1);
  8781. const char *finger = strchr(wu.str(),';');
  8782. if (finger && strnicmp(wuid, wu.str(), finger-wu.str())==0)
  8783. {
  8784. const char *finger1 = strchr(++finger,';');
  8785. if(finger1)
  8786. {
  8787. user.setLen(finger, (size32_t)(finger1-finger));
  8788. finger1++;
  8789. password.setLen(finger1, (size32_t)(wu.str() + wu.length() - finger1));
  8790. return;
  8791. }
  8792. }
  8793. throw MakeStringException(WUERR_InvalidSecurityToken, "Invalid call to extractToken");
  8794. }
  8795. }
  8796. extern WORKUNIT_API WUState getWorkUnitState(const char* state)
  8797. {
  8798. return (WUState) getEnum(state, states);
  8799. }
  8800. const LogMsgCategory MCschedconn = MCprogress(1000); // Category used to inform about schedule synchronization
  8801. class CWorkflowScheduleConnection : public CInterface, implements IWorkflowScheduleConnection
  8802. {
  8803. public:
  8804. CWorkflowScheduleConnection(char const * wuid)
  8805. {
  8806. basexpath.append("/WorkflowSchedule/").append(wuid);
  8807. flagxpath.append(basexpath.str()).append("/Active");
  8808. }
  8809. IMPLEMENT_IINTERFACE;
  8810. virtual void lock()
  8811. {
  8812. LOG(MCschedconn, "Locking base schedule connection");
  8813. baseconn.setown(querySDS().connect(basexpath.str(), myProcessSession(), RTM_CREATE_QUERY | RTM_LOCK_WRITE, INFINITE));
  8814. if(!baseconn)
  8815. throw MakeStringException(WUERR_ScheduleLockFailed, "Could not get base workflow schedule lock");
  8816. }
  8817. virtual void unlock()
  8818. {
  8819. LOG(MCschedconn, "Unlocking base schedule connection");
  8820. baseconn.clear();
  8821. }
  8822. virtual void setActive()
  8823. {
  8824. LOG(MCschedconn, "Setting active flag in schedule connection");
  8825. flagconn.setown(querySDS().connect(flagxpath.str(), myProcessSession(), RTM_CREATE | RTM_LOCK_WRITE | RTM_DELETE_ON_DISCONNECT, INFINITE));
  8826. if(!flagconn)
  8827. throw MakeStringException(WUERR_ScheduleLockFailed, "Could not get active workflow schedule lock");
  8828. }
  8829. virtual void resetActive()
  8830. {
  8831. LOG(MCschedconn, "Resetting active flag in schedule connection");
  8832. flagconn.clear();
  8833. }
  8834. virtual bool queryActive()
  8835. {
  8836. return baseconn->queryRoot()->hasProp("Active");
  8837. }
  8838. virtual bool pull(IWorkflowItemArray * workflow)
  8839. {
  8840. assertex(baseconn);
  8841. Owned<IPropertyTree> root = baseconn->getRoot();
  8842. Owned<IPropertyTree> eventQueue = root->getPropTree("EventQueue");
  8843. if(!eventQueue) return false;
  8844. if(!eventQueue->hasProp("Item")) return false;
  8845. {
  8846. Owned<IPropertyTreeIterator> eventItems = eventQueue->getElements("Item");
  8847. Owned<IPropertyTree> eventItem;
  8848. Owned<IRuntimeWorkflowItemIterator> wfItems = workflow->getSequenceIterator();
  8849. Owned<IRuntimeWorkflowItem> wfItem;
  8850. for(eventItems->first(); eventItems->isValid(); eventItems->next())
  8851. {
  8852. eventItem.setown(&eventItems->get());
  8853. const char * eventName = eventItem->queryProp("@name");
  8854. const char * eventText = eventItem->queryProp("@text");
  8855. for(wfItems->first(); wfItems->isValid(); wfItems->next())
  8856. {
  8857. wfItem.setown(wfItems->get());
  8858. if(wfItem->queryState() != WFStateWait)
  8859. continue;
  8860. Owned<IWorkflowEvent> targetEvent = wfItem->getScheduleEvent();
  8861. if(!targetEvent || !targetEvent->matches(eventName, eventText))
  8862. continue;
  8863. wfItem->setEvent(eventName, eventText);
  8864. wfItem->setState(WFStateReqd);
  8865. resetDependentsState(workflow, *wfItem);
  8866. }
  8867. }
  8868. }
  8869. bool more;
  8870. do
  8871. more = eventQueue->removeProp("Item");
  8872. while(more);
  8873. return true;
  8874. }
  8875. virtual void push(char const * name, char const * text)
  8876. {
  8877. assertex(baseconn);
  8878. Owned<IPropertyTree> root = baseconn->getRoot();
  8879. ensurePTree(root, "EventQueue");
  8880. Owned<IPropertyTree> eventQueue = root->getPropTree("EventQueue");
  8881. Owned<IPropertyTree> eventItem = createPTree();
  8882. eventItem->setProp("@name", name);
  8883. eventItem->setProp("@text", text);
  8884. eventQueue->addPropTree("Item", eventItem.getLink());
  8885. }
  8886. private:
  8887. void resetItemStateAndDependents(IWorkflowItemArray * workflow, unsigned wfid) const
  8888. {
  8889. if (wfid)
  8890. resetItemStateAndDependents(workflow, workflow->queryWfid(wfid));
  8891. }
  8892. void resetItemStateAndDependents(IWorkflowItemArray * workflow, IRuntimeWorkflowItem & item) const
  8893. {
  8894. switch(item.queryState())
  8895. {
  8896. case WFStateDone:
  8897. case WFStateFail:
  8898. {
  8899. item.setState(WFStateNull);
  8900. resetItemStateAndDependents(workflow, item.queryPersistWfid());
  8901. resetDependentsState(workflow, item);
  8902. break;
  8903. }
  8904. }
  8905. }
  8906. void resetDependentsState(IWorkflowItemArray * workflow, IRuntimeWorkflowItem & item) const
  8907. {
  8908. Owned<IWorkflowDependencyIterator> iter(item.getDependencies());
  8909. for(iter->first(); iter->isValid(); iter->next())
  8910. {
  8911. IRuntimeWorkflowItem & dep = workflow->queryWfid(iter->query());
  8912. resetItemStateAndDependents(workflow, dep);
  8913. }
  8914. }
  8915. private:
  8916. StringBuffer basexpath;
  8917. StringBuffer flagxpath;
  8918. Owned<IRemoteConnection> baseconn;
  8919. Owned<IRemoteConnection> flagconn;
  8920. };
  8921. extern WORKUNIT_API IWorkflowScheduleConnection * getWorkflowScheduleConnection(char const * wuid)
  8922. {
  8923. return new CWorkflowScheduleConnection(wuid);
  8924. }
  8925. extern WORKUNIT_API IExtendedWUInterface * queryExtendedWU(IWorkUnit * wu)
  8926. {
  8927. return QUERYINTERFACE(wu, IExtendedWUInterface);
  8928. }
  8929. extern WORKUNIT_API void addExceptionToWorkunit(IWorkUnit * wu, WUExceptionSeverity severity, const char * source, unsigned code, const char * text, const char * filename, unsigned lineno, unsigned column)
  8930. {
  8931. Owned<IWUException> we = wu->createException();
  8932. we->setSeverity(severity);
  8933. we->setExceptionMessage(text);
  8934. if (source)
  8935. we->setExceptionSource(source);
  8936. if (code)
  8937. we->setExceptionCode(code);
  8938. if (filename)
  8939. we->setExceptionFileName(filename);
  8940. if (lineno)
  8941. {
  8942. we->setExceptionLineNo(lineno);
  8943. if (column)
  8944. we->setExceptionColumn(lineno);
  8945. }
  8946. }
  8947. const char * skipLeadingXml(const char * text)
  8948. {
  8949. if (!text)
  8950. return NULL;
  8951. //skip utf8 BOM, probably excessive
  8952. if (memcmp(text, UTF8_BOM, 3) == 0)
  8953. text += 3;
  8954. loop
  8955. {
  8956. if (isspace(*text))
  8957. text++;
  8958. else if (text[0] == '<' && text[1] == '?')
  8959. {
  8960. text += 2;
  8961. loop
  8962. {
  8963. if (!*text) break;
  8964. if (text[0] == '?' && text[1] == '>')
  8965. {
  8966. text += 2;
  8967. break;
  8968. }
  8969. text++;
  8970. }
  8971. }
  8972. else if (text[0] == '<' && text[1] == '!' && text[2] == '-' && text[3] == '-')
  8973. {
  8974. text += 4;
  8975. loop
  8976. {
  8977. if (!*text) break;
  8978. if (text[0] == '-' && text[1] == '-' && text[2] == '>')
  8979. {
  8980. text += 3;
  8981. break;
  8982. }
  8983. text++;
  8984. }
  8985. }
  8986. else
  8987. break;
  8988. }
  8989. return text;
  8990. }
  8991. extern WORKUNIT_API bool isArchiveQuery(const char * text)
  8992. {
  8993. text = skipLeadingXml(text);
  8994. if (!text)
  8995. return false;
  8996. const char * archivePrefix = "<Archive";
  8997. return memicmp(text, archivePrefix, strlen(archivePrefix)) == 0;
  8998. }
  8999. extern WORKUNIT_API bool isQueryManifest(const char * text)
  9000. {
  9001. text = skipLeadingXml(text);
  9002. if (!text)
  9003. return false;
  9004. const char * manifestPrefix = "<Manifest";
  9005. return memicmp(text, manifestPrefix, strlen(manifestPrefix)) == 0;
  9006. }
  9007. //------------------------------------------------------------------------------
  9008. // Named Alias helper function
  9009. static IPropertyTree * resolveQueryByDll(IPropertyTree * queryRegistry, const char * dll)
  9010. {
  9011. StringBuffer xpath;
  9012. xpath.append("Query[@dll=\"").append(dll).append("\"]");
  9013. return queryRegistry->getPropTree(xpath);
  9014. }
  9015. static IPropertyTree * resolveQueryByWuid(IPropertyTree * queryRegistry, const char * wuid)
  9016. {
  9017. StringBuffer xpath;
  9018. xpath.append("Query[@wuid=\"").append(wuid).append("\"]");
  9019. return queryRegistry->getPropTree(xpath);
  9020. }
  9021. static void clearAliases(IPropertyTree * queryRegistry, const char * id)
  9022. {
  9023. StringBuffer lcId(id);
  9024. lcId.toLowerCase();
  9025. StringBuffer xpath;
  9026. xpath.append("Alias[@id=\"").append(lcId).append("\"]");
  9027. Owned<IPropertyTreeIterator> iter = queryRegistry->getElements(xpath);
  9028. ForEach(*iter)
  9029. {
  9030. queryRegistry->removeProp(xpath.str());
  9031. }
  9032. }
  9033. IPropertyTree * addNamedQuery(IPropertyTree * queryRegistry, const char * name, const char * wuid, const char * dll, bool library, const char *userid, const char *snapshot)
  9034. {
  9035. StringBuffer lcName(name);
  9036. lcName.toLowerCase();
  9037. StringBuffer xpath;
  9038. xpath.append("Query[@name=\"").append(lcName.str()).append("\"]");
  9039. Owned<IPropertyTreeIterator> iter = queryRegistry->getElements(xpath);
  9040. unsigned seq = 1;
  9041. ForEach(*iter)
  9042. {
  9043. IPropertyTree &item = iter->query();
  9044. const char *thisWuid = item.queryProp("@wuid");
  9045. if (strieq(wuid, thisWuid))
  9046. return &item;
  9047. unsigned thisSeq = item.getPropInt("@seq");
  9048. if (thisSeq >= seq)
  9049. seq = thisSeq + 1;
  9050. }
  9051. StringBuffer id;
  9052. id.append(lcName).append(".").append(seq);
  9053. IPropertyTree * newEntry = createPTree("Query", ipt_caseInsensitive);
  9054. newEntry->setProp("@name", lcName);
  9055. newEntry->setProp("@wuid", wuid);
  9056. newEntry->setProp("@dll", dll);
  9057. newEntry->setProp("@id", id);
  9058. newEntry->setPropInt("@seq", seq);
  9059. if (library)
  9060. newEntry->setPropBool("@isLibrary", true);
  9061. if (userid && *userid)
  9062. newEntry->setProp("@publishedBy", userid);
  9063. if (snapshot && *snapshot)
  9064. newEntry->setProp("@snapshot", snapshot);
  9065. return queryRegistry->addPropTree("Query", newEntry);
  9066. }
  9067. void removeNamedQuery(IPropertyTree * queryRegistry, const char * id)
  9068. {
  9069. StringBuffer lcId(id);
  9070. lcId.toLowerCase();
  9071. clearAliases(queryRegistry, lcId);
  9072. StringBuffer xpath;
  9073. xpath.append("Query[@id=\"").append(lcId).append("\"]");
  9074. queryRegistry->removeProp(xpath);
  9075. }
  9076. void removeDllFromNamedQueries(IPropertyTree * queryRegistry, const char * dll)
  9077. {
  9078. Owned<IPropertyTree> match = resolveQueryByDll(queryRegistry, dll);
  9079. if (!match)
  9080. return;
  9081. clearAliases(queryRegistry, match->queryProp("@id"));
  9082. queryRegistry->removeTree(match);
  9083. }
  9084. void removeWuidFromNamedQueries(IPropertyTree * queryRegistry, const char * wuid)
  9085. {
  9086. Owned<IPropertyTree> match = resolveQueryByWuid(queryRegistry, wuid);
  9087. if (!match)
  9088. return;
  9089. clearAliases(queryRegistry, match->queryProp("@id"));
  9090. queryRegistry->removeTree(match);
  9091. }
  9092. void removeAliasesFromNamedQuery(IPropertyTree * queryRegistry, const char * id)
  9093. {
  9094. clearAliases(queryRegistry, id);
  9095. }
  9096. void setQueryAlias(IPropertyTree * queryRegistry, const char * name, const char * value)
  9097. {
  9098. StringBuffer lcName(name);
  9099. lcName.toLowerCase();
  9100. StringBuffer xpath;
  9101. xpath.append("Alias[@name=\"").append(lcName).append("\"]");
  9102. IPropertyTree * match = queryRegistry->queryPropTree(xpath);
  9103. if (!match)
  9104. {
  9105. IPropertyTree * newEntry = createPTree("Alias");
  9106. newEntry->setProp("@name", lcName);
  9107. match = queryRegistry->addPropTree("Alias", newEntry);
  9108. }
  9109. match->setProp("@id", value);
  9110. }
  9111. extern WORKUNIT_API IPropertyTree * getQueryById(IPropertyTree * queryRegistry, const char *queryid)
  9112. {
  9113. if (!queryRegistry || !queryid)
  9114. return NULL;
  9115. StringBuffer xpath;
  9116. xpath.append("Query[@id=\"").append(queryid).append("\"]");
  9117. return queryRegistry->getPropTree(xpath);
  9118. }
  9119. extern WORKUNIT_API IPropertyTree * getQueryById(const char *queryset, const char *queryid, bool readonly)
  9120. {
  9121. Owned<IPropertyTree> queryRegistry = getQueryRegistry(queryset, readonly);
  9122. return getQueryById(queryRegistry, queryid);
  9123. }
  9124. extern WORKUNIT_API IPropertyTree * resolveQueryAlias(IPropertyTree * queryRegistry, const char * alias)
  9125. {
  9126. if (!queryRegistry || !alias)
  9127. return NULL;
  9128. StringBuffer xpath;
  9129. unsigned cnt = 0;
  9130. StringBuffer lc(alias);
  9131. const char * search = lc.toLowerCase().str();
  9132. loop
  9133. {
  9134. xpath.set("Alias[@name='").append(search).append("']/@id");
  9135. const char * queryId = queryRegistry->queryProp(xpath);
  9136. if (!queryId)
  9137. break;
  9138. //Check for too many alias indirections.
  9139. if (cnt++ > 10)
  9140. return NULL;
  9141. search = lc.set(queryId).toLowerCase().str();
  9142. }
  9143. return getQueryById(queryRegistry, search);
  9144. }
  9145. extern WORKUNIT_API IPropertyTree * resolveQueryAlias(const char *queryset, const char *alias, bool readonly)
  9146. {
  9147. Owned<IPropertyTree> queryRegistry = getQueryRegistry(queryset, readonly);
  9148. return resolveQueryAlias(queryRegistry, alias);
  9149. }
  9150. void setQuerySuspendedState(IPropertyTree * queryRegistry, const char *id, bool suspend, const char *userid)
  9151. {
  9152. StringBuffer lcId(id);
  9153. lcId.toLowerCase();
  9154. StringBuffer xpath;
  9155. xpath.append("Query[@id=\"").append(lcId).append("\"]");
  9156. IPropertyTree *tree = queryRegistry->queryPropTree(xpath);
  9157. if (tree)
  9158. {
  9159. if (tree->getPropBool("@suspended", false) == suspend)
  9160. return;
  9161. if (suspend)
  9162. {
  9163. tree->addPropBool("@suspended", true);
  9164. if (userid && *userid)
  9165. tree->addProp("@suspendedBy", userid);
  9166. }
  9167. else
  9168. {
  9169. tree->removeProp("@suspended");
  9170. tree->removeProp("@suspendedBy");
  9171. }
  9172. }
  9173. else
  9174. throw MakeStringException((suspend)? QUERRREG_SUSPEND : QUERRREG_UNSUSPEND, "Modifying query suspended state failed. Could not find query %s", id);
  9175. }
  9176. void setQueryCommentForNamedQuery(IPropertyTree * queryRegistry, const char *id, const char *queryComment)
  9177. {
  9178. if (queryComment)
  9179. {
  9180. StringBuffer lcId(id);
  9181. lcId.toLowerCase();
  9182. StringBuffer xpath;
  9183. xpath.append("Query[@id=\"").append(lcId).append("\"]");
  9184. IPropertyTree *tree = queryRegistry->queryPropTree(xpath);
  9185. if (tree)
  9186. tree->setProp("@queryComment", queryComment);
  9187. else
  9188. throw MakeStringException(QUERRREG_COMMENT, "Could not find query %s", id);
  9189. }
  9190. }
  9191. extern WORKUNIT_API IPropertyTree * getQueryRegistryRoot()
  9192. {
  9193. Owned<IRemoteConnection> globalLock = querySDS().connect("/QuerySets/", myProcessSession(), RTM_LOCK_READ, SDS_LOCK_TIMEOUT);
  9194. if (!globalLock)
  9195. return NULL;
  9196. //Only lock the branch for the target we're interested in.
  9197. StringBuffer xpath;
  9198. xpath.append("/QuerySets");
  9199. Owned<IRemoteConnection> conn = querySDS().connect(xpath.str(), myProcessSession(), RTM_LOCK_READ, SDS_LOCK_TIMEOUT);
  9200. if (conn)
  9201. return conn->getRoot();
  9202. else
  9203. return NULL;
  9204. }
  9205. extern WORKUNIT_API void checkAddLibrariesToQueryEntry(IPropertyTree *queryTree, IConstWULibraryIterator *libraries)
  9206. {
  9207. if (!queryTree || !libraries)
  9208. return;
  9209. if (queryTree->hasProp("@libCount")) //already added
  9210. return;
  9211. unsigned libCount=0;
  9212. ForEach(*libraries)
  9213. {
  9214. IConstWULibrary &library = libraries->query();
  9215. SCMStringBuffer libname;
  9216. if (!library.getName(libname).length())
  9217. continue;
  9218. queryTree->addProp("Library", libname.str());
  9219. libCount++;
  9220. }
  9221. queryTree->setPropInt("@libCount", libCount);
  9222. }
  9223. extern WORKUNIT_API void checkAddLibrariesToQueryEntry(IPropertyTree *queryTree, IConstWorkUnit *cw)
  9224. {
  9225. Owned<IConstWULibraryIterator> libraries = &cw->getLibraries();
  9226. checkAddLibrariesToQueryEntry(queryTree, libraries);
  9227. }
  9228. extern WORKUNIT_API IPropertyTree * getQueryRegistry(const char * wsEclId, bool readonly)
  9229. {
  9230. Owned<IRemoteConnection> globalLock = querySDS().connect("/QuerySets/", myProcessSession(), RTM_LOCK_WRITE|RTM_CREATE_QUERY, SDS_LOCK_TIMEOUT);
  9231. //Only lock the branch for the target we're interested in.
  9232. StringBuffer xpath;
  9233. xpath.append("/QuerySets/QuerySet[@id=\"").append(wsEclId).append("\"]");
  9234. Owned<IRemoteConnection> conn = querySDS().connect(xpath.str(), myProcessSession(), readonly ? RTM_LOCK_READ : RTM_LOCK_WRITE, SDS_LOCK_TIMEOUT);
  9235. if (!conn)
  9236. {
  9237. if (readonly)
  9238. return NULL;
  9239. Owned<IPropertyTree> querySet = createPTree();
  9240. querySet->setProp("@id", wsEclId);
  9241. globalLock->queryRoot()->addPropTree("QuerySet", querySet.getClear());
  9242. globalLock->commit();
  9243. conn.setown(querySDS().connect(xpath.str(), myProcessSession(), RTM_LOCK_WRITE, SDS_LOCK_TIMEOUT));
  9244. if (!conn)
  9245. throwUnexpected();
  9246. }
  9247. return conn->getRoot();
  9248. }
  9249. IPropertyTree * addNamedPackageSet(IPropertyTree * packageRegistry, const char * name, IPropertyTree *packageInfo, bool overWrite)
  9250. {
  9251. StringBuffer xpath;
  9252. StringBuffer lcName(name);
  9253. lcName.toLowerCase();
  9254. // see if "name" already exists
  9255. xpath.append("Package[@id='").append(name).append("']");
  9256. IPropertyTree *pkgTree = packageRegistry->queryPropTree(xpath.str());
  9257. if (pkgTree)
  9258. {
  9259. if (overWrite)
  9260. packageRegistry->removeTree(pkgTree);
  9261. else
  9262. throw MakeStringException(WUERR_PackageAlreadyExists, "Package name %s already exists, either delete it or specify overwrite",name);
  9263. }
  9264. IPropertyTree *tree = packageRegistry->addPropTree("Package", packageInfo);
  9265. tree->setProp("@id", lcName);
  9266. return tree;
  9267. }
  9268. void removeNamedPackage(IPropertyTree * packageRegistry, const char * id)
  9269. {
  9270. StringBuffer lcId(id);
  9271. lcId.toLowerCase();
  9272. StringBuffer xpath;
  9273. xpath.append("Package[@id=\"").append(lcId).append("\"]");
  9274. packageRegistry->removeProp(xpath);
  9275. }
  9276. extern WORKUNIT_API IPropertyTree * getPackageSetRegistry(const char * wsEclId, bool readonly)
  9277. {
  9278. Owned<IRemoteConnection> globalLock = querySDS().connect("/PackageSets/", myProcessSession(), RTM_LOCK_WRITE|RTM_CREATE_QUERY, SDS_LOCK_TIMEOUT);
  9279. //Only lock the branch for the target we're interested in.
  9280. StringBuffer xpath;
  9281. xpath.append("/PackageSets/PackageSet[@id=\"").append(wsEclId).append("\"]");
  9282. Owned<IRemoteConnection> conn = querySDS().connect(xpath.str(), myProcessSession(), readonly ? RTM_LOCK_READ : RTM_LOCK_WRITE, SDS_LOCK_TIMEOUT);
  9283. if (!conn)
  9284. {
  9285. if (readonly)
  9286. return NULL;
  9287. Owned<IPropertyTree> querySet = createPTree();
  9288. querySet->setProp("@id", wsEclId);
  9289. globalLock->queryRoot()->addPropTree("PackageSet", querySet.getClear());
  9290. globalLock->commit();
  9291. conn.setown(querySDS().connect(xpath.str(), myProcessSession(), RTM_LOCK_WRITE, SDS_LOCK_TIMEOUT));
  9292. if (!conn)
  9293. throwUnexpected();
  9294. }
  9295. return conn->getRoot();
  9296. }
  9297. void addQueryToQuerySet(IWorkUnit *workunit, IPropertyTree *queryRegistry, const char *queryName, WUQueryActivationOptions activateOption, StringBuffer &newQueryId, const char *userid)
  9298. {
  9299. StringBuffer cleanQueryName;
  9300. appendUtf8XmlName(cleanQueryName, strlen(queryName), queryName);
  9301. SCMStringBuffer dllName;
  9302. Owned<IConstWUQuery> q = workunit->getQuery();
  9303. q->getQueryDllName(dllName);
  9304. if (!dllName.length())
  9305. throw MakeStringException(WUERR_InvalidDll, "Cannot deploy query - no associated dll.");
  9306. SCMStringBuffer wuid;
  9307. workunit->getWuid(wuid);
  9308. StringBuffer currentTargetClusterType;
  9309. queryRegistry->getProp("@targetclustertype", currentTargetClusterType);
  9310. SCMStringBuffer targetClusterType;
  9311. workunit->getDebugValue("targetclustertype", targetClusterType);
  9312. SCMStringBuffer snapshot;
  9313. workunit->getSnapshot(snapshot);
  9314. if (currentTargetClusterType.length() < 1)
  9315. {
  9316. queryRegistry->setProp("@targetclustertype", targetClusterType.str());
  9317. }
  9318. else
  9319. {
  9320. if (strcmp(currentTargetClusterType.str(), "roxie") == 0 && strcmp(currentTargetClusterType.str(), targetClusterType.str())!=0)
  9321. {
  9322. throw MakeStringException(WUERR_MismatchClusterType, "TargetClusterTypes of workunit and queryset do not match.");
  9323. }
  9324. }
  9325. IPropertyTree *newEntry = addNamedQuery(queryRegistry, cleanQueryName, wuid.str(), dllName.str(), isLibrary(workunit), userid, snapshot.str());
  9326. Owned<IConstWULibraryIterator> libraries = &workunit->getLibraries();
  9327. checkAddLibrariesToQueryEntry(newEntry, libraries);
  9328. newQueryId.append(newEntry->queryProp("@id"));
  9329. workunit->setIsQueryService(true); //will check querysets before delete
  9330. workunit->commit();
  9331. activateQuery(queryRegistry, activateOption, queryName, newQueryId, userid);
  9332. }
  9333. void activateQuery(IPropertyTree *queryRegistry, WUQueryActivationOptions activateOption, const char *queryName, const char *queryId, const char *userid)
  9334. {
  9335. StringBuffer cleanQueryName;
  9336. appendUtf8XmlName(cleanQueryName, strlen(queryName), queryName);
  9337. if (activateOption == ACTIVATE_SUSPEND_PREVIOUS|| activateOption == ACTIVATE_DELETE_PREVIOUS)
  9338. {
  9339. Owned<IPropertyTree> prevQuery = resolveQueryAlias(queryRegistry, cleanQueryName);
  9340. setQueryAlias(queryRegistry, cleanQueryName, queryId);
  9341. if (prevQuery && !streq(queryId, prevQuery->queryProp("@id")))
  9342. {
  9343. if (activateOption == ACTIVATE_SUSPEND_PREVIOUS)
  9344. setQuerySuspendedState(queryRegistry, prevQuery->queryProp("@id"), true, userid);
  9345. else
  9346. removeNamedQuery(queryRegistry, prevQuery->queryProp("@id"));
  9347. }
  9348. }
  9349. else if (activateOption == MAKE_ACTIVATE || activateOption == MAKE_ACTIVATE_LOAD_DATA_ONLY)
  9350. setQueryAlias(queryRegistry, cleanQueryName, queryId);
  9351. }
  9352. void addQueryToQuerySet(IWorkUnit *workunit, const char *querySetName, const char *queryName, WUQueryActivationOptions activateOption, StringBuffer &newQueryId, const char *userid)
  9353. {
  9354. Owned<IPropertyTree> queryRegistry = getQueryRegistry(querySetName, false);
  9355. addQueryToQuerySet(workunit, queryRegistry, queryName, activateOption, newQueryId, userid);
  9356. }
  9357. bool removeQuerySetAlias(const char *querySetName, const char *alias)
  9358. {
  9359. Owned<IPropertyTree> queryRegistry = getQueryRegistry(querySetName, true);
  9360. StringBuffer xpath;
  9361. xpath.appendf("Alias[@name='%s']", alias);
  9362. IPropertyTree *t = queryRegistry->queryPropTree(xpath);
  9363. return queryRegistry->removeTree(t);
  9364. }
  9365. void addQuerySetAlias(const char *querySetName, const char *alias, const char *id)
  9366. {
  9367. Owned<IPropertyTree> queryRegistry = getQueryRegistry(querySetName, false);
  9368. setQueryAlias(queryRegistry, alias, id);
  9369. }
  9370. void setSuspendQuerySetQuery(const char *querySetName, const char *id, bool suspend, const char *userid)
  9371. {
  9372. Owned<IPropertyTree> queryRegistry = getQueryRegistry(querySetName, true);
  9373. setQuerySuspendedState(queryRegistry, id, suspend, userid);
  9374. }
  9375. void deleteQuerySetQuery(const char *querySetName, const char *id)
  9376. {
  9377. Owned<IPropertyTree> queryRegistry = getQueryRegistry(querySetName, true);
  9378. removeNamedQuery(queryRegistry, id);
  9379. }
  9380. void removeQuerySetAliasesFromNamedQuery(const char *querySetName, const char * id)
  9381. {
  9382. Owned<IPropertyTree> queryRegistry = getQueryRegistry(querySetName, true);
  9383. clearAliases(queryRegistry, id);
  9384. }
  9385. void setQueryCommentForNamedQuery(const char *querySetName, const char *id, const char *queryComment)
  9386. {
  9387. Owned<IPropertyTree> queryRegistry = getQueryRegistry(querySetName, true);
  9388. setQueryCommentForNamedQuery(queryRegistry, id, queryComment);
  9389. }
  9390. const char *queryIdFromQuerySetWuid(IPropertyTree *queryRegistry, const char *wuid, const char *queryName, IStringVal &id)
  9391. {
  9392. if (!queryRegistry)
  9393. return NULL;
  9394. StringBuffer xpath;
  9395. xpath.appendf("Query[@wuid='%s']", wuid);
  9396. if (queryName && *queryName)
  9397. xpath.appendf("[@name='%s']", queryName);
  9398. IPropertyTree *q = queryRegistry->queryPropTree(xpath.str());
  9399. if (q)
  9400. {
  9401. id.set(q->queryProp("@id"));
  9402. }
  9403. return id.str();
  9404. }
  9405. const char *queryIdFromQuerySetWuid(const char *querySetName, const char *wuid, const char *queryName, IStringVal &id)
  9406. {
  9407. Owned<IPropertyTree> queryRegistry = getQueryRegistry(querySetName, true);
  9408. return queryIdFromQuerySetWuid(queryRegistry, wuid, queryName, id);
  9409. }
  9410. extern WORKUNIT_API void gatherLibraryNames(StringArray &names, StringArray &unresolved, IWorkUnitFactory &workunitFactory, IConstWorkUnit &cw, IPropertyTree *queryset)
  9411. {
  9412. IConstWULibraryIterator &wulibraries = cw.getLibraries();
  9413. ForEach(wulibraries)
  9414. {
  9415. SCMStringBuffer libname;
  9416. IConstWULibrary &wulibrary = wulibraries.query();
  9417. wulibrary.getName(libname);
  9418. if (names.contains(libname.str()) || unresolved.contains(libname.str()))
  9419. continue;
  9420. Owned<IPropertyTree> query = resolveQueryAlias(queryset, libname.str());
  9421. if (query && query->getPropBool("@isLibrary"))
  9422. {
  9423. const char *wuid = query->queryProp("@wuid");
  9424. Owned<IConstWorkUnit> libcw = workunitFactory.openWorkUnit(wuid, false);
  9425. if (libcw)
  9426. {
  9427. names.appendUniq(libname.str());
  9428. gatherLibraryNames(names, unresolved, workunitFactory, *libcw, queryset);
  9429. continue;
  9430. }
  9431. }
  9432. unresolved.appendUniq(libname.str());
  9433. }
  9434. }
  9435. bool looksLikeAWuid(const char * wuid)
  9436. {
  9437. if (!wuid)
  9438. return false;
  9439. if (wuid[0] != 'W')
  9440. return false;
  9441. if (!isdigit(wuid[1]) || !isdigit(wuid[2]) || !isdigit(wuid[3]) || !isdigit(wuid[4]))
  9442. return false;
  9443. if (!isdigit(wuid[5]) || !isdigit(wuid[6]) || !isdigit(wuid[7]) || !isdigit(wuid[8]))
  9444. return false;
  9445. return (wuid[9]=='-');
  9446. }
  9447. IPropertyTree * resolveDefinitionInArchive(IPropertyTree * archive, const char * path)
  9448. {
  9449. IPropertyTree * module = archive;
  9450. const char * dot = strrchr(path, '.');
  9451. StringBuffer xpath;
  9452. if (dot)
  9453. {
  9454. xpath.clear().append("Module[@key='").appendLower(dot-path, path).append("']");
  9455. module = archive->queryPropTree(xpath);
  9456. path = dot+1;
  9457. }
  9458. else
  9459. module = archive->queryPropTree("Module[@key='']");
  9460. if (!module)
  9461. return NULL;
  9462. xpath.clear().append("Attribute[@key='").appendLower(strlen(path), path).append("']");
  9463. return module->queryPropTree(xpath);
  9464. }
  9465. extern WORKUNIT_API void associateLocalFile(IWUQuery * query, WUFileType type, const char * name, const char * description, unsigned crc)
  9466. {
  9467. StringBuffer hostname;
  9468. queryHostIP().getIpText(hostname);
  9469. StringBuffer fullPathname;
  9470. makeAbsolutePath(name, fullPathname);
  9471. query->addAssociatedFile(type, fullPathname, hostname, description, crc);
  9472. }
  9473. extern WORKUNIT_API void descheduleWorkunit(char const * wuid)
  9474. {
  9475. Owned<IWorkUnitFactory> factory = getWorkUnitFactory();
  9476. Owned<IWorkUnit> workunit = factory->updateWorkUnit(wuid);
  9477. if(workunit)
  9478. workunit->deschedule();
  9479. else
  9480. doDescheduleWorkkunit(wuid);
  9481. }
  9482. extern WORKUNIT_API void updateWorkunitTimeStat(IWorkUnit * wu, const char * component, const char * wuScope, const char * stat, const char * description, unsigned __int64 value, unsigned __int64 count, unsigned __int64 maxValue)
  9483. {
  9484. if (!wuScope)
  9485. wuScope = "workunit";
  9486. if (!stat)
  9487. stat = "time";
  9488. //The following line duplicates the statistics as timing information - preserved temporarily to show refactoring.
  9489. //wu->setTimerInfo(description, (unsigned)(value/1000000), (unsigned)count, (unsigned)maxValue);
  9490. wu->setStatistic(component, wuScope, stat, description, SMEASURE_TIME_NS, value, count, maxValue, false);
  9491. }
  9492. extern WORKUNIT_API void updateWorkunitTiming(IWorkUnit * wu, const char * component, const char * mangledScope, const char * description, unsigned __int64 value, unsigned __int64 count, unsigned __int64 maxValue)
  9493. {
  9494. StringAttr scopeText;
  9495. StringAttr componentText;
  9496. const char * wuScope = mangledScope;
  9497. const char * stat = "time";
  9498. //If the scope contains a semicolon then it is taken to mean (wuScope;stat or comonent;wuScope;stat)
  9499. const char * sep1 = strchr(mangledScope, ';');
  9500. if (sep1)
  9501. {
  9502. const char * sep2 = strchr(sep1+1, ';');
  9503. if (sep2)
  9504. {
  9505. componentText.set(mangledScope, sep1 - mangledScope);
  9506. scopeText.set(sep1+1, sep2-(sep1+1));
  9507. component = componentText;
  9508. wuScope = scopeText;
  9509. stat = sep2+1;
  9510. }
  9511. else
  9512. {
  9513. scopeText.set(mangledScope, sep1-mangledScope);
  9514. wuScope = scopeText.get();
  9515. stat = sep1+1;
  9516. }
  9517. }
  9518. updateWorkunitTimeStat(wu, component, wuScope, stat, description, value, count, maxValue);
  9519. }
  9520. extern WORKUNIT_API void updateWorkunitTimings(IWorkUnit * wu, ITimeReporter *timer, const char * component)
  9521. {
  9522. StringBuffer description;
  9523. StringBuffer scope;
  9524. for (unsigned i = 0; i < timer->numSections(); i++)
  9525. {
  9526. timer->getDescription(i, description.clear());
  9527. timer->getScope(i, scope.clear());
  9528. updateWorkunitTiming(wu, component, scope, description, timer->getTime(i), timer->getCount(i), timer->getMaxTime(i));
  9529. }
  9530. }