ws_dfuService.cpp 241 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680
  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. #pragma warning (disable : 4786)
  14. #include <math.h>
  15. #include "daclient.hpp"
  16. #include "daft.hpp"
  17. #include "daftcfg.hpp"
  18. #include "fterror.hpp"
  19. #include "fverror.hpp"
  20. #include "daftprogress.hpp"
  21. #include "mpbase.hpp"
  22. #include "daclient.hpp"
  23. #include "dadfs.hpp"
  24. #include "dafdesc.hpp"
  25. #include "dasds.hpp"
  26. #include "danqs.hpp"
  27. #include "dalienv.hpp"
  28. #include "dautils.hpp"
  29. #include "jfile.hpp"
  30. #include "wshelpers.hpp"
  31. #include "LogicFileWrapper.hpp"
  32. #include "rmtfile.hpp"
  33. #include "dfuutil.hpp"
  34. #include "TpWrapper.hpp"
  35. #include "WUWrapper.hpp"
  36. #include "portlist.h"
  37. #include "dfuwu.hpp"
  38. #include "fverror.hpp"
  39. #include "nbcd.hpp"
  40. #include "thorcommon.hpp"
  41. #include "jstats.h"
  42. #include "jstring.hpp"
  43. #include "exception_util.hpp"
  44. #include "hqlerror.hpp"
  45. #include "hqlexpr.hpp"
  46. #include "hqlutil.hpp"
  47. #include "eclrtl.hpp"
  48. #include "package.h"
  49. #include "daaudit.hpp"
  50. #include "jflz.hpp"
  51. #include "digisign.hpp"
  52. #include "wsdfuaccess/wsdfuaccess.hpp"
  53. #include "ws_dfuService.hpp"
  54. using namespace wsdfuaccess;
  55. using namespace cryptohelper;
  56. #define Action_Delete "Delete"
  57. #define Action_AddtoSuperfile "Add To Superfile"
  58. static const char* FEATURE_URL="DfuAccess";
  59. #define FILE_NEWEST 1
  60. #define FILE_OLDEST 2
  61. #define FILE_LARGEST 3
  62. #define FILE_SMALLEST 4
  63. #define COUNTBY_SCOPE "Scope"
  64. #define COUNTBY_OWNER "Owner"
  65. #define COUNTBY_DATE "Date"
  66. #define COUNTBY_YEAR "Year"
  67. #define COUNTBY_QUARTER "Quarter"
  68. #define COUNTBY_MONTH "Month"
  69. #define COUNTBY_DAY "Day"
  70. #define REMOVE_FILE_SDS_CONNECT_TIMEOUT (1000*15) // 15 seconds
  71. static const char *DFUFileIdSeparator = "|";
  72. static const char *DFUFileCreate_FileNamePostfix = ".wsdfucreate.tmp";
  73. static const char *DFUFileCreate_GroupNamePrefix = "wsdfucreate";
  74. static const char *ConfigurationDirectoryForDataCategory = "data";
  75. static std::atomic<unsigned> dfuCreateUniqId{1};
  76. const unsigned NODE_GROUP_CACHE_DEFAULT_TIMEOUT = 30*60*1000; //30 minutes
  77. const unsigned MAX_VIEWKEYFILE_ROWS = 1000;
  78. const unsigned MAX_KEY_ROWS = 20;
  79. short days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  80. CThorNodeGroup* CThorNodeGroupCache::readNodeGroup(const char* _groupName)
  81. {
  82. #ifndef _CONTAINERIZED
  83. Owned<IEnvironmentFactory> factory = getEnvironmentFactory(true);
  84. Owned<IConstEnvironment> env = factory->openEnvironment();
  85. Owned<IPropertyTree> root = &env->getPTree();
  86. Owned<IPropertyTreeIterator> it= root->getElements("Software/ThorCluster");
  87. ForEach(*it)
  88. {
  89. IPropertyTree& cluster = it->query();
  90. StringBuffer groupName;
  91. getClusterGroupName(cluster, groupName);
  92. if (groupName.length() && strieq(groupName.str(), _groupName))
  93. return new CThorNodeGroup(_groupName, cluster.getCount("ThorSlaveProcess"), cluster.getPropBool("@replicateOutputs", false));
  94. }
  95. #endif
  96. return NULL;
  97. }
  98. CThorNodeGroup* CThorNodeGroupCache::lookup(const char* groupName, unsigned timeout)
  99. {
  100. CriticalBlock block(sect);
  101. CThorNodeGroup* item=SuperHashTableOf<CThorNodeGroup, const char>::find(groupName);
  102. if (item && !item->checkTimeout(timeout))
  103. return LINK(item);
  104. Owned<CThorNodeGroup> e = readNodeGroup(groupName);
  105. if (e)
  106. replace(*e.getLink()); //if not exists, will be added.
  107. return e.getClear();
  108. }
  109. void CWsDfuEx::init(IPropertyTree *cfg, const char *process, const char *service)
  110. {
  111. DBGLOG("Initializing %s service [process = %s]", service, process);
  112. espProcess.set(process);
  113. VStringBuffer xpath("Software/EspProcess[@name=\"%s\"]", process);
  114. IPropertyTree *processTree = cfg->queryPropTree(xpath);
  115. if (!processTree)
  116. throw MakeStringException(-1, "config not found for process %s", process);
  117. xpath.clear().appendf("EspService[@name=\"%s\"]", service);
  118. IPropertyTree *serviceTree = processTree->queryPropTree(xpath);
  119. if (!serviceTree)
  120. throw MakeStringException(-1, "config not found for service %s", service);
  121. serviceTree->getProp("DefaultScope", defaultScope_);
  122. serviceTree->getProp("User", user_);
  123. serviceTree->getProp("Password", password_);
  124. StringBuffer disableUppercaseTranslation;
  125. serviceTree->getProp("DisableUppercaseTranslation", disableUppercaseTranslation);
  126. m_clusterName.clear();
  127. serviceTree->getProp("ClusterName", m_clusterName);
  128. const char * plugins = serviceTree->queryProp("Plugins/@path");
  129. if (plugins)
  130. queryTransformerRegistry().addPlugins(plugins);
  131. m_disableUppercaseTranslation = false;
  132. if (streq(disableUppercaseTranslation.str(), "true"))
  133. m_disableUppercaseTranslation = true;
  134. if (processTree->hasProp("@PageCacheTimeoutSeconds"))
  135. setPageCacheTimeoutMilliSeconds(processTree->getPropInt("@PageCacheTimeoutSeconds"));
  136. if (processTree->hasProp("@MaxPageCacheItems"))
  137. setMaxPageCacheItems(processTree->getPropInt("@MaxPageCacheItems"));
  138. int timeout = serviceTree->getPropInt("NodeGroupCacheMinutes", -1);
  139. if (timeout > -1)
  140. nodeGroupCacheTimeout = (unsigned) timeout*60*1000;
  141. else
  142. nodeGroupCacheTimeout = NODE_GROUP_CACHE_DEFAULT_TIMEOUT;
  143. thorNodeGroupCache.setown(new CThorNodeGroupCache());
  144. if (!daliClientActive())
  145. throw MakeStringException(-1, "No Dali Connection Active. Please Specify a Dali to connect to in you configuration file");
  146. setDaliServixSocketCaching(true);
  147. #ifdef _CONTAINERIZED
  148. IERRLOG("CONTAINERIZED(CWsDfuEx::init)");
  149. maxFileAccessExpirySeconds = defaultMaxFileAccessExpirySeconds;
  150. #else
  151. factory.setown(getEnvironmentFactory(true));
  152. env.setown(factory->openEnvironment());
  153. #endif
  154. maxFileAccessExpirySeconds = serviceTree->getPropInt("@maxFileAccessExpirySeconds", defaultMaxFileAccessExpirySeconds);
  155. }
  156. bool CWsDfuEx::onDFUSearch(IEspContext &context, IEspDFUSearchRequest & req, IEspDFUSearchResponse & resp)
  157. {
  158. try
  159. {
  160. context.ensureFeatureAccess(FEATURE_URL, SecAccess_Read, ECLWATCH_DFU_ACCESS_DENIED, "WsDfu::DFUSearch: Permission denied.");
  161. StringBuffer username;
  162. context.getUserID(username);
  163. Owned<IUserDescriptor> userdesc;
  164. if(username.length() > 0)
  165. {
  166. userdesc.setown(createUserDescriptor());
  167. userdesc->set(username.str(), context.queryPassword(), context.querySignature());
  168. }
  169. CTpWrapper dummy;
  170. IArrayOf<IEspTpCluster> clusters;
  171. dummy.getClusterProcessList(eqThorCluster, clusters);
  172. dummy.getHthorClusterList(clusters);
  173. StringArray dfuclusters;
  174. ForEachItemIn(k, clusters)
  175. {
  176. IEspTpCluster& cluster = clusters.item(k);
  177. dfuclusters.append(cluster.getName());
  178. }
  179. IArrayOf<IEspTpCluster> clusters1;
  180. dummy.getClusterProcessList(eqRoxieCluster, clusters1);
  181. ForEachItemIn(k1, clusters1)
  182. {
  183. IEspTpCluster& cluster = clusters1.item(k1);
  184. StringBuffer slaveName(cluster.getName());
  185. dfuclusters.append(slaveName.str());
  186. }
  187. StringArray ftarray;
  188. ftarray.append("Logical Files and Superfiles");
  189. ftarray.append("Logical Files Only");
  190. ftarray.append("Superfiles Only");
  191. ftarray.append("Not in Superfiles");
  192. if (req.getShowExample() && *req.getShowExample())
  193. resp.setShowExample(req.getShowExample());
  194. resp.setClusterNames(dfuclusters);
  195. resp.setFileTypes(ftarray);
  196. }
  197. catch(IException* e)
  198. {
  199. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  200. }
  201. return true;
  202. }
  203. void addToQueryString(StringBuffer &queryString, const char *name, const char *value)
  204. {
  205. if (queryString.length() > 0)
  206. {
  207. queryString.append("&");
  208. }
  209. queryString.append(name);
  210. queryString.append("=");
  211. queryString.append(value);
  212. }
  213. void addToQueryStringFromInt(StringBuffer &queryString, const char *name, __int64 value)
  214. {
  215. if (queryString.length() > 0)
  216. {
  217. queryString.append("&");
  218. }
  219. queryString.append(name);
  220. queryString.append("=");
  221. queryString.append(value);
  222. }
  223. void parseTwoStringArrays(const char *input, StringArray& strarray1, StringArray& strarray2)
  224. {
  225. if (!input || strlen(input) <= 2)
  226. return;
  227. char c0[2], c1[2];
  228. c0[0] = input[0], c0[1] = 0;
  229. c1[0] = input[1], c1[1] = 0;
  230. //the first string usually is a name; the second is a value
  231. unsigned int name_len = atoi(c0);
  232. unsigned int value_len = atoi(c1);
  233. if (name_len > 0 && value_len > 0)
  234. {
  235. char * inputText = (char *) input;
  236. inputText += 2; //skip 2 chars
  237. for (;;)
  238. {
  239. if (!inputText || strlen(inputText) < name_len + value_len)
  240. break;
  241. StringBuffer columnNameLenStr, columnValueLenStr;
  242. for (unsigned i_name = 0; i_name < name_len; i_name++)
  243. {
  244. columnNameLenStr.append(inputText[0]);
  245. inputText++;
  246. }
  247. for (unsigned i_value = 0; i_value < value_len; i_value++)
  248. {
  249. columnValueLenStr.append(inputText[0]);
  250. inputText++;
  251. }
  252. unsigned columnNameLen = atoi(columnNameLenStr.str());
  253. unsigned columnValueLen = atoi(columnValueLenStr.str());
  254. if (!inputText || strlen(inputText) < columnNameLen + columnValueLen)
  255. break;
  256. char * colon = inputText + columnNameLen;
  257. if (!colon)
  258. break;
  259. StringAttr tmp;
  260. tmp.set(inputText, columnNameLen);
  261. strarray1.append(tmp.get());
  262. tmp.set(colon, columnValueLen);
  263. //tmp.toUpperCase();
  264. strarray2.append(tmp.get());
  265. inputText = colon + columnValueLen;
  266. }
  267. }
  268. return;
  269. }
  270. bool CWsDfuEx::onDFUQuery(IEspContext &context, IEspDFUQueryRequest & req, IEspDFUQueryResponse & resp)
  271. {
  272. try
  273. {
  274. context.ensureFeatureAccess(FEATURE_URL, SecAccess_Read, ECLWATCH_DFU_ACCESS_DENIED, "WsDfu::DFUQuery: Permission denied.");
  275. StringBuffer username;
  276. context.getUserID(username);
  277. Owned<IUserDescriptor> userdesc;
  278. if(username.length() > 0)
  279. {
  280. userdesc.setown(createUserDescriptor());
  281. userdesc->set(username.str(), context.queryPassword(), context.querySignature());
  282. }
  283. doLogicalFileSearch(context, userdesc.get(), req, resp);
  284. }
  285. catch(IException* e)
  286. {
  287. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  288. }
  289. return true;
  290. }
  291. bool CWsDfuEx::onDFUInfo(IEspContext &context, IEspDFUInfoRequest &req, IEspDFUInfoResponse &resp)
  292. {
  293. try
  294. {
  295. context.ensureFeatureAccess(FEATURE_URL, SecAccess_Read, ECLWATCH_DFU_ACCESS_DENIED, "WsDfu::DFUInfo: Permission denied.");
  296. StringBuffer username;
  297. context.getUserID(username);
  298. Owned<IUserDescriptor> userdesc;
  299. if(username.length() > 0)
  300. {
  301. userdesc.setown(createUserDescriptor());
  302. userdesc->set(username.str(), context.queryPassword(), context.querySignature());
  303. }
  304. if (req.getUpdateDescription())
  305. {
  306. double version = context.getClientVersion();
  307. if (version < 1.38)
  308. doGetFileDetails(context, userdesc.get(), req.getFileName(), req.getCluster(), req.getQuerySet(), req.getQuery(), req.getFileDesc(),
  309. req.getIncludeJsonTypeInfo(), req.getIncludeBinTypeInfo(), req.getProtect(), req.getRestrict(), resp.updateFileDetail());
  310. else
  311. doGetFileDetails(context, userdesc.get(), req.getName(), req.getCluster(), req.getQuerySet(), req.getQuery(), req.getFileDesc(),
  312. req.getIncludeJsonTypeInfo(), req.getIncludeBinTypeInfo(), req.getProtect(), req.getRestrict(), resp.updateFileDetail());
  313. }
  314. else
  315. {
  316. doGetFileDetails(context, userdesc.get(), req.getName(), req.getCluster(), req.getQuerySet(), req.getQuery(), NULL,
  317. req.getIncludeJsonTypeInfo(), req.getIncludeBinTypeInfo(), req.getProtect(), req.getRestrict(), resp.updateFileDetail());
  318. }
  319. }
  320. catch(IException* e)
  321. {
  322. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  323. }
  324. return true;
  325. }
  326. bool CWsDfuEx::onDFUSpace(IEspContext &context, IEspDFUSpaceRequest & req, IEspDFUSpaceResponse & resp)
  327. {
  328. try
  329. {
  330. context.ensureFeatureAccess(FEATURE_URL, SecAccess_Read, ECLWATCH_DFU_ACCESS_DENIED, "WsDfu::DFUSpace: Permission denied.");
  331. StringBuffer username;
  332. context.getUserID(username);
  333. Owned<IUserDescriptor> userdesc;
  334. if(username.length() > 0)
  335. {
  336. userdesc.setown(createUserDescriptor());
  337. userdesc->set(username.str(), context.queryPassword(), context.querySignature());
  338. }
  339. const char *countby = req.getCountBy();
  340. if (!countby || strlen(countby) < 1)
  341. return true;
  342. char *scopeName = NULL;
  343. StringBuffer filter;
  344. if(req.getScopeUnder() && *req.getScopeUnder())
  345. {
  346. scopeName = (char *) req.getScopeUnder();
  347. filter.appendf("%s::*", scopeName);
  348. resp.setScopeUnder(req.getScopeUnder());
  349. }
  350. else
  351. {
  352. filter.append("*");
  353. }
  354. PROGLOG("DFUSpace: filter %s ", filter.str());
  355. Owned<IDFAttributesIterator> fi = queryDistributedFileDirectory().getDFAttributesIterator(filter, userdesc.get(), true, false, NULL);
  356. if(!fi)
  357. throw MakeStringException(ECLWATCH_CANNOT_GET_FILE_ITERATOR,"Cannot get information from file system.");
  358. const char *ownerUnder = NULL;
  359. if(req.getOwnerUnder() && *req.getOwnerUnder())
  360. {
  361. ownerUnder = req.getOwnerUnder();
  362. resp.setOwnerUnder(ownerUnder);
  363. }
  364. StringBuffer wuFrom, wuTo, interval;
  365. unsigned yearFrom = 0, monthFrom, dayFrom, yearTo = 0, monthTo, dayTo, hour, minute, second, nano;
  366. if(req.getStartDate() && *req.getStartDate())
  367. {
  368. CDateTime wuTime;
  369. wuTime.setString(req.getStartDate(),NULL,true);
  370. wuTime.getDate(yearFrom, monthFrom, dayFrom, true);
  371. wuTime.getTime(hour, minute, second, nano, true);
  372. wuFrom.appendf("%4d-%02d-%02d %02d:%02d:%02d",yearFrom,monthFrom,dayFrom,hour,minute,second);
  373. StringBuffer startDate;
  374. startDate.appendf("%02d/%02d/%04d", monthFrom, dayFrom, yearFrom);
  375. resp.setStartDate(startDate.str());
  376. }
  377. if(req.getEndDate() && *req.getEndDate())
  378. {
  379. CDateTime wuTime;
  380. wuTime.setString(req.getEndDate(),NULL,true);
  381. wuTime.getDate(yearTo, monthTo, dayTo, true);
  382. wuTime.getTime(hour, minute, second, nano, true);
  383. wuTo.appendf("%4d-%02d-%02d %02d:%02d:%02d",yearTo,monthTo,dayTo,hour,minute,second);
  384. StringBuffer endDate;
  385. endDate.appendf("%02d/%02d/%04d", monthTo, dayTo, yearTo);
  386. resp.setEndDate(endDate.str());
  387. }
  388. unsigned i = 0;
  389. IArrayOf<IEspSpaceItem> SpaceItems64;
  390. if (!stricmp(countby, COUNTBY_DATE))
  391. {
  392. if (yearFrom < 1 || yearTo < 1)
  393. {
  394. StringBuffer wuFrom, wuTo;
  395. bool bFirst = true;
  396. ForEach(*fi)
  397. {
  398. IPropertyTree &attr=fi->query();
  399. StringBuffer modf(attr.queryProp("@modified"));
  400. //char* t=strchr(modf.str(),'T');
  401. //if(t) *t=' ';
  402. if (bFirst)
  403. {
  404. bFirst = false;
  405. wuFrom = modf.str();
  406. wuTo = modf.str();
  407. continue;
  408. }
  409. if (strcmp(modf.str(),wuFrom.str())<0)
  410. wuFrom = modf.str();
  411. if (strcmp(modf.str(),wuTo.str())>0)
  412. wuTo = modf.str();
  413. }
  414. if (yearFrom < 1)
  415. {
  416. CDateTime wuTime;
  417. wuTime.setString(wuFrom.str(),NULL,true);
  418. wuTime.getDate(yearFrom, monthFrom, dayFrom, true);
  419. }
  420. if (yearTo < 1)
  421. {
  422. CDateTime wuTime;
  423. wuTime.setString(wuTo.str(),NULL,true);
  424. wuTime.getDate(yearTo, monthTo, dayTo, true);
  425. }
  426. }
  427. interval = req.getInterval();
  428. resp.setInterval(interval);
  429. createSpaceItemsByDate(SpaceItems64, interval, yearFrom, monthFrom, dayFrom, yearTo, monthTo, dayTo);
  430. }
  431. else
  432. {
  433. Owned<IEspSpaceItem> item64 = createSpaceItem();
  434. if (!strieq(countby, COUNTBY_OWNER))
  435. {
  436. if (scopeName)
  437. item64->setName(scopeName);
  438. else
  439. item64->setName("(root)");
  440. }
  441. else
  442. {
  443. item64->setName("(empty)");
  444. }
  445. item64->setNumOfFilesInt(0);
  446. item64->setNumOfFilesIntUnknown(0);
  447. item64->setTotalSizeInt(0);
  448. item64->setLargestSizeInt(0);
  449. item64->setSmallestSizeInt(0);
  450. item64->setLargestFile("");
  451. item64->setSmallestFile("");
  452. SpaceItems64.append(*item64.getClear());
  453. }
  454. ForEach(*fi)
  455. {
  456. IPropertyTree &attr=fi->query();
  457. if (attr.hasProp("@numsubfiles"))
  458. continue; //exclude superfiles
  459. if (ownerUnder)
  460. {
  461. const char* owner=attr.queryProp("@owner");
  462. if (owner && stricmp(owner, ownerUnder))
  463. continue;
  464. }
  465. StringBuffer modf(attr.queryProp("@modified"));
  466. char* t= (char *) strchr(modf.str(),'T');
  467. if(t) *t=' ';
  468. if (wuFrom.length() && strcmp(modf.str(),wuFrom.str())<0)
  469. continue;
  470. if (wuTo.length() && strcmp(modf.str(),wuTo.str())>0)
  471. continue;
  472. if (!stricmp(countby, COUNTBY_DATE))
  473. {
  474. setSpaceItemByDate(SpaceItems64, interval, attr.queryProp("@modified"), attr.queryProp("@name"), attr.getPropInt64("@size",-1));
  475. }
  476. else if (!stricmp(countby, COUNTBY_OWNER))
  477. {
  478. setSpaceItemByOwner(SpaceItems64, attr.queryProp("@owner"), attr.queryProp("@name"), attr.getPropInt64("@size",-1));
  479. }
  480. else
  481. {
  482. setSpaceItemByScope(SpaceItems64, scopeName, attr.queryProp("@name"), attr.getPropInt64("@size",-1));
  483. }
  484. }
  485. i = 0;
  486. IEspSpaceItem& item0 = SpaceItems64.item(0);
  487. if (item0.getNumOfFilesInt() < 1)
  488. {
  489. i++;
  490. }
  491. double version = context.getClientVersion();
  492. IArrayOf<IEspDFUSpaceItem> SpaceItems;
  493. for(; i < SpaceItems64.length();i++)
  494. {
  495. IEspSpaceItem& item64 = SpaceItems64.item(i);
  496. if (item64.getNumOfFilesInt() < 1)
  497. continue;
  498. StringBuffer buf;
  499. Owned<IEspDFUSpaceItem> item1 = createDFUSpaceItem("","");
  500. __int64 numOfFiles = item64.getNumOfFilesInt();
  501. __int64 numOfFilesIntUnknown = item64.getNumOfFilesIntUnknown();
  502. __int64 totalSize = item64.getTotalSizeInt();
  503. __int64 largestSize = item64.getLargestSizeInt();
  504. __int64 smallestSize = item64.getSmallestSizeInt();
  505. if (version >= 1.38)
  506. {
  507. item1->setNumOfFilesInt64(numOfFiles);
  508. item1->setNumOfFilesUnknownInt64(numOfFilesIntUnknown);
  509. item1->setTotalSizeInt64(totalSize);
  510. item1->setLargestSizeInt64(largestSize);
  511. item1->setSmallestSizeInt64(smallestSize);
  512. }
  513. item1->setName(item64.getName());
  514. buf << comma(numOfFiles);
  515. item1->setNumOfFiles(buf.str());
  516. buf.clear();
  517. buf << comma(numOfFilesIntUnknown);
  518. item1->setNumOfFilesUnknown(buf.str());
  519. buf.clear();
  520. buf << comma(totalSize);
  521. item1->setTotalSize(buf.str());
  522. buf.clear();
  523. buf << comma(largestSize);
  524. item1->setLargestSize(buf.str());
  525. buf.clear();
  526. buf << comma(smallestSize);
  527. item1->setSmallestSize(buf.str());
  528. item1->setLargestFile(item64.getLargestFile());
  529. item1->setSmallestFile(item64.getSmallestFile());
  530. SpaceItems.append(*item1.getClear());
  531. }
  532. resp.setDFUSpaceItems(SpaceItems);
  533. resp.setCountBy(req.getCountBy());
  534. }
  535. catch(IException* e)
  536. {
  537. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  538. }
  539. return true;
  540. }
  541. bool CWsDfuEx::setSpaceItemByScope(IArrayOf<IEspSpaceItem>& SpaceItems64, const char*scopeName, const char*logicalName, __int64 size)
  542. {
  543. char scope[1024];
  544. scope[0] = 0;
  545. const char* pName = NULL;
  546. if (!scopeName)
  547. {
  548. pName = strstr(logicalName, "::");
  549. if (!pName)
  550. return false;
  551. strncpy(scope, logicalName, pName - logicalName);
  552. scope[pName - logicalName] = 0;
  553. }
  554. else
  555. {
  556. if (strlen(logicalName) <= strlen(scopeName)+2)
  557. return false;
  558. char* ppName = (char*) logicalName + strlen(scopeName) + 2;
  559. pName = strstr(ppName, "::");
  560. if (pName)
  561. {
  562. strncpy(scope, logicalName, pName - logicalName);
  563. scope[pName - logicalName] = 0;
  564. }
  565. }
  566. if (strlen(scope) > 0)
  567. {
  568. IEspSpaceItem *item0 = NULL;
  569. for(unsigned i = 0; i < SpaceItems64.length();i++)
  570. {
  571. IEspSpaceItem& item1 = SpaceItems64.item(i);
  572. if (!stricmp(item1.getName(), scope))
  573. {
  574. item0 = &item1;
  575. break;
  576. }
  577. }
  578. if (!item0)
  579. {
  580. Owned<IEspSpaceItem> item1 = createSpaceItem();
  581. item1->setName(scope);
  582. item1->setNumOfFilesInt(1);
  583. if (size < 0)
  584. {
  585. item1->setNumOfFilesIntUnknown(1);
  586. item1->setTotalSizeInt(0);
  587. item1->setLargestSizeInt(0);
  588. item1->setSmallestSizeInt(0);
  589. item1->setLargestFile("");
  590. item1->setSmallestFile("");
  591. }
  592. else
  593. {
  594. item1->setNumOfFilesIntUnknown(0);
  595. item1->setTotalSizeInt(size);
  596. item1->setLargestSizeInt(size);
  597. item1->setSmallestSizeInt(size);
  598. item1->setLargestFile(logicalName);
  599. item1->setSmallestFile(logicalName);
  600. }
  601. SpaceItems64.append(*item1.getClear());
  602. }
  603. else if (size < 0)
  604. {
  605. item0->setNumOfFilesIntUnknown(item0->getNumOfFilesIntUnknown() + 1);
  606. item0->setNumOfFilesInt(item0->getNumOfFilesInt() + 1);
  607. }
  608. else
  609. {
  610. if (item0->getNumOfFilesInt() == item0->getNumOfFilesIntUnknown() || size > item0->getLargestSizeInt())
  611. {
  612. item0->setLargestSizeInt(size);
  613. item0->setLargestFile(logicalName);
  614. }
  615. if (item0->getNumOfFilesInt() == item0->getNumOfFilesIntUnknown() || size < item0->getSmallestSizeInt())
  616. {
  617. item0->setSmallestSizeInt(size);
  618. item0->setSmallestFile(logicalName);
  619. }
  620. item0->setNumOfFilesInt(item0->getNumOfFilesInt() + 1);
  621. item0->setTotalSizeInt(item0->getTotalSizeInt() + size);
  622. }
  623. }
  624. else
  625. {
  626. IEspSpaceItem& item0 = SpaceItems64.item(0);
  627. if (size < 0)
  628. {
  629. item0.setNumOfFilesInt(item0.getNumOfFilesInt() + 1);
  630. item0.setNumOfFilesIntUnknown(item0.getNumOfFilesIntUnknown() + 1);
  631. }
  632. else
  633. {
  634. if ((item0.getNumOfFilesInt() == item0.getNumOfFilesIntUnknown()) || (size > item0.getLargestSizeInt()))
  635. {
  636. item0.setLargestSizeInt(size);
  637. item0.setLargestFile(logicalName);
  638. }
  639. if ((item0.getNumOfFilesInt() == item0.getNumOfFilesIntUnknown()) || (size < item0.getSmallestSizeInt()))
  640. {
  641. item0.setSmallestSizeInt(size);
  642. item0.setSmallestFile(logicalName);
  643. }
  644. item0.setNumOfFilesInt(item0.getNumOfFilesInt() + 1);
  645. item0.setTotalSizeInt(item0.getTotalSizeInt() + size);
  646. }
  647. }
  648. return true;
  649. }
  650. bool CWsDfuEx::setSpaceItemByOwner(IArrayOf<IEspSpaceItem>& SpaceItems64, const char *owner, const char *logicalName, __int64 size)
  651. {
  652. if (owner && *owner)
  653. {
  654. IEspSpaceItem *item0 = NULL;
  655. for(unsigned i = 0; i < SpaceItems64.length();i++)
  656. {
  657. IEspSpaceItem& item1 = SpaceItems64.item(i);
  658. if (!stricmp(item1.getName(), owner))
  659. {
  660. item0 = &item1;
  661. break;
  662. }
  663. }
  664. if (!item0)
  665. {
  666. Owned<IEspSpaceItem> item1 = createSpaceItem();
  667. item1->setName(owner);
  668. item1->setNumOfFilesInt(1);
  669. if (size < 0)
  670. {
  671. item1->setNumOfFilesIntUnknown(1);
  672. item1->setTotalSizeInt(0);
  673. item1->setLargestSizeInt(0);
  674. item1->setSmallestSizeInt(0);
  675. item1->setLargestFile("");
  676. item1->setSmallestFile("");
  677. }
  678. else
  679. {
  680. item1->setNumOfFilesIntUnknown(0);
  681. item1->setTotalSizeInt(size);
  682. item1->setLargestSizeInt(size);
  683. item1->setSmallestSizeInt(size);
  684. item1->setLargestFile(logicalName);
  685. item1->setSmallestFile(logicalName);
  686. }
  687. SpaceItems64.append(*item1.getClear());
  688. }
  689. else if (size < 0)
  690. {
  691. item0->setNumOfFilesIntUnknown(item0->getNumOfFilesIntUnknown() + 1);
  692. item0->setNumOfFilesInt(item0->getNumOfFilesInt() + 1);
  693. }
  694. else
  695. {
  696. if (item0->getNumOfFilesInt() == item0->getNumOfFilesIntUnknown() || size > item0->getLargestSizeInt())
  697. {
  698. item0->setLargestSizeInt(size);
  699. item0->setLargestFile(logicalName);
  700. }
  701. if (item0->getNumOfFilesInt() == item0->getNumOfFilesIntUnknown() || size < item0->getSmallestSizeInt())
  702. {
  703. item0->setSmallestSizeInt(size);
  704. item0->setSmallestFile(logicalName);
  705. }
  706. item0->setNumOfFilesInt(item0->getNumOfFilesInt() + 1);
  707. item0->setTotalSizeInt(item0->getTotalSizeInt() + size);
  708. }
  709. }
  710. else
  711. {
  712. IEspSpaceItem& item0 = SpaceItems64.item(0);
  713. if (size < 0)
  714. {
  715. item0.setNumOfFilesInt(item0.getNumOfFilesInt() + 1);
  716. item0.setNumOfFilesIntUnknown(item0.getNumOfFilesIntUnknown() + 1);
  717. }
  718. else
  719. {
  720. if ((item0.getNumOfFilesInt() == item0.getNumOfFilesIntUnknown()) || (size > item0.getLargestSizeInt()))
  721. {
  722. item0.setLargestSizeInt(size);
  723. item0.setLargestFile(logicalName);
  724. }
  725. if ((item0.getNumOfFilesInt() == item0.getNumOfFilesIntUnknown()) || (size < item0.getSmallestSizeInt()))
  726. {
  727. item0.setSmallestSizeInt(size);
  728. item0.setSmallestFile(logicalName);
  729. }
  730. item0.setNumOfFilesInt(item0.getNumOfFilesInt() + 1);
  731. item0.setTotalSizeInt(item0.getTotalSizeInt() + size);
  732. }
  733. }
  734. return true;
  735. }
  736. bool CWsDfuEx::createSpaceItemsByDate(IArrayOf<IEspSpaceItem>& SpaceItems, const char *interval, unsigned& yearFrom,
  737. unsigned& monthFrom, unsigned& dayFrom, unsigned& yearTo, unsigned& monthTo, unsigned& dayTo)
  738. {
  739. if (!stricmp(interval, COUNTBY_YEAR))
  740. {
  741. for (unsigned i = yearFrom; i <= yearTo; i++)
  742. {
  743. Owned<IEspSpaceItem> item64 = createSpaceItem();
  744. StringBuffer name;
  745. name.appendf("%04d", i);
  746. item64->setName(name.str());
  747. item64->setNumOfFilesInt(0);
  748. item64->setNumOfFilesIntUnknown(0);
  749. item64->setTotalSizeInt(0);
  750. item64->setLargestSizeInt(0);
  751. item64->setSmallestSizeInt(0);
  752. item64->setLargestFile("");
  753. item64->setSmallestFile("");
  754. SpaceItems.append(*item64.getClear());
  755. }
  756. }
  757. else if (!stricmp(interval, COUNTBY_QUARTER))
  758. {
  759. for (unsigned i = yearFrom; i <= yearTo; i++)
  760. {
  761. int quartStart = 1;
  762. int quartEnd = 4;
  763. if (i == yearFrom)
  764. {
  765. if (monthFrom > 9)
  766. {
  767. quartStart = 4;
  768. }
  769. else if (monthFrom > 6)
  770. {
  771. quartStart = 3;
  772. }
  773. else if (monthFrom > 3)
  774. {
  775. quartStart = 2;
  776. }
  777. }
  778. if (i == yearTo)
  779. {
  780. if (monthTo > 9)
  781. {
  782. quartEnd = 4;
  783. }
  784. else if (monthTo > 6)
  785. {
  786. quartEnd = 3;
  787. }
  788. else if (monthTo > 3)
  789. {
  790. quartEnd = 2;
  791. }
  792. }
  793. for (int j = quartStart; j <= quartEnd; j++)
  794. {
  795. Owned<IEspSpaceItem> item64 = createSpaceItem();
  796. StringBuffer name;
  797. name.appendf("%04d quarter: %d", i, j);
  798. item64->setName(name.str());
  799. item64->setNumOfFilesInt(0);
  800. item64->setNumOfFilesIntUnknown(0);
  801. item64->setTotalSizeInt(0);
  802. item64->setLargestSizeInt(0);
  803. item64->setSmallestSizeInt(0);
  804. item64->setLargestFile("");
  805. item64->setSmallestFile("");
  806. SpaceItems.append(*item64.getClear());
  807. }
  808. }
  809. }
  810. else if (!stricmp(interval, COUNTBY_MONTH))
  811. {
  812. for (unsigned i = yearFrom; i <= yearTo; i++)
  813. {
  814. int jFrom = (i != yearFrom) ? 1 : monthFrom;
  815. int jTo = (i != yearTo) ? 12 : monthTo;
  816. for (int j = jFrom; j <= jTo; j++)
  817. {
  818. Owned<IEspSpaceItem> item64 = createSpaceItem();
  819. StringBuffer name;
  820. name.appendf("%04d-%02d", i, j);
  821. item64->setName(name.str());
  822. item64->setNumOfFilesInt(0);
  823. item64->setNumOfFilesIntUnknown(0);
  824. item64->setTotalSizeInt(0);
  825. item64->setLargestSizeInt(0);
  826. item64->setSmallestSizeInt(0);
  827. item64->setLargestFile("");
  828. item64->setSmallestFile("");
  829. SpaceItems.append(*item64.getClear());
  830. }
  831. }
  832. }
  833. else
  834. {
  835. for (unsigned i = yearFrom; i <= yearTo; i++)
  836. {
  837. int jFrom = (i != yearFrom) ? 1 : monthFrom;
  838. int jTo = (i != yearTo) ? 12 : monthTo;
  839. for (int j = jFrom; j <= jTo; j++)
  840. {
  841. int dayStart = 1;
  842. int dayEnd = days[j-1];
  843. if (i == yearFrom && j == monthFrom)
  844. {
  845. dayStart = dayFrom;
  846. }
  847. else if (i == yearTo && j == monthTo)
  848. {
  849. dayEnd = dayTo;
  850. }
  851. for (int k = dayStart; k <= dayEnd; k++)
  852. {
  853. Owned<IEspSpaceItem> item64 = createSpaceItem();
  854. StringBuffer name;
  855. name.appendf("%04d-%02d-%02d", i, j, k);
  856. item64->setName(name.str());
  857. item64->setNumOfFilesInt(0);
  858. item64->setNumOfFilesIntUnknown(0);
  859. item64->setTotalSizeInt(0);
  860. item64->setLargestSizeInt(0);
  861. item64->setSmallestSizeInt(0);
  862. item64->setLargestFile("");
  863. item64->setSmallestFile("");
  864. SpaceItems.append(*item64.getClear());
  865. }
  866. }
  867. }
  868. }
  869. return true;
  870. }
  871. bool CWsDfuEx::setSpaceItemByDate(IArrayOf<IEspSpaceItem>& SpaceItems, const char * interval, const char * mod, const char*logicalName, __int64 size)
  872. {
  873. unsigned year, month, day;
  874. CDateTime wuTime;
  875. wuTime.setString(mod,NULL,true);
  876. wuTime.getDate(year, month, day, true);
  877. StringBuffer name;
  878. if (!stricmp(interval, COUNTBY_YEAR))
  879. {
  880. name.appendf("%04d", year);
  881. }
  882. else if (!stricmp(interval, COUNTBY_QUARTER))
  883. {
  884. int quart = 1;
  885. if (month > 9)
  886. {
  887. quart = 4;
  888. }
  889. else if (month > 6)
  890. {
  891. quart = 3;
  892. }
  893. else if (month > 3)
  894. {
  895. quart = 2;
  896. }
  897. name.appendf("%04d quarter: %d", year, quart);
  898. }
  899. else if (!stricmp(interval, COUNTBY_MONTH))
  900. {
  901. name.appendf("%04d-%02d", year, month);
  902. }
  903. else
  904. {
  905. name.appendf("%04d-%02d-%02d", year, month, day);
  906. }
  907. for (unsigned i = 0; i < SpaceItems.length(); i++)
  908. {
  909. IEspSpaceItem& item0 = SpaceItems.item(i);
  910. if (!stricmp(item0.getName(), name))
  911. {
  912. if (size < 0)
  913. {
  914. item0.setNumOfFilesIntUnknown(item0.getNumOfFilesIntUnknown() + 1);
  915. }
  916. else
  917. {
  918. if ((item0.getNumOfFilesInt() == item0.getNumOfFilesIntUnknown()) || (size > item0.getLargestSizeInt()))
  919. {
  920. item0.setLargestSizeInt(size);
  921. item0.setLargestFile(logicalName);
  922. }
  923. if ((item0.getNumOfFilesInt() == item0.getNumOfFilesIntUnknown()) || (size < item0.getSmallestSizeInt()))
  924. {
  925. item0.setSmallestSizeInt(size);
  926. item0.setSmallestFile(logicalName);
  927. }
  928. item0.setTotalSizeInt(item0.getTotalSizeInt() + size);
  929. }
  930. item0.setNumOfFilesInt(item0.getNumOfFilesInt() + 1);
  931. break;
  932. }
  933. }
  934. return true;
  935. }
  936. void CWsDfuEx::parseStringArray(const char *input, StringArray& strarray)
  937. {
  938. if (!input || !*input)
  939. return;
  940. const char *ptr = input;
  941. const char *pptr = ptr;
  942. while (pptr[0])
  943. {
  944. if (pptr[0] == ',')
  945. {
  946. StringAttr tmp;
  947. tmp.set(ptr, pptr-ptr);
  948. strarray.append(tmp.get());
  949. ptr = pptr + 1;
  950. }
  951. pptr++;
  952. }
  953. if (pptr > ptr)
  954. {
  955. StringAttr tmp;
  956. tmp.set(ptr, pptr-ptr);
  957. strarray.append(tmp.get());
  958. }
  959. }
  960. int CWsDfuEx::superfileAction(IEspContext &context, const char* action, const char* superfile, StringArray& subfiles,
  961. const char* beforeSubFile, bool existingSuperfile, bool autocreatesuper, bool deleteFile, bool removeSuperfile)
  962. {
  963. if (!action || !*action)
  964. throw MakeStringException(ECLWATCH_INVALID_INPUT, "Superfile action not specified");
  965. if(!strieq(action, "add") && !strieq(action, "remove"))
  966. throw MakeStringException(ECLWATCH_INVALID_INPUT, "Only Add or Remove is allowed.");
  967. if (!superfile || !*superfile)
  968. throw MakeStringException(ECLWATCH_INVALID_INPUT, "Superfile name not specified");
  969. StringBuffer username;
  970. context.getUserID(username);
  971. Owned<IUserDescriptor> userdesc;
  972. if(username.length() > 0)
  973. {
  974. userdesc.setown(createUserDescriptor());
  975. userdesc->set(username.str(), context.queryPassword(), context.querySignature());
  976. }
  977. if (!autocreatesuper)
  978. {//a file lock created by the lookup() will be released after '}'
  979. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(superfile, userdesc.get(), true, false, false, nullptr, defaultPrivilegedUser);
  980. if (existingSuperfile)
  981. {
  982. if (!df)
  983. throw MakeStringException(ECLWATCH_FILE_NOT_EXIST,"Cannot find file %s.",superfile);
  984. if(!df->querySuperFile())
  985. throw MakeStringException(ECLWATCH_NOT_SUPERFILE,"%s is not a superfile.",superfile);
  986. }
  987. else if (df)
  988. throw MakeStringException(ECLWATCH_FILE_ALREADY_EXISTS,"The file %s already exists.",superfile);
  989. }
  990. PointerArrayOf<char> subfileArray;
  991. unsigned num = subfiles.length();
  992. if (num > 0)
  993. {
  994. StringBuffer msgHead;
  995. if(username.length() > 0)
  996. msgHead.appendf("%s: Superfile:%s, Subfile(s): ", action, superfile);
  997. else
  998. msgHead.appendf("%s: Superfile:%s, Subfile(s): ", action, superfile);
  999. unsigned filesInMsgBuf = 0;
  1000. StringBuffer msgBuf(msgHead);
  1001. for(unsigned i = 0; i < num; i++)
  1002. {
  1003. subfileArray.append((char*) subfiles.item(i));
  1004. msgBuf.appendf("%s, ", subfiles.item(i));
  1005. filesInMsgBuf++;
  1006. if (filesInMsgBuf > 9)
  1007. {
  1008. PROGLOG("%s",msgBuf.str());
  1009. msgBuf = msgHead;
  1010. filesInMsgBuf = 0;
  1011. }
  1012. }
  1013. if (filesInMsgBuf > 0)
  1014. PROGLOG("%s", msgBuf.str());
  1015. }
  1016. else
  1017. PROGLOG("%s: %s", action, superfile);
  1018. Owned<IDFUhelper> dfuhelper = createIDFUhelper();
  1019. synchronized block(m_superfilemutex);
  1020. if(strieq(action, "add"))
  1021. dfuhelper->addSuper(superfile, userdesc.get(), num, (const char**) subfileArray.getArray(), beforeSubFile, true);
  1022. else
  1023. dfuhelper->removeSuper(superfile, userdesc.get(), num, (const char**) subfileArray.getArray(), deleteFile, removeSuperfile);
  1024. PROGLOG("%s done", action);
  1025. return num;
  1026. }
  1027. bool CWsDfuEx::onAddtoSuperfile(IEspContext &context, IEspAddtoSuperfileRequest &req, IEspAddtoSuperfileResponse &resp)
  1028. {
  1029. try
  1030. {
  1031. context.ensureFeatureAccess(FEATURE_URL, SecAccess_Write, ECLWATCH_DFU_ACCESS_DENIED, "WsDfu::AddtoSuperfile: Permission denied.");
  1032. double version = context.getClientVersion();
  1033. if (version > 1.17)
  1034. {
  1035. const char* backTo = req.getBackToPage();
  1036. if (backTo && *backTo)
  1037. resp.setBackToPage(backTo);
  1038. }
  1039. resp.setSubfiles(req.getSubfiles());
  1040. const char* superfile = req.getSuperfile();
  1041. if (!superfile || !*superfile)
  1042. {
  1043. if (version > 1.15)
  1044. {//Display the subfiles inside a table
  1045. const char* files = req.getSubfiles();
  1046. if (files && *files)
  1047. {
  1048. StringArray subfileNames;
  1049. parseStringArray(files, subfileNames);
  1050. if (subfileNames.length() > 0)
  1051. resp.setSubfileNames(subfileNames);
  1052. }
  1053. }
  1054. return true;//Display a form for user to specify superfile
  1055. }
  1056. if (version > 1.15)
  1057. {
  1058. superfileAction(context, "add", superfile, req.getNames(), NULL, req.getExistingFile(), false, false);
  1059. }
  1060. else
  1061. {
  1062. StringArray subfileNames;
  1063. const char *subfilesStr = req.getSubfiles();
  1064. if (subfilesStr && *subfilesStr)
  1065. parseStringArray(subfilesStr, subfileNames);
  1066. superfileAction(context, "add", superfile, subfileNames, NULL, req.getExistingFile(), false, false);
  1067. }
  1068. resp.setRedirectUrl(StringBuffer("/WsDFU/DFUInfo?Name=").append(superfile));
  1069. }
  1070. catch(IException* e)
  1071. {
  1072. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  1073. }
  1074. return true;
  1075. }
  1076. void setDeleteFileResults(const char* fileName, const char* nodeGroup, bool failed, const char *start, const char* text, StringBuffer& resultString,
  1077. IArrayOf<IEspDFUActionInfo>& actionResults)
  1078. {
  1079. if (!fileName || !*fileName)
  1080. return;
  1081. Owned<IEspDFUActionInfo> resultObj = createDFUActionInfo("", "");
  1082. resultObj->setFileName(fileName);
  1083. resultObj->setFailed(failed);
  1084. if (nodeGroup && *nodeGroup)
  1085. resultObj->setNodeGroup(nodeGroup);
  1086. StringBuffer message;
  1087. if (start)
  1088. message.append(start).append(' ');
  1089. message.append(fileName);
  1090. if (nodeGroup && *nodeGroup)
  1091. message.append(" on ").append(nodeGroup);
  1092. if (text && *text)
  1093. message.append(failed ? ": " : " ").append(text);
  1094. resultObj->setActionResult(message);
  1095. resultString.appendf("<Message><Value>%s</Value></Message>", message.str());
  1096. actionResults.append(*resultObj.getClear());
  1097. }
  1098. void cleanLogicalFileNames(StringArray &fileNames, StringArray &uniqueFileNames)
  1099. {
  1100. ForEachItemIn(i, fileNames)
  1101. {
  1102. const char *fn = fileNames.item(i);
  1103. if (isEmptyString(fn))
  1104. continue;
  1105. uniqueFileNames.appendUniq(fn);
  1106. }
  1107. }
  1108. bool CWsDfuEx::DFUDeleteFiles(IEspContext &context, IEspDFUArrayActionRequest &req, IEspDFUArrayActionResponse &resp)
  1109. {
  1110. if (isDetachedFromDali())
  1111. throw MakeStringException(ECLWATCH_INVALID_INPUT, "ESP server is detached from Dali. Please try later.");
  1112. class CDFUDeleteFilesHelper
  1113. {
  1114. IEspContext &context;
  1115. Owned<IUserDescriptor> userdesc;
  1116. IArrayOf<IEspDFUActionInfo> actionResults;
  1117. StringBuffer returnStr, auditStr;
  1118. StringAttr espProcess;
  1119. void deleteFile(const char *fn)
  1120. {
  1121. CDfsLogicalFileName dfsLFN;
  1122. dfsLFN.set(fn);
  1123. StringBuffer group;
  1124. dfsLFN.getCluster(group);
  1125. if (!group.isEmpty() && strieq(group.str(), "null")) //null is used by new ECLWatch for a superfile
  1126. group.clear();
  1127. try
  1128. {
  1129. PROGLOG("Deleting %s", fn);
  1130. queryDistributedFileDirectory().removeEntry(fn, userdesc, nullptr, REMOVE_FILE_SDS_CONNECT_TIMEOUT, true);
  1131. LOG(MCauditInfo, "%s,%s", auditStr.str(), fn);
  1132. VStringBuffer message("File %s deleted.", fn);
  1133. addResult(dfsLFN.get(), group, false, message);
  1134. }
  1135. catch(IException *e)
  1136. {
  1137. StringBuffer emsg;
  1138. e->errorMessage(emsg);
  1139. if (e->errorCode() == DFSERR_CreateAccessDenied)
  1140. emsg.replaceString("Create ", "Delete ");
  1141. VStringBuffer message("Could not delete file %s: %s.", fn, emsg.str());
  1142. addResult(dfsLFN.get(), group, true, message);
  1143. e->Release();
  1144. }
  1145. catch(...)
  1146. {
  1147. VStringBuffer message("Could not delete file %s: unknown exception.", fn);
  1148. addResult(dfsLFN.get(), group, true, message);
  1149. }
  1150. }
  1151. void addResult(const char* fileName, const char* nodeGroup, bool failed, const char *message)
  1152. {
  1153. double version = context.getClientVersion();
  1154. if (version < 1.33)
  1155. returnStr.appendf("<Message><Value>%s</Value></Message>", message);
  1156. PROGLOG("%s", message);
  1157. if (version < 1.27)
  1158. return;
  1159. Owned<IEspDFUActionInfo> resultObj = createDFUActionInfo();
  1160. resultObj->setFileName(fileName);
  1161. resultObj->setFailed(failed);
  1162. if (!isEmptyString(nodeGroup))
  1163. resultObj->setNodeGroup(nodeGroup);
  1164. resultObj->setActionResult(message);
  1165. actionResults.append(*resultObj.getClear());
  1166. }
  1167. public:
  1168. CDFUDeleteFilesHelper(IEspContext &ctx, const char *process) : context(ctx), espProcess(process)
  1169. {
  1170. const char *user = context.queryUserId();
  1171. if (!isEmptyString(user))
  1172. {
  1173. userdesc.setown(createUserDescriptor());
  1174. userdesc->set(user, context.queryPassword(), context.querySignature());
  1175. }
  1176. auditStr.set(",FileAccess,WsDfu,DELETED,");
  1177. auditStr.append(espProcess.get());
  1178. auditStr.append(',');
  1179. if (!isEmptyString(user))
  1180. auditStr.append(user).append('@');
  1181. context.getPeer(auditStr);
  1182. }
  1183. const char *getReturnStr() const { return returnStr.str(); }
  1184. IArrayOf<IEspDFUActionInfo> &getActionResults() { return actionResults; }
  1185. void deleteFiles(StringArray &logicalFileNames, bool removeFromSuperFiles, bool removeEmptyOwningSuperFiles)
  1186. {
  1187. StringArray emptyOwningSuperFiles;
  1188. IDistributedFileDirectory &fdir = queryDistributedFileDirectory();
  1189. ForEachItemIn(i, logicalFileNames)
  1190. {
  1191. CDfsLogicalFileName dfsLFN;
  1192. dfsLFN.set(logicalFileNames.item(i));
  1193. StringBuffer group;
  1194. dfsLFN.getCluster(group);
  1195. if (!group.isEmpty() && strieq(group.str(), "null")) //null is used by new ECLWatch for a superfile
  1196. group.clear();
  1197. StringBuffer normalizeLFN;
  1198. normalizeLFN.append(dfsLFN.get());
  1199. if (group.length())
  1200. {
  1201. normalizeLFN.append("@");
  1202. dfsLFN.getCluster(normalizeLFN);
  1203. }
  1204. const char *lfn = normalizeLFN;
  1205. if (emptyOwningSuperFiles.contains(lfn))
  1206. continue;
  1207. Owned<IDistributedFile> df = fdir.lookup(lfn, userdesc, true, false, false, nullptr, defaultPrivilegedUser, 30000); // 30 sec timeout
  1208. if (!df)
  1209. {
  1210. VStringBuffer message("Could not delete file %s: file not found.", lfn);
  1211. addResult(dfsLFN.get(), group, true, message);
  1212. continue;
  1213. }
  1214. Owned<IDistributedSuperFileIterator> superOwners = df->getOwningSuperFiles();
  1215. if (!removeFromSuperFiles && superOwners->first())
  1216. {
  1217. VStringBuffer message("The file %s can not be deleted because it is owned by one or more superfiles.", lfn);
  1218. addResult(dfsLFN.get(), group, true, message);
  1219. continue;
  1220. }
  1221. bool fileCanBeDeleted = true;
  1222. ForEach(*superOwners)
  1223. {
  1224. IDistributedSuperFile &superOwner = superOwners->query();
  1225. try
  1226. {
  1227. superOwner.removeSubFile(lfn, false, false, nullptr);
  1228. PROGLOG("File %s is removed from superfile %s", lfn, superOwner.queryLogicalName());
  1229. }
  1230. catch(IException *e)
  1231. {
  1232. VStringBuffer message("Could not delete file %s from superfile %s: ", lfn, superOwner.queryLogicalName());
  1233. e->errorMessage(message);
  1234. addResult(dfsLFN.get(), group, true, message);
  1235. e->Release();
  1236. fileCanBeDeleted = false;
  1237. break;
  1238. }
  1239. catch(...)
  1240. {
  1241. VStringBuffer message("Could not delete file %s from superfile %s: unknown exception", lfn, superOwner.queryLogicalName());
  1242. addResult(dfsLFN.get(), group, true, message);
  1243. fileCanBeDeleted = false;
  1244. break;
  1245. }
  1246. if (removeEmptyOwningSuperFiles && (superOwner.numSubFiles(false)==0))
  1247. emptyOwningSuperFiles.appendUniq(superOwner.queryLogicalName());
  1248. }
  1249. if (fileCanBeDeleted)
  1250. {
  1251. superOwners.clear();
  1252. df.clear();
  1253. deleteFile(lfn);
  1254. }
  1255. }
  1256. ForEachItemIn(j, emptyOwningSuperFiles)
  1257. {
  1258. deleteFile(emptyOwningSuperFiles.item(j));
  1259. }
  1260. }
  1261. };
  1262. StringArray logicalFileNames;
  1263. cleanLogicalFileNames(req.getLogicalFiles(), logicalFileNames);
  1264. if (!logicalFileNames.length())
  1265. return true;
  1266. CDFUDeleteFilesHelper helper(context, espProcess);
  1267. helper.deleteFiles(logicalFileNames, req.getRemoveFromSuperfiles(), req.getRemoveRecursively());
  1268. double version = context.getClientVersion();
  1269. if (version >= 1.27)
  1270. resp.setActionResults(helper.getActionResults());
  1271. if (version < 1.33)
  1272. resp.setDFUArrayActionResult(helper.getReturnStr());
  1273. return true;
  1274. }
  1275. bool CWsDfuEx::onDFUArrayAction(IEspContext &context, IEspDFUArrayActionRequest &req, IEspDFUArrayActionResponse &resp)
  1276. {
  1277. try
  1278. {
  1279. CDFUArrayActions action = req.getType();
  1280. if (action == DFUArrayActions_Undefined)
  1281. throw MakeStringException(ECLWATCH_INVALID_INPUT,"Action not defined.");
  1282. if (action == CDFUArrayActions_ChangeRestriction)
  1283. return changeFileRestrictions(context, req, resp);
  1284. if (action == CDFUArrayActions_ChangeProtection)
  1285. return changeFileProtections(context, req, resp);
  1286. context.ensureFeatureAccess(FEATURE_URL, SecAccess_Write, ECLWATCH_DFU_ACCESS_DENIED, "WsDfu::DFUArrayAction: Permission denied.");
  1287. double version = context.getClientVersion();
  1288. if (version > 1.03)
  1289. {
  1290. StringBuffer backToPage(req.getBackToPage());
  1291. if (backToPage.length() > 0)
  1292. {
  1293. const char* oldStr = "&";
  1294. const char* newStr = "&amp;";
  1295. backToPage.replaceString(oldStr, newStr);
  1296. resp.setBackToPage(backToPage.str());
  1297. }
  1298. }
  1299. if (action == CDFUArrayActions_Delete)
  1300. return DFUDeleteFiles(context, req, resp);
  1301. //the code below is only for legacy ECLWatch. Other application should use AddtoSuperfile.
  1302. StringBuffer username;
  1303. context.getUserID(username);
  1304. Owned<IUserDescriptor> userdesc;
  1305. if(username.length() > 0)
  1306. {
  1307. userdesc.setown(createUserDescriptor());
  1308. userdesc->set(username.str(), context.queryPassword(), context.querySignature());
  1309. }
  1310. IArrayOf<IEspDFUActionInfo> actionResults;
  1311. StringBuffer errorStr, subfiles;
  1312. for(unsigned i = 0; i < req.getLogicalFiles().length();i++)
  1313. {
  1314. const char* file = req.getLogicalFiles().item(i);
  1315. if(!file || !*file)
  1316. continue;
  1317. unsigned len = strlen(file);
  1318. char* curfile = new char[len+1];
  1319. const char* cluster = NULL;
  1320. const char *pCh = strchr(file, '@');
  1321. if (pCh)
  1322. {
  1323. len = pCh - file;
  1324. if (len+1 < strlen(file))
  1325. cluster = pCh + 1;
  1326. }
  1327. strncpy(curfile, file, len);
  1328. curfile[len] = 0;
  1329. try
  1330. {
  1331. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(curfile, userdesc.get(), true, false, false, nullptr, defaultPrivilegedUser);
  1332. if (df)
  1333. {
  1334. if (subfiles.length() > 0)
  1335. subfiles.append(",");
  1336. subfiles.append(curfile);
  1337. }
  1338. else
  1339. setDeleteFileResults(file, NULL, true, NULL, "not found", errorStr, actionResults);
  1340. }
  1341. catch(IException* e)
  1342. {
  1343. StringBuffer emsg;
  1344. e->errorMessage(emsg);
  1345. if (e->errorCode() == DFSERR_CreateAccessDenied)
  1346. emsg.replaceString("Create ", "AddtoSuperfile ");
  1347. setDeleteFileResults(file, NULL, true, NULL, emsg.str(), errorStr, actionResults);
  1348. e->Release();
  1349. }
  1350. catch(...)
  1351. {
  1352. setDeleteFileResults(file, NULL, true, NULL, "unknown exception", errorStr, actionResults);
  1353. }
  1354. delete [] curfile;
  1355. }
  1356. if (version >= 1.27)
  1357. resp.setActionResults(actionResults);
  1358. if (errorStr.length())
  1359. {
  1360. if (version < 1.33)
  1361. resp.setDFUArrayActionResult(errorStr.str());
  1362. return false;
  1363. }
  1364. if (version < 1.18)
  1365. resp.setRedirectUrl(StringBuffer("/WsDFU/AddtoSuperfile?Subfiles=").append(subfiles.str()));
  1366. else
  1367. resp.setRedirectTo(subfiles.str());
  1368. }
  1369. catch(IException* e)
  1370. {
  1371. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  1372. }
  1373. return true;
  1374. }
  1375. void CWsDfuEx::addFileActionResult(const char* fileName, const char* nodeGroup, bool failed, const char* msg,
  1376. IArrayOf<IEspDFUActionInfo>& actionResults)
  1377. {
  1378. Owned<IEspDFUActionInfo> result = createDFUActionInfo();
  1379. result->setFileName(fileName);
  1380. if (!isEmptyString(nodeGroup))
  1381. result->setNodeGroup(nodeGroup);
  1382. result->setFailed(failed);
  1383. result->setActionResult(msg);
  1384. actionResults.append(*result.getClear());
  1385. }
  1386. bool CWsDfuEx::changeFileProtections(IEspContext &context, IEspDFUArrayActionRequest &req, IEspDFUArrayActionResponse &resp)
  1387. {
  1388. CDFUChangeProtection protect = req.getProtect();
  1389. if (protect == CDFUChangeProtection_NoChange)
  1390. return true;
  1391. #ifdef _USE_OPENLDAP
  1392. if (protect == CDFUChangeProtection_UnprotectAll)
  1393. context.ensureSuperUser(ECLWATCH_SUPER_USER_ACCESS_DENIED, "Access denied, administrators only.");
  1394. #endif
  1395. if (isDetachedFromDali())
  1396. throw makeStringException(ECLWATCH_INVALID_INPUT, "ESP server is detached from Dali. Please try later.");
  1397. StringBuffer userID;
  1398. context.getUserID(userID);
  1399. Owned<IUserDescriptor> userDesc;
  1400. if (userID.isEmpty())
  1401. userID.set("hpcc"); //The userID is needed for setProtect().
  1402. else
  1403. {
  1404. userDesc.setown(createUserDescriptor());
  1405. userDesc->set(userID, context.queryPassword(), context.querySignature());
  1406. }
  1407. IArrayOf<IEspDFUActionInfo> actionResults;
  1408. for (unsigned i = 0; i < req.getLogicalFiles().length(); i++)
  1409. {
  1410. const char *file = req.getLogicalFiles().item(i);
  1411. if (isEmptyString(file))
  1412. continue;
  1413. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(file, userDesc, false, false, true, nullptr, defaultPrivilegedUser); // lock super-owners
  1414. if (!df)
  1415. {
  1416. addFileActionResult(file, nullptr, true, "Cannot find file.", actionResults);
  1417. continue;
  1418. }
  1419. if (protect != CDFUChangeProtection_UnprotectAll)
  1420. df->setProtect(userID, protect == CDFUChangeProtection_Protect ? true : false);
  1421. else
  1422. clearFileProtections(df);
  1423. addFileActionResult(file, nullptr, false, protect == CDFUChangeProtection_Protect ? "File protected" : "File unprotected", actionResults);
  1424. }
  1425. resp.setActionResults(actionResults);
  1426. return true;
  1427. }
  1428. void CWsDfuEx::clearFileProtections(IDistributedFile *df)
  1429. {
  1430. StringArray owners;
  1431. Owned<IPropertyTreeIterator> itr = df->queryAttributes().getElements("Protect");
  1432. ForEach(*itr)
  1433. {
  1434. const char *owner = itr->query().queryProp("@name");
  1435. if (!isEmptyString(owner))
  1436. owners.append(owner);
  1437. }
  1438. ForEachItemIn(i, owners)
  1439. df->setProtect(owners.item(i), false);
  1440. }
  1441. bool CWsDfuEx::changeFileRestrictions(IEspContext &context, IEspDFUArrayActionRequest &req, IEspDFUArrayActionResponse &resp)
  1442. {
  1443. CDFUChangeRestriction changeRestriction = req.getRestrict();
  1444. if (changeRestriction == CDFUChangeRestriction_NoChange)
  1445. return true;
  1446. if (changeRestriction == CDFUChangeRestriction_NotRestricted)
  1447. context.ensureFeatureAccess("CodeSignAccess", SecAccess_Full, ECLWATCH_DFU_ACCESS_DENIED, "CodeSignAccess: Permission denied.");
  1448. if (isDetachedFromDali())
  1449. throw makeStringException(ECLWATCH_INVALID_INPUT, "ESP server is detached from Dali. Please try later.");
  1450. StringBuffer userID;
  1451. context.getUserID(userID);
  1452. Owned<IUserDescriptor> userDesc;
  1453. if (!userID.isEmpty())
  1454. {
  1455. userDesc.setown(createUserDescriptor());
  1456. userDesc->set(userID, context.queryPassword(), context.querySignature());
  1457. }
  1458. IArrayOf<IEspDFUActionInfo> actionResults;
  1459. for (unsigned i = 0; i < req.getLogicalFiles().length();i++)
  1460. {
  1461. const char *file = req.getLogicalFiles().item(i);
  1462. if (isEmptyString(file))
  1463. continue;
  1464. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(file, userDesc, false, false, true, nullptr, defaultPrivilegedUser); // lock super-owners
  1465. if (!df)
  1466. {
  1467. addFileActionResult(file, nullptr, true, "Cannot find file.", actionResults);
  1468. continue;
  1469. }
  1470. df->setRestrictedAccess(changeRestriction==CDFUChangeRestriction_Restrict);
  1471. addFileActionResult(file, nullptr, false, changeRestriction == CDFUChangeRestriction_Restrict ? "Changed to restricted" : "Changed to unrestricted", actionResults);
  1472. }
  1473. resp.setActionResults(actionResults);
  1474. return true;
  1475. }
  1476. bool CWsDfuEx::onDFUDefFile(IEspContext &context,IEspDFUDefFileRequest &req, IEspDFUDefFileResponse &resp)
  1477. {
  1478. try
  1479. {
  1480. context.ensureFeatureAccess(FEATURE_URL, SecAccess_Read, ECLWATCH_DFU_ACCESS_DENIED, "WsDfu::DFUDefFile: Permission denied.");
  1481. CDFUDefFileFormat format = req.getFormat();
  1482. if (format == DFUDefFileFormat_Undefined)
  1483. throw MakeStringException(ECLWATCH_INVALID_INPUT,"Invalid format");
  1484. const char* fileName = req.getName();
  1485. if (!fileName || !*fileName)
  1486. throw MakeStringException(ECLWATCH_MISSING_PARAMS, "File name required");
  1487. PROGLOG("DFUDefFile: %s", fileName);
  1488. StringBuffer username;
  1489. context.getUserID(username);
  1490. StringBuffer rawStr,returnStr;
  1491. Owned<IUserDescriptor> userdesc;
  1492. if(username.length() > 0)
  1493. {
  1494. userdesc.setown(createUserDescriptor());
  1495. userdesc->set(username.str(), context.queryPassword(), context.querySignature());
  1496. }
  1497. getDefFile(userdesc.get(), req.getName(),rawStr);
  1498. StringBuffer xsltFile;
  1499. xsltFile.append(getCFD()).append("smc_xslt/").append(req.getFormatAsString()).append("_def_file.xslt");
  1500. xsltTransformer(xsltFile.str(),rawStr,returnStr);
  1501. //set the file
  1502. MemoryBuffer buff;
  1503. buff.setBuffer(returnStr.length(), (void*)returnStr.str());
  1504. resp.setDefFile(buff);
  1505. //set the type
  1506. StringBuffer type("text/");
  1507. if (format == CDFUDefFileFormat_xml)
  1508. type.append("xml");
  1509. else
  1510. type.append("plain");
  1511. resp.setDefFile_mimetype(type.str());
  1512. }
  1513. catch(IException* e)
  1514. {
  1515. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  1516. }
  1517. return true;
  1518. }
  1519. IHqlExpression * getEclRecordDefinition(const char * ecl)
  1520. {
  1521. MultiErrorReceiver errs;
  1522. OwnedHqlExpr record = parseQuery(ecl, &errs);
  1523. if (errs.errCount())
  1524. {
  1525. StringBuffer errtext;
  1526. IError *first = errs.firstError();
  1527. first->toString(errtext);
  1528. throw MakeStringException(ECLWATCH_CANNOT_PARSE_ECL_QUERY, "Failed in parsing ECL record definition: %s @ %d:%d.", errtext.str(), first->getColumn(), first->getLine());
  1529. }
  1530. if(!record)
  1531. throw MakeStringException(ECLWATCH_CANNOT_PARSE_ECL_QUERY, "Failed in parsing ECL record definition.");
  1532. return record.getClear();
  1533. }
  1534. IHqlExpression * getEclRecordDefinition(IUserDescriptor* udesc, const char* FileName)
  1535. {
  1536. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(FileName, udesc, false, false, false, nullptr, defaultPrivilegedUser);
  1537. if(!df)
  1538. throw MakeStringException(ECLWATCH_FILE_NOT_EXIST,"Cannot find file %s.",FileName);
  1539. if(!df->queryAttributes().hasProp("ECL"))
  1540. throw MakeStringException(ECLWATCH_MISSING_PARAMS,"No record definition for file %s.",FileName);
  1541. return getEclRecordDefinition(df->queryAttributes().queryProp("ECL"));
  1542. }
  1543. bool getRecordFormatFromRtlType(MemoryBuffer &binLayout, StringBuffer &jsonLayout, const IPropertyTree &attr, bool includeBin, bool includeJson)
  1544. {
  1545. if (!attr.hasProp("_rtlType"))
  1546. return false;
  1547. try
  1548. {
  1549. MemoryBuffer mb;
  1550. attr.getPropBin("_rtlType", mb);
  1551. if (includeJson)
  1552. {
  1553. Owned<IRtlFieldTypeDeserializer> deserializer(createRtlFieldTypeDeserializer());
  1554. const RtlTypeInfo *typeInfo = deserializer->deserialize(mb);
  1555. dumpTypeInfo(jsonLayout, typeInfo);
  1556. }
  1557. if (includeBin)
  1558. mb.swapWith(binLayout);
  1559. return true;
  1560. }
  1561. catch (IException *e)
  1562. {
  1563. EXCLOG(e, "Failed to process _rtlType");
  1564. e->Release();
  1565. }
  1566. return false;
  1567. }
  1568. bool getRecordFormatFromECL(MemoryBuffer &binLayout, StringBuffer &jsonLayout, const IPropertyTree &attr, bool includeBin, bool includeJson)
  1569. {
  1570. if (!attr.hasProp("ECL"))
  1571. return false;
  1572. try
  1573. {
  1574. const char * kind = attr.queryProp("@kind");
  1575. bool isIndex = (kind && streq(kind, "key"));
  1576. OwnedHqlExpr record = getEclRecordDefinition(attr.queryProp("ECL"));
  1577. MemoryBuffer mb;
  1578. if (attr.hasProp("_record_layout"))
  1579. {
  1580. attr.getPropBin("_record_layout", mb);
  1581. record.setown(patchEclRecordDefinitionFromRecordLayout(record, mb));
  1582. }
  1583. if (includeJson)
  1584. exportJsonType(jsonLayout, record, isIndex);
  1585. if (includeBin)
  1586. exportBinaryType(binLayout, record, isIndex);
  1587. return true;
  1588. }
  1589. catch (IException *e)
  1590. {
  1591. EXCLOG(e, "Failed to process ECL record");
  1592. e->Release();
  1593. }
  1594. return false;
  1595. }
  1596. bool CWsDfuEx::onDFURecordTypeInfo(IEspContext &context, IEspDFURecordTypeInfoRequest &req, IEspDFURecordTypeInfoResponse &resp)
  1597. {
  1598. try
  1599. {
  1600. context.ensureFeatureAccess(FEATURE_URL, SecAccess_Read, ECLWATCH_DFU_ACCESS_DENIED, "WsDfu::DFURecordTypeInfo: Permission denied.");
  1601. const char* fileName = req.getName();
  1602. if (!fileName || !*fileName)
  1603. throw MakeStringException(ECLWATCH_MISSING_PARAMS, "File name required");
  1604. PROGLOG("DFURecordTypeInfo file: %s", fileName);
  1605. Owned<IDistributedFile> df = lookupLogicalName(context, fileName, false, false, false, nullptr, defaultPrivilegedUser);
  1606. if (!df)
  1607. throw MakeStringException(ECLWATCH_FILE_NOT_EXIST,"Cannot find file %s.",fileName);
  1608. MemoryBuffer binLayout;
  1609. StringBuffer jsonLayout;
  1610. if (getRecordFormatFromRtlType(binLayout, jsonLayout, df->queryAttributes(), req.getIncludeBinTypeInfo(), req.getIncludeJsonTypeInfo()) ||
  1611. getRecordFormatFromECL(binLayout.clear(), jsonLayout.clear(), df->queryAttributes(), req.getIncludeBinTypeInfo(), req.getIncludeJsonTypeInfo()))
  1612. {
  1613. if (req.getIncludeBinTypeInfo())
  1614. resp.setBinInfo(binLayout);
  1615. if (req.getIncludeJsonTypeInfo())
  1616. resp.setJsonInfo(jsonLayout);
  1617. }
  1618. }
  1619. catch (IException* e)
  1620. {
  1621. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  1622. }
  1623. return true;
  1624. }
  1625. bool CWsDfuEx::onEclRecordTypeInfo(IEspContext &context, IEspEclRecordTypeInfoRequest &req, IEspEclRecordTypeInfoResponse &resp)
  1626. {
  1627. try
  1628. {
  1629. OwnedHqlExpr record = getEclRecordDefinition(req.getEcl());
  1630. if (req.getIncludeJsonTypeInfo())
  1631. {
  1632. StringBuffer jsonFormat;
  1633. exportJsonType(jsonFormat, record, false); // MORE - could allow isIndex to be passed in?
  1634. resp.setJsonInfo(jsonFormat);
  1635. }
  1636. if (req.getIncludeBinTypeInfo())
  1637. {
  1638. MemoryBuffer binFormat;
  1639. exportBinaryType(binFormat, record, false);
  1640. resp.setBinInfo(binFormat);
  1641. }
  1642. }
  1643. catch(IException* e)
  1644. {
  1645. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  1646. }
  1647. return true;
  1648. }
  1649. void CWsDfuEx::xsltTransformer(const char* xsltPath,StringBuffer& source,StringBuffer& returnStr)
  1650. {
  1651. if (m_xsl.get() == 0)
  1652. {
  1653. m_xsl.setown(getXslProcessor());
  1654. }
  1655. Owned<IXslTransform> xform = m_xsl->createXslTransform();
  1656. xform->loadXslFromFile(xsltPath);
  1657. xform->setXmlSource(source.str(), source.length()+1);
  1658. xform->transform(returnStr.clear());
  1659. }
  1660. void CWsDfuEx::getDefFile(IUserDescriptor* udesc, const char* FileName,StringBuffer& returnStr)
  1661. {
  1662. OwnedHqlExpr record = getEclRecordDefinition(udesc, FileName);
  1663. Owned<IPropertyTree> data = createPTree("Table", ipt_caseInsensitive);
  1664. exportData(data, record);
  1665. const char* fname=strrchr(FileName,':');
  1666. data->setProp("filename",fname ? fname+1 : FileName);
  1667. toXML(data, returnStr, 0, 0);
  1668. }
  1669. bool CWsDfuEx::checkFileContent(IEspContext &context, IUserDescriptor* udesc, const char * logicalName, const char * cluster)
  1670. {
  1671. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(logicalName, udesc, false, false, false, nullptr, defaultPrivilegedUser);
  1672. if (!df)
  1673. return false;
  1674. if (!cluster || !stricmp(cluster, ""))
  1675. {
  1676. StringAttr eclCluster;
  1677. const char* wuid = df->queryAttributes().queryProp("@workunit");
  1678. if (wuid && *wuid)
  1679. {
  1680. try
  1681. {
  1682. Owned<IWorkUnitFactory> factory = getWorkUnitFactory();
  1683. if (factory)
  1684. {
  1685. IConstWorkUnit* wu = factory->openWorkUnit(wuid, context.querySecManager(), context.queryUser());
  1686. if (wu)
  1687. eclCluster.set(wu->queryClusterName());
  1688. }
  1689. }
  1690. catch(...)
  1691. {
  1692. return false;
  1693. }
  1694. }
  1695. if (!eclCluster.length())
  1696. return false;
  1697. }
  1698. bool blocked;
  1699. if (df->isCompressed(&blocked) && !blocked)
  1700. return false;
  1701. IPropertyTree & properties = df->queryAttributes();
  1702. const char * format = properties.queryProp("@format");
  1703. if (format && (stricmp(format,"csv")==0 || memicmp(format, "utf", 3) == 0))
  1704. {
  1705. return true;
  1706. }
  1707. const char * recordEcl = properties.queryProp("ECL");
  1708. if (!recordEcl)
  1709. return false;
  1710. MultiErrorReceiver errs;
  1711. Owned< IHqlExpression> ret = ::parseQuery(recordEcl, &errs);
  1712. return errs.errCount() == 0;
  1713. }
  1714. bool FindInStringArray(StringArray& clusters, const char *cluster)
  1715. {
  1716. bool bFound = false;
  1717. if(cluster && *cluster)
  1718. {
  1719. if (clusters.ordinality())
  1720. {
  1721. ForEachItemIn(i, clusters)
  1722. {
  1723. const char* cluster0 = clusters.item(i);
  1724. if(cluster0 && *cluster0 && !stricmp(cluster, cluster0))
  1725. return true;
  1726. }
  1727. }
  1728. }
  1729. else
  1730. {
  1731. #if 0 //Comment out since clusters are not set for some old files
  1732. if (!clusters.ordinality())
  1733. return true;
  1734. ForEachItemIn(i, clusters)
  1735. {
  1736. const char* cluster0 = clusters.item(i);
  1737. if(cluster0 && !*cluster0)
  1738. {
  1739. return true;
  1740. }
  1741. }
  1742. #else
  1743. return true;
  1744. #endif
  1745. }
  1746. return bFound;
  1747. }
  1748. static void getFilePermission(CDfsLogicalFileName &dlfn, ISecUser & user, IUserDescriptor* udesc, ISecManager* secmgr, SecAccessFlags& permission)
  1749. {
  1750. if (dlfn.isMulti())
  1751. {
  1752. if (!dlfn.isExpanded())
  1753. dlfn.expand(udesc);
  1754. unsigned i = dlfn.multiOrdinality();
  1755. while (i--)
  1756. {
  1757. getFilePermission((CDfsLogicalFileName &)dlfn.multiItem(i), user, udesc, secmgr, permission);
  1758. }
  1759. }
  1760. else
  1761. {
  1762. SecAccessFlags permissionTemp;
  1763. if (dlfn.isForeign())
  1764. {
  1765. permissionTemp = queryDistributedFileDirectory().getFilePermissions(dlfn.get(), udesc);
  1766. }
  1767. else
  1768. {
  1769. StringBuffer scopes;
  1770. dlfn.getScopes(scopes);
  1771. permissionTemp = secmgr->authorizeFileScope(user, scopes.str());
  1772. }
  1773. //Descrease the permission whenever a component has a lower permission.
  1774. if (permissionTemp < permission)
  1775. permission = permissionTemp;
  1776. }
  1777. return;
  1778. }
  1779. bool CWsDfuEx::getUserFilePermission(IEspContext &context, IUserDescriptor* udesc, const char* logicalName, SecAccessFlags& permission)
  1780. {
  1781. ISecManager* secmgr = context.querySecManager();
  1782. if (!secmgr)
  1783. {
  1784. return false;
  1785. }
  1786. CDfsLogicalFileName dlfn;
  1787. dlfn.set(logicalName);
  1788. //Start from the SecAccess_Full. Decrease the permission whenever a component has a lower permission.
  1789. permission = SecAccess_Full;
  1790. getFilePermission(dlfn, *context.queryUser(), udesc, secmgr, permission);
  1791. return true;
  1792. }
  1793. void CWsDfuEx::getFilePartsOnClusters(IEspContext &context, const char *clusterReq, StringArray &clusters,
  1794. IDistributedFile *df, IEspDFUFileDetail &fileDetails)
  1795. {
  1796. double version = context.getClientVersion();
  1797. bool compressedFile = isFileKey(df) || df->isCompressed();
  1798. IArrayOf<IConstDFUFilePartsOnCluster>& partsOnClusters = fileDetails.getDFUFilePartsOnClusters();
  1799. ForEachItemIn(i, clusters)
  1800. {
  1801. const char* clusterName = clusters.item(i);
  1802. if (isEmptyString(clusterName) || (!isEmptyString(clusterReq) && !strieq(clusterReq, clusterName)))
  1803. continue;
  1804. Owned<IEspDFUFilePartsOnCluster> partsOnCluster = createDFUFilePartsOnCluster();
  1805. partsOnCluster->setCluster(clusterName);
  1806. IArrayOf<IConstDFUPart> &filePartList = partsOnCluster->getDFUFileParts();
  1807. Owned<IFileDescriptor> fdesc = df->getFileDescriptor(clusterName);
  1808. Owned<IPartDescriptorIterator> pi = fdesc->getIterator();
  1809. ForEach(*pi)
  1810. {
  1811. IPartDescriptor &part = pi->query();
  1812. unsigned partIndex = part.queryPartIndex();
  1813. __int64 size = -1;
  1814. __int64 compressedSize = -1;
  1815. StringBuffer partSizeStr;
  1816. IPropertyTree *partPropertyTree = &part.queryProperties();
  1817. if (!partPropertyTree)
  1818. partSizeStr.set("<N/A>");
  1819. else
  1820. {
  1821. size = partPropertyTree->getPropInt64("@size", -1);
  1822. comma c4(size);
  1823. partSizeStr<<c4;
  1824. if (compressedFile && (version >= 1.58))
  1825. compressedSize = partPropertyTree->getPropInt64("@compressedSize", -1);
  1826. }
  1827. for (unsigned i=0; i<part.numCopies(); i++)
  1828. {
  1829. StringBuffer url;
  1830. part.queryNode(i)->endpoint().getUrlStr(url);
  1831. Owned<IEspDFUPart> FilePart = createDFUPart();
  1832. FilePart->setId(partIndex+1);
  1833. FilePart->setPartsize(partSizeStr.str());
  1834. if (version >= 1.38)
  1835. FilePart->setPartSizeInt64(size);
  1836. if (compressedFile && (version >= 1.58))
  1837. {
  1838. if (compressedSize != -1)
  1839. FilePart->setCompressedSize(compressedSize);
  1840. else
  1841. FilePart->setCompressedSize(size);
  1842. }
  1843. FilePart->setIp(url.str());
  1844. FilePart->setCopy(i+1);
  1845. filePartList.append(*FilePart.getClear());
  1846. }
  1847. }
  1848. if (version >= 1.31)
  1849. {
  1850. IClusterInfo *clusterInfo = fdesc->queryCluster(clusterName);
  1851. if (clusterInfo) //Should be valid. But, check it just in case.
  1852. {
  1853. partsOnCluster->setReplicate(clusterInfo->queryPartDiskMapping().isReplicated());
  1854. #ifndef _CONTAINERIZED
  1855. Owned<CThorNodeGroup> nodeGroup = thorNodeGroupCache->lookup(clusterName, nodeGroupCacheTimeout);
  1856. if (nodeGroup)
  1857. partsOnCluster->setCanReplicate(nodeGroup->queryCanReplicate());
  1858. #endif
  1859. const char *defaultDir = fdesc->queryDefaultDir();
  1860. if (!isEmptyString(defaultDir))
  1861. {
  1862. DFD_OS os = SepCharBaseOs(getPathSepChar(defaultDir));
  1863. StringBuffer baseDir, repDir;
  1864. clusterInfo->getBaseDir(baseDir, os);
  1865. clusterInfo->getReplicateDir(repDir, os);
  1866. partsOnCluster->setBaseDir(baseDir.str());
  1867. partsOnCluster->setReplicateDir(baseDir.str());
  1868. }
  1869. }
  1870. }
  1871. partsOnClusters.append(*partsOnCluster.getClear());
  1872. }
  1873. }
  1874. void CWsDfuEx::parseFieldMask(unsigned __int64 fieldMask, unsigned &fieldCount, IntArray &fieldIndexArray)
  1875. {
  1876. while (fieldMask > 0)
  1877. {
  1878. if (fieldMask & 1)
  1879. fieldIndexArray.append(fieldCount); //index from 0
  1880. fieldMask >>= 1;
  1881. fieldCount++;
  1882. }
  1883. }
  1884. void CWsDfuEx::queryFieldNames(IEspContext &context, const char *fileName, const char *cluster,
  1885. unsigned __int64 fieldMask, StringArray &fieldNames)
  1886. {
  1887. if (!fileName || !*fileName)
  1888. throw MakeStringException(ECLWATCH_MISSING_PARAMS, "File name required");
  1889. Owned<IResultSetFactory> resultSetFactory = getSecResultSetFactory(context.querySecManager(), context.queryUser(), context.queryUserId(), context.queryPassword());
  1890. Owned<INewResultSet> result = resultSetFactory->createNewFileResultSet(fileName, cluster);
  1891. if (!result)
  1892. throw MakeStringException(ECLWATCH_INVALID_INPUT, "Failed to access FileResultSet for %s.", fileName);
  1893. unsigned fieldCount = 0;
  1894. IntArray fieldIndexArray;
  1895. parseFieldMask(fieldMask, fieldCount, fieldIndexArray);
  1896. const IResultSetMetaData& metaData = result->getMetaData();
  1897. unsigned totalColumns = (unsigned) metaData.getColumnCount();
  1898. if (fieldCount > totalColumns)
  1899. throw MakeStringException(ECLWATCH_INVALID_INPUT, "Invalid FieldMask %" I64F "u: total fields %u, ask for %u.",
  1900. fieldMask, totalColumns, fieldCount);
  1901. ForEachItemIn(i, fieldIndexArray)
  1902. {
  1903. int fieldIndex = fieldIndexArray.item(i);
  1904. SCMStringBuffer columnLabel;
  1905. if (metaData.hasSetTranslation(fieldIndex))
  1906. metaData.getNaturalColumnLabel(columnLabel, fieldIndex);
  1907. if (columnLabel.length() < 1)
  1908. metaData.getColumnLabel(columnLabel, fieldIndex);
  1909. fieldNames.append(columnLabel.str());
  1910. }
  1911. }
  1912. void CWsDfuEx::doGetFileDetails(IEspContext &context, IUserDescriptor *udesc, const char *name, const char *cluster,
  1913. const char *querySet, const char *query, const char *description, bool includeJsonTypeInfo, bool includeBinTypeInfo,
  1914. CDFUChangeProtection protect, CDFUChangeRestriction changeRestriction, IEspDFUFileDetail &FileDetails)
  1915. {
  1916. if (!name || !*name)
  1917. throw MakeStringException(ECLWATCH_MISSING_PARAMS, "File name required");
  1918. PROGLOG("doGetFileDetails: %s", name);
  1919. double version = context.getClientVersion();
  1920. if ((version >= 1.38) && !isEmptyString(querySet) && !isEmptyString(query))
  1921. {
  1922. if (getQueryFile(name, querySet, query, FileDetails))
  1923. return;
  1924. }
  1925. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(name, udesc, false, false, true, nullptr, defaultPrivilegedUser); // lock super-owners
  1926. if(!df)
  1927. throw MakeStringException(ECLWATCH_FILE_NOT_EXIST,"Cannot find file %s.",name);
  1928. StringArray clusters;
  1929. df->getClusterNames(clusters);
  1930. if (cluster && *cluster && !FindInStringArray(clusters, cluster))
  1931. throw MakeStringException(ECLWATCH_FILE_NOT_EXIST,"Cannot find file %s on %s.", name, cluster);
  1932. if (protect != CDFUChangeProtection_NoChange)
  1933. {
  1934. #ifdef _USE_OPENLDAP
  1935. if (protect == CDFUChangeProtection_UnprotectAll)
  1936. context.ensureSuperUser(ECLWATCH_SUPER_USER_ACCESS_DENIED, "Access denied, administrators only.");
  1937. #endif
  1938. if (protect == CDFUChangeProtection_UnprotectAll)
  1939. clearFileProtections(df);
  1940. else
  1941. {
  1942. StringBuffer userID;
  1943. context.getUserID(userID);
  1944. if (userID.isEmpty())
  1945. userID.set("hpcc");
  1946. df->setProtect(userID.str(), protect == CDFUChangeProtection_Protect ? true : false);
  1947. }
  1948. }
  1949. if (changeRestriction != CDFUChangeRestriction_NoChange)
  1950. {
  1951. if (changeRestriction == CDFUChangeRestriction_NotRestricted)
  1952. context.ensureFeatureAccess("CodeSignAccess", SecAccess_Full, ECLWATCH_DFU_ACCESS_DENIED, "CodeSignAccess: Permission denied.");
  1953. df->setRestrictedAccess(changeRestriction==CDFUChangeRestriction_Restrict);
  1954. }
  1955. offset_t size=queryDistributedFileSystem().getSize(df), recordSize=df->queryAttributes().getPropInt64("@recordSize",0);
  1956. CDateTime dt;
  1957. df->getModificationTime(dt);
  1958. const char* lname=df->queryLogicalName(), *fname=strrchr(lname,':');
  1959. FileDetails.setName(lname);
  1960. FileDetails.setFilename(fname ? fname+1 : lname);
  1961. FileDetails.setDir(df->queryDefaultDir());
  1962. FileDetails.setPathMask(df->queryPartMask());
  1963. if (version >= 1.28)
  1964. {
  1965. StringBuffer buf;
  1966. FileDetails.setPrefix(WsDFUHelpers::getPrefixFromLogicalName(lname, buf));
  1967. if (cluster && *cluster)
  1968. FileDetails.setNodeGroup(cluster);
  1969. else if (clusters.length() == 1)
  1970. FileDetails.setNodeGroup(clusters.item(0));
  1971. IArrayOf<IEspDFUFileProtect> protectList;
  1972. Owned<IPropertyTreeIterator> itr= df->queryAttributes().getElements("Protect");
  1973. ForEach(*itr)
  1974. {
  1975. IPropertyTree &tree = itr->query();
  1976. const char *owner = tree.queryProp("@name");
  1977. const char *modified = tree.queryProp("@modified");
  1978. Owned<IEspDFUFileProtect> protect= createDFUFileProtect();
  1979. if(owner && *owner)
  1980. protect->setOwner(owner);
  1981. if(modified && *modified)
  1982. protect->setModified(modified);
  1983. if (version < 1.54)
  1984. protect->setCount(1);
  1985. protectList.append(*protect.getLink());
  1986. }
  1987. FileDetails.setProtectList(protectList);
  1988. }
  1989. StringBuffer strDesc(df->queryAttributes().queryProp("@description"));
  1990. if (description)
  1991. {
  1992. DistributedFilePropertyLock lock(df);
  1993. lock.queryAttributes().setProp("@description",description);
  1994. strDesc = description;
  1995. }
  1996. FileDetails.setDescription(strDesc);
  1997. if (version >= 1.38)
  1998. FileDetails.setFileSizeInt64(size);
  1999. comma c1(size);
  2000. StringBuffer tmpstr;
  2001. tmpstr<<c1;
  2002. FileDetails.setFilesize(tmpstr.str());
  2003. bool isKeyFile = isFileKey(df);
  2004. if (isKeyFile || df->isCompressed())
  2005. {
  2006. if (version < 1.22)
  2007. FileDetails.setZipFile(true);
  2008. else
  2009. {
  2010. FileDetails.setIsCompressed(true);
  2011. if (df->queryAttributes().hasProp("@compressedSize"))
  2012. {
  2013. __int64 compressedSize = df->queryAttributes().getPropInt64("@compressedSize");
  2014. FileDetails.setCompressedFileSize(compressedSize);
  2015. if (version >= 1.34)
  2016. {
  2017. __int64 diff = size - compressedSize;
  2018. Decimal d(((double) diff)/size*100);
  2019. d.round(2);
  2020. FileDetails.setPercentCompressed(d.getCString());
  2021. }
  2022. }
  2023. else if (isKeyFile)
  2024. FileDetails.setCompressedFileSize(size);
  2025. if (isKeyFile && (version >= 1.41))
  2026. {
  2027. if (isFilePartitionKey(df))
  2028. FileDetails.setKeyType("Partitioned");
  2029. else if (isFileLocalKey(df))
  2030. FileDetails.setKeyType("Local");
  2031. else
  2032. FileDetails.setKeyType("Distributed");
  2033. }
  2034. }
  2035. }
  2036. if (version >= 1.53)
  2037. FileDetails.setIsRestricted(df->isRestrictedAccess());
  2038. if (version >= 1.38)
  2039. FileDetails.setRecordSizeInt64(recordSize);
  2040. comma c2(recordSize);
  2041. tmpstr.clear();
  2042. tmpstr<<c2;
  2043. FileDetails.setRecordSize(tmpstr.str());
  2044. tmpstr.clear();
  2045. __int64 recordCount = -1;
  2046. if (df->queryAttributes().hasProp("@recordCount"))
  2047. {
  2048. recordCount = df->queryAttributes().getPropInt64("@recordCount");
  2049. }
  2050. else if (recordSize)
  2051. {
  2052. recordCount = size/recordSize;
  2053. }
  2054. if (version >= 1.38)
  2055. FileDetails.setRecordCountInt64(recordCount);
  2056. if (recordCount != -1)
  2057. {
  2058. comma c3(recordCount);
  2059. tmpstr<<c3;
  2060. }
  2061. FileDetails.setRecordCount(tmpstr.str());
  2062. FileDetails.setOwner(df->queryAttributes().queryProp("@owner"));
  2063. FileDetails.setJobName(df->queryAttributes().queryProp("@job"));
  2064. if (version >= 1.39)
  2065. {
  2066. if (df->queryAttributes().hasProp("@partitionFieldMask"))
  2067. {
  2068. StringArray partitionFieldNames;
  2069. unsigned __int64 partitionFieldMask = df->queryAttributes().getPropInt64("@partitionFieldMask");
  2070. queryFieldNames(context, name, cluster, partitionFieldMask, partitionFieldNames);
  2071. IEspDFUFilePartition &partition = FileDetails.updatePartition();
  2072. partition.setFieldMask(partitionFieldMask);
  2073. partition.setFieldNames(partitionFieldNames);
  2074. }
  2075. IArrayOf<IEspDFUFileBloom> bloomList;
  2076. Owned<IPropertyTreeIterator> itr= df->queryAttributes().getElements("Bloom");
  2077. ForEach(*itr)
  2078. {
  2079. IPropertyTree &bloomTree = itr->query();
  2080. StringArray bloomFieldNames;
  2081. unsigned __int64 bloomFieldMask = bloomTree.getPropInt64("@bloomFieldMask");
  2082. queryFieldNames(context, name, cluster, bloomFieldMask, bloomFieldNames);
  2083. Owned<IEspDFUFileBloom> bloom= createDFUFileBloom();
  2084. bloom->setFieldMask(bloomFieldMask);
  2085. bloom->setFieldNames(bloomFieldNames);
  2086. bloom->setLimit(bloomTree.getPropInt64("@bloomLimit"));
  2087. bloom->setProbability(bloomTree.queryProp("@bloomProbability"));
  2088. bloomList.append(*bloom.getLink());
  2089. }
  2090. if (bloomList.ordinality())
  2091. FileDetails.setBlooms(bloomList);
  2092. }
  2093. if ((version >= 1.40) && df->queryAttributes().hasProp("@expireDays"))
  2094. FileDetails.setExpireDays(df->queryAttributes().getPropInt("@expireDays"));
  2095. //#14280
  2096. IDistributedSuperFile *sf = df->querySuperFile();
  2097. if(sf)
  2098. {
  2099. StringArray farray;
  2100. Owned<IDistributedFileIterator> iter=sf->getSubFileIterator();
  2101. ForEach(*iter)
  2102. {
  2103. StringBuffer subfileName;
  2104. iter->getName(subfileName);
  2105. farray.append(subfileName.str());
  2106. }
  2107. unsigned numSubFiles = farray.length();
  2108. if(numSubFiles > 0)
  2109. {
  2110. FileDetails.setSubfiles(farray);
  2111. }
  2112. if ((version >= 1.28) && (numSubFiles > 1))
  2113. FileDetails.setBrowseData(false); //ViewKeyFile Cannot handle superfile with multiple subfiles
  2114. FileDetails.setIsSuperfile(true);
  2115. return;
  2116. }
  2117. //#14280
  2118. FileDetails.setWuid(df->queryAttributes().queryProp("@workunit"));
  2119. if (version >= 1.28)
  2120. FileDetails.setNumParts(df->numParts());
  2121. //#17430
  2122. {
  2123. IArrayOf<IEspDFULogicalFile> LogicalFiles;
  2124. Owned<IDistributedSuperFileIterator> iter = df->getOwningSuperFiles();
  2125. if(iter.get() != NULL)
  2126. {
  2127. ForEach(*iter)
  2128. {
  2129. //printf("%s,%s\n",iter->query().queryLogicalName(),lname);
  2130. Owned<IEspDFULogicalFile> File = createDFULogicalFile("","");
  2131. File->setName(iter->queryName());
  2132. LogicalFiles.append(*File.getClear());
  2133. }
  2134. }
  2135. if(LogicalFiles.length() > 0)
  2136. {
  2137. FileDetails.setSuperfiles(LogicalFiles);
  2138. }
  2139. }
  2140. //#17430
  2141. //new (optional) attribute on a logical file (@persistent)
  2142. //indicates the ESP page that shows the details of a file. It indicates
  2143. //whether the file was created with a PERSIST() ecl attribute.
  2144. FileDetails.setPersistent(df->queryAttributes().queryProp("@persistent"));
  2145. //@format - what format the file is (if not fixed with)
  2146. FileDetails.setFormat(df->queryAttributes().queryProp("@format"));
  2147. if ((version >= 1.21) && (df->queryAttributes().hasProp("@kind")))
  2148. FileDetails.setContentType(df->queryAttributes().queryProp("@kind"));
  2149. //@maxRecordSize - what the maximum length of records is
  2150. FileDetails.setMaxRecordSize(df->queryAttributes().queryProp("@maxRecordSize"));
  2151. //@csvSeparate - separators between fields for a CSV/utf file
  2152. FileDetails.setCsvSeparate(df->queryAttributes().queryProp("@csvSeparate"));
  2153. //@csvQuote - character used to quote fields for a csv/utf file.
  2154. FileDetails.setCsvQuote(df->queryAttributes().queryProp("@csvQuote"));
  2155. //@csvTerminate - characters used to terminate a record in a csv.utf file
  2156. FileDetails.setCsvTerminate(df->queryAttributes().queryProp("@csvTerminate"));
  2157. //@csvEscape - character used to define escape for a csv/utf file.
  2158. if (version >= 1.20)
  2159. FileDetails.setCsvEscape(df->queryAttributes().queryProp("@csvEscape"));
  2160. //Time and date of the file
  2161. tmpstr.clear();
  2162. dt.getDateString(tmpstr);
  2163. tmpstr.append(" ");
  2164. dt.getTimeString(tmpstr);
  2165. FileDetails.setModified(tmpstr.str());
  2166. if(df->queryAttributes().hasProp("ECL"))
  2167. FileDetails.setEcl(df->queryAttributes().queryProp("ECL"));
  2168. StringBuffer clusterStr;
  2169. ForEachItemIn(i, clusters)
  2170. {
  2171. if (!clusterStr.length())
  2172. clusterStr.append(clusters.item(i));
  2173. else
  2174. clusterStr.append(",").append(clusters.item(i));
  2175. }
  2176. if (clusterStr.length() > 0)
  2177. {
  2178. if (!checkFileContent(context, udesc, name, clusterStr.str()))
  2179. FileDetails.setShowFileContent(false);
  2180. if (version > 1.05)
  2181. {
  2182. bool fromRoxieCluster = false;
  2183. StringArray roxieClusterNames;
  2184. IArrayOf<IEspTpCluster> roxieclusters;
  2185. CTpWrapper dummy;
  2186. dummy.getClusterProcessList(eqRoxieCluster, roxieclusters);
  2187. ForEachItemIn(k, roxieclusters)
  2188. {
  2189. IEspTpCluster& r_cluster = roxieclusters.item(k);
  2190. StringBuffer sName(r_cluster.getName());
  2191. if (FindInStringArray(clusters, sName.str()))
  2192. {
  2193. fromRoxieCluster = true;
  2194. break;
  2195. }
  2196. }
  2197. FileDetails.setFromRoxieCluster(fromRoxieCluster);
  2198. }
  2199. }
  2200. if (version >= 1.25)
  2201. getFilePartsOnClusters(context, cluster, clusters, df, FileDetails);
  2202. else
  2203. {
  2204. FileDetails.setCluster(clusters.item(0));
  2205. IArrayOf<IConstDFUPart>& PartList = FileDetails.getDFUFileParts();
  2206. Owned<IDistributedFilePartIterator> pi = df->getIterator();
  2207. ForEach(*pi)
  2208. {
  2209. Owned<IDistributedFilePart> part = &pi->get();
  2210. for (unsigned int i=0; i<part->numCopies(); i++)
  2211. {
  2212. Owned<IEspDFUPart> FilePart = createDFUPart();
  2213. StringBuffer url;
  2214. part->queryNode(i)->endpoint().getUrlStr(url);
  2215. FilePart->setId(part->getPartIndex()+1);
  2216. FilePart->setCopy(i+1);
  2217. FilePart->setIp(url.str());
  2218. FilePart->setPartsize("<N/A>");
  2219. try
  2220. {
  2221. offset_t size = queryDistributedFileSystem().getSize(part);
  2222. if (version >= 1.38)
  2223. FilePart->setPartSizeInt64(size);
  2224. comma c4(size);
  2225. tmpstr.clear();
  2226. tmpstr<<c4;
  2227. FilePart->setPartsize(tmpstr.str());
  2228. }
  2229. catch(IException *e)
  2230. {
  2231. StringBuffer msg;
  2232. IERRLOG("Exception %d:%s in WS_DFU queryDistributedFileSystem().getSize()", e->errorCode(), e->errorMessage(msg).str());
  2233. e->Release();
  2234. }
  2235. catch(...)
  2236. {
  2237. IERRLOG("Unknown exception in WS_DFU queryDistributedFileSystem().getSize()");
  2238. }
  2239. PartList.append(*FilePart.getClear());
  2240. }
  2241. }
  2242. }
  2243. unsigned maxSkew, minSkew, maxSkewPart, minSkewPart;
  2244. if (df->getSkewInfo(maxSkew, minSkew, maxSkewPart, minSkewPart, true))
  2245. {
  2246. IEspDFUFileStat& Stat = FileDetails.updateStat();
  2247. if (version >= 1.38)
  2248. {
  2249. Stat.setMinSkewInt64(minSkew);
  2250. Stat.setMaxSkewInt64(maxSkew);
  2251. }
  2252. if (version >= 1.52)
  2253. {
  2254. Stat.setMinSkewPart(minSkewPart);
  2255. Stat.setMaxSkewPart(maxSkewPart);
  2256. }
  2257. VStringBuffer minSkewString("%s%.2f", (minSkew>0) ? "-" : "", ((double)minSkew)/100);
  2258. Stat.setMinSkew(minSkewString.str());
  2259. VStringBuffer maxSkewString("%.2f", ((double)maxSkew)/100);
  2260. Stat.setMaxSkew(maxSkewString.str());
  2261. }
  2262. if (version > 1.06)
  2263. {
  2264. const char *wuid = df->queryAttributes().queryProp("@workunit");
  2265. if (wuid && *wuid && (wuid[0]=='W'))
  2266. {
  2267. try
  2268. {
  2269. CWUWrapper wu(wuid, context);
  2270. StringArray graphs;
  2271. Owned<IPropertyTreeIterator> f=&wu->getFileIterator();
  2272. ForEach(*f)
  2273. {
  2274. IPropertyTree &query = f->query();
  2275. const char *fileName = query.queryProp("@name");
  2276. const char *graphName = query.queryProp("@graph");
  2277. if (!fileName || !graphName || !*graphName || stricmp(fileName, name))
  2278. continue;
  2279. graphs.append(graphName);
  2280. }
  2281. FileDetails.setGraphs(graphs);
  2282. }
  2283. catch(...)
  2284. {
  2285. IERRLOG("Failed in retrieving graphs from workunit %s", wuid);
  2286. }
  2287. }
  2288. }
  2289. if (version > 1.08 && udesc)
  2290. {
  2291. SecAccessFlags permission;
  2292. if (getUserFilePermission(context, udesc, name, permission))
  2293. {
  2294. switch (permission)
  2295. {
  2296. case SecAccess_Full:
  2297. FileDetails.setUserPermission("Full Access Permission");
  2298. break;
  2299. case SecAccess_Write:
  2300. FileDetails.setUserPermission("Write Access Permission");
  2301. break;
  2302. case SecAccess_Read:
  2303. FileDetails.setUserPermission("Read Access Permission");
  2304. break;
  2305. case SecAccess_Access:
  2306. FileDetails.setUserPermission("Access Permission");
  2307. break;
  2308. case SecAccess_None:
  2309. FileDetails.setUserPermission("None Access Permission");
  2310. break;
  2311. default:
  2312. FileDetails.setUserPermission("Permission Unknown");
  2313. break;
  2314. }
  2315. }
  2316. }
  2317. if (includeJsonTypeInfo||includeBinTypeInfo)
  2318. {
  2319. MemoryBuffer binLayout;
  2320. StringBuffer jsonLayout;
  2321. if (getRecordFormatFromRtlType(binLayout, jsonLayout, df->queryAttributes(), includeBinTypeInfo, includeJsonTypeInfo) ||
  2322. getRecordFormatFromECL(binLayout.clear(), jsonLayout.clear(), df->queryAttributes(), includeBinTypeInfo, includeJsonTypeInfo))
  2323. {
  2324. if (includeBinTypeInfo)
  2325. FileDetails.setBinInfo(binLayout);
  2326. if (includeJsonTypeInfo)
  2327. FileDetails.setJsonInfo(jsonLayout);
  2328. }
  2329. }
  2330. if (version >= 1.59)
  2331. {
  2332. double totalCost = df->getCost(cluster);
  2333. StringBuffer s;
  2334. formatMoney(s, money2cost_type(totalCost));
  2335. FileDetails.setCost(s);
  2336. }
  2337. PROGLOG("doGetFileDetails: %s done", name);
  2338. }
  2339. bool CWsDfuEx::getQueryFile(const char *logicalName, const char *querySet, const char *queryID, IEspDFUFileDetail &fileDetails)
  2340. {
  2341. Owned<IConstWUClusterInfo> info = getWUClusterInfoByName(querySet);
  2342. if (!info || (info->getPlatform()!=RoxieCluster))
  2343. return false;
  2344. SCMStringBuffer process;
  2345. info->getRoxieProcess(process);
  2346. if (!process.length())
  2347. return false;
  2348. Owned<IHpccPackageSet> ps = createPackageSet(process.str());
  2349. if (!ps)
  2350. return false;
  2351. const IHpccPackageMap *pm = ps->queryActiveMap(querySet);
  2352. if (!pm)
  2353. return false;
  2354. const IHpccPackage *pkg = pm->matchPackage(queryID);
  2355. if (!pkg)
  2356. return false;
  2357. const char *pkgid = pkg->locateSuperFile(logicalName);
  2358. if (!pkgid)
  2359. return false;
  2360. fileDetails.setName(logicalName);
  2361. fileDetails.setIsSuperfile(true);
  2362. fileDetails.setPackageID(pkgid);
  2363. StringArray subFiles;
  2364. Owned<ISimpleSuperFileEnquiry> ssfe = pkg->resolveSuperFile(logicalName);
  2365. if (ssfe && ssfe->numSubFiles()>0)
  2366. {
  2367. unsigned count = ssfe->numSubFiles();
  2368. while (count--)
  2369. {
  2370. StringBuffer subfile;
  2371. ssfe->getSubFileName(count, subfile);
  2372. subFiles.append(subfile.str());
  2373. }
  2374. if (!subFiles.empty())
  2375. fileDetails.setSubfiles(subFiles);
  2376. }
  2377. return true;
  2378. }
  2379. void CWsDfuEx::getLogicalFileAndDirectory(IEspContext &context, IUserDescriptor* udesc, const char *dirname,
  2380. bool includeSuperOwner, IArrayOf<IEspDFULogicalFile>& logicalFiles, int& numFiles, int& numDirs)
  2381. {
  2382. double version = context.getClientVersion();
  2383. if (dirname && *dirname)
  2384. PROGLOG("getLogicalFileAndDirectory: %s", dirname);
  2385. else
  2386. PROGLOG("getLogicalFileAndDirectory: folder not specified");
  2387. numFiles = 0;
  2388. numDirs = 0;
  2389. if (dirname && *dirname)
  2390. {
  2391. StringBuffer filterBuf;
  2392. setFileNameFilter(NULL, dirname, filterBuf);
  2393. if (includeSuperOwner)
  2394. filterBuf.append(DFUQFTincludeFileAttr).append(DFUQFilterSeparator).append(DFUQSFAOincludeSuperOwner).append(DFUQFilterSeparator);
  2395. //filters used to filter query result received from dali server.
  2396. DFUQResultField localFilters[8];
  2397. localFilters[0] = DFUQRFterm;
  2398. DFUQResultField sortOrder[] = {DFUQRFterm};
  2399. __int64 cacheHint = 0; //No page
  2400. unsigned totalFiles = 0;
  2401. bool allMatchingFilesReceived = true;
  2402. Owned<IDFAttributesIterator> it = queryDistributedFileDirectory().getLogicalFiles(udesc, sortOrder, filterBuf.str(),
  2403. localFilters, NULL, 0, (unsigned)-1, &cacheHint, &totalFiles, &allMatchingFilesReceived, false, false);
  2404. if(!it)
  2405. throw MakeStringException(ECLWATCH_CANNOT_GET_FILE_ITERATOR,"Cannot get LogicalFile information from file system.");
  2406. ForEach(*it)
  2407. WsDFUHelpers::addToLogicalFileList(it->query(), NULL, version, logicalFiles);
  2408. numFiles = totalFiles;
  2409. }
  2410. Owned<IDFScopeIterator> iter = queryDistributedFileDirectory().getScopeIterator(udesc,dirname,false);
  2411. if(iter)
  2412. {
  2413. ForEach(*iter)
  2414. {
  2415. const char *scope = iter->query();
  2416. if (scope && *scope)
  2417. {
  2418. Owned<IEspDFULogicalFile> file = createDFULogicalFile("","");
  2419. file->setDirectory(scope);
  2420. file->setIsDirectory(true);
  2421. logicalFiles.append(*file.getClear());
  2422. numDirs++;
  2423. }
  2424. }
  2425. }
  2426. }
  2427. bool CWsDfuEx::onDFUFileView(IEspContext &context, IEspDFUFileViewRequest &req, IEspDFUFileViewResponse &resp)
  2428. {
  2429. try
  2430. {
  2431. context.ensureFeatureAccess(FEATURE_URL, SecAccess_Read, ECLWATCH_DFU_ACCESS_DENIED, "WsDfu::DFUFileView: Permission denied.");
  2432. Owned<IUserDescriptor> userdesc;
  2433. StringBuffer username;
  2434. context.getUserID(username);
  2435. if(username.length() > 0)
  2436. {
  2437. userdesc.setown(createUserDescriptor());
  2438. userdesc->set(username.str(), context.queryPassword(), context.querySignature());
  2439. }
  2440. int numDirs = 0;
  2441. int numFiles = 0;
  2442. IArrayOf<IEspDFULogicalFile> logicalFiles;
  2443. getLogicalFileAndDirectory(context, userdesc.get(), req.getScope(), !req.getIncludeSuperOwner_isNull() && req.getIncludeSuperOwner(), logicalFiles, numFiles, numDirs);
  2444. if (numFiles > 0)
  2445. resp.setNumFiles(numFiles);
  2446. if (req.getScope() && *req.getScope())
  2447. resp.setScope(req.getScope());
  2448. else
  2449. resp.setScope("");
  2450. resp.setDFULogicalFiles(logicalFiles);
  2451. }
  2452. catch(IException* e)
  2453. {
  2454. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  2455. }
  2456. return true;
  2457. }
  2458. __int64 CWsDfuEx::findPositionBySize(const __int64 size, bool descend, IArrayOf<IEspDFULogicalFile>& LogicalFiles)
  2459. {
  2460. __int64 addToPos = -1;
  2461. ForEachItemIn(i, LogicalFiles)
  2462. {
  2463. IEspDFULogicalFile& File = LogicalFiles.item(i);
  2464. const char* sSize = File.getLongSize();
  2465. __int64 nSize = atoi64_l(sSize,strlen(sSize));
  2466. if (descend && size > nSize)
  2467. {
  2468. addToPos = i;
  2469. break;
  2470. }
  2471. if (!descend && size < nSize)
  2472. {
  2473. addToPos = i;
  2474. break;
  2475. }
  2476. }
  2477. return addToPos;
  2478. }
  2479. __int64 CWsDfuEx::findPositionByParts(const __int64 parts, bool descend, IArrayOf<IEspDFULogicalFile>& LogicalFiles)
  2480. {
  2481. __int64 addToPos = -1;
  2482. ForEachItemIn(i, LogicalFiles)
  2483. {
  2484. IEspDFULogicalFile& File = LogicalFiles.item(i);
  2485. const char* sParts = File.getParts();
  2486. __int64 nParts = atoi64_l(sParts,strlen(sParts));
  2487. if (descend && parts > nParts)
  2488. {
  2489. addToPos = i;
  2490. break;
  2491. }
  2492. if (!descend && parts < nParts)
  2493. {
  2494. addToPos = i;
  2495. break;
  2496. }
  2497. }
  2498. return addToPos;
  2499. }
  2500. __int64 CWsDfuEx::findPositionByRecords(const __int64 records, bool descend, IArrayOf<IEspDFULogicalFile>& LogicalFiles)
  2501. {
  2502. __int64 addToPos = -1;
  2503. ForEachItemIn(i, LogicalFiles)
  2504. {
  2505. IEspDFULogicalFile& File = LogicalFiles.item(i);
  2506. const char* sRecords = File.getLongRecordCount();
  2507. __int64 nRecords = atoi64_l(sRecords,strlen(sRecords));
  2508. if (descend && records > nRecords)
  2509. {
  2510. addToPos = i;
  2511. break;
  2512. }
  2513. if (!descend && records < nRecords)
  2514. {
  2515. addToPos = i;
  2516. break;
  2517. }
  2518. }
  2519. return addToPos;
  2520. }
  2521. __int64 CWsDfuEx::findPositionByName(const char *name, bool descend, IArrayOf<IEspDFULogicalFile>& LogicalFiles)
  2522. {
  2523. if (!name || (strlen(name) < 1))
  2524. {
  2525. if (descend)
  2526. return -1;
  2527. else
  2528. return 0;
  2529. }
  2530. __int64 addToPos = -1;
  2531. ForEachItemIn(i, LogicalFiles)
  2532. {
  2533. IEspDFULogicalFile& File = LogicalFiles.item(i);
  2534. const char *Name = File.getName();
  2535. if (!Name)
  2536. continue;
  2537. if (descend && strcmp(name, Name)>0)
  2538. {
  2539. addToPos = i;
  2540. break;
  2541. }
  2542. if (!descend && strcmp(name, Name)<0)
  2543. {
  2544. addToPos = i;
  2545. break;
  2546. }
  2547. }
  2548. return addToPos;
  2549. }
  2550. __int64 CWsDfuEx::findPositionByNodeGroup(double version, const char *node, bool descend, IArrayOf<IEspDFULogicalFile>& LogicalFiles)
  2551. {
  2552. if (!node || !*node)
  2553. {
  2554. if (descend)
  2555. return -1;
  2556. else
  2557. return 0;
  2558. }
  2559. __int64 addToPos = -1;
  2560. ForEachItemIn(i, LogicalFiles)
  2561. {
  2562. IEspDFULogicalFile& File = LogicalFiles.item(i);
  2563. const char *nodeGroup = NULL;
  2564. if (version < 1.26)
  2565. nodeGroup = File.getClusterName();
  2566. else
  2567. nodeGroup = File.getNodeGroup();
  2568. if (!nodeGroup)
  2569. continue;
  2570. if (descend && strcmp(node, nodeGroup)>0)
  2571. {
  2572. addToPos = i;
  2573. break;
  2574. }
  2575. if (!descend && strcmp(node, nodeGroup)<0)
  2576. {
  2577. addToPos = i;
  2578. break;
  2579. }
  2580. }
  2581. return addToPos;
  2582. }
  2583. __int64 CWsDfuEx::findPositionByOwner(const char *owner, bool descend, IArrayOf<IEspDFULogicalFile>& LogicalFiles)
  2584. {
  2585. if (!owner || (strlen(owner) < 1))
  2586. {
  2587. if (descend)
  2588. return -1;
  2589. else
  2590. return 0;
  2591. }
  2592. __int64 addToPos = -1;
  2593. ForEachItemIn(i, LogicalFiles)
  2594. {
  2595. IEspDFULogicalFile& File = LogicalFiles.item(i);
  2596. const char *Owner = File.getOwner();
  2597. if (!Owner)
  2598. continue;
  2599. if (descend && strcmp(owner, Owner)>0)
  2600. {
  2601. addToPos = i;
  2602. break;
  2603. }
  2604. if (!descend && strcmp(owner, Owner)<0)
  2605. {
  2606. addToPos = i;
  2607. break;
  2608. }
  2609. }
  2610. return addToPos;
  2611. }
  2612. __int64 CWsDfuEx::findPositionByDate(const char *datetime, bool descend, IArrayOf<IEspDFULogicalFile>& LogicalFiles)
  2613. {
  2614. if (!datetime || (strlen(datetime) < 1))
  2615. {
  2616. if (descend)
  2617. return -1;
  2618. else
  2619. return 0;
  2620. }
  2621. __int64 addToPos = -1;
  2622. ForEachItemIn(i, LogicalFiles)
  2623. {
  2624. IEspDFULogicalFile& File = LogicalFiles.item(i);
  2625. const char *modDate = File.getModified();
  2626. if (!modDate)
  2627. continue;
  2628. if (descend && strcmp(datetime, modDate)>0)
  2629. {
  2630. addToPos = i;
  2631. break;
  2632. }
  2633. if (!descend && strcmp(datetime, modDate)<0)
  2634. {
  2635. addToPos = i;
  2636. break;
  2637. }
  2638. }
  2639. return addToPos;
  2640. }
  2641. __int64 CWsDfuEx::findPositionByDescription(const char *description, bool descend, IArrayOf<IEspDFULogicalFile>& LogicalFiles)
  2642. {
  2643. if (!description || (strlen(description) < 1))
  2644. {
  2645. if (descend)
  2646. return -1;
  2647. else
  2648. return 0;
  2649. }
  2650. __int64 addToPos = -1;
  2651. ForEachItemIn(i, LogicalFiles)
  2652. {
  2653. IEspDFULogicalFile& File = LogicalFiles.item(i);
  2654. const char *Description = File.getDescription();
  2655. if (!Description)
  2656. continue;
  2657. if (descend && strcmp(description, Description)>0)
  2658. {
  2659. addToPos = i;
  2660. break;
  2661. }
  2662. if (!descend && strcmp(description, Description)<0)
  2663. {
  2664. addToPos = i;
  2665. break;
  2666. }
  2667. }
  2668. return addToPos;
  2669. }
  2670. //The code inside this method is copied from previous code for legacy (< 5.0) dali support
  2671. void CWsDfuEx::getAPageOfSortedLogicalFile(IEspContext &context, IUserDescriptor* udesc, IEspDFUQueryRequest & req, IEspDFUQueryResponse & resp)
  2672. {
  2673. double version = context.getClientVersion();
  2674. IArrayOf<IEspDFULogicalFile> LogicalFiles;
  2675. StringBuffer filter;
  2676. const char* fname = req.getLogicalName();
  2677. if(fname && *fname)
  2678. {
  2679. filter.append(fname);
  2680. }
  2681. else
  2682. {
  2683. if(req.getPrefix() && *req.getPrefix())
  2684. {
  2685. filter.append(req.getPrefix());
  2686. filter.append("::");
  2687. }
  2688. filter.append("*");
  2689. }
  2690. Owned<IDFAttributesIterator> fi;
  2691. bool bNotInSuperfile = false;
  2692. const char* sFileType = req.getFileType();
  2693. if (sFileType && !stricmp(sFileType, "Not in Superfiles"))
  2694. {
  2695. bNotInSuperfile = true;
  2696. }
  2697. if (bNotInSuperfile)
  2698. {
  2699. fi.setown(createSubFileFilter(
  2700. queryDistributedFileDirectory().getDFAttributesIterator(filter.toLowerCase().str(),udesc,true,true, NULL),udesc,false)); // NB wrapper owns wrapped iterator
  2701. }
  2702. else
  2703. {
  2704. fi.setown(queryDistributedFileDirectory().getDFAttributesIterator(filter.toLowerCase().str(), udesc,true,true, NULL));
  2705. }
  2706. if(!fi)
  2707. throw MakeStringException(ECLWATCH_CANNOT_GET_FILE_ITERATOR,"Cannot get information from file system.");
  2708. StringBuffer wuFrom, wuTo;
  2709. if(req.getStartDate() && *req.getStartDate())
  2710. {
  2711. CDateTime wuTime;
  2712. wuTime.setString(req.getStartDate(),NULL,true);
  2713. unsigned year, month, day, hour, minute, second, nano;
  2714. wuTime.getDate(year, month, day, true);
  2715. wuTime.getTime(hour, minute, second, nano, true);
  2716. wuFrom.appendf("%4d-%02d-%02d %02d:%02d:%02d",year,month,day,hour,minute,second);
  2717. }
  2718. if(req.getEndDate() && *req.getEndDate())
  2719. {
  2720. CDateTime wuTime;
  2721. wuTime.setString(req.getEndDate(),NULL,true);
  2722. unsigned year, month, day, hour, minute, second, nano;
  2723. wuTime.getDate(year, month, day, true);
  2724. wuTime.getTime(hour, minute, second, nano, true);
  2725. wuTo.appendf("%4d-%02d-%02d %02d:%02d:%02d",year,month,day,hour,minute,second);
  2726. }
  2727. StringBuffer sortBy;
  2728. if(req.getSortby() && *req.getSortby())
  2729. {
  2730. sortBy.append(req.getSortby());
  2731. }
  2732. unsigned pagesize = req.getPageSize();
  2733. if (pagesize < 1)
  2734. {
  2735. pagesize = 100;
  2736. }
  2737. __int64 displayStartReq = 1;
  2738. if (req.getPageStartFrom() > 0)
  2739. displayStartReq = req.getPageStartFrom();
  2740. __int64 displayStart = displayStartReq - 1;
  2741. __int64 displayEnd = displayStart + pagesize;
  2742. bool descending = req.getDescending();
  2743. const int nFirstN = req.getFirstN();
  2744. const char* sFirstNType = req.getFirstNType();
  2745. const __int64 nFileSizeFrom = req.getFileSizeFrom();
  2746. const __int64 nFileSizeTo = req.getFileSizeTo();
  2747. if (nFirstN > 0)
  2748. {
  2749. displayStart = 0;
  2750. displayEnd = nFirstN;
  2751. if (!stricmp(sFirstNType, "newest"))
  2752. {
  2753. sortBy.set("Modified");
  2754. descending = true;
  2755. }
  2756. else if (!stricmp(sFirstNType, "oldest"))
  2757. {
  2758. sortBy.set("Modified");
  2759. descending = false;
  2760. }
  2761. else if (!stricmp(sFirstNType, "largest"))
  2762. {
  2763. sortBy.set("FileSize");
  2764. descending = true;
  2765. }
  2766. else if (!stricmp(sFirstNType, "smallest"))
  2767. {
  2768. sortBy.set("FileSize");
  2769. descending = false;
  2770. }
  2771. pagesize = nFirstN;
  2772. }
  2773. StringArray roxieClusterNames;
  2774. IArrayOf<IEspTpCluster> roxieclusters;
  2775. CTpWrapper dummy;
  2776. dummy.getClusterProcessList(eqRoxieCluster, roxieclusters);
  2777. ForEachItemIn(k, roxieclusters)
  2778. {
  2779. IEspTpCluster& cluster = roxieclusters.item(k);
  2780. StringBuffer sName(cluster.getName());
  2781. roxieClusterNames.append(sName.str());
  2782. }
  2783. StringArray nodeGroupsReq;
  2784. const char* nodeGroupsReqString = req.getNodeGroup();
  2785. if (nodeGroupsReqString && *nodeGroupsReqString)
  2786. nodeGroupsReq.appendListUniq(nodeGroupsReqString, ",");
  2787. StringBuffer size;
  2788. __int64 totalFiles = 0;
  2789. IArrayOf<IEspDFULogicalFile> LogicalFileList;
  2790. ForEach(*fi)
  2791. {
  2792. IPropertyTree &attr=fi->query();
  2793. const char* logicalName=attr.queryProp("@name");
  2794. if (!logicalName || (logicalName[0] == 0))
  2795. continue;
  2796. try
  2797. {
  2798. StringBuffer pref;
  2799. const char *c=strstr(logicalName, "::");
  2800. if (c)
  2801. pref.append(c-logicalName, logicalName);
  2802. else
  2803. pref.append(logicalName);
  2804. const char* owner=attr.queryProp("@owner");
  2805. if (req.getOwner() && *req.getOwner()!=0)
  2806. {
  2807. if (!owner || stricmp(owner, req.getOwner()))
  2808. continue;
  2809. }
  2810. StringArray nodeGroups;
  2811. StringArray fileNodeGroups;
  2812. if (getFileGroups(&attr,fileNodeGroups)==0)
  2813. {
  2814. if (!nodeGroupsReq.length())
  2815. nodeGroups.append("");
  2816. }
  2817. else if (nodeGroupsReq.length() > 0) // check specified cluster name in list
  2818. {
  2819. ForEachItemIn(ii,nodeGroupsReq)
  2820. {
  2821. const char* nodeGroupReq = nodeGroupsReq.item(ii);
  2822. ForEachItemIn(i,fileNodeGroups)
  2823. {
  2824. if (strieq(fileNodeGroups.item(i), nodeGroupReq))
  2825. {
  2826. nodeGroups.append(nodeGroupReq);
  2827. break;
  2828. }
  2829. }
  2830. }
  2831. }
  2832. else if (fileNodeGroups.length())
  2833. {
  2834. ForEachItemIn(i,fileNodeGroups)
  2835. nodeGroups.append(fileNodeGroups.item(i));
  2836. }
  2837. if (sFileType && *sFileType)
  2838. {
  2839. bool bHasSubFiles = attr.hasProp("@numsubfiles");
  2840. if (bHasSubFiles && (bNotInSuperfile || !stricmp(sFileType, "Logical Files Only")))
  2841. continue;
  2842. else if (!bHasSubFiles && !stricmp(sFileType, "Superfiles Only"))
  2843. continue;
  2844. }
  2845. __int64 recordSize=attr.getPropInt64("@recordSize",0), size=attr.getPropInt64("@size",-1);
  2846. if (nFileSizeFrom > 0 && size < nFileSizeFrom)
  2847. continue;
  2848. if (nFileSizeTo > 0 && size > nFileSizeTo)
  2849. continue;
  2850. StringBuffer modf(attr.queryProp("@modified"));
  2851. char* t=(char *) strchr(modf.str(),'T');
  2852. if(t) *t=' ';
  2853. if (wuFrom.length() && strcmp(modf.str(),wuFrom.str())<0)
  2854. continue;
  2855. if (wuTo.length() && strcmp(modf.str(),wuTo.str())>0)
  2856. continue;
  2857. __int64 parts = 0;
  2858. if(!attr.hasProp("@numsubfiles"))
  2859. parts = attr.getPropInt64("@numparts");
  2860. __int64 records = 0;
  2861. if (attr.hasProp("@recordCount"))
  2862. records = attr.getPropInt64("@recordCount");
  2863. else if(recordSize)
  2864. records = size/recordSize;
  2865. const char* desc = attr.queryProp("@description");
  2866. ForEachItemIn(i, nodeGroups)
  2867. {
  2868. const char* nodeGroup = nodeGroups.item(i);
  2869. __int64 addToPos = -1; //Add to tail
  2870. if (stricmp(sortBy, "FileSize")==0)
  2871. {
  2872. addToPos = findPositionBySize(size, descending, LogicalFileList);
  2873. }
  2874. else if (stricmp(sortBy, "Parts")==0)
  2875. {
  2876. addToPos = findPositionByParts(parts, descending, LogicalFileList);
  2877. }
  2878. else if (stricmp(sortBy, "Owner")==0)
  2879. {
  2880. addToPos = findPositionByOwner(owner, descending, LogicalFileList);
  2881. }
  2882. else if (stricmp(sortBy, "NodeGroup")==0)
  2883. {
  2884. addToPos = findPositionByNodeGroup(version, nodeGroup, descending, LogicalFileList);
  2885. }
  2886. else if (stricmp(sortBy, "Records")==0)
  2887. {
  2888. addToPos = findPositionByRecords(records, descending, LogicalFileList);
  2889. }
  2890. else if (stricmp(sortBy, "Modified")==0)
  2891. {
  2892. addToPos = findPositionByDate(modf.str(), descending, LogicalFileList);
  2893. }
  2894. else if (stricmp(sortBy, "Description")==0)
  2895. {
  2896. addToPos = findPositionByDescription(desc, descending, LogicalFileList);
  2897. }
  2898. else
  2899. {
  2900. addToPos = findPositionByName(logicalName, descending, LogicalFileList);
  2901. }
  2902. totalFiles++;
  2903. if (addToPos < 0 && (totalFiles > displayEnd))
  2904. continue;
  2905. Owned<IEspDFULogicalFile> File = createDFULogicalFile("","");
  2906. File->setPrefix(pref);
  2907. if (version < 1.26)
  2908. File->setClusterName(nodeGroup);
  2909. else
  2910. File->setNodeGroup(nodeGroup);
  2911. File->setName(logicalName);
  2912. File->setOwner(owner);
  2913. File->setDescription(desc);
  2914. File->setModified(modf.str());
  2915. File->setReplicate(true);
  2916. ForEachItemIn(j, roxieClusterNames)
  2917. {
  2918. const char* roxieClusterName = roxieClusterNames.item(j);
  2919. if (roxieClusterName && nodeGroup && strieq(roxieClusterName, nodeGroup))
  2920. {
  2921. File->setFromRoxieCluster(true);
  2922. break;
  2923. }
  2924. }
  2925. bool bSuperfile = false;
  2926. int numSubFiles = attr.hasProp("@numsubfiles");
  2927. if(!numSubFiles)
  2928. {
  2929. File->setDirectory(attr.queryProp("@directory"));
  2930. File->setParts(attr.queryProp("@numparts"));
  2931. }
  2932. else
  2933. {
  2934. bSuperfile = true;
  2935. }
  2936. File->setIsSuperfile(bSuperfile);
  2937. if (version < 1.22)
  2938. File->setIsZipfile(isCompressed(attr));
  2939. else
  2940. {
  2941. File->setIsCompressed(isCompressed(attr));
  2942. if (attr.hasProp("@compressedSize"))
  2943. File->setCompressedFileSize(attr.getPropInt64("@compressedSize"));
  2944. }
  2945. //File->setBrowseData(bKeyFile); //Bug: 39750 - All files should be viewable through ViewKeyFile function
  2946. if (numSubFiles > 1) //Bug 41379 - ViewKeyFile Cannot handle superfile with multiple subfiles
  2947. File->setBrowseData(false);
  2948. else
  2949. File->setBrowseData(true);
  2950. if (version > 1.13)
  2951. {
  2952. bool bKeyFile = false;
  2953. const char * kind = attr.queryProp("@kind");
  2954. if (kind && (stricmp(kind, "key") == 0))
  2955. {
  2956. bKeyFile = true;
  2957. }
  2958. if (version < 1.24)
  2959. File->setIsKeyFile(bKeyFile);
  2960. else if (kind && *kind)
  2961. File->setContentType(kind);
  2962. }
  2963. StringBuffer buf;
  2964. buf << comma(size);
  2965. File->setTotalsize(buf.str());
  2966. char temp[64];
  2967. numtostr(temp, size);
  2968. File->setLongSize(temp);
  2969. numtostr(temp, records);
  2970. File->setLongRecordCount(temp);
  2971. if (records > 0)
  2972. File->setRecordCount((buf.clear()<<comma(records)).str());
  2973. if (addToPos < 0)
  2974. LogicalFileList.append(*File.getClear());
  2975. else
  2976. LogicalFileList.add(*File.getClear(), (int) addToPos);
  2977. if (LogicalFileList.length() > displayEnd)
  2978. LogicalFileList.pop();
  2979. }
  2980. }
  2981. catch(IException* e)
  2982. {
  2983. VStringBuffer msg("Failed to retrieve data for logical file %s: ", logicalName);
  2984. int code = e->errorCode();
  2985. e->errorMessage(msg);
  2986. e->Release();
  2987. throw MakeStringException(code, "%s", msg.str());
  2988. }
  2989. }
  2990. if (displayEnd > LogicalFileList.length())
  2991. displayEnd = LogicalFileList.length();
  2992. for (int i = (int) displayStart; i < (int) displayEnd; i++)
  2993. {
  2994. Owned<IEspDFULogicalFile> File = createDFULogicalFile("","");
  2995. IEspDFULogicalFile& File0 = LogicalFileList.item(i);
  2996. File->copy(File0);
  2997. LogicalFiles.append(*File.getClear());
  2998. }
  2999. resp.setNumFiles(totalFiles);
  3000. resp.setPageSize(pagesize);
  3001. resp.setPageStartFrom(displayStart+1);
  3002. resp.setPageEndAt(displayEnd);
  3003. if (displayStart - pagesize > 0)
  3004. resp.setPrevPageFrom(displayStart - pagesize + 1);
  3005. else if(displayStart > 0)
  3006. resp.setPrevPageFrom(1);
  3007. if(displayEnd < totalFiles)
  3008. {
  3009. resp.setNextPageFrom(displayEnd+1);
  3010. resp.setLastPageFrom((int)(pagesize * floor((double) ((totalFiles-1) / pagesize)) + 1));
  3011. }
  3012. StringBuffer basicQuery;
  3013. if (req.getNodeGroup() && *req.getNodeGroup())
  3014. {
  3015. if (version < 1.26)
  3016. resp.setClusterName(req.getNodeGroup());
  3017. else
  3018. resp.setNodeGroup(req.getNodeGroup());
  3019. addToQueryString(basicQuery, "NodeGroup", req.getNodeGroup());
  3020. }
  3021. if (req.getOwner() && *req.getOwner())
  3022. {
  3023. resp.setOwner(req.getOwner());
  3024. addToQueryString(basicQuery, "Owner", req.getOwner());
  3025. }
  3026. if (req.getPrefix() && *req.getPrefix())
  3027. {
  3028. resp.setPrefix(req.getPrefix());
  3029. addToQueryString(basicQuery, "Prefix", req.getPrefix());
  3030. }
  3031. if (req.getLogicalName() && *req.getLogicalName())
  3032. {
  3033. resp.setLogicalName(req.getLogicalName());
  3034. addToQueryString(basicQuery, "LogicalName", req.getLogicalName());
  3035. }
  3036. if (req.getStartDate() && *req.getStartDate())
  3037. {
  3038. resp.setStartDate(req.getStartDate());
  3039. addToQueryString(basicQuery, "StartDate", req.getStartDate());
  3040. }
  3041. if (req.getEndDate() && *req.getEndDate())
  3042. {
  3043. resp.setEndDate(req.getEndDate());
  3044. addToQueryString(basicQuery, "EndDate", req.getEndDate());
  3045. }
  3046. if (req.getFileType() && *req.getFileType())
  3047. {
  3048. resp.setFileType(req.getFileType());
  3049. addToQueryString(basicQuery, "FileType", req.getFileType());
  3050. }
  3051. if (req.getFileSizeFrom())
  3052. {
  3053. resp.setFileSizeFrom(req.getFileSizeFrom());
  3054. addToQueryStringFromInt(basicQuery, "FileSizeFrom", req.getFileSizeFrom());
  3055. }
  3056. if (req.getFileSizeTo())
  3057. {
  3058. resp.setFileSizeTo(req.getFileSizeTo());
  3059. addToQueryStringFromInt(basicQuery, "FileSizeTo", req.getFileSizeTo());
  3060. }
  3061. StringBuffer ParametersForFilters(basicQuery);
  3062. StringBuffer ParametersForPaging(basicQuery);
  3063. addToQueryStringFromInt(ParametersForFilters, "PageSize",pagesize);
  3064. addToQueryStringFromInt(ParametersForPaging, "PageSize", pagesize);
  3065. if (ParametersForFilters.length() > 0)
  3066. resp.setFilters(ParametersForFilters.str());
  3067. sortBy.clear();
  3068. descending = false;
  3069. if ((req.getFirstN() > 0) && req.getFirstNType() && *req.getFirstNType())
  3070. {
  3071. const char *sFirstNType = req.getFirstNType();
  3072. if (!stricmp(sFirstNType, "newest"))
  3073. {
  3074. sortBy.set("Modified");
  3075. descending = true;
  3076. }
  3077. else if (!stricmp(sFirstNType, "oldest"))
  3078. {
  3079. sortBy.set("Modified");
  3080. descending = false;
  3081. }
  3082. else if (!stricmp(sFirstNType, "largest"))
  3083. {
  3084. sortBy.set("FileSize");
  3085. descending = true;
  3086. }
  3087. else if (!stricmp(sFirstNType, "smallest"))
  3088. {
  3089. sortBy.set("FileSize");
  3090. descending = false;
  3091. }
  3092. }
  3093. else if (req.getSortby() && *req.getSortby())
  3094. {
  3095. sortBy.set(req.getSortby());
  3096. if (req.getDescending())
  3097. descending = req.getDescending();
  3098. }
  3099. if (sortBy.length())
  3100. {
  3101. resp.setSortby(sortBy);
  3102. resp.setDescending(descending);
  3103. StringBuffer strbuf(sortBy);
  3104. strbuf.append("=");
  3105. String str1(strbuf.str());
  3106. String str(basicQuery.str());
  3107. if (str.indexOf(str1) < 0)
  3108. {
  3109. addToQueryString(ParametersForPaging, "Sortby", sortBy);
  3110. addToQueryString(basicQuery, "Sortby", sortBy);
  3111. if (descending)
  3112. {
  3113. addToQueryString(ParametersForPaging, "Descending", "1");
  3114. addToQueryString(basicQuery, "Descending", "1");
  3115. }
  3116. }
  3117. }
  3118. if (basicQuery.length() > 0)
  3119. resp.setBasicQuery(basicQuery.str());
  3120. if (ParametersForPaging.length() > 0)
  3121. resp.setParametersForPaging(ParametersForPaging.str());
  3122. resp.setDFULogicalFiles(LogicalFiles);
  3123. return;
  3124. }
  3125. void CWsDfuEx::setFileTypeFilter(const char* fileType, StringBuffer& filterBuf)
  3126. {
  3127. DFUQFileTypeFilter fileTypeFilter = DFUQFFTall;
  3128. if (!fileType || !*fileType)
  3129. {
  3130. filterBuf.append(DFUQFTspecial).append(DFUQFilterSeparator).append(DFUQSFFileType).append(DFUQFilterSeparator).append(fileTypeFilter).append(DFUQFilterSeparator);
  3131. return;
  3132. }
  3133. bool notInSuperfile = false;
  3134. if (strieq(fileType, "Superfiles Only"))
  3135. fileTypeFilter = DFUQFFTsuperfileonly;
  3136. else if (strieq(fileType, "Logical Files Only"))
  3137. fileTypeFilter = DFUQFFTnonsuperfileonly;
  3138. else if (strieq(fileType, "Not in Superfiles"))
  3139. notInSuperfile = true;
  3140. else
  3141. fileTypeFilter = DFUQFFTall;
  3142. filterBuf.append(DFUQFTspecial).append(DFUQFilterSeparator).append(DFUQSFFileType).append(DFUQFilterSeparator).append(fileTypeFilter).append(DFUQFilterSeparator);
  3143. if (notInSuperfile)
  3144. WsDFUHelpers::appendDFUQueryFilter(getDFUQFilterFieldName(DFUQFFsuperowner), DFUQFThasProp, "0", filterBuf);
  3145. }
  3146. void CWsDfuEx::setFileNameFilter(const char* fname, const char* prefix, StringBuffer &filterBuf)
  3147. {
  3148. StringBuffer fileNameFilter;
  3149. if(fname && *fname)
  3150. fileNameFilter.append(fname);//ex. *part_of_file_name*
  3151. else
  3152. {
  3153. if(prefix && *prefix)
  3154. {
  3155. fileNameFilter.append(prefix);
  3156. fileNameFilter.append("::");
  3157. }
  3158. fileNameFilter.append("*");
  3159. }
  3160. fileNameFilter.toLowerCase();
  3161. filterBuf.append(DFUQFTspecial).append(DFUQFilterSeparator).append(DFUQSFFileNameWithPrefix).append(DFUQFilterSeparator).append(fileNameFilter.str()).append(DFUQFilterSeparator);
  3162. }
  3163. void CWsDfuEx::setFileIterateFilter(unsigned maxFiles, StringBuffer &filterBuf)
  3164. {
  3165. filterBuf.append(DFUQFTspecial).append(DFUQFilterSeparator).append(DFUQSFMaxFiles).append(DFUQFilterSeparator)
  3166. .append(maxFiles).append(DFUQFilterSeparator);
  3167. }
  3168. void CWsDfuEx::setDFUQueryFilters(IEspDFUQueryRequest& req, StringBuffer& filterBuf)
  3169. {
  3170. setFileNameFilter(req.getLogicalName(), req.getPrefix(), filterBuf);
  3171. setFileTypeFilter(req.getFileType(), filterBuf);
  3172. WsDFUHelpers::appendDFUQueryFilter(getDFUQFilterFieldName(DFUQFFattrowner), DFUQFTwildcardMatch, req.getOwner(), filterBuf);
  3173. WsDFUHelpers::appendDFUQueryFilter(getDFUQFilterFieldName(DFUQFFkind), DFUQFTwildcardMatch, req.getContentType(), filterBuf);
  3174. WsDFUHelpers::appendDFUQueryFilter(getDFUQFilterFieldName(DFUQFFgroup), DFUQFTcontainString, req.getNodeGroup(), ",", filterBuf);
  3175. if (!req.getIncludeSuperOwner_isNull() && req.getIncludeSuperOwner())
  3176. filterBuf.append(DFUQFTincludeFileAttr).append(DFUQFilterSeparator).append(DFUQSFAOincludeSuperOwner).append(DFUQFilterSeparator);
  3177. __int64 sizeFrom = req.getFileSizeFrom();
  3178. __int64 sizeTo = req.getFileSizeTo();
  3179. if ((sizeFrom > 0) || (sizeTo > 0))
  3180. {
  3181. StringBuffer buf;
  3182. if (sizeFrom > 0)
  3183. buf.append(sizeFrom);
  3184. buf.append(DFUQFilterSeparator);
  3185. if (sizeTo > 0)
  3186. buf.append(sizeTo);
  3187. filterBuf.append(DFUQFTinteger64Range).append(DFUQFilterSeparator).append(getDFUQFilterFieldName(DFUQFFattrsize));
  3188. filterBuf.append(DFUQFilterSeparator).append(buf.str()).append(DFUQFilterSeparator);
  3189. }
  3190. setTimeRangeFilter(req.getStartDate(), req.getEndDate(), DFUQFFtimemodified, filterBuf);
  3191. setTimeRangeFilter(req.getStartAccessedTime(), req.getEndAccessedTime(), DFUQFFaccessed, filterBuf);
  3192. }
  3193. void CWsDfuEx::setTimeRangeFilter(const char *from, const char *to, DFUQFilterField filterID, StringBuffer &filterBuf)
  3194. {
  3195. if (isEmptyString(from) && isEmptyString(to))
  3196. return;
  3197. StringBuffer filterValue;
  3198. if (!isEmptyString(from))
  3199. appendTimeString(from, filterValue);
  3200. filterValue.append(DFUQFilterSeparator);
  3201. if (!isEmptyString(to))
  3202. appendTimeString(to, filterValue);
  3203. filterBuf.append(DFUQFTstringRange).append(DFUQFilterSeparator).append(getDFUQFilterFieldName(filterID));
  3204. filterBuf.append(DFUQFilterSeparator).append(filterValue).append(DFUQFilterSeparator);
  3205. }
  3206. void CWsDfuEx::appendTimeString(const char *in, StringBuffer &out)
  3207. {
  3208. CDateTime wuTime;
  3209. wuTime.setString(in, nullptr);
  3210. wuTime.getString(out);
  3211. }
  3212. void CWsDfuEx::setDFUQuerySortOrder(IEspDFUQueryRequest& req, StringBuffer& sortBy, bool& descending, DFUQResultField* sortOrder)
  3213. {
  3214. const char* sortByReq = req.getSortby();
  3215. if (!sortByReq || !*sortByReq)
  3216. return;
  3217. sortBy.set(sortByReq);
  3218. if (req.getDescending())
  3219. descending = req.getDescending();
  3220. const char* sortByPtr = sortBy.str();
  3221. if (strieq(sortByPtr, "FileSize"))
  3222. sortOrder[0] = (DFUQResultField) (DFUQRFsize | DFUQRFnumeric);
  3223. else if (strieq(sortByPtr, "IsCompressed"))
  3224. sortOrder[0] = (DFUQResultField) (DFUQRFiscompressed | DFUQRFnumeric);
  3225. else if (strieq(sortByPtr, "CompressedSize"))
  3226. sortOrder[0] = (DFUQResultField) (DFUQRFcompressedsize | DFUQRFnumeric);
  3227. else if (strieq(sortByPtr, "Parts"))
  3228. sortOrder[0] = (DFUQResultField) (DFUQRFnumparts | DFUQRFnumeric);
  3229. else if (strieq(sortByPtr, "Records"))
  3230. sortOrder[0] = (DFUQResultField) (DFUQRFrecordcount | DFUQRFnumeric);
  3231. else if (strieq(sortByPtr, "Owner"))
  3232. sortOrder[0] = DFUQRFowner;
  3233. else if (strieq(sortByPtr, "NodeGroup"))
  3234. sortOrder[0] = DFUQRFnodegroup;
  3235. else if (strieq(sortByPtr, "Modified"))
  3236. sortOrder[0] = DFUQRFtimemodified;
  3237. else if (strieq(sortByPtr, "Accessed"))
  3238. sortOrder[0] = DFUQRFaccessed;
  3239. else if (strieq(sortByPtr, "ContentType"))
  3240. sortOrder[0] = DFUQRFkind;
  3241. else
  3242. sortOrder[0] = DFUQRFname;
  3243. sortOrder[0] = (DFUQResultField) (sortOrder[0] | DFUQRFnocase);
  3244. if (descending)
  3245. sortOrder[0] = (DFUQResultField) (sortOrder[0] | DFUQRFreverse);
  3246. return;
  3247. }
  3248. void CWsDfuEx::setDFUQueryResponse(IEspContext &context, unsigned totalFiles, StringBuffer& sortBy, bool descending, unsigned pageStart, unsigned pageSize,
  3249. IEspDFUQueryRequest& req, IEspDFUQueryResponse& resp)
  3250. {
  3251. //for legacy
  3252. double version = context.getClientVersion();
  3253. unsigned pageEnd = pageStart + pageSize;
  3254. if (pageEnd > totalFiles)
  3255. pageEnd = totalFiles;
  3256. resp.setNumFiles(totalFiles);
  3257. resp.setPageSize(pageSize);
  3258. resp.setPageStartFrom(pageStart+1);
  3259. resp.setPageEndAt(pageEnd);
  3260. if (pageStart > pageSize)
  3261. resp.setPrevPageFrom(pageStart - pageSize + 1);
  3262. else if(pageStart > 0)
  3263. resp.setPrevPageFrom(1);
  3264. if(pageEnd < totalFiles)
  3265. {
  3266. resp.setNextPageFrom(pageEnd+1);
  3267. resp.setLastPageFrom((int)(pageSize * floor((double) ((totalFiles-1) / pageSize)) + 1));
  3268. }
  3269. StringBuffer queryReq;
  3270. if (req.getNodeGroup() && *req.getNodeGroup())
  3271. {
  3272. if (version < 1.26)
  3273. resp.setClusterName(req.getNodeGroup());
  3274. else
  3275. resp.setNodeGroup(req.getNodeGroup());
  3276. addToQueryString(queryReq, "NodeGroup", req.getNodeGroup());
  3277. }
  3278. if (req.getOwner() && *req.getOwner())
  3279. {
  3280. resp.setOwner(req.getOwner());
  3281. addToQueryString(queryReq, "Owner", req.getOwner());
  3282. }
  3283. if (req.getPrefix() && *req.getPrefix())
  3284. {
  3285. resp.setPrefix(req.getPrefix());
  3286. addToQueryString(queryReq, "Prefix", req.getPrefix());
  3287. }
  3288. if (req.getLogicalName() && *req.getLogicalName())
  3289. {
  3290. resp.setLogicalName(req.getLogicalName());
  3291. addToQueryString(queryReq, "LogicalName", req.getLogicalName());
  3292. }
  3293. if (req.getStartDate() && *req.getStartDate())
  3294. {
  3295. resp.setStartDate(req.getStartDate());
  3296. addToQueryString(queryReq, "StartDate", req.getStartDate());
  3297. }
  3298. if (req.getEndDate() && *req.getEndDate())
  3299. {
  3300. resp.setEndDate(req.getEndDate());
  3301. addToQueryString(queryReq, "EndDate", req.getEndDate());
  3302. }
  3303. if (req.getFileType() && *req.getFileType())
  3304. {
  3305. resp.setFileType(req.getFileType());
  3306. addToQueryString(queryReq, "FileType", req.getFileType());
  3307. }
  3308. if (req.getFileSizeFrom())
  3309. {
  3310. resp.setFileSizeFrom(req.getFileSizeFrom());
  3311. addToQueryStringFromInt(queryReq, "FileSizeFrom", req.getFileSizeFrom());
  3312. }
  3313. if (req.getFileSizeTo())
  3314. {
  3315. resp.setFileSizeTo(req.getFileSizeTo());
  3316. addToQueryStringFromInt(queryReq, "FileSizeTo", req.getFileSizeTo());
  3317. }
  3318. StringBuffer queryReqNoPageSize(queryReq);
  3319. addToQueryStringFromInt(queryReq, "PageSize", pageSize);
  3320. resp.setFilters(queryReq.str());
  3321. if (sortBy.length())
  3322. {
  3323. resp.setSortby(sortBy.str());
  3324. resp.setDescending(descending);
  3325. addToQueryString(queryReq, "Sortby", sortBy.str());
  3326. addToQueryString(queryReqNoPageSize, "Sortby", sortBy.str());
  3327. if (descending)
  3328. {
  3329. addToQueryString(queryReq, "Descending", "1");
  3330. addToQueryString(queryReqNoPageSize, "Descending", "1");
  3331. }
  3332. }
  3333. resp.setBasicQuery(queryReqNoPageSize.str());
  3334. resp.setParametersForPaging(queryReq.str());
  3335. return;
  3336. }
  3337. bool CWsDfuEx::doLogicalFileSearch(IEspContext &context, IUserDescriptor* udesc, IEspDFUQueryRequest & req, IEspDFUQueryResponse & resp)
  3338. {
  3339. double version = context.getClientVersion();
  3340. if (req.getOneLevelDirFileReturn())
  3341. {
  3342. int numDirs = 0;
  3343. int numFiles = 0;
  3344. IArrayOf<IEspDFULogicalFile> logicalFiles;
  3345. getLogicalFileAndDirectory(context, udesc, req.getLogicalName(), !req.getIncludeSuperOwner_isNull() && req.getIncludeSuperOwner(), logicalFiles, numFiles, numDirs);
  3346. return true;
  3347. }
  3348. if (queryDaliServerVersion().compare("3.11") < 0)
  3349. {//Dali server does not support Filtered File Query. Use legacy code.
  3350. PROGLOG("DFUQuery: getAPageOfSortedLogicalFile");
  3351. getAPageOfSortedLogicalFile(context, udesc, req, resp);
  3352. return true;
  3353. }
  3354. StringBuffer filterBuf;
  3355. setDFUQueryFilters(req, filterBuf);
  3356. //Now, set filters which are used to filter query result received from dali server.
  3357. unsigned short localFilterCount = 0;
  3358. DFUQResultField localFilters[8];
  3359. MemoryBuffer localFilterBuf;
  3360. WsDFUHelpers::addDFUQueryFilter(localFilters, localFilterCount, localFilterBuf, req.getNodeGroup(), DFUQRFnodegroup);
  3361. localFilters[localFilterCount] = DFUQRFterm;
  3362. StringBuffer sortBy;
  3363. bool descending = false;
  3364. DFUQResultField sortOrder[2] = {DFUQRFname, DFUQRFterm};
  3365. setDFUQuerySortOrder(req, sortBy, descending, sortOrder);
  3366. unsigned pageStart = 0;
  3367. if (req.getPageStartFrom() > 0)
  3368. pageStart = req.getPageStartFrom() - 1;
  3369. unsigned pageSize = req.getPageSize();
  3370. if (pageSize < 1)
  3371. pageSize = 100;
  3372. const int firstN = req.getFirstN();
  3373. if (firstN > 0)
  3374. {
  3375. pageStart = 0;
  3376. pageSize = firstN;
  3377. }
  3378. unsigned maxFiles = 0;
  3379. if(!req.getMaxNumberOfFiles_isNull())
  3380. maxFiles = req.getMaxNumberOfFiles();
  3381. if (maxFiles == 0)
  3382. maxFiles = ITERATE_FILTEREDFILES_LIMIT;
  3383. if (maxFiles != ITERATE_FILTEREDFILES_LIMIT)
  3384. setFileIterateFilter(maxFiles, filterBuf);
  3385. __int64 cacheHint = 0;
  3386. if (!req.getCacheHint_isNull())
  3387. cacheHint = req.getCacheHint();
  3388. bool allMatchingFilesReceived = true;
  3389. unsigned totalFiles = 0;
  3390. PROGLOG("DFUQuery: getLogicalFilesSorted");
  3391. Owned<IDFAttributesIterator> it = queryDistributedFileDirectory().getLogicalFilesSorted(udesc, sortOrder, filterBuf.str(),
  3392. localFilters, localFilterBuf.bufferBase(), pageStart, pageSize, &cacheHint, &totalFiles, &allMatchingFilesReceived);
  3393. if(!it)
  3394. throw MakeStringException(ECLWATCH_CANNOT_GET_FILE_ITERATOR,"Cannot get information from file system.");
  3395. PROGLOG("DFUQuery: getLogicalFilesSorted done");
  3396. IArrayOf<IEspDFULogicalFile> logicalFiles;
  3397. ForEach(*it)
  3398. WsDFUHelpers::addToLogicalFileList(it->query(), NULL, version, logicalFiles);
  3399. if (!allMatchingFilesReceived)
  3400. {
  3401. VStringBuffer warning("The returned results (%d files) represent a subset of the total number of matches. Using a correct filter may reduce the number of matches.",
  3402. maxFiles);
  3403. resp.setWarning(warning.str());
  3404. resp.setIsSubsetOfFiles(!allMatchingFilesReceived);
  3405. }
  3406. resp.setCacheHint(cacheHint);
  3407. resp.setDFULogicalFiles(logicalFiles);
  3408. setDFUQueryResponse(context, totalFiles, sortBy, descending, pageStart, pageSize, req, resp); //This call may be removed after 5.0
  3409. return true;
  3410. }
  3411. bool CWsDfuEx::onSuperfileList(IEspContext &context, IEspSuperfileListRequest &req, IEspSuperfileListResponse &resp)
  3412. {
  3413. try
  3414. {
  3415. const char* superfile = req.getSuperfile();
  3416. if (!superfile || !*superfile)
  3417. throw MakeStringException(ECLWATCH_MISSING_PARAMS, "Superfile name required");
  3418. PROGLOG("SuperfileList: %s", superfile);
  3419. StringBuffer username;
  3420. context.getUserID(username);
  3421. Owned<IUserDescriptor> userdesc;
  3422. if(username.length() > 0)
  3423. {
  3424. userdesc.setown(createUserDescriptor());
  3425. userdesc->set(username.str(), context.queryPassword(), context.querySignature());
  3426. }
  3427. Owned<IDFUhelper> dfuhelper = createIDFUhelper();
  3428. StringArray farray;
  3429. StringAttrArray subfiles;
  3430. dfuhelper->listSubFiles(req.getSuperfile(), subfiles, userdesc.get());
  3431. for(unsigned i = 0; i < subfiles.length(); i++)
  3432. {
  3433. StringAttrItem& subfile = subfiles.item(i);
  3434. farray.append(subfile.text);
  3435. }
  3436. if(farray.length() > 0)
  3437. resp.setSubfiles(farray);
  3438. resp.setSuperfile(req.getSuperfile());
  3439. }
  3440. catch(IException* e)
  3441. {
  3442. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  3443. }
  3444. return true;
  3445. }
  3446. bool CWsDfuEx::onSuperfileAction(IEspContext &context, IEspSuperfileActionRequest &req, IEspSuperfileActionResponse &resp)
  3447. {
  3448. try
  3449. {
  3450. context.ensureFeatureAccess(FEATURE_URL, SecAccess_Write, ECLWATCH_DFU_ACCESS_DENIED, "WsDfu::SuperfileAction: Permission denied.");
  3451. const char* action = req.getAction();
  3452. const char* superfile = req.getSuperfile();
  3453. superfileAction(context, action, superfile, req.getSubfiles(), req.getBefore(), true, true, req.getDelete(), req.getRemoveSuperfile());
  3454. resp.setRetcode(0);
  3455. if (superfile && *superfile && action && strieq(action, "remove"))
  3456. {
  3457. Owned<IUserDescriptor> udesc;
  3458. udesc.setown(createUserDescriptor());
  3459. udesc->set(context.queryUserId(), context.queryPassword(), context.querySignature());
  3460. Owned<IDistributedSuperFile> fp = queryDistributedFileDirectory().lookupSuperFile(superfile,udesc);
  3461. if (!fp)
  3462. resp.setRetcode(-1); //Superfile has been removed.
  3463. }
  3464. resp.setSuperfile(req.getSuperfile());
  3465. }
  3466. catch(IException* e)
  3467. {
  3468. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  3469. }
  3470. return true;
  3471. }
  3472. bool CWsDfuEx::onSavexml(IEspContext &context, IEspSavexmlRequest &req, IEspSavexmlResponse &resp)
  3473. {
  3474. try
  3475. {
  3476. StringBuffer username;
  3477. context.getUserID(username);
  3478. Owned<IUserDescriptor> userdesc;
  3479. if(username.length() > 0)
  3480. {
  3481. userdesc.setown(createUserDescriptor());
  3482. userdesc->set(username.str(), context.queryPassword(), context.querySignature());
  3483. }
  3484. if (!req.getName() || !*req.getName())
  3485. throw MakeStringException(ECLWATCH_MISSING_PARAMS, "Name required");
  3486. PROGLOG("getFileXML: %s", req.getName());
  3487. Owned<IDFUhelper> dfuhelper = createIDFUhelper();
  3488. StringBuffer out;
  3489. dfuhelper->getFileXML(req.getName(), out, userdesc.get());
  3490. MemoryBuffer xmlmap;
  3491. int len = out.length();
  3492. xmlmap.setBuffer(len, out.detach(), true);
  3493. resp.setXmlmap(xmlmap);
  3494. }
  3495. catch(IException* e)
  3496. {
  3497. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  3498. }
  3499. return true;
  3500. }
  3501. bool CWsDfuEx::onAdd(IEspContext &context, IEspAddRequest &req, IEspAddResponse &resp)
  3502. {
  3503. try
  3504. {
  3505. StringBuffer username;
  3506. context.getUserID(username);
  3507. Owned<IUserDescriptor> userdesc;
  3508. if(username.length() > 0)
  3509. {
  3510. userdesc.setown(createUserDescriptor());
  3511. userdesc->set(username.str(), context.queryPassword(), context.querySignature());
  3512. }
  3513. if (!req.getDstname() || !*req.getDstname())
  3514. throw MakeStringException(ECLWATCH_MISSING_PARAMS, "Dstname required.");
  3515. PROGLOG("addFileXML: %s", req.getDstname());
  3516. Owned<IDFUhelper> dfuhelper = createIDFUhelper();
  3517. StringBuffer xmlstr(req.getXmlmap().length(),(const char*)req.getXmlmap().bufferBase());
  3518. dfuhelper->addFileXML(req.getDstname(), xmlstr, req.getDstcluster(), userdesc.get());
  3519. }
  3520. catch(IException* e)
  3521. {
  3522. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  3523. }
  3524. return true;
  3525. }
  3526. bool CWsDfuEx::onAddRemote(IEspContext &context, IEspAddRemoteRequest &req, IEspAddRemoteResponse &resp)
  3527. {
  3528. try
  3529. {
  3530. StringBuffer username;
  3531. context.getUserID(username);
  3532. Owned<IUserDescriptor> userdesc;
  3533. if(username.length() > 0)
  3534. {
  3535. userdesc.setown(createUserDescriptor());
  3536. userdesc->set(username.str(), context.queryPassword(), context.querySignature());
  3537. }
  3538. const char* srcusername = req.getSrcusername();
  3539. Owned<IUserDescriptor> srcuserdesc;
  3540. if(srcusername && *srcusername)
  3541. {
  3542. srcuserdesc.setown(createUserDescriptor());
  3543. srcuserdesc->set(srcusername, req.getSrcpassword(), context.querySignature());
  3544. }
  3545. const char* srcname = req.getSrcname();
  3546. if(srcname == NULL || *srcname == '\0')
  3547. throw MakeStringException(ECLWATCH_INVALID_INPUT, "srcname can't be empty.");
  3548. const char* srcdali = req.getSrcdali();
  3549. if(srcdali == NULL || *srcdali == '\0')
  3550. throw MakeStringException(ECLWATCH_INVALID_INPUT, "srcdali can't be empty.");
  3551. const char* dstname = req.getDstname();
  3552. if(dstname == NULL || *dstname == '\0')
  3553. throw MakeStringException(ECLWATCH_INVALID_INPUT, "dstname can't be empty.");
  3554. PROGLOG("addFileRemote: Srcdali %s, Srcname %s, Dstname %s", srcdali, srcname, dstname);
  3555. SocketEndpoint ep(srcdali);
  3556. Owned<IDFUhelper> dfuhelper = createIDFUhelper();
  3557. dfuhelper->addFileRemote(dstname, ep, srcname, srcuserdesc.get(), userdesc.get());
  3558. }
  3559. catch(IException* e)
  3560. {
  3561. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  3562. }
  3563. return true;
  3564. }
  3565. const int INTEGELSIZE = 20;
  3566. const int REALSIZE = 32;
  3567. const int STRINGSIZE = 128;
  3568. bool CWsDfuEx::onDFUGetDataColumns(IEspContext &context, IEspDFUGetDataColumnsRequest &req, IEspDFUGetDataColumnsResponse &resp)
  3569. {
  3570. try
  3571. {
  3572. context.ensureFeatureAccess(FEATURE_URL, SecAccess_Read, ECLWATCH_DFU_ACCESS_DENIED, "WsDfu::DFUGetDataColumns: Permission denied.");
  3573. StringBuffer logicalNameStr;
  3574. char* logicalName0 = (char*) req.getOpenLogicalName();
  3575. if (logicalName0 && *logicalName0)
  3576. {
  3577. logicalNameStr.append(logicalName0);
  3578. logicalNameStr.trim();
  3579. }
  3580. if (logicalNameStr.length() > 0)
  3581. {
  3582. PROGLOG("DFUGetDataColumns: %s", logicalNameStr.str());
  3583. __int64 startIndex = req.getStartIndex();
  3584. __int64 endIndex = req.getEndIndex();
  3585. if (startIndex < 1)
  3586. startIndex = 1;
  3587. if (endIndex < 1)
  3588. endIndex = 100;
  3589. StringArray filterByNames, filterByValues;
  3590. double version = context.getClientVersion();
  3591. if (version > 1.04)
  3592. {
  3593. const char* filterBy = req.getFilterBy();
  3594. if (filterBy && *filterBy)
  3595. {
  3596. parseTwoStringArrays(filterBy, filterByNames, filterByValues);
  3597. }
  3598. const char* showColumns = req.getShowColumns();
  3599. if (showColumns && *showColumns)
  3600. {
  3601. resp.setShowColumns(showColumns);
  3602. }
  3603. }
  3604. Owned<IResultSetFactory> resultSetFactory = getSecResultSetFactory(context.querySecManager(), context.queryUser(), context.queryUserId(), context.queryPassword());
  3605. Owned<INewResultSet> result;
  3606. if (m_clusterName.length() > 0)
  3607. {
  3608. result.setown(resultSetFactory->createNewFileResultSet(logicalNameStr.str(), m_clusterName.str()));
  3609. }
  3610. else
  3611. {
  3612. result.setown(resultSetFactory->createNewFileResultSet(logicalNameStr.str(), NULL));
  3613. }
  3614. __int64 total=result->getNumRows();
  3615. {
  3616. IArrayOf<IEspDFUDataColumn> dataKeyedColumns[MAX_KEY_ROWS];
  3617. IArrayOf<IEspDFUDataColumn> dataNonKeyedColumns[MAX_KEY_ROWS];
  3618. const IResultSetMetaData & meta = result->getMetaData();
  3619. int columnCount = meta.getColumnCount();
  3620. int keyedColumnCount = meta.getNumKeyedColumns();
  3621. unsigned columnSize = 0;
  3622. int lineSizeCount = 0;
  3623. int lineCount = 0;
  3624. for (int i = 0; i < keyedColumnCount; i++)
  3625. {
  3626. Owned<IEspDFUDataColumn> item = createDFUDataColumn("","");
  3627. bool bNaturalColumn = true;
  3628. SCMStringBuffer columnLabel;
  3629. if (meta.hasSetTranslation(i))
  3630. {
  3631. meta.getNaturalColumnLabel(columnLabel, i);
  3632. }
  3633. if (columnLabel.length() < 1)
  3634. {
  3635. meta.getColumnLabel(columnLabel, i);
  3636. bNaturalColumn = false;
  3637. }
  3638. item->setColumnLabel(columnLabel.str());
  3639. if (version > 1.04 && filterByNames.length() > 0)
  3640. {
  3641. for (unsigned ii = 0; ii < filterByNames.length(); ii++)
  3642. {
  3643. const char* name = filterByNames.item(ii);
  3644. if (name && !stricmp(name, columnLabel.str()))
  3645. {
  3646. const char* value = filterByValues.item(ii);
  3647. if (value && *value)
  3648. {
  3649. item->setColumnValue(value);
  3650. break;
  3651. }
  3652. }
  3653. }
  3654. }
  3655. DisplayType columnType = meta.getColumnDisplayType(i);
  3656. if (bNaturalColumn)
  3657. {
  3658. item->setColumnType("Others");
  3659. item->setColumnSize(STRINGSIZE);
  3660. columnSize = STRINGSIZE;
  3661. item->setMaxSize(columnSize);
  3662. }
  3663. else if (columnType == TypeBoolean)
  3664. {
  3665. item->setColumnType("Boolean");
  3666. item->setMaxSize(1);
  3667. item->setColumnSize(strlen(columnLabel.str()));
  3668. columnSize = 2;
  3669. }
  3670. else
  3671. {
  3672. if (columnType == TypeInteger || columnType == TypeUnsignedInteger)
  3673. {
  3674. item->setColumnType("Integer");
  3675. item->setMaxSize(INTEGELSIZE);
  3676. columnSize = INTEGELSIZE;
  3677. if (strlen(columnLabel.str()) > columnSize)
  3678. columnSize = strlen(columnLabel.str());
  3679. item->setColumnSize(columnSize);
  3680. }
  3681. else if (columnType == TypeReal)
  3682. {
  3683. item->setColumnType("Real");
  3684. item->setMaxSize(REALSIZE);
  3685. columnSize = REALSIZE;
  3686. if (strlen(columnLabel.str()) > columnSize)
  3687. columnSize = strlen(columnLabel.str());
  3688. item->setColumnSize(columnSize);
  3689. }
  3690. else if (columnType == TypeString)
  3691. {
  3692. columnSize = meta.getColumnRawSize(i);
  3693. columnSize = rtlQStrLength(columnSize);
  3694. if (columnSize < 1)
  3695. columnSize = STRINGSIZE;
  3696. else if (columnSize > STRINGSIZE)
  3697. columnSize = STRINGSIZE;
  3698. item->setColumnType("String");
  3699. item->setMaxSize(columnSize);
  3700. if (strlen(columnLabel.str()) > columnSize)
  3701. columnSize = strlen(columnLabel.str());
  3702. item->setColumnSize(columnSize);
  3703. }
  3704. else if (columnType == TypeUnicode)
  3705. {
  3706. item->setColumnType("Others");
  3707. columnSize = (int) (meta.getColumnRawSize(i) * 0.5);
  3708. if (columnSize > STRINGSIZE)
  3709. columnSize = STRINGSIZE;
  3710. item->setColumnSize(columnSize);
  3711. item->setMaxSize(columnSize);
  3712. }
  3713. else
  3714. {
  3715. item->setColumnType("Others");
  3716. columnSize = STRINGSIZE;
  3717. item->setColumnSize(columnSize);
  3718. item->setMaxSize(columnSize);
  3719. }
  3720. }
  3721. columnSize += 7;
  3722. if ((lineSizeCount == 0) && (columnSize > STRINGSIZE)) //One field is big enough to use one line
  3723. {
  3724. if (lineCount >= MAX_KEY_ROWS)
  3725. break;
  3726. dataKeyedColumns[lineCount].append(*item.getLink());
  3727. lineCount++;
  3728. }
  3729. else
  3730. {
  3731. if (lineSizeCount + columnSize < STRINGSIZE)
  3732. {
  3733. lineSizeCount += columnSize;
  3734. }
  3735. else //too big in this line...so, switch to another line
  3736. {
  3737. lineCount++;
  3738. lineSizeCount = columnSize;
  3739. }
  3740. if (lineCount >= MAX_KEY_ROWS)
  3741. break;
  3742. dataKeyedColumns[lineCount].append(*item.getLink());
  3743. }
  3744. }
  3745. columnSize = 0;
  3746. lineSizeCount = 0;
  3747. lineCount = 0;
  3748. for (int ii = keyedColumnCount; ii < columnCount; ii++)
  3749. {
  3750. Owned<IEspDFUDataColumn> item = createDFUDataColumn("","");
  3751. bool bNaturalColumn = true;
  3752. SCMStringBuffer columnLabel;
  3753. if (meta.hasSetTranslation(ii))
  3754. {
  3755. meta.getNaturalColumnLabel(columnLabel, ii);
  3756. }
  3757. if (columnLabel.length() < 1)
  3758. {
  3759. meta.getColumnLabel(columnLabel, ii);
  3760. bNaturalColumn = false;
  3761. }
  3762. item->setColumnLabel(columnLabel.str());
  3763. if (version > 1.04 && filterByNames.length() > 0)
  3764. {
  3765. for (unsigned ii = 0; ii < filterByNames.length(); ii++)
  3766. {
  3767. const char* name = filterByNames.item(ii);
  3768. if (name && !stricmp(name, columnLabel.str()))
  3769. {
  3770. const char* value = filterByValues.item(ii);
  3771. if (value && *value)
  3772. {
  3773. item->setColumnValue(value);
  3774. break;
  3775. }
  3776. }
  3777. }
  3778. }
  3779. DisplayType columnType = meta.getColumnDisplayType(ii);
  3780. if (bNaturalColumn)
  3781. {
  3782. item->setColumnType("Others");
  3783. item->setColumnSize(STRINGSIZE);
  3784. columnSize = STRINGSIZE;
  3785. }
  3786. else if (columnType == TypeBoolean)
  3787. {
  3788. item->setColumnType("Boolean");
  3789. item->setMaxSize(1);
  3790. item->setColumnSize(strlen(columnLabel.str()));
  3791. columnSize = 2;
  3792. }
  3793. else
  3794. {
  3795. if (columnType == TypeInteger || columnType == TypeUnsignedInteger)
  3796. {
  3797. item->setColumnType("Integer");
  3798. item->setMaxSize(INTEGELSIZE);
  3799. columnSize = INTEGELSIZE;
  3800. if (strlen(columnLabel.str()) > columnSize)
  3801. columnSize = strlen(columnLabel.str());
  3802. item->setColumnSize(columnSize);
  3803. }
  3804. else if (columnType == TypeReal)
  3805. {
  3806. item->setColumnType("Real");
  3807. item->setMaxSize(REALSIZE);
  3808. columnSize = REALSIZE;
  3809. if (strlen(columnLabel.str()) > columnSize)
  3810. columnSize = strlen(columnLabel.str());
  3811. item->setColumnSize(columnSize);
  3812. }
  3813. else if (columnType == TypeString)
  3814. {
  3815. columnSize = meta.getColumnRawSize(ii);
  3816. columnSize = rtlQStrLength(columnSize);
  3817. if (columnSize < 1)
  3818. columnSize = STRINGSIZE;
  3819. else if (columnSize > STRINGSIZE)
  3820. columnSize = STRINGSIZE;
  3821. item->setColumnType("String");
  3822. item->setMaxSize(columnSize);
  3823. if (strlen(columnLabel.str()) > columnSize)
  3824. columnSize = strlen(columnLabel.str());
  3825. item->setColumnSize(columnSize);
  3826. }
  3827. else if (columnType == TypeUnicode)
  3828. {
  3829. item->setColumnType("Others");
  3830. columnSize = (int) (meta.getColumnRawSize(ii) * 0.5);
  3831. if (columnSize > STRINGSIZE)
  3832. columnSize = STRINGSIZE;
  3833. item->setColumnSize(columnSize);
  3834. item->setMaxSize(columnSize);
  3835. }
  3836. else
  3837. {
  3838. item->setColumnType("Others");
  3839. columnSize = STRINGSIZE;
  3840. item->setColumnSize(columnSize);
  3841. item->setMaxSize(columnSize);
  3842. }
  3843. }
  3844. columnSize += 7;
  3845. if ((lineSizeCount == 0) && (columnSize > STRINGSIZE))
  3846. {
  3847. if (lineCount >= MAX_KEY_ROWS)
  3848. break;
  3849. dataNonKeyedColumns[lineCount].append(*item.getLink());
  3850. lineCount++;
  3851. }
  3852. else
  3853. {
  3854. if (lineSizeCount + columnSize < STRINGSIZE)
  3855. {
  3856. lineSizeCount += columnSize;
  3857. }
  3858. else
  3859. {
  3860. lineCount++;
  3861. lineSizeCount = columnSize;
  3862. }
  3863. if (lineCount >= MAX_KEY_ROWS)
  3864. break;
  3865. dataNonKeyedColumns[lineCount].append(*item.getLink());
  3866. }
  3867. }
  3868. if (dataKeyedColumns[0].length() > 0)
  3869. resp.setDFUDataKeyedColumns1(dataKeyedColumns[0]);
  3870. if (dataKeyedColumns[1].length() > 0)
  3871. resp.setDFUDataKeyedColumns2(dataKeyedColumns[1]);
  3872. if (dataKeyedColumns[2].length() > 0)
  3873. resp.setDFUDataKeyedColumns3(dataKeyedColumns[2]);
  3874. if (dataKeyedColumns[3].length() > 0)
  3875. resp.setDFUDataKeyedColumns4(dataKeyedColumns[3]);
  3876. if (dataKeyedColumns[4].length() > 0)
  3877. resp.setDFUDataKeyedColumns5(dataKeyedColumns[4]);
  3878. if (dataKeyedColumns[5].length() > 0)
  3879. resp.setDFUDataKeyedColumns6(dataKeyedColumns[5]);
  3880. if (dataKeyedColumns[6].length() > 0)
  3881. resp.setDFUDataKeyedColumns7(dataKeyedColumns[6]);
  3882. if (dataKeyedColumns[7].length() > 0)
  3883. resp.setDFUDataKeyedColumns8(dataKeyedColumns[7]);
  3884. if (dataKeyedColumns[8].length() > 0)
  3885. resp.setDFUDataKeyedColumns9(dataKeyedColumns[8]);
  3886. if (dataKeyedColumns[9].length() > 0)
  3887. resp.setDFUDataKeyedColumns10(dataKeyedColumns[9]);
  3888. if (version > 1.14)
  3889. {
  3890. if (dataKeyedColumns[10].length() > 0)
  3891. resp.setDFUDataKeyedColumns11(dataKeyedColumns[10]);
  3892. if (dataKeyedColumns[11].length() > 0)
  3893. resp.setDFUDataKeyedColumns12(dataKeyedColumns[11]);
  3894. if (dataKeyedColumns[12].length() > 0)
  3895. resp.setDFUDataKeyedColumns13(dataKeyedColumns[12]);
  3896. if (dataKeyedColumns[13].length() > 0)
  3897. resp.setDFUDataKeyedColumns14(dataKeyedColumns[13]);
  3898. if (dataKeyedColumns[14].length() > 0)
  3899. resp.setDFUDataKeyedColumns15(dataKeyedColumns[14]);
  3900. if (dataKeyedColumns[15].length() > 0)
  3901. resp.setDFUDataKeyedColumns16(dataKeyedColumns[15]);
  3902. if (dataKeyedColumns[16].length() > 0)
  3903. resp.setDFUDataKeyedColumns17(dataKeyedColumns[16]);
  3904. if (dataKeyedColumns[17].length() > 0)
  3905. resp.setDFUDataKeyedColumns18(dataKeyedColumns[17]);
  3906. if (dataKeyedColumns[18].length() > 0)
  3907. resp.setDFUDataKeyedColumns19(dataKeyedColumns[18]);
  3908. if (dataKeyedColumns[19].length() > 0)
  3909. resp.setDFUDataKeyedColumns20(dataKeyedColumns[19]);
  3910. }
  3911. if (dataNonKeyedColumns[0].length() > 0)
  3912. resp.setDFUDataNonKeyedColumns1(dataNonKeyedColumns[0]);
  3913. if (dataNonKeyedColumns[1].length() > 0)
  3914. resp.setDFUDataNonKeyedColumns2(dataNonKeyedColumns[1]);
  3915. if (dataNonKeyedColumns[2].length() > 0)
  3916. resp.setDFUDataNonKeyedColumns3(dataNonKeyedColumns[2]);
  3917. if (dataNonKeyedColumns[3].length() > 0)
  3918. resp.setDFUDataNonKeyedColumns4(dataNonKeyedColumns[3]);
  3919. if (dataNonKeyedColumns[4].length() > 0)
  3920. resp.setDFUDataNonKeyedColumns5(dataNonKeyedColumns[4]);
  3921. if (dataNonKeyedColumns[5].length() > 0)
  3922. resp.setDFUDataNonKeyedColumns6(dataNonKeyedColumns[5]);
  3923. if (dataNonKeyedColumns[6].length() > 0)
  3924. resp.setDFUDataNonKeyedColumns7(dataNonKeyedColumns[6]);
  3925. if (dataNonKeyedColumns[7].length() > 0)
  3926. resp.setDFUDataNonKeyedColumns8(dataNonKeyedColumns[7]);
  3927. if (dataNonKeyedColumns[8].length() > 0)
  3928. resp.setDFUDataNonKeyedColumns9(dataNonKeyedColumns[8]);
  3929. if (dataNonKeyedColumns[9].length() > 0)
  3930. resp.setDFUDataNonKeyedColumns10(dataNonKeyedColumns[9]);
  3931. if (version > 1.14)
  3932. {
  3933. if (dataNonKeyedColumns[10].length() > 0)
  3934. resp.setDFUDataNonKeyedColumns11(dataNonKeyedColumns[10]);
  3935. if (dataNonKeyedColumns[11].length() > 0)
  3936. resp.setDFUDataNonKeyedColumns12(dataNonKeyedColumns[11]);
  3937. if (dataNonKeyedColumns[12].length() > 0)
  3938. resp.setDFUDataNonKeyedColumns13(dataNonKeyedColumns[12]);
  3939. if (dataNonKeyedColumns[13].length() > 0)
  3940. resp.setDFUDataNonKeyedColumns14(dataNonKeyedColumns[13]);
  3941. if (dataNonKeyedColumns[14].length() > 0)
  3942. resp.setDFUDataNonKeyedColumns15(dataNonKeyedColumns[14]);
  3943. if (dataNonKeyedColumns[15].length() > 0)
  3944. resp.setDFUDataNonKeyedColumns16(dataNonKeyedColumns[15]);
  3945. if (dataNonKeyedColumns[16].length() > 0)
  3946. resp.setDFUDataNonKeyedColumns17(dataNonKeyedColumns[16]);
  3947. if (dataNonKeyedColumns[17].length() > 0)
  3948. resp.setDFUDataNonKeyedColumns18(dataNonKeyedColumns[17]);
  3949. if (dataNonKeyedColumns[18].length() > 0)
  3950. resp.setDFUDataNonKeyedColumns19(dataNonKeyedColumns[18]);
  3951. if (dataNonKeyedColumns[19].length() > 0)
  3952. resp.setDFUDataNonKeyedColumns20(dataNonKeyedColumns[19]);
  3953. }
  3954. //resp.setColumnCount(columnCount);
  3955. resp.setRowCount(total);
  3956. }
  3957. resp.setLogicalName(logicalNameStr.str());
  3958. resp.setStartIndex(startIndex);
  3959. resp.setEndIndex(endIndex);
  3960. if (version > 1.11)
  3961. {
  3962. if (req.getCluster() && *req.getCluster())
  3963. {
  3964. resp.setCluster(req.getCluster());
  3965. }
  3966. if (req.getClusterType() && *req.getClusterType())
  3967. {
  3968. resp.setClusterType(req.getClusterType());
  3969. }
  3970. }
  3971. }
  3972. if (req.getChooseFile())
  3973. resp.setChooseFile(1);
  3974. else
  3975. resp.setChooseFile(0);
  3976. }
  3977. catch(IException* e)
  3978. {
  3979. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  3980. }
  3981. return true;
  3982. }
  3983. bool CWsDfuEx::onDFUSearchData(IEspContext &context, IEspDFUSearchDataRequest &req, IEspDFUSearchDataResponse &resp)
  3984. {
  3985. try
  3986. {
  3987. context.ensureFeatureAccess(FEATURE_URL, SecAccess_Read, ECLWATCH_DFU_ACCESS_DENIED, "WsDfu::DFUSearchData: Permission denied.");
  3988. double version = context.getClientVersion();
  3989. resp.setCluster(req.getCluster());
  3990. resp.setClusterType(req.getClusterType());
  3991. resp.setFile(req.getFile());
  3992. resp.setKey(req.getKey());
  3993. const char* selectedKey = req.getSelectedKey();
  3994. if (strlen(selectedKey) > 0)
  3995. {
  3996. resp.setSelectedKey(req.getSelectedKey());
  3997. }
  3998. else
  3999. {
  4000. resp.setSelectedKey(req.getKey());
  4001. }
  4002. resp.setParentName(req.getParentName());
  4003. resp.setRoxieSelections(req.getRoxieSelections());
  4004. resp.setDisableUppercaseTranslation(req.getDisableUppercaseTranslation());
  4005. const char* openLogicalName = req.getOpenLogicalName();
  4006. if (strlen(openLogicalName) > 0)
  4007. {
  4008. PROGLOG("DFUSearchData: %s", openLogicalName);
  4009. Owned<IEspDFUGetDataColumnsRequest> DataColumnsRequest = createDFUGetDataColumnsRequest();
  4010. Owned<IEspDFUGetDataColumnsResponse> DataColumnsResponse = createDFUGetDataColumnsResponse();
  4011. DataColumnsRequest->setOpenLogicalName(req.getOpenLogicalName());
  4012. DataColumnsRequest->setFilterBy(req.getFilterBy());
  4013. DataColumnsRequest->setShowColumns(req.getShowColumns());
  4014. DataColumnsRequest->setChooseFile(req.getChooseFile());
  4015. DataColumnsRequest->setCluster(req.getCluster());
  4016. DataColumnsRequest->setClusterType(req.getClusterType());
  4017. try
  4018. {
  4019. onDFUGetDataColumns(context, *DataColumnsRequest, *DataColumnsResponse);
  4020. }
  4021. catch(IException* e)
  4022. {
  4023. if (version < 1.08)
  4024. throw e;
  4025. StringBuffer emsg;
  4026. e->errorMessage(emsg);
  4027. e->Release();
  4028. resp.setMsgToDisplay(emsg);
  4029. return true;
  4030. }
  4031. resp.setOpenLogicalName(req.getOpenLogicalName());
  4032. resp.setLogicalName(DataColumnsResponse->getLogicalName());
  4033. resp.setStartIndex(DataColumnsResponse->getStartIndex());
  4034. resp.setEndIndex(DataColumnsResponse->getEndIndex());
  4035. resp.setDFUDataKeyedColumns1(DataColumnsResponse->getDFUDataKeyedColumns1());
  4036. resp.setDFUDataKeyedColumns2(DataColumnsResponse->getDFUDataKeyedColumns2());
  4037. resp.setDFUDataKeyedColumns3(DataColumnsResponse->getDFUDataKeyedColumns3());
  4038. resp.setDFUDataKeyedColumns4(DataColumnsResponse->getDFUDataKeyedColumns4());
  4039. resp.setDFUDataKeyedColumns5(DataColumnsResponse->getDFUDataKeyedColumns5());
  4040. resp.setDFUDataKeyedColumns6(DataColumnsResponse->getDFUDataKeyedColumns6());
  4041. resp.setDFUDataKeyedColumns7(DataColumnsResponse->getDFUDataKeyedColumns7());
  4042. resp.setDFUDataKeyedColumns8(DataColumnsResponse->getDFUDataKeyedColumns8());
  4043. resp.setDFUDataKeyedColumns9(DataColumnsResponse->getDFUDataKeyedColumns9());
  4044. resp.setDFUDataKeyedColumns10(DataColumnsResponse->getDFUDataKeyedColumns10());
  4045. if (version > 1.14)
  4046. {
  4047. resp.setDFUDataKeyedColumns11(DataColumnsResponse->getDFUDataKeyedColumns11());
  4048. resp.setDFUDataKeyedColumns12(DataColumnsResponse->getDFUDataKeyedColumns12());
  4049. resp.setDFUDataKeyedColumns13(DataColumnsResponse->getDFUDataKeyedColumns13());
  4050. resp.setDFUDataKeyedColumns14(DataColumnsResponse->getDFUDataKeyedColumns14());
  4051. resp.setDFUDataKeyedColumns15(DataColumnsResponse->getDFUDataKeyedColumns15());
  4052. resp.setDFUDataKeyedColumns16(DataColumnsResponse->getDFUDataKeyedColumns16());
  4053. resp.setDFUDataKeyedColumns17(DataColumnsResponse->getDFUDataKeyedColumns17());
  4054. resp.setDFUDataKeyedColumns18(DataColumnsResponse->getDFUDataKeyedColumns18());
  4055. resp.setDFUDataKeyedColumns19(DataColumnsResponse->getDFUDataKeyedColumns19());
  4056. resp.setDFUDataKeyedColumns20(DataColumnsResponse->getDFUDataKeyedColumns20());
  4057. }
  4058. resp.setDFUDataNonKeyedColumns1(DataColumnsResponse->getDFUDataNonKeyedColumns1());
  4059. resp.setDFUDataNonKeyedColumns2(DataColumnsResponse->getDFUDataNonKeyedColumns2());
  4060. resp.setDFUDataNonKeyedColumns3(DataColumnsResponse->getDFUDataNonKeyedColumns3());
  4061. resp.setDFUDataNonKeyedColumns4(DataColumnsResponse->getDFUDataNonKeyedColumns4());
  4062. resp.setDFUDataNonKeyedColumns5(DataColumnsResponse->getDFUDataNonKeyedColumns5());
  4063. resp.setDFUDataNonKeyedColumns6(DataColumnsResponse->getDFUDataNonKeyedColumns6());
  4064. resp.setDFUDataNonKeyedColumns7(DataColumnsResponse->getDFUDataNonKeyedColumns7());
  4065. resp.setDFUDataNonKeyedColumns8(DataColumnsResponse->getDFUDataNonKeyedColumns8());
  4066. resp.setDFUDataNonKeyedColumns9(DataColumnsResponse->getDFUDataNonKeyedColumns9());
  4067. resp.setDFUDataNonKeyedColumns10(DataColumnsResponse->getDFUDataNonKeyedColumns10());
  4068. if (version > 1.14)
  4069. {
  4070. resp.setDFUDataNonKeyedColumns11(DataColumnsResponse->getDFUDataNonKeyedColumns11());
  4071. resp.setDFUDataNonKeyedColumns12(DataColumnsResponse->getDFUDataNonKeyedColumns12());
  4072. resp.setDFUDataNonKeyedColumns13(DataColumnsResponse->getDFUDataNonKeyedColumns13());
  4073. resp.setDFUDataNonKeyedColumns14(DataColumnsResponse->getDFUDataNonKeyedColumns14());
  4074. resp.setDFUDataNonKeyedColumns15(DataColumnsResponse->getDFUDataNonKeyedColumns15());
  4075. resp.setDFUDataNonKeyedColumns16(DataColumnsResponse->getDFUDataNonKeyedColumns16());
  4076. resp.setDFUDataNonKeyedColumns17(DataColumnsResponse->getDFUDataNonKeyedColumns17());
  4077. resp.setDFUDataNonKeyedColumns18(DataColumnsResponse->getDFUDataNonKeyedColumns18());
  4078. resp.setDFUDataNonKeyedColumns19(DataColumnsResponse->getDFUDataNonKeyedColumns19());
  4079. resp.setDFUDataNonKeyedColumns20(DataColumnsResponse->getDFUDataNonKeyedColumns20());
  4080. }
  4081. resp.setRowCount(DataColumnsResponse->getRowCount());
  4082. resp.setShowColumns(DataColumnsResponse->getShowColumns());
  4083. resp.setChooseFile(DataColumnsResponse->getChooseFile());
  4084. }
  4085. const char* logicalName = req.getLogicalName();
  4086. if (strlen(logicalName) == 0 && strlen(openLogicalName) > 0)
  4087. {
  4088. logicalName = openLogicalName;
  4089. }
  4090. if (strlen(logicalName) > 0)
  4091. {
  4092. Owned<IEspDFUBrowseDataRequest> browseDataRequest = createDFUBrowseDataRequest();
  4093. Owned<IEspDFUBrowseDataResponse> browseDataResponse = createDFUBrowseDataResponse();
  4094. browseDataRequest->setLogicalName(logicalName);
  4095. const char* parentName = req.getParentName();
  4096. if (parentName && *parentName)
  4097. browseDataRequest->setParentName(parentName);
  4098. browseDataRequest->setFilterBy(req.getFilterBy());
  4099. browseDataRequest->setShowColumns(req.getShowColumns());
  4100. browseDataRequest->setStartForGoback(req.getStartForGoback());
  4101. browseDataRequest->setCountForGoback(req.getCountForGoback());
  4102. browseDataRequest->setChooseFile(req.getChooseFile());
  4103. browseDataRequest->setStart(req.getStart());
  4104. browseDataRequest->setCount(req.getCount());
  4105. browseDataRequest->setSchemaOnly(req.getSchemaOnly());
  4106. browseDataRequest->setCluster(req.getCluster());
  4107. browseDataRequest->setClusterType(req.getClusterType());
  4108. browseDataRequest->setDisableUppercaseTranslation(req.getDisableUppercaseTranslation());
  4109. onDFUBrowseData(context, *browseDataRequest, *browseDataResponse);
  4110. resp.setName(browseDataResponse->getName());
  4111. resp.setLogicalName(browseDataResponse->getLogicalName());
  4112. resp.setFilterBy(browseDataResponse->getFilterBy());
  4113. resp.setFilterForGoBack(browseDataResponse->getFilterForGoBack());
  4114. resp.setColumnsHidden(browseDataResponse->getColumnsHidden());
  4115. resp.setColumnsHidden(browseDataResponse->getColumnsHidden());
  4116. resp.setColumnCount(browseDataResponse->getColumnCount());
  4117. resp.setStartForGoback(browseDataResponse->getStartForGoback());
  4118. resp.setCountForGoback(browseDataResponse->getCountForGoback());
  4119. resp.setChooseFile(browseDataResponse->getChooseFile());
  4120. resp.setStart(browseDataResponse->getStart());
  4121. resp.setCount(browseDataResponse->getCount());
  4122. resp.setPageSize(browseDataResponse->getPageSize());
  4123. resp.setTotal(browseDataResponse->getTotal());
  4124. resp.setResult(browseDataResponse->getResult());
  4125. resp.setMsgToDisplay(browseDataResponse->getMsgToDisplay());
  4126. resp.setSchemaOnly(browseDataResponse->getSchemaOnly());
  4127. resp.setAutoUppercaseTranslation(!m_disableUppercaseTranslation);
  4128. }
  4129. }
  4130. catch(IException* e)
  4131. {
  4132. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  4133. }
  4134. return true;
  4135. }
  4136. static const char * const columnTypes[] = { "Boolean", "Integer", "Unsigned Integer", "Real", "String",
  4137. "Data", "Unicode", "Unknown", "BeginIfBlock", "EndIfBlock", "BeginRecord", "EndRecord", "Set", "Dataset", NULL };
  4138. bool CWsDfuEx::onDFUGetFileMetaData(IEspContext &context, IEspDFUGetFileMetaDataRequest & req, IEspDFUGetFileMetaDataResponse & resp)
  4139. {
  4140. class CDFUFileMetaDataReader
  4141. {
  4142. unsigned totalColumnCount;
  4143. unsigned keyedColumnCount;
  4144. StringBuffer XmlSchema, XmlXPathSchema;
  4145. IArrayOf<IEspDFUDataColumn> dataColumns;
  4146. const IResultSetMetaData& metaRoot;
  4147. bool readRootLevelColumns;
  4148. IEspContext &context;
  4149. bool readColumnLabel(const IResultSetMetaData* meta, unsigned columnID, IEspDFUDataColumn* out)
  4150. {
  4151. SCMStringBuffer columnLabel;
  4152. bool isNaturalColumn = true;
  4153. if (meta->hasSetTranslation(columnID))
  4154. meta->getNaturalColumnLabel(columnLabel, columnID);
  4155. if (columnLabel.length() < 1)
  4156. {
  4157. meta->getColumnLabel(columnLabel, columnID);
  4158. isNaturalColumn = false;
  4159. }
  4160. out->setColumnLabel(columnLabel.str());
  4161. out->setIsNaturalColumn(isNaturalColumn);
  4162. return isNaturalColumn;
  4163. }
  4164. void readColumn(const IResultSetMetaData* meta, unsigned& columnID, const bool isKeyed,
  4165. IArrayOf<IEspDFUDataColumn>& dataColumns)
  4166. {
  4167. double version = context.getClientVersion();
  4168. Owned<IEspDFUDataColumn> dataItem = createDFUDataColumn();
  4169. dataItem->setColumnID(columnID+1);
  4170. dataItem->setIsKeyedColumn(isKeyed);
  4171. SCMStringBuffer s;
  4172. dataItem->setColumnEclType(meta->getColumnEclType(s, columnID).str());
  4173. DisplayType columnType = meta->getColumnDisplayType(columnID);
  4174. if ((columnType == TypeUnicode) || columnType == TypeString)
  4175. dataItem->setColumnRawSize(meta->getColumnRawSize(columnID));
  4176. if (readColumnLabel(meta, columnID, dataItem))
  4177. dataItem->setColumnType("Others");
  4178. else if (columnType == TypeBeginRecord)
  4179. dataItem->setColumnType("Record");
  4180. else
  4181. dataItem->setColumnType(columnTypes[columnType]);
  4182. if ((version >= 1.31) && ((columnType == TypeSet) || (columnType == TypeDataset) || (columnType == TypeBeginRecord)))
  4183. checkAndReadNestedColumn(meta, columnID, columnType, dataItem);
  4184. dataColumns.append(*dataItem.getClear());
  4185. }
  4186. void readColumns(const IResultSetMetaData* meta, IArrayOf<IEspDFUDataColumn>& dataColumnArray)
  4187. {
  4188. if (!meta)
  4189. return;
  4190. if (readRootLevelColumns)
  4191. {
  4192. readRootLevelColumns = false;
  4193. totalColumnCount = (unsigned)meta->getColumnCount();
  4194. keyedColumnCount = meta->getNumKeyedColumns();
  4195. unsigned i = 0;
  4196. for (; i < keyedColumnCount; i++)
  4197. readColumn(meta, i, true, dataColumnArray);
  4198. for (i = keyedColumnCount; i < totalColumnCount; i++)
  4199. readColumn(meta, i, false, dataColumnArray);
  4200. }
  4201. else
  4202. {
  4203. unsigned columnCount = (unsigned)meta->getColumnCount();
  4204. for (unsigned i = 0; i < columnCount; i++)
  4205. readColumn(meta, i, false, dataColumnArray);
  4206. }
  4207. }
  4208. void checkAndReadNestedColumn(const IResultSetMetaData* meta, unsigned& columnID,
  4209. DisplayType columnType, IEspDFUDataColumn* dataItem)
  4210. {
  4211. IArrayOf<IEspDFUDataColumn> curDataColumnArray;
  4212. if (columnType == TypeBeginRecord)
  4213. {
  4214. columnID++;
  4215. do
  4216. {
  4217. readColumn(meta, columnID, false, curDataColumnArray);
  4218. } while (meta->getColumnDisplayType(++columnID) != TypeEndRecord);
  4219. }
  4220. else
  4221. readColumns(meta->getChildMeta(columnID), curDataColumnArray);
  4222. dataItem->setDataColumns(curDataColumnArray);
  4223. }
  4224. public:
  4225. CDFUFileMetaDataReader(IEspContext& _context, const IResultSetMetaData& _meta)
  4226. : context(_context), metaRoot(_meta), readRootLevelColumns(true)
  4227. {
  4228. readColumns(&metaRoot, dataColumns);
  4229. };
  4230. inline unsigned getTotalColumnCount() { return totalColumnCount; }
  4231. inline unsigned getKeyedColumnCount() { return keyedColumnCount; }
  4232. inline IArrayOf<IEspDFUDataColumn>& getDataColumns() { return dataColumns; }
  4233. inline StringBuffer& getXmlSchema(StringBuffer& s, const bool addHeader)
  4234. {
  4235. StringBufferAdaptor schema(s);
  4236. metaRoot.getXmlSchema(schema, addHeader);
  4237. return s;
  4238. }
  4239. inline StringBuffer& getXmlXPathSchema(StringBuffer& s, const bool addHeader)
  4240. {
  4241. StringBufferAdaptor XPathSchema(s);
  4242. metaRoot.getXmlXPathSchema(XPathSchema, addHeader);
  4243. return s;
  4244. }
  4245. };
  4246. try
  4247. {
  4248. StringBuffer fileNameStr(req.getLogicalFileName());
  4249. const char* fileName = fileNameStr.trim().str();
  4250. if (!fileName || !*fileName)
  4251. throw MakeStringException(ECLWATCH_INVALID_INPUT, "CWsDfuEx::onDFUGetFileMetaData: LogicalFileName not set");
  4252. const char* cluster = NULL;
  4253. StringBuffer clusterNameStr(req.getClusterName());
  4254. if (clusterNameStr.trim().length() > 0)
  4255. cluster = clusterNameStr.str();
  4256. PROGLOG("DFUGetFileMetaData: %s", fileName);
  4257. Owned<IResultSetFactory> resultSetFactory = getSecResultSetFactory(context.querySecManager(), context.queryUser(), context.queryUserId(), context.queryPassword());
  4258. Owned<INewResultSet> result = resultSetFactory->createNewFileResultSet(fileName, cluster);
  4259. if (!result)
  4260. throw MakeStringException(ECLWATCH_INVALID_INPUT, "CWsDfuEx::onDFUGetFileMetaData: Failed to access FileResultSet for %s.", fileName);
  4261. CDFUFileMetaDataReader dataReader(context, result->getMetaData());
  4262. resp.setTotalColumnCount(dataReader.getTotalColumnCount());
  4263. resp.setKeyedColumnCount(dataReader.getKeyedColumnCount());
  4264. resp.setDataColumns(dataReader.getDataColumns());
  4265. StringBuffer s, s1;
  4266. if (req.getIncludeXmlSchema())
  4267. resp.setXmlSchema(dataReader.getXmlSchema(s, req.getAddHeaderInXmlSchema()).str());
  4268. if (req.getIncludeXmlXPathSchema())
  4269. resp.setXmlXPathSchema(dataReader.getXmlXPathSchema(s1, req.getAddHeaderInXmlXPathSchema()).str());
  4270. resp.setTotalResultRows(result->getNumRows());
  4271. }
  4272. catch(IException* e)
  4273. {
  4274. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  4275. }
  4276. return true;
  4277. }
  4278. bool CWsDfuEx::onDFUBrowseData(IEspContext &context, IEspDFUBrowseDataRequest &req, IEspDFUBrowseDataResponse &resp)
  4279. {
  4280. try
  4281. {
  4282. context.ensureFeatureAccess(FEATURE_URL, SecAccess_Read, ECLWATCH_DFU_ACCESS_DENIED, "WsDfu::DFUBrowseData: Permission denied.");
  4283. const char* logicalName0 = req.getLogicalName();
  4284. const char* parentName = req.getParentName();
  4285. if (!logicalName0 || !*logicalName0)
  4286. throw MakeStringException(ECLWATCH_INVALID_INPUT,"No LogicalName defined.");
  4287. StringBuffer logicalNameStr;
  4288. if (logicalName0 && *logicalName0)
  4289. {
  4290. logicalNameStr.append(logicalName0);
  4291. logicalNameStr.trim();
  4292. if (logicalNameStr.length() < 1)
  4293. throw MakeStringException(ECLWATCH_INVALID_INPUT,"No LogicalName defined.");
  4294. }
  4295. PROGLOG("DFUBrowseData: %s", logicalNameStr.str());
  4296. __int64 start = req.getStart() > 0 ? req.getStart() : 0;
  4297. __int64 count=req.getCount() ? req.getCount() : 20, requested=count;
  4298. if (count > MAX_VIEWKEYFILE_ROWS)
  4299. throw MakeStringException(ECLWATCH_TOO_MANY_DATA_ROWS,"Browser Cannot display more than %d data rows.", MAX_VIEWKEYFILE_ROWS);
  4300. bool bSchemaOnly=req.getSchemaOnly() ? req.getSchemaOnly() : false;
  4301. bool bDisableUppercaseTranslation = req.getDisableUppercaseTranslation() ? req.getDisableUppercaseTranslation() : false;
  4302. const char* filterBy = req.getFilterBy();
  4303. const char* showColumns = req.getShowColumns();
  4304. __int64 read=0;
  4305. __int64 total = 0;
  4306. StringBuffer msg;
  4307. StringArray columnLabels, columnLabelsType;
  4308. IArrayOf<IEspDFUData> DataList;
  4309. int iRet = GetIndexData(context, bSchemaOnly, logicalNameStr.str(), parentName, filterBy, start, count, read, total, msg, columnLabels, columnLabelsType, DataList, bDisableUppercaseTranslation);
  4310. if (iRet > 0)
  4311. resp.setMsgToDisplay("This search has timed out due to the restrictive filter. There may be more records.");
  4312. //GetIndexData(context, bSchemaOnly, logicalNameStr.str(), "roxie::thor_data400::key::bankruptcyv2::20090721::search::tmsid", filterBy, start, count, read, total, msg, columnLabels, columnLabelsType, DataList);
  4313. resp.setResult(DataList.item(0).getData());
  4314. unsigned int max_name_length = 3; //max length for name length
  4315. unsigned int max_value_length = 4; //max length for value length:
  4316. StringBuffer filterByStr, filterByStr0;
  4317. filterByStr0.appendf("%d%d", max_name_length, max_value_length);
  4318. unsigned columnCount = columnLabels.length();
  4319. IArrayOf<IEspDFUDataColumn> dataColumns;
  4320. double version = context.getClientVersion();
  4321. if (version > 1.04 && columnCount > 0)
  4322. {
  4323. //Find out which columns need to be displayed
  4324. int lenShowCols = 0, showCols[1024];
  4325. const char* showColumns = req.getShowColumns();
  4326. char *pShowColumns = (char*) showColumns;
  4327. while (pShowColumns && *pShowColumns)
  4328. {
  4329. StringBuffer buf;
  4330. while (pShowColumns && isdigit(pShowColumns[0]))
  4331. {
  4332. buf.append(pShowColumns[0]);
  4333. pShowColumns++;
  4334. }
  4335. if (buf.length() > 0)
  4336. {
  4337. showCols[lenShowCols] = atoi(buf.str());
  4338. lenShowCols++;
  4339. }
  4340. if (!pShowColumns || !*pShowColumns)
  4341. break;
  4342. pShowColumns++;
  4343. }
  4344. for(unsigned col = 0; col < columnCount; col++)
  4345. {
  4346. const char* label = columnLabels.item(col);
  4347. const char* type = columnLabelsType.item(col);
  4348. if (!label || !*label || !type || !*type)
  4349. continue;
  4350. Owned<IEspDFUDataColumn> item = createDFUDataColumn("","");
  4351. item->setColumnLabel(label);
  4352. item->setColumnType(type);
  4353. item->setColumnSize(0); //not show this column
  4354. if (!showColumns || !*showColumns)
  4355. {
  4356. item->setColumnSize(1); //Show this column
  4357. }
  4358. else
  4359. {
  4360. for(int col1 = 0; col1 < lenShowCols; col1++)
  4361. {
  4362. if (col == showCols[col1])
  4363. {
  4364. item->setColumnSize(1); //Show this column
  4365. break;
  4366. }
  4367. }
  4368. }
  4369. dataColumns.append(*item.getLink());
  4370. }
  4371. //Re-build filters
  4372. if (filterBy && *filterBy)
  4373. {
  4374. StringArray filterByNames, filterByValues;
  4375. parseTwoStringArrays(filterBy, filterByNames, filterByValues);
  4376. if (filterByNames.length() > 0)
  4377. {
  4378. for (unsigned ii = 0; ii < filterByNames.length(); ii++)
  4379. {
  4380. const char* columnName = filterByNames.item(ii);
  4381. const char* columnValue = filterByValues.item(ii);
  4382. if (columnName && *columnName && columnValue && *columnValue)
  4383. {
  4384. filterByStr.appendf("%s[%s]", columnName, columnValue);
  4385. filterByStr0.appendf("%03d%04d%s%s", (int) strlen(columnName), (int) strlen(columnValue), columnName, columnValue);
  4386. }
  4387. }
  4388. }
  4389. }
  4390. if (req.getStartForGoback())
  4391. resp.setStartForGoback(req.getStartForGoback());
  4392. if (req.getCountForGoback())
  4393. resp.setCountForGoback(req.getCountForGoback());
  4394. }
  4395. //resp.setFilterBy(filterByStr.str());
  4396. if (filterByStr.length() > 0)
  4397. {
  4398. const char* oldStr = "&";
  4399. const char* newStr = "&amp;";
  4400. filterByStr.replaceString(oldStr, newStr);
  4401. resp.setFilterBy(filterByStr.str());
  4402. }
  4403. if (version > 1.04)
  4404. {
  4405. //resp.setFilterForGoBack(filterByStr0.str());
  4406. if (filterByStr0.length() > 0)
  4407. {
  4408. const char* oldStr = "&";
  4409. const char* newStr = "&amp;";
  4410. filterByStr0.replaceString(oldStr, newStr);
  4411. resp.setFilterForGoBack(filterByStr0.str());
  4412. }
  4413. resp.setColumnCount(columnCount);
  4414. if (dataColumns.length() > 0)
  4415. resp.setColumnsHidden(dataColumns);
  4416. }
  4417. if (version > 1.10)
  4418. {
  4419. resp.setSchemaOnly(bSchemaOnly);
  4420. }
  4421. //resp.setName(name.str());
  4422. resp.setLogicalName(logicalNameStr.str());
  4423. resp.setStart(start);
  4424. //if (requested > read)
  4425. // requested = read;
  4426. resp.setPageSize(requested);
  4427. if (count > read)
  4428. {
  4429. count = read;
  4430. }
  4431. resp.setCount(count);
  4432. if (total != UNKNOWN_NUM_ROWS)
  4433. resp.setTotal(total);
  4434. else
  4435. resp.setTotal(-1);
  4436. if (req.getChooseFile())
  4437. resp.setChooseFile(1);
  4438. else
  4439. resp.setChooseFile(0);
  4440. if (version > 1.11)
  4441. {
  4442. if (req.getCluster() && *req.getCluster())
  4443. {
  4444. resp.setCluster(req.getCluster());
  4445. }
  4446. if (req.getClusterType() && *req.getClusterType())
  4447. {
  4448. resp.setClusterType(req.getClusterType());
  4449. }
  4450. }
  4451. if ((version > 1.12) && parentName && *parentName)
  4452. {
  4453. resp.setParentName(parentName);
  4454. }
  4455. }
  4456. catch(IException* e)
  4457. {
  4458. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  4459. }
  4460. return true;
  4461. }
  4462. void storeHistoryTreeToArray(IPropertyTree *history, IArrayOf<IEspHistory>& arrHistory)
  4463. {
  4464. Owned<IPropertyTreeIterator> historyIter = history->getElements("*");
  4465. ForEach(*historyIter)
  4466. {
  4467. Owned<IEspHistory> historyRecord = createHistory();
  4468. IPropertyTree & item = historyIter->query();
  4469. historyRecord->setIP(item.queryProp("@ip"));
  4470. historyRecord->setName(item.queryProp("@name"));
  4471. historyRecord->setOperation(item.queryProp("@operation"));
  4472. historyRecord->setOwner(item.queryProp("@owner"));
  4473. historyRecord->setPath(item.queryProp("@path"));
  4474. historyRecord->setTimestamp(item.queryProp("@timestamp"));
  4475. historyRecord->setWorkunit(item.queryProp("@workunit"));
  4476. arrHistory.append(*historyRecord.getClear());
  4477. }
  4478. }
  4479. bool CWsDfuEx::onListHistory(IEspContext &context, IEspListHistoryRequest &req, IEspListHistoryResponse &resp)
  4480. {
  4481. try
  4482. {
  4483. if (!req.getName() || !*req.getName())
  4484. throw MakeStringException(ECLWATCH_MISSING_PARAMS, "Name required");
  4485. PROGLOG("onListHistory: %s", req.getName());
  4486. MemoryBuffer xmlmap;
  4487. IArrayOf<IEspHistory> arrHistory;
  4488. Owned<IDistributedFile> file = lookupLogicalName(context, req.getName(), false, false, false, nullptr, defaultPrivilegedUser);
  4489. if (file)
  4490. {
  4491. IPropertyTree *history = file->queryHistory();
  4492. if (history)
  4493. {
  4494. storeHistoryTreeToArray(history, arrHistory);
  4495. if (context.getClientVersion() < 1.36)
  4496. history->serialize(xmlmap);
  4497. }
  4498. if (arrHistory.ordinality())
  4499. resp.setHistory(arrHistory);
  4500. }
  4501. else
  4502. throw MakeStringException(ECLWATCH_FILE_NOT_EXIST,"CWsDfuEx::onListHistory: Could not find file '%s'.", req.getName());
  4503. if (xmlmap.length())
  4504. resp.setXmlmap(xmlmap);
  4505. }
  4506. catch(IException* e)
  4507. {
  4508. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  4509. }
  4510. return true;
  4511. }
  4512. bool CWsDfuEx::onEraseHistory(IEspContext &context, IEspEraseHistoryRequest &req, IEspEraseHistoryResponse &resp)
  4513. {
  4514. try
  4515. {
  4516. context.ensureFeatureAccess(FEATURE_URL, SecAccess_Full, ECLWATCH_DFU_ACCESS_DENIED, "WsDfu::EraseHistory: Permission denied.");
  4517. if (!req.getName() || !*req.getName())
  4518. throw MakeStringException(ECLWATCH_MISSING_PARAMS, "Name required");
  4519. PROGLOG("onEraseHistory: %s", req.getName());
  4520. MemoryBuffer xmlmap;
  4521. IArrayOf<IEspHistory> arrHistory;
  4522. Owned<IDistributedFile> file = lookupLogicalName(context, req.getName(), false, false, false, nullptr, defaultPrivilegedUser);
  4523. if (file)
  4524. {
  4525. IPropertyTree *history = file->queryHistory();
  4526. if (history)
  4527. {
  4528. storeHistoryTreeToArray(history, arrHistory);
  4529. if (context.getClientVersion() < 1.36)
  4530. history->serialize(xmlmap);
  4531. file->resetHistory();
  4532. }
  4533. if (arrHistory.ordinality())
  4534. resp.setHistory(arrHistory);
  4535. }
  4536. else
  4537. throw MakeStringException(ECLWATCH_FILE_NOT_EXIST,"CWsDfuEx::onEraseHistory: Could not find file '%s'.", req.getName());
  4538. if (xmlmap.length())
  4539. resp.setXmlmap(xmlmap);
  4540. }
  4541. catch(IException* e)
  4542. {
  4543. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  4544. }
  4545. return true;
  4546. }
  4547. //////////////////////HPCC Browser//////////////////////////
  4548. static const char* SCHEMANAME = "myschema";
  4549. //void CWsDfuEx::setRootFilter(INewResultSet* result, const char* filterBy, IFilteredResultSet* filter)
  4550. void CWsDfuEx::setRootFilter(INewResultSet* result, const char* filterBy, IResultSetFilter* filter, bool disableUppercaseTranslation)
  4551. {
  4552. if (!filterBy || !*filterBy || !result)
  4553. return;
  4554. //Owned<IFilteredResultSet> filter = result->createFiltered();
  4555. filter->clearFilters();
  4556. const IResultSetMetaData &meta = result->getMetaData();
  4557. unsigned columnCount = meta.getColumnCount();
  4558. if (columnCount < 1)
  4559. return;
  4560. StringArray filterByNames, filterByValues;
  4561. parseTwoStringArrays(filterBy, filterByNames, filterByValues);
  4562. if (filterByNames.length() < 1)
  4563. return;
  4564. for (unsigned ii = 0; ii < filterByNames.length(); ii++)
  4565. {
  4566. const char* columnName = filterByNames.item(ii);
  4567. const char* columnValue0 = filterByValues.item(ii);
  4568. if (!columnName || !*columnName || !columnValue0 || !*columnValue0)
  4569. continue;
  4570. StringBuffer buf(columnValue0);
  4571. if (!disableUppercaseTranslation)
  4572. buf.toUpperCase();
  4573. const char* columnValue = buf.str();
  4574. for(unsigned col = 0; col < columnCount; col++)
  4575. {
  4576. bool hasSetTranslation = false;
  4577. SCMStringBuffer scmbuf;
  4578. if (meta.hasSetTranslation(col))
  4579. {
  4580. hasSetTranslation = true;
  4581. meta.getNaturalColumnLabel(scmbuf, col);
  4582. }
  4583. if (scmbuf.length() < 1)
  4584. {
  4585. meta.getColumnLabel(scmbuf, col);
  4586. }
  4587. if (!stricmp(scmbuf.str(), columnName))
  4588. {
  4589. //filter->addFilter(col, columnValue);
  4590. //filterByStr.appendf("%s[%s]", columnName, columnValue);
  4591. //filterByStr0.appendf("%03d%04d%s%s", strlen(columnName), strlen(columnValue), columnName, columnValue);
  4592. if (hasSetTranslation)
  4593. filter->addNaturalFilter(col, strlen(columnValue), columnValue);
  4594. else
  4595. filter->addFilter(col, strlen(columnValue), columnValue);
  4596. break;
  4597. }
  4598. }
  4599. }
  4600. //result.setown(filter->create());
  4601. return;
  4602. }
  4603. void CWsDfuEx::getMappingColumns(IRelatedBrowseFile * file, bool isPrimary, UnsignedArray& cols)
  4604. {
  4605. const char* logicalName = file->queryDefinition()->queryDistributedFile()->queryLogicalName();
  4606. const char* primaryName = file->queryParentRelation()->queryFileRelationship()->queryPrimaryFilename();
  4607. if (!logicalName || !primaryName || strcmp(logicalName, primaryName))
  4608. return;
  4609. IViewRelation* parentRelation = file->queryParentRelation();
  4610. for (unsigned i=0; i < parentRelation->numMappingFields(); i++)
  4611. {
  4612. //find out the column numbers to remove
  4613. unsigned col = parentRelation->queryMappingField(i, isPrimary);
  4614. cols.append(col);
  4615. }
  4616. #ifdef TESTDATASET
  4617. cols.kill();
  4618. cols.append(2);
  4619. cols.append(3);
  4620. #endif
  4621. return;
  4622. }
  4623. void CWsDfuEx::readColumnsForDisplay(StringBuffer& schemaText, StringArray& columnsDisplay, StringArray& columnsDisplayType)
  4624. {
  4625. if (schemaText.length() < 1)
  4626. return;
  4627. Owned<IPropertyTree> schema = createPTreeFromXMLString(schemaText.str());
  4628. if (!schema)
  4629. return;
  4630. //Find out labels from the second schema used for column mapping
  4631. columnsDisplay.kill();
  4632. Owned<IPropertyTreeIterator> rows4 = schema->getElements("xs:element[@name=\"Dataset\"]/xs:complexType/xs:sequence/xs:element[@name=\"Row\"]/xs:complexType/xs:sequence/*");
  4633. ForEach(*rows4)
  4634. {
  4635. IPropertyTree &e = rows4->query();
  4636. const char* name = e.queryProp("@name");
  4637. const char* type = e.queryProp("@type");
  4638. bool hasChildren = e.hasChildren();
  4639. if (!name || !*name)
  4640. continue;
  4641. columnsDisplay.append(name); //Display this column
  4642. if (type && *type)
  4643. columnsDisplayType.append(type);
  4644. else if (hasChildren)
  4645. columnsDisplayType.append("Object");
  4646. else
  4647. columnsDisplayType.append("Unknown");
  4648. }
  4649. return;
  4650. }
  4651. void CWsDfuEx::mergeSchema(IRelatedBrowseFile * file, StringBuffer& schemaText, const char * schemaText2,
  4652. StringArray& columnsDisplay, StringArray& columnsDisplayType, StringArray& columnsHide)
  4653. {
  4654. if (schemaText.length() < 1)
  4655. return;
  4656. if (isEmptyString(schemaText2))
  4657. return;
  4658. Owned<IPropertyTree> schema = createPTreeFromXMLString(schemaText.str());
  4659. Owned<IPropertyTree> schema2 = createPTreeFromXMLString(schemaText2);
  4660. if (!schema || !schema2)
  4661. return;
  4662. //Process simpleType part
  4663. Owned<IPropertyTreeIterator> rows1 = schema->getElements("xs:simpleType");
  4664. Owned<IPropertyTreeIterator> rows2 = schema2->getElements("xs:simpleType");
  4665. if (!rows1 || !rows2)
  4666. return;
  4667. ForEach(*rows2)
  4668. {
  4669. IPropertyTree &e = rows2->query();
  4670. const char* name = e.queryProp("@name");
  4671. if (!name || !*name)
  4672. continue;
  4673. bool bFound = false;
  4674. ForEach(*rows1)
  4675. {
  4676. IPropertyTree &e1 = rows1->query();
  4677. const char* name1 = e1.queryProp("@name");
  4678. if (!name1 || !*name1 || stricmp(name1, name))
  4679. continue;
  4680. bFound = true;
  4681. break;
  4682. }
  4683. if (!bFound)
  4684. schema->addPropTree(e.queryName(), LINK(&e));
  4685. }
  4686. IPropertyTree* rows = schema->queryBranch("xs:element[@name=\"Dataset\"]/xs:complexType/xs:sequence/xs:element[@name=\"Row\"]/xs:complexType/xs:sequence");
  4687. if (!rows)
  4688. return;
  4689. //Find out labels used for column mapping
  4690. columnsDisplay.kill();
  4691. columnsDisplayType.kill();
  4692. columnsHide.kill();
  4693. Owned<IPropertyTreeIterator> rows4 = schema->getElements("xs:element[@name=\"Dataset\"]/xs:complexType/xs:sequence/xs:element[@name=\"Row\"]/xs:complexType/xs:sequence/*");
  4694. ForEach(*rows4)
  4695. {
  4696. IPropertyTree &e = rows4->query();
  4697. const char* name = e.queryProp("@name");
  4698. const char* type = e.queryProp("@type");
  4699. bool hasChildren = e.hasChildren();
  4700. if (!name || !*name)
  4701. continue;
  4702. columnsDisplay.append(name); //Display this column
  4703. if (type && *type)
  4704. columnsDisplayType.append(type);
  4705. else if (hasChildren)
  4706. columnsDisplayType.append("Object");
  4707. else
  4708. columnsDisplayType.append("Unknown");
  4709. }
  4710. UnsignedArray cols;
  4711. bool isPrimary = true;
  4712. getMappingColumns(file, isPrimary, cols);
  4713. //Process complexType part for labels
  4714. unsigned col0 = 0;
  4715. Owned<IPropertyTreeIterator> rows3 = schema2->getElements("xs:element[@name=\"Dataset\"]/xs:complexType/xs:sequence/xs:element[@name=\"Row\"]/xs:complexType/xs:sequence/*");
  4716. ForEach(*rows3)
  4717. {
  4718. IPropertyTree &e = rows3->query();
  4719. const char* name = e.queryProp("@name");
  4720. const char* type = e.queryProp("@type");
  4721. bool hasChildren = e.hasChildren();
  4722. if (!name || !*name)
  4723. continue;
  4724. bool bAdd = true;
  4725. bool bRename = false;
  4726. if (cols.ordinality() != 0)
  4727. {
  4728. ForEachItemIn(i1,cols)
  4729. {
  4730. unsigned col = cols.item(i1);
  4731. if (col == col0)
  4732. {
  4733. bAdd = false;
  4734. break;
  4735. }
  4736. }
  4737. }
  4738. #define RENAMESAMECOLUMN
  4739. #ifdef RENAMESAMECOLUMN
  4740. if (columnsDisplay.length() > 0)
  4741. {
  4742. for (unsigned i = 0; i < columnsDisplay.length(); i++)
  4743. {
  4744. const char* label = columnsDisplay.item(i);
  4745. if (!label || strcmp(label, name))
  4746. continue;
  4747. bRename = true;
  4748. break;
  4749. }
  4750. }
  4751. #endif
  4752. if (!bAdd)
  4753. {
  4754. columnsHide.append(name); //hide this column
  4755. }
  4756. else
  4757. {
  4758. if (type && *type)
  4759. columnsDisplayType.append(type);
  4760. else if (hasChildren)
  4761. columnsDisplayType.append("Object");
  4762. else
  4763. columnsDisplayType.append("Unknown");
  4764. #ifdef RENAMESAMECOLUMN
  4765. if (bRename)
  4766. {
  4767. StringBuffer newName(name);
  4768. newName.append("-2");
  4769. columnsDisplay.append(newName.str()); //Display this column
  4770. e.setProp("@name", newName.str());
  4771. rows->addPropTree(e.queryName(), LINK(&e));
  4772. }
  4773. else
  4774. {
  4775. #endif
  4776. columnsDisplay.append(name); //Display this column
  4777. rows->addPropTree(e.queryName(), LINK(&e));
  4778. #ifdef RENAMESAMECOLUMN
  4779. }
  4780. #endif
  4781. }
  4782. col0++;
  4783. }
  4784. //Convert schema tree to schame now
  4785. schemaText.clear();
  4786. toXML(schema, schemaText);
  4787. return;
  4788. }
  4789. void CWsDfuEx::mergeDataRow(StringBuffer& newRow, int depth, IPropertyTreeIterator* it, StringArray& columnsHide, StringArray& columnsUsed)
  4790. {
  4791. if (!it)
  4792. return;
  4793. it->first();
  4794. while(it->isValid())
  4795. {
  4796. IPropertyTree* e = &it->query();
  4797. if (e)
  4798. {
  4799. const char* label = e->queryName();
  4800. if (label && *label)
  4801. {
  4802. #ifdef RENAMESAMECOLUMN
  4803. if (depth < 1)
  4804. columnsUsed.append(label);
  4805. #endif
  4806. bool bHide = false;
  4807. if (columnsHide.length() > 0)
  4808. {
  4809. for (unsigned i = 0 ; i < columnsHide.length(); i++)
  4810. {
  4811. const char* key = columnsHide.item(i);
  4812. if (!key || strcmp(key, label))
  4813. continue;
  4814. bHide = true;
  4815. break;
  4816. }
  4817. }
  4818. #ifdef RENAMESAMECOLUMN
  4819. if (!bHide && depth > 0 && columnsUsed.length() > 0)
  4820. {
  4821. for (unsigned i = 0 ; i < columnsUsed.length(); i++)
  4822. {
  4823. const char* key = columnsUsed.item(i);
  4824. if (!key || strcmp(key, label))
  4825. continue;
  4826. StringBuffer newName(label);
  4827. newName.append("-2");
  4828. e->renameProp("/", newName.str());
  4829. break;
  4830. }
  4831. }
  4832. #endif
  4833. if (!bHide)
  4834. {
  4835. StringBuffer dataRow;
  4836. toXML(e, dataRow);
  4837. newRow.append(dataRow);
  4838. }
  4839. }
  4840. }
  4841. it->next();
  4842. }
  4843. return;
  4844. }
  4845. void CWsDfuEx::mergeDataRow(StringBuffer& newRow, const char * dataRow1, const char * dataRow2, StringArray& columnsHide)
  4846. {
  4847. if (isEmptyString(dataRow1))
  4848. return;
  4849. if (isEmptyString(dataRow2))
  4850. return;
  4851. Owned<IPropertyTree> data1 = createPTreeFromXMLString(dataRow1);
  4852. Owned<IPropertyTree> data2 = createPTreeFromXMLString(dataRow2);
  4853. if (!data1 || !data2)
  4854. return;
  4855. newRow.clear();
  4856. newRow.append("<Row>");
  4857. StringArray columnLabels;
  4858. Owned<IPropertyTreeIterator> it = data1->getElements("*");
  4859. if (it)
  4860. {
  4861. StringArray columnLabels0;
  4862. mergeDataRow(newRow, 0, it, columnLabels0, columnLabels);
  4863. }
  4864. Owned<IPropertyTreeIterator> it2 = data2->getElements("*");
  4865. if (it2)
  4866. {
  4867. mergeDataRow(newRow, 1, it2, columnsHide, columnLabels);
  4868. }
  4869. newRow.append("</Row>");
  4870. return;
  4871. }
  4872. void CWsDfuEx::browseRelatedFileSchema(IRelatedBrowseFile * file, const char* parentName, unsigned depth, StringBuffer& schemaText,
  4873. StringArray& columnsDisplay, StringArray& columnsDisplayType, StringArray& columnsHide)
  4874. {
  4875. //if (file in set of files to display or iterate)
  4876. IResultSetCursor * cursor = file->queryCursor();
  4877. if (cursor && cursor->first())
  4878. {
  4879. if (depth < 1)
  4880. {
  4881. const IResultSetMetaData & meta = cursor->queryResultSet()->getMetaData();
  4882. StringBufferAdaptor adaptor(schemaText);
  4883. meta.getXmlSchema(adaptor, false);
  4884. #ifdef TESTDATASET
  4885. schemaText.clear();
  4886. schemaText.append("<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" elementFormDefault=\"qualified\"");
  4887. schemaText.append(" attributeFormDefault=\"unqualified\">");
  4888. schemaText.append("<xs:element name=\"Dataset\"><xs:complexType><xs:sequence minOccurs=\"0\" maxOccurs=\"unbounded\">");
  4889. schemaText.append("<xs:element name=\"Row\"><xs:complexType><xs:sequence>");
  4890. schemaText.append("<xs:element name=\"state\" type=\"string2\"/>");
  4891. schemaText.append("<xs:element name=\"rtype\" type=\"string2\"/>");
  4892. schemaText.append("<xs:element name=\"id\" type=\"string20\"/>");
  4893. schemaText.append("<xs:element name=\"seq\" type=\"xs:nonNegativeInteger\"/>");
  4894. schemaText.append("<xs:element name=\"num\" type=\"xs:nonNegativeInteger\"/>");
  4895. schemaText.append("<xs:element name=\"date\" type=\"string8\"/>");
  4896. schemaText.append("<xs:element name=\"imglength\" type=\"xs:nonNegativeInteger\"/>");
  4897. schemaText.append("<xs:element name=\"__filepos\" type=\"xs:nonNegativeInteger\"/>");
  4898. schemaText.append("</xs:sequence></xs:complexType></xs:element>");
  4899. schemaText.append("</xs:sequence></xs:complexType></xs:element>");
  4900. schemaText.append("<xs:simpleType name=\"string2\"><xs:restriction base=\"xs:string\"><xs:maxLength value=\"2\"/>");
  4901. schemaText.append("</xs:restriction></xs:simpleType>");
  4902. schemaText.append("<xs:simpleType name=\"string20\"><xs:restriction base=\"xs:string\"><xs:maxLength value=\"20\"/>");
  4903. schemaText.append("</xs:restriction></xs:simpleType>");
  4904. schemaText.append("<xs:simpleType name=\"string8\"><xs:restriction base=\"xs:string\"><xs:maxLength value=\"8\"/>");
  4905. schemaText.append("</xs:restriction></xs:simpleType>");
  4906. schemaText.append("</xs:schema>");
  4907. #endif
  4908. readColumnsForDisplay(schemaText, columnsDisplay, columnsDisplayType);
  4909. }
  4910. else
  4911. {
  4912. StringBuffer schemaText0;
  4913. const IResultSetMetaData & meta = cursor->queryResultSet()->getMetaData();
  4914. StringBufferAdaptor adaptor(schemaText0);
  4915. meta.getXmlSchema(adaptor, false);
  4916. #ifdef TESTDATASET
  4917. schemaText0.clear();
  4918. schemaText0.append("<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" elementFormDefault=\"qualified\"");
  4919. schemaText0.append(" attributeFormDefault=\"unqualified\">");
  4920. schemaText0.append("<xs:element name=\"Dataset\"><xs:complexType><xs:sequence minOccurs=\"0\" maxOccurs=\"unbounded\">");
  4921. schemaText0.append("<xs:element name=\"Row\"><xs:complexType><xs:sequence>");
  4922. schemaText0.append("<xs:element name=\"date_first_reported\" type=\"string12\"/>");
  4923. schemaText0.append("<xs:element name=\"msa\" type=\"string8\"/>");
  4924. schemaText0.append("<xs:element name=\"sid\" type=\"string20\"/>");
  4925. schemaText0.append("<xs:element name=\"seq\" type=\"xs:nonNegativeInteger\"/>"); //not add
  4926. schemaText0.append("</xs:sequence></xs:complexType></xs:element>");
  4927. schemaText0.append("</xs:sequence></xs:complexType></xs:element>");
  4928. schemaText0.append("<xs:simpleType name=\"string12\"><xs:restriction base=\"xs:string\"><xs:maxLength value=\"12\"/>");
  4929. schemaText0.append("</xs:restriction></xs:simpleType>");
  4930. schemaText0.append("</xs:schema>");
  4931. #endif
  4932. mergeSchema(file, schemaText, schemaText0, columnsDisplay, columnsDisplayType, columnsHide);
  4933. }
  4934. if (parentName && *parentName)
  4935. {
  4936. for (unsigned i = 0;;i++)
  4937. {
  4938. IRelatedBrowseFile * next = file->queryChild(i);
  4939. if (!next)
  4940. break;
  4941. IViewRelatedFile * viewRelatedFile = next->queryDefinition();
  4942. if (!viewRelatedFile)
  4943. continue;
  4944. IDistributedFile * file = viewRelatedFile->queryDistributedFile();
  4945. if (!file)
  4946. continue;
  4947. const char* logicName0 = file->queryLogicalName();
  4948. if (logicName0 && !strcmp(logicName0, parentName))
  4949. browseRelatedFileSchema(next, NULL, depth+1, schemaText, columnsDisplay, columnsDisplayType, columnsHide);
  4950. }
  4951. }
  4952. }
  4953. return;
  4954. }
  4955. int CWsDfuEx::browseRelatedFileDataSet(double version, IRelatedBrowseFile * file, const char* parentName, unsigned depth, __int64 start, __int64& count, __int64& read,
  4956. StringArray& columnsHide, StringArray& dataSetOutput)
  4957. {
  4958. int iRet = 0;
  4959. int rows = 0;
  4960. try
  4961. {
  4962. //if (file in set of files to display or iterate)
  4963. IResultSetCursor * cursor = file->queryCursor();
  4964. if (cursor->first())
  4965. {
  4966. for(bool ok=cursor->absolute(start);ok;ok=cursor->next())
  4967. {
  4968. StringBuffer text;
  4969. StringBufferAdaptor adaptor2(text);
  4970. cursor->getXmlRow(adaptor2);
  4971. StringArray dataSetOutput0;
  4972. if (parentName && *parentName)
  4973. {
  4974. for (unsigned i = 0;;i++)
  4975. {
  4976. IRelatedBrowseFile * next = file->queryChild(i);
  4977. if (!next)
  4978. break;
  4979. IViewRelatedFile * viewRelatedFile = next->queryDefinition();
  4980. if (!viewRelatedFile)
  4981. continue;
  4982. IDistributedFile * file = viewRelatedFile->queryDistributedFile();
  4983. if (!file)
  4984. continue;
  4985. const char* logicName0 = file->queryLogicalName();
  4986. if (logicName0 && !strcmp(logicName0, parentName))
  4987. iRet = browseRelatedFileDataSet(version, next, NULL, depth+1, 0, count, read, columnsHide, dataSetOutput0);
  4988. }
  4989. }
  4990. if (dataSetOutput0.length() < 1)
  4991. {
  4992. dataSetOutput.append(text);
  4993. }
  4994. else
  4995. {
  4996. for (unsigned ii = 0; ii<dataSetOutput0.length(); ii++)
  4997. {
  4998. StringBuffer text0;
  4999. StringBuffer text1(dataSetOutput0.item(ii));
  5000. if (text1.length() > 0)
  5001. {
  5002. mergeDataRow(text0, text, text1, columnsHide);
  5003. }
  5004. dataSetOutput.append(text0);
  5005. }
  5006. }
  5007. if (depth < 1)
  5008. {
  5009. read++;
  5010. if(read>=count)
  5011. break;
  5012. }
  5013. }
  5014. if (depth < 1)
  5015. {
  5016. if (count > read)
  5017. count = read;
  5018. }
  5019. }
  5020. }
  5021. catch(IException* e)
  5022. {
  5023. if ((version < 1.08) || (e->errorCode() != FVERR_FilterTooRestrictive))
  5024. throw e;
  5025. e->Release();
  5026. iRet = 1;
  5027. }
  5028. return iRet;
  5029. }
  5030. //sample filterBy: 340020001id1
  5031. //sample data: <XmlSchema name="myschema">...</XmlSchema><Dataset xmlSchema="myschema">...</Dataset>
  5032. int CWsDfuEx::GetIndexData(IEspContext &context, bool bSchemaOnly, const char* indexName, const char* parentName, const char* filterBy, __int64 start,
  5033. __int64& count, __int64& read, __int64& total, StringBuffer& message, StringArray& columnLabels,
  5034. StringArray& columnLabelsType, IArrayOf<IEspDFUData>& DataList, bool webDisableUppercaseTranslation)
  5035. {
  5036. if (!indexName || !*indexName)
  5037. return -1;
  5038. double version = context.getClientVersion();
  5039. StringBuffer cluster;
  5040. bool disableUppercaseTranslation = false;
  5041. Owned<IDistributedFile> df;
  5042. try
  5043. {
  5044. df.setown(lookupLogicalName(context, indexName, false, false, false, nullptr, defaultPrivilegedUser));
  5045. if(!df)
  5046. throw MakeStringException(ECLWATCH_FILE_NOT_EXIST,"Could not find file %s.", indexName);
  5047. //Check disableUppercaseTranslation
  5048. StringBuffer mapping;
  5049. df->getColumnMapping(mapping);
  5050. if (mapping.length() > 37 && strstr(mapping.str(), "word{set(stringlib.StringToLowerCase)}"))
  5051. disableUppercaseTranslation = true;
  5052. else if (webDisableUppercaseTranslation)
  5053. disableUppercaseTranslation = webDisableUppercaseTranslation;
  5054. else
  5055. disableUppercaseTranslation = m_disableUppercaseTranslation;
  5056. const char* wuid = df->queryAttributes().queryProp("@workunit");
  5057. if (wuid && *wuid)
  5058. {
  5059. CWUWrapper wu(wuid, context);
  5060. if (wu)
  5061. cluster.append(wu->queryClusterName());
  5062. }
  5063. }
  5064. catch (IException *e)
  5065. {
  5066. IERRLOG(e);
  5067. e->Release();
  5068. }
  5069. catch(...)
  5070. {
  5071. IERRLOG("Unknown Exception - view data file: %s", indexName);
  5072. }
  5073. Owned<IResultSetFactory> resultSetFactory = getSecResultSetFactory(context.querySecManager(), context.queryUser(), context.queryUserId(), context.queryPassword());
  5074. Owned<IViewFileWeb> web;
  5075. Owned<IUserDescriptor> udesc;
  5076. ISecUser * secUser = context.queryUser();
  5077. if(secUser && secUser->getName() && *secUser->getName())
  5078. {
  5079. udesc.setown(createUserDescriptor());
  5080. udesc->set(secUser->getName(), secUser->credentials().getPassword(), context.querySignature());
  5081. }
  5082. if (cluster.length())
  5083. {
  5084. web.setown(createViewFileWeb(*resultSetFactory, cluster, udesc.getLink()));
  5085. }
  5086. else if (m_clusterName.length() > 0)
  5087. {
  5088. web.setown(createViewFileWeb(*resultSetFactory, m_clusterName.str(), udesc.getLink()));
  5089. }
  5090. else
  5091. {
  5092. web.setown(createViewFileWeb(*resultSetFactory, NULL, udesc.getLink()));
  5093. }
  5094. ViewGatherOptions options;
  5095. options.primaryDepth = 100; // we want to traverse secondary->primary, but not the reverse
  5096. options.secondaryDepth = 0;
  5097. options.setPayloadFilter(true); // we're only interested in payload links
  5098. char *indexName0 = (char *) indexName;
  5099. Owned<IFileTreeBrowser> browser;
  5100. try
  5101. {
  5102. web->gatherWeb(indexName0, df, options);
  5103. browser.setown(web->createBrowseTree(indexName0));
  5104. }
  5105. catch(IException* e)
  5106. {
  5107. if ((e->errorCode() != FVERR_CouldNotResolveX) || (indexName[0] != '~'))
  5108. {
  5109. throw e;
  5110. }
  5111. else
  5112. {
  5113. e->Release();
  5114. indexName0 = (char *) (indexName+1);
  5115. web->gatherWeb(indexName0, df, options);
  5116. browser.setown(web->createBrowseTree(indexName0));
  5117. }
  5118. }
  5119. Owned<INewResultSet> result;
  5120. if (cluster && *cluster)
  5121. {
  5122. result.setown(resultSetFactory->createNewFileResultSet(indexName0, cluster));
  5123. }
  5124. else if (m_clusterName.length() > 0)
  5125. {
  5126. result.setown(resultSetFactory->createNewFileResultSet(indexName0, m_clusterName.str()));
  5127. }
  5128. else
  5129. {
  5130. result.setown(resultSetFactory->createNewFileResultSet(indexName0, NULL));
  5131. }
  5132. // Apply the filter to the root node
  5133. if (filterBy && *filterBy)
  5134. {
  5135. //Owned<IFilteredResultSet> filter = result->createFiltered();
  5136. IResultSetFilter* filter = browser->queryRootFilter();
  5137. setRootFilter(result, filterBy, filter, disableUppercaseTranslation);
  5138. ///result.setown(filter->create());
  5139. }
  5140. StringBuffer text, schemaText;
  5141. StringArray columnsHide;
  5142. browseRelatedFileSchema(browser->queryRootFile(), parentName, 0, schemaText, columnLabels, columnLabelsType, columnsHide);
  5143. text.appendf("<XmlSchema name=\"%s\">", SCHEMANAME);
  5144. text.append(schemaText);
  5145. text.append("</XmlSchema>").newline();
  5146. int iRet = 0;
  5147. if (!bSchemaOnly)
  5148. {
  5149. StringArray dataSetOutput;
  5150. iRet = browseRelatedFileDataSet(version, browser->queryRootFile(), parentName, 0, start, count, read, columnsHide, dataSetOutput);
  5151. StringBuffer dataSetText;
  5152. dataSetText.appendf("<Dataset xmlSchema=\"%s\" >", SCHEMANAME);
  5153. dataSetText.newline();
  5154. for (unsigned i = 0; i<dataSetOutput.length(); i++)
  5155. {
  5156. StringBuffer text0(dataSetOutput.item(i));
  5157. if (text0.length() > 0)
  5158. {
  5159. dataSetText.append(text0);
  5160. dataSetText.newline();
  5161. }
  5162. }
  5163. dataSetText.append("</Dataset>");
  5164. text.append(dataSetText.str());
  5165. }
  5166. MemoryBuffer data;
  5167. struct MemoryBuffer2IStringVal : public CInterface, implements IStringVal
  5168. {
  5169. MemoryBuffer2IStringVal(MemoryBuffer & _buffer) : buffer(_buffer) {}
  5170. IMPLEMENT_IINTERFACE;
  5171. virtual const char * str() const { UNIMPLEMENTED; }
  5172. virtual void set(const char *val) { buffer.append(strlen(val),val); }
  5173. virtual void clear() { } // clearing when appending does nothing
  5174. virtual void setLen(const char *val, unsigned length) { buffer.append(length, val); }
  5175. virtual unsigned length() const { return buffer.length(); };
  5176. MemoryBuffer & buffer;
  5177. } adaptor0(data);
  5178. adaptor0.set(text.str());
  5179. data.append(0);
  5180. total=result->getNumRows();
  5181. Owned<IEspDFUData> item = createDFUData("","");
  5182. item->setName(indexName);
  5183. item->setNumRows(total);
  5184. item->setData(data.toByteArray());
  5185. DataList.append(*item.getClear());
  5186. return iRet;
  5187. }
  5188. void CWsDfuEx::getFilePartsInfo(IEspContext &context, IFileDescriptor &fileDesc, bool forFileCreate, IEspDFUFileAccessInfo &accessInfo)
  5189. {
  5190. double version = context.getClientVersion();
  5191. IArrayOf<IEspDFUFilePart> dfuParts;
  5192. IArrayOf<IEspDFUPartLocation> dfuPartLocations;
  5193. unsigned newLocationIndex = 0;
  5194. MapStringTo<unsigned> partLocationMap;
  5195. // NB: both CopyIndex and PartIndex are 1 based in response.
  5196. Owned<IPartDescriptorIterator> pi = fileDesc.getIterator();
  5197. ForEach(*pi)
  5198. {
  5199. IPartDescriptor& part = pi->query();
  5200. bool isTLKPart = isPartTLK(&part);
  5201. if (version <= 1.55 && isTLKPart)
  5202. continue;
  5203. IArrayOf<IEspDFUFileCopy> fileCopies;
  5204. for (unsigned int i=0; i<part.numCopies(); i++)
  5205. {
  5206. StringBuffer host, path;
  5207. part.getPath(path, i);
  5208. Owned<IEspDFUFileCopy> fileCopy = createDFUFileCopy();
  5209. if (forFileCreate)
  5210. fileCopy->setPath(path.str());
  5211. fileCopy->setCopyIndex(i + 1);
  5212. part.queryNode(i)->endpoint().getUrlStr(host);
  5213. unsigned *locationIndex = partLocationMap.getValue(host.str());
  5214. if (locationIndex)
  5215. fileCopy->setLocationIndex(*locationIndex);
  5216. else
  5217. {
  5218. partLocationMap.setValue(host.str(), ++newLocationIndex);
  5219. fileCopy->setLocationIndex(newLocationIndex);
  5220. Owned<IEspDFUPartLocation> partLocation = createDFUPartLocation();
  5221. partLocation->setLocationIndex(newLocationIndex);
  5222. partLocation->setHost(host.str());
  5223. dfuPartLocations.append(*partLocation.getClear());
  5224. }
  5225. fileCopies.append(*fileCopy.getClear());
  5226. }
  5227. Owned<IEspDFUFilePart> filePart = createDFUFilePart();
  5228. filePart->setPartIndex(part.queryPartIndex() + 1);
  5229. filePart->setCopies(fileCopies);
  5230. if (version > 1.55)
  5231. filePart->setTopLevelKey(isTLKPart);
  5232. dfuParts.append(*filePart.getClear());
  5233. }
  5234. accessInfo.setNumParts(fileDesc.numParts());
  5235. accessInfo.setFileParts(dfuParts);
  5236. accessInfo.setFileLocations(dfuPartLocations);
  5237. }
  5238. void CWsDfuEx::getFileDafilesrvConfiguration(StringBuffer &keyPairName, unsigned &port, bool &secure, const char *group)
  5239. {
  5240. port = DEFAULT_ROWSERVICE_PORT;
  5241. secure = false;
  5242. #ifdef _CONTAINERIZED
  5243. IERRLOG("CONTAINERIZED(CWsDfuEx::getFileDafilesrvConfiguration)");
  5244. #else
  5245. keyPairName.set(env->getClusterGroupKeyPairName(group));
  5246. Owned<IConstDaFileSrvInfo> daFileSrvInfo = env->getDaFileSrvGroupInfo(group);
  5247. if (daFileSrvInfo)
  5248. {
  5249. port = daFileSrvInfo->getPort();
  5250. secure = daFileSrvInfo->getSecure();
  5251. }
  5252. #endif
  5253. }
  5254. void CWsDfuEx::getFileDafilesrvConfiguration(StringBuffer &keyPairName, unsigned &retPort, bool &retSecure, const char *fileName, std::vector<std::string> &groups)
  5255. {
  5256. retPort = DEFAULT_ROWSERVICE_PORT;
  5257. retSecure = false;
  5258. bool firstGroup = true;
  5259. for (auto &group: groups)
  5260. {
  5261. StringBuffer _keyPairName;
  5262. unsigned port;
  5263. bool secure;
  5264. getFileDafilesrvConfiguration(_keyPairName, port, secure, group.c_str());
  5265. if (firstGroup)
  5266. {
  5267. firstGroup = false;
  5268. keyPairName.set(_keyPairName);
  5269. retPort = port;
  5270. retSecure = secure;
  5271. }
  5272. else
  5273. {
  5274. if (!strsame(keyPairName, _keyPairName))
  5275. throwStringExceptionV(0, "Configuration issue - file '%s' is on multiple clusters, keys for file access must match", fileName);
  5276. if (retPort != port)
  5277. throwStringExceptionV(0, "Configuration issue - file '%s' is on multiple clusters, dafilesrv's port for file access must match", fileName);
  5278. if (retSecure != secure)
  5279. throwStringExceptionV(0, "Configuration issue - file '%s' is on multiple clusters, dafilesrv's security setting for file access must match", fileName);
  5280. }
  5281. }
  5282. }
  5283. static void getJsonTypeInfo(IFileDescriptor &fileDesc, IEspDFUFileAccessInfo &accessInfo)
  5284. {
  5285. MemoryBuffer binLayout;
  5286. StringBuffer jsonLayout;
  5287. if (!getRecordFormatFromRtlType(binLayout, jsonLayout, fileDesc.queryProperties(), false, true))
  5288. getRecordFormatFromECL(binLayout, jsonLayout, fileDesc.queryProperties(), false, true);
  5289. if (jsonLayout.length())
  5290. accessInfo.setRecordTypeInfoJson(jsonLayout.str());
  5291. }
  5292. SecAccessFlags translateToSecAccessFlags(CSecAccessType from)
  5293. {
  5294. switch (from)
  5295. {
  5296. case CSecAccessType_Access:
  5297. return SecAccess_Access;
  5298. case CSecAccessType_Read:
  5299. return SecAccess_Read;
  5300. case CSecAccessType_Write:
  5301. return SecAccess_Write;
  5302. case CSecAccessType_Full:
  5303. return SecAccess_Full;
  5304. case CSecAccessType_None:
  5305. default:
  5306. return SecAccess_None;
  5307. }
  5308. }
  5309. void CWsDfuEx::dFUFileAccessCommon(IEspContext &context, const CDfsLogicalFileName &lfn, SessionId clientSessionId, const char *requestId, unsigned expirySecs, bool returnTextResponse, unsigned lockTimeoutMs, IEspDFUFileAccessResponse &resp)
  5310. {
  5311. double version = context.getClientVersion();
  5312. StringBuffer fileName;
  5313. lfn.get(fileName, false, true);
  5314. if (0 == fileName.length())
  5315. throw MakeStringException(ECLWATCH_INVALID_INPUT, "DFU File lookup: No Name defined. (requestId=%s, expirySecs=%u)", requestId, expirySecs);
  5316. StringBuffer userID;
  5317. context.getUserID(userID);
  5318. Owned<IUserDescriptor> userDesc;
  5319. if (!userID.isEmpty())
  5320. {
  5321. userDesc.setown(createUserDescriptor());
  5322. userDesc->set(userID.str(), context.queryPassword(), context.querySignature());
  5323. }
  5324. checkLogicalName(fileName, userDesc, true, false, false, nullptr); // check for read permissions
  5325. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(fileName, userDesc, false, false, true, nullptr, defaultPrivilegedUser, lockTimeoutMs); // lock super-owners
  5326. if (!df)
  5327. throw MakeStringException(ECLWATCH_FILE_NOT_EXIST,"Cannot find file '%s'.", fileName.str());
  5328. StringBuffer cluster;
  5329. lfn.getCluster(cluster);
  5330. Owned<IFileDescriptor> fileDesc = df->getFileDescriptor(cluster);
  5331. // NB: if file has copies on >1 cluster, they must share the same key
  5332. std::vector<std::string> groups;
  5333. unsigned numClusters = df->numClusters();
  5334. for (unsigned c=0; c<numClusters; c++)
  5335. {
  5336. StringBuffer clusterName;
  5337. const char *clusterGroup = df->getClusterName(c, clusterName.clear());
  5338. groups.push_back(clusterGroup);
  5339. }
  5340. StringBuffer keyPairName;
  5341. unsigned port;
  5342. bool secure;
  5343. getFileDafilesrvConfiguration(keyPairName, port, secure, fileName, groups);
  5344. #ifdef _USE_OPENSSL
  5345. if (secure && keyPairName.isEmpty())
  5346. throw makeStringExceptionV(-1, "No keyPairName is found for '%s' in environment settings: /EnvSettings/Keys/ClusterGroup.", cluster.str());
  5347. #endif
  5348. IEspDFUFileAccessInfo &accessInfo = resp.updateAccessInfo();
  5349. Owned<IPropertyTree> metaInfo = createDFUFileMetaInfo(fileName, fileDesc, requestId, "READ", expirySecs, userDesc, keyPairName, port, secure, maxFileAccessExpirySeconds);
  5350. StringBuffer metaInfoBlob;
  5351. encodeDFUFileMeta(metaInfoBlob, metaInfo, env);
  5352. accessInfo.setMetaInfoBlob(metaInfoBlob);
  5353. CDFUFileType kind = CDFUFileType_Unset;
  5354. if (returnTextResponse)
  5355. {
  5356. getFilePartsInfo(context, *fileDesc, false, accessInfo);
  5357. getJsonTypeInfo(*fileDesc, accessInfo);
  5358. accessInfo.setExpiryTime(metaInfo->queryProp("expiryTime"));
  5359. accessInfo.setFileAccessPort(metaInfo->getPropInt("port"));
  5360. accessInfo.setFileAccessSSL(metaInfo->getPropBool("secure"));
  5361. if (isFileKey(fileDesc))
  5362. {
  5363. kind = CDFUFileType_Index;
  5364. if (version > 1.55)
  5365. {
  5366. if (isFileLocalKey(fileDesc))
  5367. kind = CDFUFileType_IndexLocal;
  5368. else if (isFilePartitionKey(fileDesc))
  5369. kind = CDFUFileType_IndexPartitioned;
  5370. }
  5371. }
  5372. else
  5373. {
  5374. const char *kindStr = queryFileKind(fileDesc);
  5375. if (!isEmptyString(kindStr))
  5376. {
  5377. if (streq("flat", kindStr))
  5378. kind = CDFUFileType_Flat;
  5379. else if (streq("csv", kindStr))
  5380. kind = CDFUFileType_Csv;
  5381. else if (streq("xml", kindStr))
  5382. kind = CDFUFileType_Xml;
  5383. else if (streq("json", kindStr))
  5384. kind = CDFUFileType_Json;
  5385. }
  5386. }
  5387. }
  5388. resp.setType(kind);
  5389. df->setAccessed();
  5390. LOG(MCauditInfo,",FileAccess,EspProcess,READ,%s,%s,%s,jobid=%s,expirySecs=%d", cluster.str(), userID.str(), fileName.str(), requestId, expirySecs);
  5391. }
  5392. // NB: deprecated from ver >= 1.50
  5393. bool CWsDfuEx::onDFUFileAccess(IEspContext &context, IEspDFUFileAccessRequest &req, IEspDFUFileAccessResponse &resp)
  5394. {
  5395. try
  5396. {
  5397. IConstDFUFileAccessRequestBase &requestBase = req.getRequestBase();
  5398. bool returnTextResponse = CFileAccessRole_External == requestBase.getAccessRole();
  5399. CDfsLogicalFileName lfn;
  5400. lfn.set(requestBase.getName());
  5401. lfn.setCluster(requestBase.getCluster());
  5402. dFUFileAccessCommon(context, lfn, 0, requestBase.getJobId(), requestBase.getExpirySeconds(), returnTextResponse, 0, resp);
  5403. }
  5404. catch (IException *e)
  5405. {
  5406. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  5407. }
  5408. return true;
  5409. }
  5410. bool CWsDfuEx::onDFUFileAccessV2(IEspContext &context, IEspDFUFileAccessV2Request &req, IEspDFUFileAccessResponse &resp)
  5411. {
  5412. try
  5413. {
  5414. CDfsLogicalFileName lfn;
  5415. lfn.set(req.getName());
  5416. lfn.setCluster(req.getCluster());
  5417. dFUFileAccessCommon(context, lfn, req.getSessionId(), req.getRequestId(), req.getExpirySeconds(), req.getReturnTextResponse(), req.getLockTimeoutMs(), resp);
  5418. }
  5419. catch (IException *e)
  5420. {
  5421. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  5422. }
  5423. return true;
  5424. }
  5425. // NB: deprecated from ver >= 1.50
  5426. static IGroup *getDFUFileIGroup(const char *clusterName, ClusterType clusterType, const char *clusterTypeEx, StringArray &locations, StringBuffer &groupName)
  5427. {
  5428. #ifdef _CONTAINERIZED
  5429. UNIMPLEMENTED_X("CONTAINERIZED(getDFUFileIGroup)"); // call to getClusterGroupName() is not available.
  5430. #else
  5431. GroupType groupType;
  5432. StringBuffer basedir;
  5433. getClusterGroupName(groupName, clusterName);
  5434. Owned<IGroup> groupFound = queryNamedGroupStore().lookup(groupName.str(), basedir, groupType);
  5435. if (!groupFound)
  5436. throw MakeStringException(ECLWATCH_INVALID_INPUT, "getDFUFileIGroup: Failed to get Group for Group %s.", groupName.str());
  5437. if (!locations.ordinality())
  5438. return groupFound.getClear();
  5439. StringBuffer locationStr;
  5440. SocketEndpointArray epa;
  5441. ForEachItemIn(i, locations)
  5442. {
  5443. SocketEndpoint ep(locations.item(i));
  5444. if (ep.isNull())
  5445. throw MakeStringException(ECLWATCH_INVALID_INPUT, "getDFUFileIGroup: Invalid location '%s'.", locations.item(i));
  5446. epa.append(ep);
  5447. locationStr.append(locations.item(i)).append(";");
  5448. }
  5449. Owned<IGroup> group = createIGroup(epa);
  5450. if (group->equals(groupFound))
  5451. return group.getClear();
  5452. groupName.set(DFUFileCreate_GroupNamePrefix).append(hashc((unsigned char*) locationStr.str(), locationStr.length(), 0));
  5453. bool foundGroup = false;
  5454. unsigned groupNameLength = groupName.length();
  5455. while (true)
  5456. {
  5457. GroupType groupType;
  5458. StringBuffer basedir;
  5459. Owned<IGroup> groupFound = queryNamedGroupStore().lookup(groupName.str(), basedir, groupType);
  5460. if (!groupFound)
  5461. break;
  5462. if (group->equals(groupFound))
  5463. {
  5464. foundGroup = true;
  5465. ESPLOG(LogMax, "Found DFUFileIGroup %s", groupName.str());
  5466. break;
  5467. }
  5468. //The original group name is used by another group. Rename it to: 'original name + _ + a random number'.
  5469. //We have to check if the new name is also used by another group. If yes, rename it to:
  5470. //'the original name + _ + another random number' until we find out a name which is not used.
  5471. groupName.setLength(groupNameLength); //remove _rand if any
  5472. groupName.append("_").append(rand());
  5473. }
  5474. if (!foundGroup)
  5475. {
  5476. StringBuffer defaultDir;
  5477. if (!getConfigurationDirectory(nullptr, ConfigurationDirectoryForDataCategory, clusterTypeEx, groupName.str(), defaultDir))
  5478. throw MakeStringException(ECLWATCH_INVALID_INPUT, "getDFUFileIGroup: Failed to get ConfigurationDirectory: %s.", groupName.str());
  5479. GroupType grpType = (clusterType == ThorLCRCluster) ? grp_thor : ((clusterType == HThorCluster) ? grp_hthor : grp_roxie);
  5480. std::vector<std::string> hosts;
  5481. ForEachItemIn(l, locations)
  5482. hosts.push_back(locations.item(l));
  5483. queryNamedGroupStore().add(groupName, hosts, false, defaultDir, grpType);
  5484. ESPLOG(LogMin, "DFUFileIGroup %s added", groupName.str());
  5485. }
  5486. return group.getClear();
  5487. #endif
  5488. }
  5489. void CWsDfuEx::exportRecordDefinitionBinaryType(const char *recordDefinition, MemoryBuffer &layoutBin)
  5490. {
  5491. MultiErrorReceiver errs;
  5492. Owned<IHqlExpression> expr = parseQuery(recordDefinition, &errs);
  5493. if (errs.errCount() > 0)
  5494. {
  5495. StringBuffer errorMsg;
  5496. throw MakeStringException(ECLWATCH_INVALID_INPUT, "exportRecordDefinitionBinaryType: Failed in parsing ECL %s: %s.", recordDefinition, errs.toString(errorMsg).str());
  5497. }
  5498. if (!expr)
  5499. throw MakeStringException(ECLWATCH_INVALID_INPUT, "exportRecordDefinitionBinaryType: Failed in parsing ECL: %s.", recordDefinition);
  5500. if (!exportBinaryType(layoutBin, expr, false))
  5501. throw MakeStringException(ECLWATCH_INVALID_INPUT, "exportRecordDefinitionBinaryType: Failed in exportBinaryType.");
  5502. }
  5503. // NB: deprecated from ver >= 1.50
  5504. bool CWsDfuEx::onDFUFileCreate(IEspContext &context, IEspDFUFileCreateRequest &req, IEspDFUFileCreateResponse &resp)
  5505. {
  5506. try
  5507. {
  5508. #ifdef _CONTAINERIZED
  5509. UNIMPLEMENTED_X("CONTAINERIZED(CWsDfuEx::onDFUFileCreate)");
  5510. #else
  5511. IConstDFUFileAccessRequestBase &requestBase = req.getRequestBase();
  5512. const char *fileName = requestBase.getName();
  5513. const char *clusterName = requestBase.getCluster();
  5514. const char *recordDefinition = req.getECLRecordDefinition();
  5515. StringBuffer requestId(requestBase.getJobId());
  5516. unsigned expirySecs = requestBase.getExpirySeconds();
  5517. bool returnTextResponse = true;
  5518. if (isEmptyString(fileName))
  5519. throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "DFUFileCreate: No Name defined.");
  5520. if (isEmptyString(clusterName))
  5521. throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "DFUFileCreate: No Cluster defined.");
  5522. if (isEmptyString(recordDefinition))
  5523. throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "DFUFileCreate: No ECLRecordDefinition defined.");
  5524. StringBuffer userId;
  5525. context.getUserID(userId);
  5526. Owned<IUserDescriptor> userDesc;
  5527. if (!userId.isEmpty())
  5528. {
  5529. userDesc.setown(createUserDescriptor());
  5530. userDesc->set(userId.str(), context.queryPassword(), context.querySignature());
  5531. }
  5532. ClusterType clusterType = getClusterTypeByClusterName(clusterName);
  5533. if (clusterType == NoCluster)
  5534. throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "DFUFileCreate: Cluster %s not found.", clusterName);
  5535. CDfsLogicalFileName lfn;
  5536. lfn.set(fileName);
  5537. StringBuffer normalizedFileName(lfn.get());
  5538. checkLogicalName(normalizedFileName, userDesc, false, true, false, nullptr);
  5539. const char *clusterTypeEx = clusterTypeString(clusterType, false);
  5540. StringBuffer groupName;
  5541. Owned<IGroup> group = getDFUFileIGroup(clusterName, clusterType, clusterTypeEx, req.getPartLocations(), groupName);
  5542. StringBuffer tempFileName(normalizedFileName);
  5543. tempFileName.append(DFUFileCreate_FileNamePostfix);
  5544. //create FileId
  5545. StringBuffer fileId;
  5546. fileId.set(groupName.str()).append(DFUFileIdSeparator).append(clusterName).append(DFUFileIdSeparator).append(tempFileName.str());
  5547. resp.setFileId(fileId.str());
  5548. if (requestId.isEmpty())
  5549. requestId.appendf("Create %s on %s", normalizedFileName.str(), clusterName);
  5550. Owned<IFileDescriptor> fileDesc = createFileDescriptor(tempFileName, clusterTypeString(clusterType, false), groupName, group);
  5551. fileDesc->queryProperties().setProp("@job", requestId);
  5552. if (!userId.isEmpty())
  5553. fileDesc->queryProperties().setProp("@owner", userId);
  5554. MemoryBuffer layoutBin;
  5555. exportRecordDefinitionBinaryType(recordDefinition, layoutBin);
  5556. if (0 == layoutBin.length())
  5557. throw makeStringExceptionV(ECLWATCH_INVALID_ECLRECDEF, "DFUFileCreate: Failed to parse ECL record definition: %s.", recordDefinition);
  5558. fileDesc->queryProperties().setPropBin("_rtlType", layoutBin.length(), layoutBin.toByteArray());
  5559. fileDesc->queryProperties().setProp("ECL", recordDefinition);
  5560. // NB: if file has copies on >1 cluster, they must share the same key
  5561. StringBuffer keyPairName;
  5562. unsigned port;
  5563. bool secure;
  5564. std::vector<std::string> groups;
  5565. groups.push_back(groupName.str());
  5566. getFileDafilesrvConfiguration(keyPairName, port, secure, normalizedFileName, groups);
  5567. Owned<IPropertyTree> metaInfo = createDFUFileMetaInfo(tempFileName, fileDesc, requestId, "WRITE", expirySecs, userDesc, keyPairName, port, secure, maxFileAccessExpirySeconds);
  5568. metaInfo->setProp("clusterName", clusterName);
  5569. StringBuffer metaInfoBlob;
  5570. encodeDFUFileMeta(metaInfoBlob, metaInfo, env);
  5571. IEspDFUFileAccessInfo &accessInfo = resp.updateAccessInfo();
  5572. accessInfo.setMetaInfoBlob(metaInfoBlob);
  5573. getFilePartsInfo(context, *fileDesc, true, accessInfo);
  5574. getJsonTypeInfo(*fileDesc, accessInfo);
  5575. accessInfo.setExpiryTime(metaInfo->queryProp("expiryTime"));
  5576. accessInfo.setFileAccessPort(metaInfo->getPropInt("port"));
  5577. accessInfo.setFileAccessSSL(metaInfo->getPropBool("secure"));
  5578. #endif
  5579. }
  5580. catch (IException *e)
  5581. {
  5582. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  5583. }
  5584. return true;
  5585. }
  5586. bool CWsDfuEx::onDFUFileCreateV2(IEspContext &context, IEspDFUFileCreateV2Request &req, IEspDFUFileCreateResponse &resp)
  5587. {
  5588. try
  5589. {
  5590. #ifdef _CONTAINERIZED
  5591. UNIMPLEMENTED_X("CONTAINERIZED(CWsDfuEx::onDFUFileCreateV2)");
  5592. #else
  5593. const char *fileName = req.getName();
  5594. const char *clusterName = req.getCluster();
  5595. const char *recordDefinition = req.getECLRecordDefinition();
  5596. unsigned expirySecs = req.getExpirySeconds();
  5597. StringBuffer requestId(req.getRequestId());
  5598. bool returnTextResponse = req.getReturnTextResponse();
  5599. if (isEmptyString(fileName))
  5600. throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "DFUFileCreateV2: No Name defined.");
  5601. if (isEmptyString(clusterName))
  5602. throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "DFUFileCreateV2: No Cluster defined.");
  5603. if (isEmptyString(recordDefinition))
  5604. throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "DFUFileCreateV2: No ECLRecordDefinition defined.");
  5605. StringBuffer userId;
  5606. context.getUserID(userId);
  5607. Owned<IUserDescriptor> userDesc;
  5608. if (!userId.isEmpty())
  5609. {
  5610. userDesc.setown(createUserDescriptor());
  5611. userDesc->set(userId.str(), context.queryPassword(), context.querySignature());
  5612. }
  5613. ClusterType clusterType = getClusterTypeByClusterName(clusterName);
  5614. if (clusterType == NoCluster)
  5615. throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "DFUFileCreateV2: Cluster %s not found.", clusterName);
  5616. StringBuffer groupName;
  5617. getClusterGroupName(groupName, clusterName);
  5618. if (isEmptyString(groupName))
  5619. throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "DFUFileCreateV2: Group for cluster %s not found.", clusterName);
  5620. Owned<IGroup> group = queryNamedGroupStore().lookup(groupName.str());
  5621. if (!group)
  5622. throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "DFUFileCreateV2: Failed to get Group %s.", groupName.str());
  5623. CDfsLogicalFileName lfn;
  5624. lfn.set(fileName);
  5625. StringBuffer normalizedFileName(lfn.get());
  5626. checkLogicalName(normalizedFileName, userDesc, false, true, false, nullptr);
  5627. StringBuffer tempFileName(normalizedFileName);
  5628. tempFileName.append(".").append(dfuCreateUniqId++); // avoid potential clash if >1 creating file. One will succeed at publish time.
  5629. tempFileName.append(DFUFileCreate_FileNamePostfix);
  5630. if (requestId.isEmpty())
  5631. requestId.appendf("Create %s on %s", normalizedFileName.str(), clusterName);
  5632. Owned<IFileDescriptor> fileDesc = createFileDescriptor(tempFileName, clusterTypeString(clusterType, false), groupName, group);
  5633. fileDesc->queryProperties().setProp("@job", requestId);
  5634. if (!userId.isEmpty())
  5635. fileDesc->queryProperties().setProp("@owner", userId);
  5636. fileDesc->queryProperties().setProp("ECL", recordDefinition);
  5637. const char *fileType = nullptr;
  5638. CDFUFileType kind = req.getType();
  5639. switch (kind)
  5640. {
  5641. case CDFUFileType_Flat:
  5642. fileType = "flat";
  5643. break;
  5644. case CDFUFileType_Csv:
  5645. fileType = "csv";
  5646. break;
  5647. case CDFUFileType_Xml:
  5648. fileType = "xml";
  5649. break;
  5650. case CDFUFileType_Json:
  5651. fileType = "json";
  5652. break;
  5653. case CDFUFileType_Index:
  5654. fileType = "key";
  5655. default:
  5656. throw makeStringExceptionV(ECLWATCH_MISSING_FILETYPE, "DFUFileCreateV2: File type not provided");
  5657. }
  5658. fileDesc->queryProperties().setProp("@kind", fileType);
  5659. //create FileId
  5660. StringBuffer fileId;
  5661. fileId.set(groupName).append(DFUFileIdSeparator).append(clusterName).append(DFUFileIdSeparator).append(tempFileName);
  5662. fileId.append(DFUFileIdSeparator).append(boolToStr(req.getCompressed()));
  5663. fileId.append(DFUFileIdSeparator).append(fileType);
  5664. resp.setFileId(fileId.str());
  5665. MemoryBuffer layoutBin;
  5666. exportRecordDefinitionBinaryType(recordDefinition, layoutBin);
  5667. if (0 == layoutBin.length())
  5668. throw makeStringExceptionV(ECLWATCH_INVALID_ECLRECDEF, "DFUFileCreateV2: Failed to parse ECL record definition: %s.", recordDefinition);
  5669. fileDesc->queryProperties().setPropBin("_rtlType", layoutBin.length(), layoutBin.toByteArray());
  5670. if (req.getCompressed())
  5671. fileDesc->queryProperties().setPropBool("@blockCompressed", true);
  5672. // NB: if file has copies on >1 cluster, they must share the same key
  5673. StringBuffer keyPairName;
  5674. unsigned port;
  5675. bool secure;
  5676. std::vector<std::string> groups;
  5677. groups.push_back(groupName.str());
  5678. getFileDafilesrvConfiguration(keyPairName, port, secure, normalizedFileName, groups);
  5679. Owned<IPropertyTree> metaInfo = createDFUFileMetaInfo(tempFileName, fileDesc, requestId, "WRITE", expirySecs, userDesc, keyPairName, port, secure, maxFileAccessExpirySeconds);
  5680. metaInfo->setProp("clusterName", clusterName);
  5681. StringBuffer metaInfoBlob;
  5682. encodeDFUFileMeta(metaInfoBlob, metaInfo, env);
  5683. IEspDFUFileAccessInfo &accessInfo = resp.updateAccessInfo();
  5684. accessInfo.setMetaInfoBlob(metaInfoBlob);
  5685. if (returnTextResponse)
  5686. {
  5687. getFilePartsInfo(context, *fileDesc, true, accessInfo);
  5688. getJsonTypeInfo(*fileDesc, accessInfo);
  5689. accessInfo.setExpiryTime(metaInfo->queryProp("expiryTime"));
  5690. accessInfo.setFileAccessPort(metaInfo->getPropInt("port"));
  5691. accessInfo.setFileAccessSSL(metaInfo->getPropBool("secure"));
  5692. }
  5693. #endif
  5694. }
  5695. catch (IException *e)
  5696. {
  5697. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  5698. }
  5699. return true;
  5700. }
  5701. bool CWsDfuEx::onDFUFilePublish(IEspContext &context, IEspDFUFilePublishRequest &req, IEspDFUFilePublishResponse &resp)
  5702. {
  5703. Owned<IException> exception;
  5704. Owned<IDistributedFile> newFile;
  5705. Owned<IFileDescriptor> fileDesc;
  5706. StringBuffer normalizeTempFileName;
  5707. try
  5708. {
  5709. const char *fileId = req.getFileId();
  5710. if (isEmptyString(fileId))
  5711. throw makeStringException(ECLWATCH_INVALID_INPUT, "DFUFilePublish: No FileId defined.");
  5712. const char *recordDefinition = req.getECLRecordDefinition();
  5713. StringArray fileIdItems;
  5714. fileIdItems.appendList(fileId, DFUFileIdSeparator);
  5715. const char *groupName = fileIdItems.item(0);
  5716. const char *clusterName = fileIdItems.item(1);
  5717. const char *tempFileName = fileIdItems.item(2);
  5718. if (isEmptyString(groupName))
  5719. throw makeStringException(ECLWATCH_INVALID_INPUT, "DFUFilePublish: Invalid FileId: empty groupName.");
  5720. if (isEmptyString(clusterName))
  5721. throw makeStringException(ECLWATCH_INVALID_INPUT, "DFUFilePublish: Invalid FileId: empty clusterName.");
  5722. if (isEmptyString(tempFileName))
  5723. throw makeStringException(ECLWATCH_INVALID_INPUT, "DFUFilePublish: Invalid FileId: empty FileName.");
  5724. CDfsLogicalFileName lfn;
  5725. lfn.set(tempFileName);
  5726. normalizeTempFileName.set(lfn.get());
  5727. size32_t postFixLen = strlen(DFUFileCreate_FileNamePostfix);
  5728. if (normalizeTempFileName.length() <= postFixLen)
  5729. throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "DFUFilePublish: Invalid temporary filename: %s.", fileId);
  5730. const MemoryBuffer &fDescBlob = req.getFileDescriptorBlob();
  5731. if (fDescBlob.length())
  5732. {
  5733. MemoryBuffer mb;
  5734. mb.setBuffer(fDescBlob.length(), (void *)fDescBlob.toByteArray());
  5735. fileDesc.setown(deserializeFileDescriptor(mb));
  5736. }
  5737. else
  5738. {
  5739. if (isEmptyString(recordDefinition))
  5740. throw makeStringException(ECLWATCH_INVALID_INPUT, "DFUFilePublish: No ECLRecordDefinition defined.");
  5741. #ifdef _CONTAINERIZED
  5742. IERRLOG("CONTAINERIZED(CWsDfuEx::onDFUFilePublish)");
  5743. ClusterType clusterType = NoCluster;
  5744. #else
  5745. ClusterType clusterType = getClusterTypeByClusterName(clusterName);
  5746. #endif
  5747. const char *clusterTypeEx = clusterTypeString(clusterType, false);
  5748. GroupType groupType;
  5749. StringBuffer basedir;
  5750. Owned<IGroup> group = queryNamedGroupStore().lookup(groupName, basedir, groupType);
  5751. if (!group)
  5752. throw makeStringExceptionV(ECLWATCH_FILE_NOT_EXIST, "DFUFilePublish: Failed to find group %s.", groupName);
  5753. fileDesc.setown(createFileDescriptor(normalizeTempFileName, clusterTypeEx, groupName, group));
  5754. if (fileIdItems.ordinality()>3) // compressed
  5755. {
  5756. bool compressed = strToBool(fileIdItems.item(3));
  5757. if (compressed)
  5758. fileDesc->queryProperties().setPropBool("@blockCompressed", true);
  5759. if (fileIdItems.ordinality()>4) // fileType
  5760. fileDesc->queryProperties().setProp("@kind", fileIdItems.item(4));
  5761. }
  5762. }
  5763. StringBuffer newFileName(normalizeTempFileName);
  5764. const char *start = newFileName;
  5765. const char *pos = start + (newFileName.length() - postFixLen);
  5766. const char *startPos = pos;
  5767. if (!streq(pos, DFUFileCreate_FileNamePostfix))
  5768. throw makeStringExceptionV(ECLWATCH_INVALID_INPUT, "DFUFilePublish: Invalid temporary filename: %s.", fileId);
  5769. while (true)
  5770. {
  5771. --pos;
  5772. if (pos == start)
  5773. {
  5774. // old style ( <= 1.39 ), without unique id
  5775. newFileName.setLength(startPos-start);
  5776. break;
  5777. }
  5778. else if ('.' == *pos)
  5779. {
  5780. newFileName.setLength(pos-start);
  5781. break;
  5782. }
  5783. }
  5784. newFileName.setLength(pos-start);
  5785. if (!isEmptyString(recordDefinition))
  5786. {
  5787. MemoryBuffer layoutBin;
  5788. exportRecordDefinitionBinaryType(recordDefinition, layoutBin);
  5789. fileDesc->queryProperties().setPropBin("_rtlType", layoutBin.length(), layoutBin.toByteArray());
  5790. fileDesc->queryProperties().setProp("ECL", recordDefinition);
  5791. }
  5792. if (!req.getRecordCount_isNull())
  5793. fileDesc->queryProperties().setPropInt64("@recordCount", req.getRecordCount());
  5794. if (!req.getFileSize_isNull())
  5795. fileDesc->queryProperties().setPropInt64("@size", req.getFileSize());
  5796. StringBuffer userId;
  5797. Owned<IUserDescriptor> userDesc;
  5798. context.getUserID(userId);
  5799. if (!userId.isEmpty())
  5800. {
  5801. userDesc.setown(createUserDescriptor());
  5802. userDesc->set(userId.str(), context.queryPassword(), context.querySignature());
  5803. fileDesc->queryProperties().setProp("@owner", userId);
  5804. }
  5805. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(newFileName, userDesc, false, false, true, nullptr, defaultPrivilegedUser, req.getLockTimeoutMs());
  5806. if (df)
  5807. {
  5808. if (!req.getOverwrite())
  5809. throw makeStringExceptionV(ECLWATCH_FILE_ALREADY_EXISTS, "DFUFilePublish: File already exists (%s) and overwrite not specified.", newFileName.str());
  5810. df->detach(req.getLockTimeoutMs());
  5811. }
  5812. setPublishFileSize(newFileName, fileDesc);
  5813. newFile.setown(queryDistributedFileDirectory().createNew(fileDesc));
  5814. newFile->validate();
  5815. newFile->setAccessed();
  5816. // JCSMORE attach() should have a timeout, then req.getLockTimeoutMs() should be used here.
  5817. newFile->attach(normalizeTempFileName, userDesc);
  5818. if (!newFile->renamePhysicalPartFiles(newFileName, nullptr, nullptr, fileDesc->queryDefaultDir()))
  5819. throw makeStringExceptionV(ECLWATCH_FILE_NOT_EXIST, "DFUFilePublish: Failed in renamePhysicalPartFiles %s.", newFileName.str());
  5820. newFile->rename(newFileName, userDesc);
  5821. LOG(MCauditInfo,",FileAccess,EspProcess,CREATED,%s,%s,%s", groupName, userId.str(), newFileName.str());
  5822. }
  5823. catch (IException *e)
  5824. {
  5825. exception.setown(e);
  5826. }
  5827. if (exception)
  5828. {
  5829. if (fileDesc)
  5830. {
  5831. Owned<IMultiException> exceptions = MakeMultiException("CWsDfuEx::onDFUFilePublish");
  5832. queryDistributedFileDirectory().removePhysicalPartFiles(normalizeTempFileName, fileDesc, exceptions);
  5833. if (exceptions->ordinality())
  5834. {
  5835. StringBuffer errMsg("Error whilst clearing up temporary file: ");
  5836. EXCLOG(exceptions, errMsg.append(normalizeTempFileName).str());
  5837. }
  5838. }
  5839. if (newFile)
  5840. newFile->detach(30000);
  5841. FORWARDEXCEPTION(context, exception.getClear(), ECLWATCH_INTERNAL_ERROR);
  5842. }
  5843. return true;
  5844. }
  5845. void CWsDfuEx::setPublishFileSize(const char *lfn, IFileDescriptor *fileDesc)
  5846. {
  5847. auto funcFilePartSize = [lfn, fileDesc](unsigned partNum)
  5848. {
  5849. bool compressed = fileDesc->isCompressed();
  5850. IPartDescriptor *partDesc = fileDesc->queryPart(partNum);
  5851. IPropertyTree &props = partDesc->queryProperties();
  5852. unsigned numCopies = partDesc->numCopies();
  5853. for (unsigned c = 0; c < numCopies; c++)
  5854. {
  5855. RemoteFilename rfn;
  5856. partDesc->getFilename(c, rfn);
  5857. try
  5858. {
  5859. Owned<IFile> file = createIFile(rfn);
  5860. if (compressed)
  5861. {
  5862. props.setPropInt64("@compressedSize", file->size());
  5863. Owned<IFileIO> io = createCompressedFileReader(file);
  5864. if (io)
  5865. props.setPropInt64("@size", io->size());
  5866. }
  5867. else
  5868. {
  5869. props.setPropInt64("@size", file->size());
  5870. }
  5871. break;
  5872. }
  5873. catch (IException *e)
  5874. {
  5875. VStringBuffer tmp("%s: ", lfn);
  5876. rfn.getPath(tmp);
  5877. EXCLOG(e, tmp.str());
  5878. e->Release();
  5879. }
  5880. }
  5881. };
  5882. //collect and set the sizes for file parts
  5883. CAsyncForFunc<decltype(funcFilePartSize)> async(funcFilePartSize);
  5884. async.For(fileDesc->numParts(), 100);
  5885. }
  5886. //////////////////////HPCC Browser//////////////////////////