hthor.cpp 309 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #include <algorithm>
  14. #include "hthor.ipp"
  15. #include "jexcept.hpp"
  16. #include "jmisc.hpp"
  17. #include "jthread.hpp"
  18. #include "jsocket.hpp"
  19. #include "jprop.hpp"
  20. #include "jdebug.hpp"
  21. #include "jlzw.hpp"
  22. #include "jisem.hpp"
  23. #include "roxiedebug.hpp"
  24. #include "roxierow.hpp"
  25. #include "roxiemem.hpp"
  26. #include "eclhelper.hpp"
  27. #include "workunit.hpp"
  28. #include "jfile.hpp"
  29. #include "keybuild.hpp"
  30. #include "hrpc.hpp"
  31. #include "hrpcsock.hpp"
  32. #include "dafdesc.hpp"
  33. #include "dautils.hpp"
  34. #include "dasess.hpp"
  35. #include "dadfs.hpp"
  36. #include "thorfile.hpp"
  37. #include "thorparse.ipp"
  38. #include "thorxmlwrite.hpp"
  39. #include "jsmartsock.hpp"
  40. #include "thorstep.hpp"
  41. #include "eclagent.ipp"
  42. #include "roxierowbuff.hpp"
  43. #include "ftbase.ipp"
  44. #define EMPTY_LOOP_LIMIT 1000
  45. static unsigned const hthorReadBufferSize = 0x10000;
  46. static offset_t const defaultHThorDiskWriteSizeLimit = I64C(10*1024*1024*1024); //10 GB, per Nigel
  47. static size32_t const spillStreamBufferSize = 0x10000;
  48. static unsigned const hthorPipeWaitTimeout = 100; //100ms - fairly arbitrary choice
  49. using roxiemem::IRowManager;
  50. using roxiemem::OwnedRoxieRow;
  51. using roxiemem::OwnedRoxieString;
  52. using roxiemem::OwnedConstRoxieRow;
  53. IRowManager * theRowManager;
  54. void setHThorRowManager(IRowManager * manager)
  55. {
  56. theRowManager = manager;
  57. }
  58. IRowManager * queryRowManager()
  59. {
  60. return theRowManager;
  61. }
  62. void throwOOMException(size_t size, char const * label)
  63. {
  64. throw MakeStringException(0, "Out of Memory in hthor: trying to allocate %" I64F "u bytes for %s", (unsigned __int64) size, label);
  65. }
  66. void * checked_malloc(size_t size, char const * label)
  67. {
  68. void * ret = malloc(size);
  69. if(!ret)
  70. throwOOMException(size, label);
  71. return ret;
  72. }
  73. void * checked_calloc(size_t size, size_t num, char const * label)
  74. {
  75. void * ret = calloc(size, num);
  76. if(!ret)
  77. throwOOMException(size*num, label);
  78. return ret;
  79. }
  80. inline bool checkIsCompressed(unsigned int flags, size32_t fixedSize, bool grouped)
  81. {
  82. return ((flags & TDWnewcompress) || ((flags & TDXcompress) && (fixedSize+(grouped?1:0) >= MIN_ROWCOMPRESS_RECSIZE)));
  83. }
  84. //=====================================================================================================
  85. //=====================================================================================================
  86. CRowBuffer::CRowBuffer(IRecordSize * _recsize, bool _grouped) : recsize(_recsize), grouped(_grouped)
  87. {
  88. fixsize = recsize->getFixedSize();
  89. count = 0;
  90. index = 0;
  91. }
  92. void CRowBuffer::insert(const void * next)
  93. {
  94. buff.append(next);
  95. count++;
  96. }
  97. bool CRowBuffer::pull(IHThorInput * input, unsigned __int64 rowLimit)
  98. {
  99. while(true)
  100. {
  101. OwnedConstRoxieRow next(input->nextInGroup());
  102. if(!next)
  103. {
  104. next.setown(input->nextInGroup());
  105. if(!next)
  106. break;
  107. if(grouped)
  108. buff.append(NULL);
  109. }
  110. insert(next.getClear());
  111. if(count > rowLimit)
  112. return false;
  113. }
  114. return true;
  115. }
  116. void CRowBuffer::clear()
  117. {
  118. buff.clear();
  119. index = 0;
  120. count = 0;
  121. }
  122. const void * CRowBuffer::next()
  123. {
  124. if(buff.isItem(index))
  125. return buff.itemClear(index++);
  126. else
  127. return NULL;
  128. }
  129. //=====================================================================================================
  130. CHThorActivityBase::CHThorActivityBase(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorArg & _help, ThorActivityKind _kind) : agent(_agent), help(_help), outputMeta(help.queryOutputMeta()), kind(_kind), activityId(_activityId), subgraphId(_subgraphId)
  131. {
  132. input = NULL;
  133. processed = 0;
  134. rowAllocator = NULL;
  135. }
  136. void CHThorActivityBase::setInput(unsigned index, IHThorInput *_input)
  137. {
  138. assertex(index == 0);
  139. input = _input;
  140. }
  141. IHThorInput *CHThorActivityBase::queryOutput(unsigned index)
  142. {
  143. agent.fail(255, "internal logic error: CHThorActivityBase::queryOutput");
  144. // never returns....
  145. return NULL;
  146. }
  147. void CHThorActivityBase::ready()
  148. {
  149. if (input)
  150. input->ready();
  151. if (needsAllocator())
  152. createRowAllocator();
  153. initialProcessed = processed;
  154. }
  155. CHThorActivityBase::~CHThorActivityBase()
  156. {
  157. ::Release(rowAllocator);
  158. }
  159. void CHThorActivityBase::createRowAllocator()
  160. {
  161. if (!rowAllocator)
  162. rowAllocator = agent.queryCodeContext()->getRowAllocator(outputMeta.queryOriginal(), activityId);
  163. }
  164. __int64 CHThorActivityBase::getCount()
  165. {
  166. throw MakeStringException(2, "Internal error: CHThorActivityBase::getCount");
  167. return 0;
  168. }
  169. void CHThorActivityBase::execute()
  170. {
  171. agent.fail(255, "internal logic error: CHThorActivityBase::execute");
  172. }
  173. void CHThorActivityBase::extractResult(unsigned & len, void * & ret)
  174. {
  175. agent.fail(255, "internal logic error: CHThorActivityBase::extractResult");
  176. }
  177. void CHThorActivityBase::done()
  178. {
  179. if (input)
  180. input->done();
  181. }
  182. void CHThorActivityBase::updateProgress(IStatisticGatherer &progress) const
  183. {
  184. updateProgressForOther(progress, activityId, subgraphId);
  185. if (input)
  186. input->updateProgress(progress);
  187. }
  188. void CHThorActivityBase::updateProgressForOther(IStatisticGatherer &progress, unsigned otherActivity, unsigned otherSubgraph) const
  189. {
  190. updateProgressForOther(progress, otherActivity, otherSubgraph, 0, processed);
  191. }
  192. void CHThorActivityBase::updateProgressForOther(IStatisticGatherer &progress, unsigned otherActivity, unsigned otherSubgraph, unsigned whichOutput, unsigned __int64 numProcessed) const
  193. {
  194. StatsEdgeScope scope(progress, otherActivity, whichOutput);
  195. progress.addStatistic(StNumRowsProcessed, numProcessed);
  196. progress.addStatistic(StNumStarted, 1); // wrong for an activity in a subquery
  197. progress.addStatistic(StNumStopped, 1);
  198. progress.addStatistic(StNumSlaves, 1); // MORE: A bit pointless for an hthor graph
  199. }
  200. ILocalEclGraphResults * CHThorActivityBase::resolveLocalQuery(__int64 graphId)
  201. {
  202. return static_cast<ILocalEclGraphResults *>(agent.queryCodeContext()->resolveLocalQuery(graphId));
  203. }
  204. IException * CHThorActivityBase::makeWrappedException(IException * e) const
  205. {
  206. if(dynamic_cast<IHThorException *>(e) || dynamic_cast<IUserException *>(e))
  207. return e;
  208. else
  209. return makeHThorException(kind, activityId, subgraphId, e);
  210. }
  211. IException * CHThorActivityBase::makeWrappedException(IException * e, char const * extra) const
  212. {
  213. if(dynamic_cast<IHThorException *>(e) || dynamic_cast<IUserException *>(e))
  214. return e;
  215. else
  216. return makeHThorException(kind, activityId, subgraphId, e, extra);
  217. }
  218. bool CHThorActivityBase::isPassThrough()
  219. {
  220. return false;
  221. }
  222. //=====================================================================================================
  223. CHThorSimpleActivityBase::CHThorSimpleActivityBase(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorArg & _help, ThorActivityKind _kind) : CHThorActivityBase(_agent, _activityId, _subgraphId, _help, _kind)
  224. {
  225. }
  226. IHThorInput * CHThorSimpleActivityBase::queryOutput(unsigned index)
  227. {
  228. assertex(index == 0);
  229. return this;
  230. }
  231. bool CHThorSimpleActivityBase::isGrouped()
  232. {
  233. return input ? input->isGrouped() : outputMeta.isGrouped();
  234. }
  235. IOutputMetaData * CHThorSimpleActivityBase::queryOutputMeta() const
  236. {
  237. return outputMeta;
  238. }
  239. //=====================================================================================================
  240. class CHThorClusterWriteHandler : public ClusterWriteHandler
  241. {
  242. IAgentContext &agent;
  243. public:
  244. CHThorClusterWriteHandler(char const * _logicalName, char const * _activityType, IAgentContext &_agent)
  245. : agent(_agent), ClusterWriteHandler(_logicalName, _activityType)
  246. {
  247. }
  248. private:
  249. virtual void getTempFilename(StringAttr & out) const
  250. {
  251. StringBuffer buff;
  252. agent.getTempfileBase(buff).appendf(".cluster_write_%p.%" I64F "d_%u", this, (__int64)GetCurrentThreadId(), GetCurrentProcessId());
  253. out.set(buff.str());
  254. }
  255. };
  256. ClusterWriteHandler *createClusterWriteHandler(IAgentContext &agent, IHThorIndexWriteArg *iwHelper, IHThorDiskWriteArg *dwHelper, const char * lfn, StringAttr &fn, bool extend)
  257. {
  258. Owned<CHThorClusterWriteHandler> clusterHandler;
  259. unsigned clusterIdx = 0;
  260. while(true)
  261. {
  262. OwnedRoxieString cluster(iwHelper ? iwHelper->getCluster(clusterIdx++) : dwHelper->getCluster(clusterIdx++));
  263. if(!cluster)
  264. break;
  265. if(!clusterHandler)
  266. {
  267. if(extend)
  268. throw MakeStringException(0, "Cannot combine EXTEND and CLUSTER flags on disk write of file %s", lfn);
  269. clusterHandler.setown(new CHThorClusterWriteHandler(lfn, "OUTPUT", agent));
  270. }
  271. clusterHandler->addCluster(cluster);
  272. }
  273. if(clusterHandler)
  274. {
  275. clusterHandler->getLocalPhysicalFilename(fn);
  276. }
  277. else if (!agent.queryResolveFilesLocally())
  278. {
  279. StringBuffer filenameText;
  280. bool wasDFS;
  281. makeSinglePhysicalPartName(lfn, filenameText, true, wasDFS);
  282. fn.set(filenameText.str());
  283. }
  284. else
  285. {
  286. fn.set(lfn);
  287. }
  288. StringBuffer dir;
  289. splitFilename(fn, &dir, &dir, NULL, NULL);
  290. recursiveCreateDirectory(dir.str());
  291. return clusterHandler.getClear();
  292. }
  293. //=====================================================================================================
  294. CHThorDiskWriteActivity::CHThorDiskWriteActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorDiskWriteArg &_arg, ThorActivityKind _kind) : CHThorActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  295. {
  296. incomplete = false;
  297. }
  298. CHThorDiskWriteActivity::~CHThorDiskWriteActivity()
  299. {
  300. diskout.clear();
  301. if(incomplete)
  302. {
  303. PROGLOG("Disk write incomplete, deleting physical file: %s", filename.get());
  304. diskout.clear();
  305. outSeq.clear();
  306. file->remove();
  307. }
  308. }
  309. void CHThorDiskWriteActivity::ready()
  310. {
  311. CHThorActivityBase::ready();
  312. grouped = (helper.getFlags() & TDXgrouped) != 0;
  313. extend = ((helper.getFlags() & TDWextend) != 0);
  314. overwrite = ((helper.getFlags() & TDWoverwrite) != 0);
  315. resolve();
  316. uncompressedBytesWritten = 0;
  317. numRecords = 0;
  318. sizeLimit = agent.queryWorkUnit()->getDebugValueInt64("hthorDiskWriteSizeLimit", defaultHThorDiskWriteSizeLimit);
  319. rowIf.setown(createRowInterfaces(input->queryOutputMeta(), activityId, agent.queryCodeContext()));
  320. open();
  321. }
  322. void CHThorDiskWriteActivity::execute()
  323. {
  324. // Loop thru the results
  325. numRecords = 0;
  326. while (next())
  327. numRecords++;
  328. finishOutput();
  329. }
  330. void CHThorDiskWriteActivity::done()
  331. {
  332. outSeq->flush();
  333. if(blockcompressed)
  334. uncompressedBytesWritten = outSeq->getPosition();
  335. updateWorkUnitResult(numRecords);
  336. close();
  337. if((helper.getFlags() & (TDXtemporary | TDXjobtemp) ) == 0 && !agent.queryResolveFilesLocally())
  338. publish();
  339. incomplete = false;
  340. if(clusterHandler)
  341. clusterHandler->finish(file);
  342. CHThorActivityBase::done();
  343. }
  344. void CHThorDiskWriteActivity::resolve()
  345. {
  346. OwnedRoxieString rawname = helper.getFileName();
  347. mangleHelperFileName(mangledHelperFileName, rawname, agent.queryWuid(), helper.getFlags());
  348. assertex(mangledHelperFileName.str());
  349. if((helper.getFlags() & (TDXtemporary | TDXjobtemp)) == 0)
  350. {
  351. Owned<ILocalOrDistributedFile> f = agent.resolveLFN(mangledHelperFileName.str(),"Cannot write, invalid logical name",true,false,true,&lfn);
  352. if (f)
  353. {
  354. if (f->queryDistributedFile())
  355. {
  356. // An already existing dali file
  357. if(extend)
  358. agent.logFileAccess(f->queryDistributedFile(), "HThor", "EXTENDED");
  359. else if(overwrite) {
  360. PrintLog("Removing %s from DFS", lfn.str());
  361. agent.logFileAccess(f->queryDistributedFile(), "HThor", "DELETED");
  362. if (!agent.queryResolveFilesLocally())
  363. f->queryDistributedFile()->detach();
  364. else
  365. {
  366. Owned<IFile> file = createIFile(lfn);
  367. if (file->exists())
  368. file->remove();
  369. }
  370. }
  371. else
  372. throw MakeStringException(99, "Cannot write %s, file already exists (missing OVERWRITE attribute?)", lfn.str());
  373. }
  374. else if (f->exists() || f->isExternal() || agent.queryResolveFilesLocally())
  375. {
  376. // special/local/external file
  377. if (f->numParts()!=1)
  378. throw MakeStringException(99, "Cannot write %s, external file has multiple parts)", lfn.str());
  379. RemoteFilename rfn;
  380. f->getPartFilename(rfn,0);
  381. StringBuffer full;
  382. if (rfn.isLocal())
  383. rfn.getLocalPath(full);
  384. else
  385. rfn.getRemotePath(full);
  386. filename.set(full);
  387. if (isSpecialPath(filename))
  388. {
  389. PROGLOG("Writing to query %s", filename.get());
  390. return;
  391. }
  392. if (stdIoHandle(filename)>=0) {
  393. PROGLOG("Writing to %s", filename.get());
  394. return;
  395. }
  396. Owned<IFile> file = createIFile(filename);
  397. if (file->exists())
  398. {
  399. if (!overwrite)
  400. throw MakeStringException(99, "Cannot write %s, file already exists (missing OVERWRITE attribute?)", full.str());
  401. file->remove();
  402. }
  403. //Ensure target folder exists
  404. if (!recursiveCreateDirectoryForFile(filename.get()))
  405. {
  406. throw MakeStringException(99, "Cannot create file folder for %s", filename.str());
  407. }
  408. PROGLOG("Writing to file %s", filename.get());
  409. }
  410. f.clear();
  411. }
  412. if (filename.isEmpty()) // wasn't local or special (i.e. DFS file)
  413. {
  414. CDfsLogicalFileName dfsLogicalName;
  415. dfsLogicalName.allowOsPath(agent.queryResolveFilesLocally());
  416. if (!dfsLogicalName.setValidate(lfn.str()))
  417. {
  418. throw MakeStringException(99, "Could not resolve DFS Logical file %s", lfn.str());
  419. }
  420. clusterHandler.setown(createClusterWriteHandler(agent, NULL, &helper, dfsLogicalName.get(), filename, extend));
  421. }
  422. }
  423. else
  424. {
  425. StringBuffer mangledName;
  426. mangleLocalTempFilename(mangledName, mangledHelperFileName.str());
  427. filename.set(agent.noteTemporaryFile(mangledName.str()));
  428. PROGLOG("DISKWRITE: using temporary filename %s", filename.get());
  429. }
  430. }
  431. void CHThorDiskWriteActivity::open()
  432. {
  433. // Open an output file...
  434. file.setown(createIFile(filename));
  435. serializedOutputMeta.set(input->queryOutputMeta()->querySerializedDiskMeta());//returns outputMeta if serialization not needed
  436. Linked<IRecordSize> groupedMeta = input->queryOutputMeta()->querySerializedDiskMeta();
  437. if(grouped)
  438. groupedMeta.setown(createDeltaRecordSize(groupedMeta, +1));
  439. blockcompressed = checkIsCompressed(helper.getFlags(), serializedOutputMeta.getFixedSize(), grouped);//TDWnewcompress for new compression, else check for row compression
  440. void *ekey;
  441. size32_t ekeylen;
  442. helper.getEncryptKey(ekeylen,ekey);
  443. encrypted = false;
  444. Owned<ICompressor> ecomp;
  445. if (ekeylen!=0) {
  446. ecomp.setown(createAESCompressor256(ekeylen,ekey));
  447. memset(ekey,0,ekeylen);
  448. rtlFree(ekey);
  449. encrypted = true;
  450. blockcompressed = true;
  451. }
  452. Owned<IFileIO> io;
  453. if(blockcompressed)
  454. io.setown(createCompressedFileWriter(file, groupedMeta->getFixedSize(), extend, true, ecomp));
  455. else
  456. io.setown(file->open(extend ? IFOwrite : IFOcreate));
  457. if(!io)
  458. throw MakeStringException(errno, "Failed to create%s file %s for writing", (encrypted ? " encrypted" : (blockcompressed ? " compressed" : "")), filename.get());
  459. incomplete = true;
  460. diskout.setown(createBufferedIOStream(io));
  461. if(extend)
  462. diskout->seek(0, IFSend);
  463. unsigned rwFlags = rw_autoflush;
  464. if(grouped)
  465. rwFlags |= rw_grouped;
  466. if(!agent.queryWorkUnit()->getDebugValueBool("skipFileFormatCrcCheck", false) && !(helper.getFlags() & TDRnocrccheck))
  467. rwFlags |= rw_crc;
  468. IExtRowWriter * writer = createRowWriter(diskout, rowIf, rwFlags);
  469. outSeq.setown(writer);
  470. }
  471. const void * CHThorDiskWriteActivity::getNext()
  472. { // through operation (writes and returns row)
  473. // needs a one row lookahead to preserve group
  474. if (!nextrow.get())
  475. {
  476. nextrow.setown(input->nextInGroup());
  477. if (!nextrow.get())
  478. {
  479. nextrow.setown(input->nextInGroup());
  480. if (nextrow.get()&&grouped) // only write eog if not at eof
  481. outSeq->putRow(NULL);
  482. return NULL;
  483. }
  484. }
  485. outSeq->putRow(nextrow.getLink());
  486. checkSizeLimit();
  487. return nextrow.getClear();
  488. }
  489. bool CHThorDiskWriteActivity::next()
  490. {
  491. if (!nextrow.get())
  492. {
  493. OwnedConstRoxieRow row(input->nextInGroup());
  494. if (!row.get())
  495. {
  496. row.setown(input->nextInGroup());
  497. if (!row.get())
  498. return false; // we are done
  499. if (grouped)
  500. outSeq->putRow(NULL);
  501. }
  502. outSeq->putRow(row.getClear());
  503. }
  504. else
  505. outSeq->putRow(nextrow.getClear());
  506. checkSizeLimit();
  507. return true;
  508. }
  509. void CHThorDiskWriteActivity::finishOutput()
  510. {
  511. }
  512. void CHThorDiskWriteActivity::close()
  513. {
  514. diskout.clear();
  515. outSeq.clear();
  516. if(clusterHandler)
  517. clusterHandler->copyPhysical(file, agent.queryWorkUnit()->getDebugValueBool("__output_cluster_no_copy_physical", false));
  518. }
  519. void CHThorDiskWriteActivity::publish()
  520. {
  521. StringBuffer dir,base;
  522. offset_t fileSize = file->size();
  523. if(clusterHandler)
  524. clusterHandler->splitPhysicalFilename(dir, base);
  525. else
  526. splitFilename(filename, &dir, &dir, &base, &base);
  527. Owned<IFileDescriptor> desc = createFileDescriptor();
  528. desc->setDefaultDir(dir.str());
  529. Owned<IPropertyTree> attrs;
  530. if(clusterHandler)
  531. attrs.setown(createPTree("Part")); // clusterHandler is going to set attributes
  532. else
  533. {
  534. // add cluster
  535. StringBuffer mygroupname;
  536. Owned<IGroup> mygrp = agent.getHThorGroup(mygroupname);
  537. ClusterPartDiskMapSpec partmap; // will get this from group at some point
  538. desc->setNumParts(1);
  539. desc->setPartMask(base.str());
  540. desc->addCluster(mygroupname.str(),mygrp, partmap);
  541. attrs.set(&desc->queryPart(0)->queryProperties());
  542. }
  543. //properties of the first file part.
  544. if(blockcompressed)
  545. {
  546. attrs->setPropInt64("@size", uncompressedBytesWritten);
  547. attrs->setPropInt64("@compressedSize", fileSize);
  548. }
  549. else
  550. attrs->setPropInt64("@size", fileSize);
  551. CDateTime createTime, modifiedTime, accessedTime;
  552. file->getTime(&createTime, &modifiedTime, &accessedTime);
  553. // round file time down to nearest sec. Nanosec accurancy is not preserved elsewhere and can lead to mismatch later.
  554. unsigned hour, min, sec, nanosec;
  555. modifiedTime.getTime(hour, min, sec, nanosec);
  556. modifiedTime.setTime(hour, min, sec, 0);
  557. StringBuffer timestr;
  558. modifiedTime.getString(timestr);
  559. if(timestr.length())
  560. attrs->setProp("@modified", timestr.str());
  561. if(clusterHandler)
  562. clusterHandler->setDescriptorParts(desc, base.str(), attrs);
  563. // properties of the logical file
  564. IPropertyTree & properties = desc->queryProperties();
  565. properties.setPropInt64("@size", (blockcompressed) ? uncompressedBytesWritten : fileSize);
  566. if (encrypted)
  567. properties.setPropBool("@encrypted", true);
  568. if (blockcompressed)
  569. {
  570. properties.setPropInt64("@compressedSize", fileSize);
  571. properties.setPropBool("@blockCompressed", true);
  572. }
  573. if (helper.getFlags() & TDWpersist)
  574. properties.setPropBool("@persistent", true);
  575. if (grouped)
  576. properties.setPropBool("@grouped", true);
  577. properties.setPropInt64("@recordCount", numRecords);
  578. properties.setProp("@owner", agent.queryWorkUnit()->queryUser());
  579. if (helper.getFlags() & (TDWowned|TDXjobtemp|TDXtemporary))
  580. properties.setPropBool("@owned", true);
  581. if (helper.getFlags() & TDWresult)
  582. properties.setPropBool("@result", true);
  583. properties.setProp("@workunit", agent.queryWorkUnit()->queryWuid());
  584. properties.setProp("@job", agent.queryWorkUnit()->queryJobName());
  585. setFormat(desc);
  586. if (helper.getFlags() & TDWexpires)
  587. setExpiryTime(properties, helper.getExpiryDays());
  588. if (helper.getFlags() & TDWupdate)
  589. {
  590. unsigned eclCRC;
  591. unsigned __int64 totalCRC;
  592. helper.getUpdateCRCs(eclCRC, totalCRC);
  593. properties.setPropInt("@eclCRC", eclCRC);
  594. properties.setPropInt64("@totalCRC", totalCRC);
  595. }
  596. properties.setPropInt("@formatCrc", helper.getFormatCrc());
  597. StringBuffer lfn;
  598. expandLogicalFilename(lfn, mangledHelperFileName.str(), agent.queryWorkUnit(), agent.queryResolveFilesLocally(), false);
  599. CDfsLogicalFileName logicalName;
  600. if (agent.queryResolveFilesLocally())
  601. logicalName.allowOsPath(true);
  602. if (!logicalName.setValidate(lfn.str()))
  603. throw MakeStringException(99, "Cannot publish %s, invalid logical name", lfn.str());
  604. if (!logicalName.isExternal()) // no need to publish externals
  605. {
  606. Owned<IDistributedFile> file = queryDistributedFileDirectory().createNew(desc);
  607. if(file->getModificationTime(modifiedTime))
  608. file->setAccessedTime(modifiedTime);
  609. file->attach(logicalName.get(), agent.queryCodeContext()->queryUserDescriptor());
  610. agent.logFileAccess(file, "HThor", "CREATED");
  611. }
  612. }
  613. void CHThorDiskWriteActivity::updateWorkUnitResult(unsigned __int64 reccount)
  614. {
  615. if(lfn.length()) //this is required as long as temp files don't get a name which can be stored in the WU and automatically deleted by the WU
  616. {
  617. WorkunitUpdate wu = agent.updateWorkUnit();
  618. StringArray clusters;
  619. if (clusterHandler)
  620. clusterHandler->getClusters(clusters);
  621. else
  622. clusters.append(wu->queryClusterName());
  623. unsigned flags = helper.getFlags();
  624. if (!agent.queryResolveFilesLocally())
  625. {
  626. WUFileKind fileKind;
  627. if (TDXtemporary & flags)
  628. fileKind = WUFileTemporary;
  629. else if(TDXjobtemp & flags)
  630. fileKind = WUFileJobOwned;
  631. else if(TDWowned & flags)
  632. fileKind = WUFileOwned;
  633. else
  634. fileKind = WUFileStandard;
  635. wu->addFile(lfn.str(), &clusters, helper.getTempUsageCount(), fileKind, NULL);
  636. }
  637. else if ((TDXtemporary | TDXjobtemp) & flags)
  638. agent.noteTemporaryFilespec(filename);//note for later deletion
  639. if (!(flags & TDXtemporary) && helper.getSequence() >= 0)
  640. {
  641. Owned<IWUResult> result = wu->updateResultBySequence(helper.getSequence());
  642. if (result)
  643. {
  644. result->setResultTotalRowCount(reccount);
  645. result->setResultStatus(ResultStatusCalculated);
  646. if (helper.getFlags() & TDWresult)
  647. result->setResultFilename(lfn.str());
  648. else
  649. result->setResultLogicalName(lfn.str());
  650. }
  651. }
  652. }
  653. }
  654. void CHThorDiskWriteActivity::setFormat(IFileDescriptor * desc)
  655. {
  656. if ((serializedOutputMeta.isFixedSize()) && !isOutputTransformed())
  657. desc->queryProperties().setPropInt("@recordSize", serializedOutputMeta.getFixedSize() + (grouped ? 1 : 0));
  658. const char *recordECL = helper.queryRecordECL();
  659. if (recordECL && *recordECL)
  660. desc->queryProperties().setProp("ECL", recordECL);
  661. desc->queryProperties().setProp("@kind", "flat");
  662. }
  663. void CHThorDiskWriteActivity::checkSizeLimit()
  664. {
  665. if(sizeLimit && outSeq && (outSeq->getPosition() > sizeLimit))
  666. {
  667. StringBuffer msg;
  668. msg.append("Exceeded disk write size limit of ").append(sizeLimit).append(" while writing file ").append(mangledHelperFileName.str());
  669. throw MakeStringExceptionDirect(0, msg.str());
  670. }
  671. }
  672. //=====================================================================================================
  673. CHThorSpillActivity::CHThorSpillActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorSpillArg &_arg, ThorActivityKind _kind) : CHThorDiskWriteActivity(_agent, _activityId, _subgraphId, _arg, _kind)
  674. {
  675. }
  676. void CHThorSpillActivity::setInput(unsigned index, IHThorInput *_input)
  677. {
  678. CHThorActivityBase::setInput(index, _input);
  679. }
  680. void CHThorSpillActivity::ready()
  681. {
  682. CHThorDiskWriteActivity::ready();
  683. }
  684. void CHThorSpillActivity::execute()
  685. {
  686. UNIMPLEMENTED;
  687. }
  688. const void *CHThorSpillActivity::nextInGroup()
  689. {
  690. const void *nextrec = getNext();
  691. if (nextrec)
  692. {
  693. numRecords++;
  694. processed++;
  695. }
  696. return nextrec;
  697. }
  698. void CHThorSpillActivity::done()
  699. {
  700. loop
  701. {
  702. OwnedConstRoxieRow nextrec(nextInGroup());
  703. if (!nextrec)
  704. {
  705. nextrec.setown(nextInGroup());
  706. if (!nextrec)
  707. break;
  708. }
  709. }
  710. finishOutput();
  711. CHThorDiskWriteActivity::done();
  712. }
  713. //=====================================================================================================
  714. CHThorCsvWriteActivity::CHThorCsvWriteActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorCsvWriteArg &_arg, ThorActivityKind _kind) : CHThorDiskWriteActivity(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  715. {
  716. csvOutput.init(helper.queryCsvParameters(),agent.queryWorkUnit()->getDebugValueBool("oldCSVoutputFormat", false));
  717. }
  718. void CHThorCsvWriteActivity::execute()
  719. {
  720. OwnedRoxieString header(helper.queryCsvParameters()->getHeader());
  721. if (header) {
  722. csvOutput.beginLine();
  723. csvOutput.writeHeaderLn(strlen(header), header);
  724. diskout->write(csvOutput.length(), csvOutput.str());
  725. }
  726. // Loop thru the results
  727. numRecords = 0;
  728. loop
  729. {
  730. OwnedConstRoxieRow nextrec(input->nextInGroup());
  731. if (!nextrec)
  732. {
  733. nextrec.setown(input->nextInGroup());
  734. if (!nextrec)
  735. break;
  736. }
  737. try
  738. {
  739. csvOutput.beginLine();
  740. helper.writeRow((const byte *)nextrec.get(), &csvOutput);
  741. csvOutput.endLine();
  742. }
  743. catch(IException * e)
  744. {
  745. throw makeWrappedException(e);
  746. }
  747. diskout->write(csvOutput.length(), csvOutput.str());
  748. numRecords++;
  749. }
  750. OwnedRoxieString footer(helper.queryCsvParameters()->getFooter());
  751. if (footer) {
  752. csvOutput.beginLine();
  753. csvOutput.writeHeaderLn(strlen(footer), footer);
  754. diskout->write(csvOutput.length(), csvOutput.str());
  755. }
  756. }
  757. void CHThorCsvWriteActivity::setFormat(IFileDescriptor * desc)
  758. {
  759. // MORE - should call parent's setFormat too?
  760. ICsvParameters * csvInfo = helper.queryCsvParameters();
  761. OwnedRoxieString rs(csvInfo->getSeparator(0));
  762. StringBuffer separator;
  763. const char *s = rs;
  764. while (s && *s)
  765. {
  766. if (',' == *s)
  767. separator.append("\\,");
  768. else
  769. separator.append(*s);
  770. ++s;
  771. }
  772. desc->queryProperties().setProp("@csvSeparate", separator.str());
  773. desc->queryProperties().setProp("@csvQuote", rs.setown(csvInfo->getQuote(0)));
  774. desc->queryProperties().setProp("@csvTerminate", rs.setown(csvInfo->getTerminator(0)));
  775. desc->queryProperties().setProp("@csvEscape", rs.setown(csvInfo->getEscape(0)));
  776. desc->queryProperties().setProp("@format","utf8n");
  777. desc->queryProperties().setProp("@kind", "csv");
  778. const char *recordECL = helper.queryRecordECL();
  779. if (recordECL && *recordECL)
  780. desc->queryProperties().setProp("ECL", recordECL);
  781. }
  782. //=====================================================================================================
  783. CHThorXmlWriteActivity::CHThorXmlWriteActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorXmlWriteArg &_arg, ThorActivityKind _kind) : CHThorDiskWriteActivity(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg), headerLength(0), footerLength(0)
  784. {
  785. OwnedRoxieString xmlpath(helper.getXmlIteratorPath());
  786. if (!xmlpath)
  787. rowTag.append(DEFAULTXMLROWTAG);
  788. else
  789. {
  790. const char *path = xmlpath;
  791. if (*path == '/') path++;
  792. if (strchr(path, '/')) UNIMPLEMENTED; // more what do we do with /mydata/row
  793. rowTag.append(path);
  794. }
  795. }
  796. void CHThorXmlWriteActivity::execute()
  797. {
  798. // Loop thru the results
  799. numRecords = 0;
  800. StringBuffer header;
  801. OwnedRoxieString suppliedHeader(helper.getHeader());
  802. if (kind==TAKjsonwrite)
  803. buildJsonHeader(header, suppliedHeader, rowTag);
  804. else if (suppliedHeader)
  805. header.set(suppliedHeader);
  806. else
  807. header.append(DEFAULTXMLHEADER).newline();
  808. headerLength = header.length();
  809. diskout->write(headerLength, header.str());
  810. Owned<IXmlWriterExt> writer = createIXmlWriterExt(helper.getXmlFlags(), 0, NULL, (kind==TAKjsonwrite) ? WTJSON : WTStandard);
  811. writer->outputBeginArray(rowTag); //need to set up the array
  812. writer->clear(); //but not output it
  813. loop
  814. {
  815. OwnedConstRoxieRow nextrec(input->nextInGroup());
  816. if (!nextrec)
  817. {
  818. nextrec.setown(input->nextInGroup());
  819. if (!nextrec)
  820. break;
  821. }
  822. try
  823. {
  824. writer->clear().outputBeginNested(rowTag, false);
  825. helper.toXML((const byte *)nextrec.get(), *writer);
  826. writer->outputEndNested(rowTag);
  827. }
  828. catch(IException * e)
  829. {
  830. throw makeWrappedException(e);
  831. }
  832. diskout->write(writer->length(), writer->str());
  833. numRecords++;
  834. }
  835. OwnedRoxieString suppliedFooter(helper.getFooter());
  836. StringBuffer footer;
  837. if (kind==TAKjsonwrite)
  838. buildJsonFooter(footer.newline(), suppliedFooter, rowTag);
  839. else if (suppliedFooter)
  840. footer.append(suppliedFooter);
  841. else
  842. footer.append(DEFAULTXMLFOOTER).newline();
  843. footerLength=footer.length();
  844. diskout->write(footerLength, footer);
  845. }
  846. void CHThorXmlWriteActivity::setFormat(IFileDescriptor * desc)
  847. {
  848. desc->queryProperties().setProp("@format","utf8n");
  849. desc->queryProperties().setProp("@rowTag",rowTag.str());
  850. desc->queryProperties().setProp("@kind", (kind==TAKjsonwrite) ? "json" : "xml");
  851. desc->queryProperties().setPropInt(FPheaderLength, headerLength);
  852. desc->queryProperties().setPropInt(FPfooterLength, footerLength);
  853. const char *recordECL = helper.queryRecordECL();
  854. if (recordECL && *recordECL)
  855. desc->queryProperties().setProp("ECL", recordECL);
  856. }
  857. //=====================================================================================================
  858. void throwPipeProcessError(unsigned err, char const * preposition, char const * program, IPipeProcess * pipe)
  859. {
  860. StringBuffer msg;
  861. msg.append("Error piping ").append(preposition).append(" (").append(program).append("): process failed with code ").append(err);
  862. if(pipe->hasError())
  863. {
  864. try
  865. {
  866. char error[512];
  867. size32_t sz = pipe->readError(sizeof(error), error);
  868. if(sz && sz!=(size32_t)-1)
  869. msg.append(", stderr: '").append(sz, error).append("'");
  870. }
  871. catch (IException *e)
  872. {
  873. EXCLOG(e, "Error reading pipe stderr");
  874. e->Release();
  875. }
  876. }
  877. throw MakeStringExceptionDirect(2, msg.str());
  878. }
  879. //=====================================================================================================
  880. CHThorIndexWriteActivity::CHThorIndexWriteActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorIndexWriteArg &_arg, ThorActivityKind _kind) : CHThorActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  881. {
  882. incomplete = false;
  883. StringBuffer lfn;
  884. OwnedRoxieString fname(helper.getFileName());
  885. expandLogicalFilename(lfn, fname, agent.queryWorkUnit(), agent.queryResolveFilesLocally(), false);
  886. if (!agent.queryResolveFilesLocally())
  887. {
  888. Owned<IDistributedFile> f = queryDistributedFileDirectory().lookup(lfn, agent.queryCodeContext()->queryUserDescriptor(), true);
  889. if (f)
  890. {
  891. if (TIWoverwrite & helper.getFlags())
  892. {
  893. PrintLog("Removing %s from DFS", lfn.str());
  894. agent.logFileAccess(f, "HThor", "DELETED");
  895. f->detach();
  896. }
  897. else // not quite sure about raising exceptions in constructors
  898. throw MakeStringException(99, "Cannot write %s, file already exists (missing OVERWRITE attribute?)", lfn.str());
  899. }
  900. }
  901. clusterHandler.setown(createClusterWriteHandler(agent, &helper, NULL, lfn, filename, false));
  902. sizeLimit = agent.queryWorkUnit()->getDebugValueInt64("hthorDiskWriteSizeLimit", defaultHThorDiskWriteSizeLimit);
  903. }
  904. CHThorIndexWriteActivity::~CHThorIndexWriteActivity()
  905. {
  906. if(incomplete)
  907. {
  908. PROGLOG("Index write incomplete, deleting physical file: %s", filename.get());
  909. file->remove();
  910. }
  911. }
  912. void CHThorIndexWriteActivity::execute()
  913. {
  914. size32_t maxDiskRecordSize;
  915. if (helper.queryDiskRecordSize()->isVariableSize())
  916. {
  917. if (helper.getFlags() & TIWmaxlength)
  918. maxDiskRecordSize = helper.getMaxKeySize();
  919. else
  920. maxDiskRecordSize = KEYBUILD_MAXLENGTH; // Current default behaviour, could be improved in the future
  921. }
  922. else
  923. maxDiskRecordSize = helper.queryDiskRecordSize()->getFixedSize();
  924. if (maxDiskRecordSize > KEYBUILD_MAXLENGTH)
  925. throw MakeStringException(99, "Index maximum record length (%d) exceeds 32K internal limit", maxDiskRecordSize);
  926. OwnedMalloc<char> rowBuffer(maxDiskRecordSize, true);
  927. // Loop thru the results
  928. unsigned __int64 reccount = 0;
  929. unsigned int fileCrc = -1;
  930. file.setown(createIFile(filename.get()));
  931. {
  932. OwnedIFileIO io;
  933. try
  934. {
  935. io.setown(file->open(IFOcreate));
  936. }
  937. catch(IException * e)
  938. {
  939. e->Release();
  940. clearKeyStoreCache(false);
  941. io.setown(file->open(IFOcreate));
  942. }
  943. incomplete = true;
  944. Owned<IFileIOStream> out = createIOStream(io);
  945. bool isVariable = helper.queryDiskRecordSize()->isVariableSize();
  946. unsigned flags = COL_PREFIX | HTREE_FULLSORT_KEY;
  947. if (helper.getFlags() & TIWrowcompress)
  948. flags |= HTREE_COMPRESSED_KEY|HTREE_QUICK_COMPRESSED_KEY;
  949. else if (!(helper.getFlags() & TIWnolzwcompress))
  950. flags |= HTREE_COMPRESSED_KEY;
  951. if (isVariable)
  952. flags |= HTREE_VARSIZE;
  953. Owned<IPropertyTree> metadata;
  954. buildUserMetadata(metadata);
  955. buildLayoutMetadata(metadata);
  956. unsigned nodeSize = metadata ? metadata->getPropInt("_nodeSize", NODESIZE) : NODESIZE;
  957. size32_t keyMaxSize = helper.queryDiskRecordSize()->getRecordSize(NULL);
  958. Owned<IKeyBuilder> builder = createKeyBuilder(out, flags, keyMaxSize, nodeSize, helper.getKeyedSize(), 0);
  959. class BcWrapper : implements IBlobCreator
  960. {
  961. IKeyBuilder *builder;
  962. public:
  963. BcWrapper(IKeyBuilder *_builder) : builder(_builder) {}
  964. virtual unsigned __int64 createBlob(size32_t size, const void * ptr)
  965. {
  966. return builder->createBlob(size, (const char *) ptr);
  967. }
  968. } bc(builder);
  969. loop
  970. {
  971. OwnedConstRoxieRow nextrec(input->nextInGroup());
  972. if (!nextrec)
  973. {
  974. nextrec.setown(input->nextInGroup());
  975. if (!nextrec)
  976. break;
  977. }
  978. try
  979. {
  980. unsigned __int64 fpos;
  981. RtlStaticRowBuilder rowBuilder(rowBuffer, maxDiskRecordSize);
  982. size32_t thisSize = helper.transform(rowBuilder, nextrec, &bc, fpos);
  983. builder->processKeyData(rowBuffer, fpos, thisSize);
  984. }
  985. catch(IException * e)
  986. {
  987. throw makeWrappedException(e);
  988. }
  989. if(sizeLimit && (out->tell() > sizeLimit))
  990. {
  991. StringBuffer msg;
  992. OwnedRoxieString fname(helper.getFileName());
  993. msg.append("Exceeded disk write size limit of ").append(sizeLimit).append(" while writing index ").append(fname);
  994. throw MakeStringExceptionDirect(0, msg.str());
  995. }
  996. reccount++;
  997. }
  998. if(metadata)
  999. builder->finish(metadata,&fileCrc);
  1000. else
  1001. builder->finish(&fileCrc);
  1002. out->flush();
  1003. out.clear();
  1004. }
  1005. if(clusterHandler)
  1006. clusterHandler->copyPhysical(file, agent.queryWorkUnit()->getDebugValueBool("__output_cluster_no_copy_physical", false));
  1007. // Now publish to name services
  1008. StringBuffer dir,base;
  1009. offset_t indexFileSize = file->size();
  1010. if(clusterHandler)
  1011. clusterHandler->splitPhysicalFilename(dir, base);
  1012. else
  1013. splitFilename(filename, &dir, &dir, &base, &base);
  1014. Owned<IFileDescriptor> desc = createFileDescriptor();
  1015. desc->setDefaultDir(dir.str());
  1016. //properties of the first file part.
  1017. Owned<IPropertyTree> attrs;
  1018. if(clusterHandler)
  1019. attrs.setown(createPTree("Part")); // clusterHandler is going to set attributes
  1020. else
  1021. {
  1022. // add cluster
  1023. StringBuffer mygroupname;
  1024. Owned<IGroup> mygrp = NULL;
  1025. if (!agent.queryResolveFilesLocally())
  1026. mygrp.setown(agent.getHThorGroup(mygroupname));
  1027. ClusterPartDiskMapSpec partmap; // will get this from group at some point
  1028. desc->setNumParts(1);
  1029. desc->setPartMask(base.str());
  1030. desc->addCluster(mygroupname.str(),mygrp, partmap);
  1031. attrs.set(&desc->queryPart(0)->queryProperties());
  1032. }
  1033. attrs->setPropInt64("@size", indexFileSize);
  1034. CDateTime createTime, modifiedTime, accessedTime;
  1035. file->getTime(&createTime, &modifiedTime, &accessedTime);
  1036. // round file time down to nearest sec. Nanosec accurancy is not preserved elsewhere and can lead to mismatch later.
  1037. unsigned hour, min, sec, nanosec;
  1038. modifiedTime.getTime(hour, min, sec, nanosec);
  1039. modifiedTime.setTime(hour, min, sec, 0);
  1040. StringBuffer timestr;
  1041. modifiedTime.getString(timestr);
  1042. if(timestr.length())
  1043. attrs->setProp("@modified", timestr.str());
  1044. if(clusterHandler)
  1045. clusterHandler->setDescriptorParts(desc, base.str(), attrs);
  1046. // properties of the logical file
  1047. IPropertyTree & properties = desc->queryProperties();
  1048. properties.setProp("@kind", "key");
  1049. properties.setPropInt64("@size", indexFileSize);
  1050. properties.setPropInt64("@recordCount", reccount);
  1051. properties.setProp("@owner", agent.queryWorkUnit()->queryUser());
  1052. properties.setProp("@workunit", agent.queryWorkUnit()->queryWuid());
  1053. properties.setProp("@job", agent.queryWorkUnit()->queryJobName());
  1054. #if 0
  1055. IRecordSize * irecsize = helper.queryDiskRecordSize();
  1056. if(irecsize && (irecsize->isFixedSize()))
  1057. properties.setPropInt("@recordSize", irecsize->getFixedSize());
  1058. #endif
  1059. char const * rececl = helper.queryRecordECL();
  1060. if(rececl && *rececl)
  1061. properties.setProp("ECL", rececl);
  1062. if (helper.getFlags() & TIWexpires)
  1063. setExpiryTime(properties, helper.getExpiryDays());
  1064. if (helper.getFlags() & TIWupdate)
  1065. {
  1066. unsigned eclCRC;
  1067. unsigned __int64 totalCRC;
  1068. helper.getUpdateCRCs(eclCRC, totalCRC);
  1069. properties.setPropInt("@eclCRC", eclCRC);
  1070. properties.setPropInt64("@totalCRC", totalCRC);
  1071. }
  1072. properties.setPropInt("@fileCrc", fileCrc);
  1073. properties.setPropInt("@formatCrc", helper.getFormatCrc());
  1074. void * layoutMetaBuff;
  1075. size32_t layoutMetaSize;
  1076. if(helper.getIndexLayout(layoutMetaSize, layoutMetaBuff))
  1077. {
  1078. properties.setPropBin("_record_layout", layoutMetaSize, layoutMetaBuff);
  1079. rtlFree(layoutMetaBuff);
  1080. }
  1081. StringBuffer lfn;
  1082. Owned<IDistributedFile> dfile = NULL;
  1083. if (!agent.queryResolveFilesLocally())
  1084. {
  1085. dfile.setown(queryDistributedFileDirectory().createNew(desc));
  1086. OwnedRoxieString fname(helper.getFileName());
  1087. expandLogicalFilename(lfn, fname, agent.queryWorkUnit(), agent.queryResolveFilesLocally(), false);
  1088. dfile->attach(lfn.str(),agent.queryCodeContext()->queryUserDescriptor());
  1089. agent.logFileAccess(dfile, "HThor", "CREATED");
  1090. }
  1091. else
  1092. lfn = filename;
  1093. incomplete = false;
  1094. if(clusterHandler)
  1095. clusterHandler->finish(file);
  1096. // and update wu info
  1097. if (helper.getSequence() >= 0)
  1098. {
  1099. WorkunitUpdate wu = agent.updateWorkUnit();
  1100. Owned<IWUResult> result = wu->updateResultBySequence(helper.getSequence());
  1101. if (result)
  1102. {
  1103. result->setResultTotalRowCount(reccount);
  1104. result->setResultStatus(ResultStatusCalculated);
  1105. result->setResultLogicalName(lfn.str());
  1106. }
  1107. }
  1108. }
  1109. void CHThorIndexWriteActivity::buildUserMetadata(Owned<IPropertyTree> & metadata)
  1110. {
  1111. size32_t nameLen;
  1112. char * nameBuff;
  1113. size32_t valueLen;
  1114. char * valueBuff;
  1115. unsigned idx = 0;
  1116. while(helper.getIndexMeta(nameLen, nameBuff, valueLen, valueBuff, idx++))
  1117. {
  1118. StringBuffer name(nameLen, nameBuff);
  1119. StringBuffer value(valueLen, valueBuff);
  1120. if(*nameBuff == '_' && strcmp(name, "_nodeSize") != 0)
  1121. {
  1122. OwnedRoxieString fname(helper.getFileName());
  1123. throw MakeStringException(0, "Invalid name %s in user metadata for index %s (names beginning with underscore are reserved)", name.str(), fname.get());
  1124. }
  1125. if(!validateXMLTag(name.str()))
  1126. {
  1127. OwnedRoxieString fname(helper.getFileName());
  1128. throw MakeStringException(0, "Invalid name %s in user metadata for index %s (not legal XML element name)", name.str(), fname.get());
  1129. }
  1130. if(!metadata) metadata.setown(createPTree("metadata"));
  1131. metadata->setProp(name.str(), value.str());
  1132. }
  1133. }
  1134. void CHThorIndexWriteActivity::buildLayoutMetadata(Owned<IPropertyTree> & metadata)
  1135. {
  1136. if(!metadata) metadata.setown(createPTree("metadata"));
  1137. metadata->setProp("_record_ECL", helper.queryRecordECL());
  1138. void * layoutMetaBuff;
  1139. size32_t layoutMetaSize;
  1140. if(helper.getIndexLayout(layoutMetaSize, layoutMetaBuff))
  1141. {
  1142. metadata->setPropBin("_record_layout", layoutMetaSize, layoutMetaBuff);
  1143. rtlFree(layoutMetaBuff);
  1144. }
  1145. }
  1146. //=====================================================================================================
  1147. class CHThorPipeReadActivity : public CHThorSimpleActivityBase
  1148. {
  1149. IHThorPipeReadArg &helper;
  1150. Owned<IPipeProcess> pipe;
  1151. StringAttr pipeCommand;
  1152. Owned<IOutputRowDeserializer> rowDeserializer;
  1153. Owned<IReadRowStream> readTransformer;
  1154. bool groupSignalled;
  1155. public:
  1156. CHThorPipeReadActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorPipeReadArg &_arg, ThorActivityKind _kind)
  1157. : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  1158. {
  1159. groupSignalled = true;
  1160. }
  1161. virtual bool needsAllocator() const { return true; }
  1162. virtual void ready()
  1163. {
  1164. groupSignalled = true; // i.e. don't start with a NULL row
  1165. CHThorSimpleActivityBase::ready();
  1166. rowDeserializer.setown(rowAllocator->createDiskDeserializer(agent.queryCodeContext()));
  1167. OwnedRoxieString xmlIteratorPath(helper.getXmlIteratorPath());
  1168. readTransformer.setown(createReadRowStream(rowAllocator, rowDeserializer, helper.queryXmlTransformer(), helper.queryCsvTransformer(), xmlIteratorPath, helper.getPipeFlags()));
  1169. OwnedRoxieString pipeProgram(helper.getPipeProgram());
  1170. openPipe(pipeProgram);
  1171. }
  1172. virtual void done()
  1173. {
  1174. //Need to close the output (or read it in its entirety), otherwise we might wait forever for the
  1175. //program to finish
  1176. if (pipe)
  1177. pipe->closeOutput();
  1178. pipe.clear();
  1179. readTransformer->setStream(NULL);
  1180. CHThorSimpleActivityBase::done();
  1181. }
  1182. virtual const void *nextInGroup()
  1183. {
  1184. while (!waitForPipe())
  1185. {
  1186. if (!pipe)
  1187. return NULL;
  1188. if (helper.getPipeFlags() & TPFgroupeachrow)
  1189. {
  1190. if (!groupSignalled)
  1191. {
  1192. groupSignalled = true;
  1193. return NULL;
  1194. }
  1195. }
  1196. }
  1197. const void *ret = readTransformer->next();
  1198. assertex(ret != NULL); // if ret can ever be NULL then we need to recode this logic
  1199. processed++;
  1200. groupSignalled = false;
  1201. return ret;
  1202. }
  1203. protected:
  1204. bool waitForPipe()
  1205. {
  1206. if (!pipe)
  1207. return false; // done
  1208. if (!readTransformer->eos())
  1209. return true;
  1210. verifyPipe();
  1211. return false;
  1212. }
  1213. void openPipe(char const * cmd)
  1214. {
  1215. pipeCommand.setown(cmd);
  1216. pipe.setown(createPipeProcess(agent.queryAllowedPipePrograms()));
  1217. if(!pipe->run(NULL, cmd, ".", false, true, true, 0x10000))
  1218. throw MakeStringException(2, "Could not run pipe process %s", cmd);
  1219. Owned<ISimpleReadStream> pipeReader = pipe->getOutputStream();
  1220. readTransformer->setStream(pipeReader.get());
  1221. }
  1222. void verifyPipe()
  1223. {
  1224. if (pipe)
  1225. {
  1226. unsigned err = pipe->wait();
  1227. if(err && !(helper.getPipeFlags() & TPFnofail))
  1228. throwPipeProcessError(err, "from", pipeCommand.get(), pipe);
  1229. pipe.clear();
  1230. }
  1231. }
  1232. };
  1233. //=====================================================================================================
  1234. // Through pipe code - taken from Roxie implementation
  1235. interface IPipeRecordPullerCallback : extends IExceptionHandler
  1236. {
  1237. virtual void processRow(const void *row) = 0;
  1238. virtual void processDone() = 0;
  1239. virtual const void *nextInput() = 0;
  1240. };
  1241. class CPipeRecordPullerThread : public Thread
  1242. {
  1243. protected:
  1244. IPipeRecordPullerCallback *helper;
  1245. bool eog;
  1246. public:
  1247. CPipeRecordPullerThread() : Thread("PipeRecordPullerThread")
  1248. {
  1249. helper = NULL;
  1250. eog = false;
  1251. }
  1252. void setInput(IPipeRecordPullerCallback *_helper)
  1253. {
  1254. helper = _helper;
  1255. }
  1256. virtual int run()
  1257. {
  1258. try
  1259. {
  1260. loop
  1261. {
  1262. const void * row = helper->nextInput();
  1263. if (row)
  1264. {
  1265. eog = false;
  1266. helper->processRow(row);
  1267. }
  1268. else if (!eog)
  1269. {
  1270. eog = true;
  1271. }
  1272. else
  1273. {
  1274. break;
  1275. }
  1276. }
  1277. helper->processDone();
  1278. }
  1279. catch (IException *e)
  1280. {
  1281. helper->fireException(e);
  1282. }
  1283. catch (...)
  1284. {
  1285. helper->fireException(MakeStringException(2, "Unexpected exception caught in PipeRecordPullerThread::run"));
  1286. }
  1287. return 0;
  1288. }
  1289. };
  1290. class CHThorPipeThroughActivity : public CHThorSimpleActivityBase, implements IPipeRecordPullerCallback
  1291. {
  1292. IHThorPipeThroughArg &helper;
  1293. CPipeRecordPullerThread puller;
  1294. Owned<IPipeProcess> pipe;
  1295. StringAttr pipeCommand;
  1296. InterruptableSemaphore pipeVerified;
  1297. InterruptableSemaphore pipeOpened;
  1298. CachedOutputMetaData inputMeta;
  1299. Owned<IOutputRowSerializer> rowSerializer;
  1300. Owned<IOutputRowDeserializer> rowDeserializer;
  1301. Owned<IPipeWriteXformHelper> writeTransformer;
  1302. Owned<IReadRowStream> readTransformer;
  1303. bool firstRead;
  1304. bool recreate;
  1305. bool inputExhausted;
  1306. bool groupSignalled;
  1307. public:
  1308. CHThorPipeThroughActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorPipeThroughArg &_arg, ThorActivityKind _kind)
  1309. : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  1310. {
  1311. recreate = helper.recreateEachRow();
  1312. groupSignalled = true;
  1313. firstRead = false;
  1314. inputExhausted = false;
  1315. puller.setInput(this);
  1316. }
  1317. virtual void ready()
  1318. {
  1319. CHThorSimpleActivityBase::ready();
  1320. // From the create() in roxie
  1321. inputMeta.set(input->queryOutputMeta());
  1322. rowSerializer.setown(inputMeta.createDiskSerializer(agent.queryCodeContext(), activityId));
  1323. rowDeserializer.setown(rowAllocator->createDiskDeserializer(agent.queryCodeContext()));
  1324. writeTransformer.setown(createPipeWriteXformHelper(helper.getPipeFlags(), helper.queryXmlOutput(), helper.queryCsvOutput(), rowSerializer));
  1325. // From the start() in roxie
  1326. firstRead = true;
  1327. inputExhausted = false;
  1328. groupSignalled = true; // i.e. don't start with a NULL row
  1329. pipeVerified.reinit();
  1330. pipeOpened.reinit();
  1331. writeTransformer->ready();
  1332. if (!readTransformer)
  1333. {
  1334. OwnedRoxieString xmlIterator(helper.getXmlIteratorPath());
  1335. readTransformer.setown(createReadRowStream(rowAllocator, rowDeserializer, helper.queryXmlTransformer(), helper.queryCsvTransformer(), xmlIterator, helper.getPipeFlags()));
  1336. }
  1337. if(!recreate)
  1338. {
  1339. OwnedRoxieString pipeProgram(helper.getPipeProgram());
  1340. openPipe(pipeProgram);
  1341. }
  1342. puller.start();
  1343. }
  1344. void done()
  1345. {
  1346. //Need to close the output (or read it in its entirety), otherwise we might wait forever for the
  1347. //program to finish
  1348. if (pipe)
  1349. pipe->closeOutput();
  1350. pipeVerified.interrupt(NULL);
  1351. pipeOpened.interrupt(NULL);
  1352. puller.join();
  1353. CHThorSimpleActivityBase::done();
  1354. pipe.clear();
  1355. readTransformer->setStream(NULL);
  1356. }
  1357. virtual bool needsAllocator() const { return true; }
  1358. virtual const void *nextInGroup()
  1359. {
  1360. while (!waitForPipe())
  1361. {
  1362. if (!pipe)
  1363. return NULL;
  1364. if (helper.getPipeFlags() & TPFgroupeachrow)
  1365. {
  1366. if (!groupSignalled)
  1367. {
  1368. groupSignalled = true;
  1369. return NULL;
  1370. }
  1371. }
  1372. }
  1373. const void *ret = readTransformer->next();
  1374. assertex(ret != NULL); // if ret can ever be NULL then we need to recode this logic
  1375. processed++;
  1376. groupSignalled = false;
  1377. return ret;
  1378. }
  1379. virtual bool isGrouped()
  1380. {
  1381. return outputMeta.isGrouped();
  1382. }
  1383. virtual void processRow(const void *row)
  1384. {
  1385. // called from puller thread
  1386. if(recreate)
  1387. openPipe(helper.getNameFromRow(row));
  1388. writeTransformer->writeTranslatedText(row, pipe);
  1389. ReleaseRoxieRow(row);
  1390. if(recreate)
  1391. {
  1392. closePipe();
  1393. pipeVerified.wait();
  1394. }
  1395. }
  1396. virtual void processDone()
  1397. {
  1398. // called from puller thread
  1399. if(recreate)
  1400. {
  1401. inputExhausted = true;
  1402. pipeOpened.signal();
  1403. }
  1404. else
  1405. {
  1406. closePipe();
  1407. pipeVerified.wait();
  1408. }
  1409. }
  1410. virtual const void *nextInput()
  1411. {
  1412. return input->nextInGroup();
  1413. }
  1414. virtual bool fireException(IException *e)
  1415. {
  1416. inputExhausted = true;
  1417. pipeOpened.interrupt(LINK(e));
  1418. pipeVerified.interrupt(e);
  1419. return true;
  1420. }
  1421. private:
  1422. bool waitForPipe()
  1423. {
  1424. if (firstRead)
  1425. {
  1426. pipeOpened.wait();
  1427. firstRead = false;
  1428. }
  1429. if (!pipe)
  1430. return false; // done
  1431. if (!readTransformer->eos())
  1432. return true;
  1433. verifyPipe();
  1434. if (recreate && !inputExhausted)
  1435. pipeOpened.wait();
  1436. return false;
  1437. }
  1438. void openPipe(char const * cmd)
  1439. {
  1440. pipeCommand.setown(cmd);
  1441. pipe.setown(createPipeProcess(agent.queryAllowedPipePrograms()));
  1442. if(!pipe->run(NULL, cmd, ".", true, true, true, 0x10000))
  1443. throw MakeStringException(2, "Could not run pipe process %s", cmd);
  1444. writeTransformer->writeHeader(pipe);
  1445. Owned<ISimpleReadStream> pipeReader = pipe->getOutputStream();
  1446. readTransformer->setStream(pipeReader.get());
  1447. pipeOpened.signal();
  1448. }
  1449. void closePipe()
  1450. {
  1451. writeTransformer->writeFooter(pipe);
  1452. pipe->closeInput();
  1453. }
  1454. void verifyPipe()
  1455. {
  1456. if (pipe)
  1457. {
  1458. unsigned err = pipe->wait();
  1459. if(err && !(helper.getPipeFlags() & TPFnofail))
  1460. throwPipeProcessError(err, "through", pipeCommand.get(), pipe);
  1461. pipe.clear();
  1462. pipeVerified.signal();
  1463. }
  1464. }
  1465. };
  1466. class CHThorPipeWriteActivity : public CHThorActivityBase
  1467. {
  1468. IHThorPipeWriteArg &helper;
  1469. Owned<IPipeProcess> pipe;
  1470. StringAttr pipeCommand;
  1471. CachedOutputMetaData inputMeta;
  1472. Owned<IOutputRowSerializer> rowSerializer;
  1473. Owned<IPipeWriteXformHelper> writeTransformer;
  1474. bool firstRead;
  1475. bool recreate;
  1476. bool inputExhausted;
  1477. public:
  1478. IMPLEMENT_SINKACTIVITY;
  1479. CHThorPipeWriteActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorPipeWriteArg &_arg, ThorActivityKind _kind)
  1480. : CHThorActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  1481. {
  1482. recreate = helper.recreateEachRow();
  1483. firstRead = false;
  1484. inputExhausted = false;
  1485. }
  1486. virtual bool needsAllocator() const { return true; }
  1487. virtual void ready()
  1488. {
  1489. CHThorActivityBase::ready();
  1490. inputMeta.set(input->queryOutputMeta());
  1491. rowSerializer.setown(inputMeta.createDiskSerializer(agent.queryCodeContext(), activityId));
  1492. writeTransformer.setown(createPipeWriteXformHelper(helper.getPipeFlags(), helper.queryXmlOutput(), helper.queryCsvOutput(), rowSerializer));
  1493. firstRead = true;
  1494. inputExhausted = false;
  1495. writeTransformer->ready();
  1496. if(!recreate)
  1497. {
  1498. OwnedRoxieString pipeProgram(helper.getPipeProgram());
  1499. openPipe(pipeProgram);
  1500. }
  1501. }
  1502. virtual void execute()
  1503. {
  1504. loop
  1505. {
  1506. const void *row = input->nextInGroup();
  1507. if (!row)
  1508. {
  1509. row = input->nextInGroup();
  1510. if (!row)
  1511. break;
  1512. }
  1513. processed++;
  1514. if(recreate)
  1515. openPipe(helper.getNameFromRow(row));
  1516. writeTransformer->writeTranslatedText(row, pipe);
  1517. ReleaseRoxieRow(row);
  1518. if(recreate)
  1519. closePipe();
  1520. }
  1521. closePipe();
  1522. if (helper.getSequence() >= 0)
  1523. {
  1524. WorkunitUpdate wu = agent.updateWorkUnit();
  1525. Owned<IWUResult> result = wu->updateResultBySequence(helper.getSequence());
  1526. if (result)
  1527. {
  1528. result->setResultTotalRowCount(processed);
  1529. result->setResultStatus(ResultStatusCalculated);
  1530. }
  1531. }
  1532. }
  1533. private:
  1534. void openPipe(char const * cmd)
  1535. {
  1536. pipeCommand.setown(cmd);
  1537. pipe.setown(createPipeProcess(agent.queryAllowedPipePrograms()));
  1538. if(!pipe->run(NULL, cmd, ".", true, false, true, 0x10000))
  1539. throw MakeStringException(2, "Could not run pipe process %s", cmd);
  1540. writeTransformer->writeHeader(pipe);
  1541. }
  1542. void closePipe()
  1543. {
  1544. writeTransformer->writeFooter(pipe);
  1545. pipe->closeInput();
  1546. unsigned err = pipe->wait();
  1547. if(err && !(helper.getPipeFlags() & TPFnofail))
  1548. throwPipeProcessError(err, "to", pipeCommand.get(), pipe);
  1549. pipe.clear();
  1550. }
  1551. };
  1552. //=====================================================================================================
  1553. CHThorIterateActivity::CHThorIterateActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorIterateArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  1554. {
  1555. }
  1556. void CHThorIterateActivity::done()
  1557. {
  1558. CHThorSimpleActivityBase::done();
  1559. right.clear();
  1560. left.clear();
  1561. }
  1562. void CHThorIterateActivity::ready()
  1563. {
  1564. CHThorSimpleActivityBase::ready();
  1565. if (!defaultRecord)
  1566. {
  1567. RtlDynamicRowBuilder rowBuilder(rowAllocator);
  1568. size32_t thisSize = helper.createDefault(rowBuilder);
  1569. defaultRecord.setown(rowBuilder.finalizeRowClear(thisSize));
  1570. }
  1571. counter = 0;
  1572. }
  1573. const void *CHThorIterateActivity::nextInGroup()
  1574. {
  1575. loop
  1576. {
  1577. right.setown(input->nextInGroup());
  1578. if(!right)
  1579. {
  1580. bool skippedGroup = (!left) && (counter > 0); //we have just skipped entire group, but shouldn't output a double null
  1581. left.clear();
  1582. counter = 0;
  1583. if(skippedGroup) continue;
  1584. return NULL;
  1585. }
  1586. try
  1587. {
  1588. RtlDynamicRowBuilder rowBuilder(rowAllocator);
  1589. unsigned outSize = helper.transform(rowBuilder, left ? left : defaultRecord, right, ++counter);
  1590. if (outSize)
  1591. {
  1592. left.setown(rowBuilder.finalizeRowClear(outSize));
  1593. processed++;
  1594. return left.getLink();
  1595. }
  1596. }
  1597. catch(IException * e)
  1598. {
  1599. throw makeWrappedException(e);
  1600. }
  1601. }
  1602. }
  1603. //=====================================================================================================
  1604. CHThorProcessActivity::CHThorProcessActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorProcessArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  1605. {
  1606. }
  1607. CHThorProcessActivity::~CHThorProcessActivity()
  1608. {
  1609. }
  1610. void CHThorProcessActivity::ready()
  1611. {
  1612. CHThorSimpleActivityBase::ready();
  1613. rightRowAllocator.setown(agent.queryCodeContext()->getRowAllocator( helper.queryRightRecordSize(), activityId));
  1614. RtlDynamicRowBuilder rowBuilder(rightRowAllocator);
  1615. size32_t thisSize = helper.createInitialRight(rowBuilder);
  1616. initialRight.setown(rowBuilder.finalizeRowClear(thisSize));
  1617. curRight.set(initialRight);
  1618. counter = 0;
  1619. }
  1620. const void *CHThorProcessActivity::nextInGroup()
  1621. {
  1622. try
  1623. {
  1624. loop
  1625. {
  1626. OwnedConstRoxieRow next(input->nextInGroup());
  1627. if (!next)
  1628. {
  1629. bool eog = (curRight != initialRight); // processed any records?
  1630. counter = 0;
  1631. curRight.set(initialRight);
  1632. if (eog)
  1633. return NULL;
  1634. next.setown(input->nextInGroup());
  1635. if (!next)
  1636. return NULL;
  1637. }
  1638. RtlDynamicRowBuilder rowBuilder(rowAllocator);
  1639. RtlDynamicRowBuilder rightRowBuilder(rightRowAllocator);
  1640. size32_t outSize = helper.transform(rowBuilder, rightRowBuilder, next, curRight, ++counter);
  1641. if (outSize)
  1642. {
  1643. size32_t rightSize = rightRowAllocator->queryOutputMeta()->getRecordSize(rightRowBuilder.getSelf()); // yuk
  1644. curRight.setown(rightRowBuilder.finalizeRowClear(rightSize));
  1645. processed++;
  1646. return rowBuilder.finalizeRowClear(outSize);
  1647. }
  1648. }
  1649. }
  1650. catch(IException * e)
  1651. {
  1652. throw makeWrappedException(e);
  1653. }
  1654. }
  1655. //=====================================================================================================
  1656. CHThorNormalizeActivity::CHThorNormalizeActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorNormalizeArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  1657. {
  1658. IRecordSize* recSize = outputMeta;
  1659. if (recSize == NULL)
  1660. throw MakeStringException(2, "Unexpected null pointer from helper.queryOutputMeta()");
  1661. }
  1662. CHThorNormalizeActivity::~CHThorNormalizeActivity()
  1663. {
  1664. }
  1665. void CHThorNormalizeActivity::ready()
  1666. {
  1667. CHThorSimpleActivityBase::ready();
  1668. numThisRow = 0;
  1669. curRow = 0;
  1670. numProcessedLastGroup = processed;
  1671. }
  1672. const void *CHThorNormalizeActivity::nextInGroup()
  1673. {
  1674. loop
  1675. {
  1676. while (curRow == numThisRow)
  1677. {
  1678. inbuff.setown(input->nextInGroup());
  1679. if (!inbuff && (processed == numProcessedLastGroup))
  1680. inbuff.setown(input->nextInGroup());
  1681. if (!inbuff)
  1682. {
  1683. numProcessedLastGroup = processed;
  1684. return NULL;
  1685. }
  1686. curRow = 0;
  1687. numThisRow = helper.numExpandedRows(inbuff);
  1688. }
  1689. try
  1690. {
  1691. RtlDynamicRowBuilder rowBuilder(rowAllocator);
  1692. memsize_t thisSize = helper.transform(rowBuilder, inbuff, ++curRow);
  1693. if(thisSize != 0)
  1694. {
  1695. processed++;
  1696. return rowBuilder.finalizeRowClear(thisSize);
  1697. }
  1698. }
  1699. catch(IException * e)
  1700. {
  1701. throw makeWrappedException(e);
  1702. }
  1703. }
  1704. }
  1705. //=====================================================================================================
  1706. CHThorNormalizeChildActivity::CHThorNormalizeChildActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorNormalizeChildArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  1707. {
  1708. }
  1709. CHThorNormalizeChildActivity::~CHThorNormalizeChildActivity()
  1710. {
  1711. }
  1712. bool CHThorNormalizeChildActivity::advanceInput()
  1713. {
  1714. loop
  1715. {
  1716. inbuff.setown(input->nextInGroup());
  1717. if (!inbuff && (processed == numProcessedLastGroup))
  1718. inbuff.setown(input->nextInGroup());
  1719. if (!inbuff)
  1720. {
  1721. numProcessedLastGroup = processed;
  1722. return false;
  1723. }
  1724. curChildRow = cursor->first(inbuff);
  1725. if (curChildRow)
  1726. {
  1727. curRow = 0;
  1728. return true;
  1729. }
  1730. }
  1731. }
  1732. void CHThorNormalizeChildActivity::done()
  1733. {
  1734. inbuff.clear();
  1735. CHThorSimpleActivityBase::done();
  1736. }
  1737. void CHThorNormalizeChildActivity::ready()
  1738. {
  1739. CHThorSimpleActivityBase::ready();
  1740. curRow = 0;
  1741. numProcessedLastGroup = processed;
  1742. cursor = helper.queryIterator();
  1743. curChildRow = NULL;
  1744. }
  1745. const void *CHThorNormalizeChildActivity::nextInGroup()
  1746. {
  1747. loop
  1748. {
  1749. if (!inbuff)
  1750. {
  1751. if (!advanceInput())
  1752. return NULL;
  1753. }
  1754. try
  1755. {
  1756. RtlDynamicRowBuilder rowBuilder(rowAllocator);
  1757. size32_t outSize = helper.transform(rowBuilder, inbuff, curChildRow, ++curRow);
  1758. curChildRow = cursor->next();
  1759. if (!curChildRow)
  1760. inbuff.clear();
  1761. if (outSize != 0)
  1762. {
  1763. processed++;
  1764. return rowBuilder.finalizeRowClear(outSize);
  1765. }
  1766. }
  1767. catch(IException * e)
  1768. {
  1769. throw makeWrappedException(e);
  1770. }
  1771. }
  1772. }
  1773. //=================================================================================
  1774. bool CHThorNormalizeLinkedChildActivity::advanceInput()
  1775. {
  1776. loop
  1777. {
  1778. curParent.setown(input->nextInGroup());
  1779. if (!curParent && (processed == numProcessedLastGroup))
  1780. curParent.setown(input->nextInGroup());
  1781. if (!curParent)
  1782. {
  1783. numProcessedLastGroup = processed;
  1784. return false;
  1785. }
  1786. curChild.set(helper.first(curParent));
  1787. if (curChild)
  1788. return true;
  1789. }
  1790. }
  1791. CHThorNormalizeLinkedChildActivity::CHThorNormalizeLinkedChildActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorNormalizeLinkedChildArg &_arg, ThorActivityKind _kind)
  1792. : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  1793. {
  1794. }
  1795. CHThorNormalizeLinkedChildActivity::~CHThorNormalizeLinkedChildActivity()
  1796. {
  1797. }
  1798. void CHThorNormalizeLinkedChildActivity::ready()
  1799. {
  1800. numProcessedLastGroup = 0;
  1801. CHThorSimpleActivityBase::ready();
  1802. }
  1803. void CHThorNormalizeLinkedChildActivity::done()
  1804. {
  1805. curParent.clear();
  1806. curChild.clear();
  1807. CHThorSimpleActivityBase::done();
  1808. }
  1809. const void * CHThorNormalizeLinkedChildActivity::nextInGroup()
  1810. {
  1811. loop
  1812. {
  1813. if (!curParent)
  1814. {
  1815. if (!advanceInput())
  1816. return NULL;
  1817. }
  1818. try
  1819. {
  1820. const void *ret = curChild.getClear();
  1821. curChild.set(helper.next());
  1822. if (!curChild)
  1823. curParent.clear();
  1824. if (ret)
  1825. {
  1826. processed++;
  1827. return ret;
  1828. }
  1829. }
  1830. catch (IException *E)
  1831. {
  1832. throw makeWrappedException(E);
  1833. }
  1834. }
  1835. }
  1836. //=====================================================================================================
  1837. CHThorProjectActivity::CHThorProjectActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorProjectArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  1838. {
  1839. }
  1840. CHThorProjectActivity::~CHThorProjectActivity()
  1841. {
  1842. }
  1843. void CHThorProjectActivity::ready()
  1844. {
  1845. CHThorSimpleActivityBase::ready();
  1846. numProcessedLastGroup = processed;
  1847. }
  1848. const void * CHThorProjectActivity::nextInGroup()
  1849. {
  1850. loop
  1851. {
  1852. OwnedConstRoxieRow in(input->nextInGroup());
  1853. if (!in)
  1854. {
  1855. if (numProcessedLastGroup == processed)
  1856. in.setown(input->nextInGroup());
  1857. if (!in)
  1858. {
  1859. numProcessedLastGroup = processed;
  1860. return NULL;
  1861. }
  1862. }
  1863. try
  1864. {
  1865. RtlDynamicRowBuilder rowBuilder(rowAllocator);
  1866. size32_t outSize = helper.transform(rowBuilder, in);
  1867. if (outSize)
  1868. {
  1869. processed++;
  1870. return rowBuilder.finalizeRowClear(outSize);
  1871. }
  1872. }
  1873. catch(IException * e)
  1874. {
  1875. throw makeWrappedException(e);
  1876. }
  1877. }
  1878. }
  1879. //=====================================================================================================
  1880. CHThorPrefetchProjectActivity::CHThorPrefetchProjectActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorPrefetchProjectArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  1881. {
  1882. }
  1883. void CHThorPrefetchProjectActivity::ready()
  1884. {
  1885. CHThorSimpleActivityBase::ready();
  1886. recordCount = 0;
  1887. numProcessedLastGroup = processed;
  1888. eof = !helper.canMatchAny();
  1889. child = helper.queryChild();
  1890. }
  1891. const void * CHThorPrefetchProjectActivity::nextInGroup()
  1892. {
  1893. if (eof)
  1894. return NULL;
  1895. loop
  1896. {
  1897. try
  1898. {
  1899. OwnedConstRoxieRow row(input->nextInGroup());
  1900. if (!row)
  1901. {
  1902. if (numProcessedLastGroup == processed)
  1903. row.setown(input->nextInGroup());
  1904. if (!row)
  1905. {
  1906. numProcessedLastGroup = processed;
  1907. return NULL;
  1908. }
  1909. }
  1910. ++recordCount;
  1911. rtlRowBuilder extract;
  1912. if (helper.preTransform(extract,row,recordCount))
  1913. {
  1914. Owned<IEclGraphResults> results;
  1915. if (child)
  1916. {
  1917. results.setown(child->evaluate(extract.size(), extract.getbytes()));
  1918. }
  1919. RtlDynamicRowBuilder rowBuilder(rowAllocator);
  1920. size32_t outSize = helper.transform(rowBuilder, row, results, recordCount);
  1921. if (outSize)
  1922. {
  1923. processed++;
  1924. return rowBuilder.finalizeRowClear(outSize);
  1925. }
  1926. }
  1927. }
  1928. catch(IException * e)
  1929. {
  1930. throw makeWrappedException(e);
  1931. }
  1932. }
  1933. }
  1934. //=====================================================================================================
  1935. CHThorFilterProjectActivity::CHThorFilterProjectActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorFilterProjectArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  1936. {
  1937. }
  1938. CHThorFilterProjectActivity::~CHThorFilterProjectActivity()
  1939. {
  1940. }
  1941. void CHThorFilterProjectActivity::ready()
  1942. {
  1943. CHThorSimpleActivityBase::ready();
  1944. recordCount = 0;
  1945. numProcessedLastGroup = processed;
  1946. eof = !helper.canMatchAny();
  1947. }
  1948. const void * CHThorFilterProjectActivity::nextInGroup()
  1949. {
  1950. if (eof)
  1951. return NULL;
  1952. loop
  1953. {
  1954. OwnedConstRoxieRow in = input->nextInGroup();
  1955. if (!in)
  1956. {
  1957. recordCount = 0;
  1958. if (numProcessedLastGroup == processed)
  1959. in.setown(input->nextInGroup());
  1960. if (!in)
  1961. {
  1962. numProcessedLastGroup = processed;
  1963. return NULL;
  1964. }
  1965. }
  1966. try
  1967. {
  1968. RtlDynamicRowBuilder rowBuilder(rowAllocator);
  1969. size32_t outSize = helper.transform(rowBuilder, in, ++recordCount);
  1970. if (outSize)
  1971. {
  1972. processed++;
  1973. return rowBuilder.finalizeRowClear(outSize);
  1974. }
  1975. }
  1976. catch(IException * e)
  1977. {
  1978. throw makeWrappedException(e);
  1979. }
  1980. }
  1981. }
  1982. //=====================================================================================================
  1983. CHThorCountProjectActivity::CHThorCountProjectActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorCountProjectArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  1984. {
  1985. }
  1986. CHThorCountProjectActivity::~CHThorCountProjectActivity()
  1987. {
  1988. }
  1989. void CHThorCountProjectActivity::ready()
  1990. {
  1991. CHThorSimpleActivityBase::ready();
  1992. recordCount = 0;
  1993. numProcessedLastGroup = processed;
  1994. }
  1995. const void * CHThorCountProjectActivity::nextInGroup()
  1996. {
  1997. loop
  1998. {
  1999. OwnedConstRoxieRow in = input->nextInGroup();
  2000. if (!in)
  2001. {
  2002. recordCount = 0;
  2003. if (numProcessedLastGroup == processed)
  2004. in.setown(input->nextInGroup());
  2005. if (!in)
  2006. {
  2007. numProcessedLastGroup = processed;
  2008. return NULL;
  2009. }
  2010. }
  2011. try
  2012. {
  2013. RtlDynamicRowBuilder rowBuilder(rowAllocator);
  2014. size32_t outSize = helper.transform(rowBuilder, in, ++recordCount);
  2015. if (outSize)
  2016. {
  2017. processed++;
  2018. return rowBuilder.finalizeRowClear(outSize);
  2019. }
  2020. }
  2021. catch(IException * e)
  2022. {
  2023. throw makeWrappedException(e);
  2024. }
  2025. }
  2026. }
  2027. //=====================================================================================================
  2028. CHThorRollupActivity::CHThorRollupActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorRollupArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  2029. {
  2030. }
  2031. CHThorRollupActivity::~CHThorRollupActivity()
  2032. {
  2033. }
  2034. void CHThorRollupActivity::ready()
  2035. {
  2036. CHThorSimpleActivityBase::ready();
  2037. left.setown(input->nextInGroup());
  2038. prev.set(left);
  2039. }
  2040. void CHThorRollupActivity::done()
  2041. {
  2042. left.clear();
  2043. prev.clear();
  2044. right.clear();
  2045. CHThorSimpleActivityBase::done();
  2046. }
  2047. const void *CHThorRollupActivity::nextInGroup()
  2048. {
  2049. loop
  2050. {
  2051. right.setown(input->nextInGroup());
  2052. if(!prev || !right || !helper.matches(prev,right))
  2053. {
  2054. const void * ret = left.getClear();
  2055. if(ret)
  2056. {
  2057. processed++;
  2058. }
  2059. left.setown(right.getClear());
  2060. prev.set(left);
  2061. return ret;
  2062. }
  2063. try
  2064. {
  2065. //MORE: could optimise by reusing buffer, but would have to make sure to call destructor on previous contents before overwriting
  2066. RtlDynamicRowBuilder rowBuilder(rowAllocator);
  2067. if(unsigned outSize = helper.transform(rowBuilder, left, right))
  2068. {
  2069. left.setown(rowBuilder.finalizeRowClear(outSize));
  2070. }
  2071. if (helper.getFlags() & RFrolledismatchleft)
  2072. prev.set(left);
  2073. else
  2074. prev.set(right);
  2075. }
  2076. catch(IException * e)
  2077. {
  2078. throw makeWrappedException(e);
  2079. }
  2080. }
  2081. }
  2082. //=====================================================================================================
  2083. CHThorGroupDedupActivity::CHThorGroupDedupActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorDedupArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  2084. {
  2085. }
  2086. void CHThorGroupDedupActivity::ready()
  2087. {
  2088. CHThorSimpleActivityBase::ready();
  2089. numToKeep = helper.numToKeep();
  2090. numKept = 0;
  2091. }
  2092. //=====================================================================================================
  2093. CHThorGroupDedupKeepLeftActivity::CHThorGroupDedupKeepLeftActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorDedupArg &_arg, ThorActivityKind _kind) : CHThorGroupDedupActivity(_agent, _activityId, _subgraphId, _arg, _kind)
  2094. {
  2095. }
  2096. void CHThorGroupDedupKeepLeftActivity::ready()
  2097. {
  2098. CHThorGroupDedupActivity::ready();
  2099. prev.clear();
  2100. }
  2101. void CHThorGroupDedupKeepLeftActivity::done()
  2102. {
  2103. prev.clear();
  2104. CHThorSimpleActivityBase::done();
  2105. }
  2106. const void *CHThorGroupDedupKeepLeftActivity::nextInGroup()
  2107. {
  2108. OwnedConstRoxieRow next;
  2109. loop
  2110. {
  2111. next.setown(input->nextInGroup());
  2112. if (!prev || !next || !helper.matches(prev,next))
  2113. {
  2114. numKept = 0;
  2115. break;
  2116. }
  2117. if (numKept < numToKeep-1)
  2118. {
  2119. numKept++;
  2120. break;
  2121. }
  2122. }
  2123. const void * ret = next.getClear();
  2124. prev.set(ret);
  2125. if(ret)
  2126. processed++;
  2127. return ret;
  2128. }
  2129. const void * CHThorGroupDedupKeepLeftActivity::nextGE(const void * seek, unsigned numFields)
  2130. {
  2131. OwnedConstRoxieRow next;
  2132. loop
  2133. {
  2134. next.setown(input->nextGE(seek, numFields));
  2135. if (!prev || !next || !helper.matches(prev,next))
  2136. {
  2137. numKept = 0;
  2138. break;
  2139. }
  2140. if (numKept < numToKeep-1)
  2141. {
  2142. numKept++;
  2143. break;
  2144. }
  2145. }
  2146. const void * ret = next.getClear();
  2147. prev.set(ret);
  2148. if(ret)
  2149. processed++;
  2150. return ret;
  2151. }
  2152. void CHThorGroupDedupKeepLeftActivity::setInput(unsigned index, IHThorInput *_input)
  2153. {
  2154. CHThorGroupDedupActivity::setInput(index, _input);
  2155. if (input)
  2156. inputStepping = input->querySteppingMeta();
  2157. }
  2158. IInputSteppingMeta * CHThorGroupDedupKeepLeftActivity::querySteppingMeta()
  2159. {
  2160. return inputStepping;
  2161. }
  2162. bool CHThorGroupDedupKeepLeftActivity::gatherConjunctions(ISteppedConjunctionCollector & collector)
  2163. {
  2164. return input->gatherConjunctions(collector);
  2165. }
  2166. void CHThorGroupDedupKeepLeftActivity::resetEOF()
  2167. {
  2168. input->resetEOF();
  2169. }
  2170. //=====================================================================================================
  2171. CHThorGroupDedupKeepRightActivity::CHThorGroupDedupKeepRightActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorDedupArg &_arg, ThorActivityKind _kind) : CHThorGroupDedupActivity(_agent, _activityId, _subgraphId, _arg, _kind)
  2172. {
  2173. }
  2174. void CHThorGroupDedupKeepRightActivity::ready()
  2175. {
  2176. CHThorGroupDedupActivity::ready();
  2177. assertex(numToKeep==1);
  2178. firstDone = false;
  2179. }
  2180. void CHThorGroupDedupKeepRightActivity::done()
  2181. {
  2182. kept.clear();
  2183. CHThorGroupDedupActivity::done();
  2184. }
  2185. const void *CHThorGroupDedupKeepRightActivity::nextInGroup()
  2186. {
  2187. if (!firstDone)
  2188. {
  2189. firstDone = true;
  2190. kept.setown(input->nextInGroup());
  2191. }
  2192. OwnedConstRoxieRow next;
  2193. loop
  2194. {
  2195. next.setown(input->nextInGroup());
  2196. if (!kept || !next || !helper.matches(kept,next))
  2197. {
  2198. numKept = 0;
  2199. break;
  2200. }
  2201. if (numKept < numToKeep-1)
  2202. {
  2203. numKept++;
  2204. break;
  2205. }
  2206. kept.setown(next.getClear());
  2207. }
  2208. const void * ret = kept.getClear();
  2209. kept.setown(next.getClear());
  2210. if(ret)
  2211. processed++;
  2212. return ret;
  2213. }
  2214. //=====================================================================================================
  2215. CHThorGroupDedupAllActivity::CHThorGroupDedupAllActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorDedupArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  2216. {
  2217. }
  2218. void CHThorGroupDedupAllActivity::ready()
  2219. {
  2220. CHThorSimpleActivityBase::ready();
  2221. keepLeft = helper.keepLeft();
  2222. primaryCompare = helper.queryComparePrimary();
  2223. assertex(helper.numToKeep() == 1);
  2224. firstDone = false;
  2225. survivorIndex = 0;
  2226. }
  2227. void CHThorGroupDedupAllActivity::done()
  2228. {
  2229. survivors.clear();
  2230. CHThorSimpleActivityBase::done();
  2231. }
  2232. bool CHThorGroupDedupAllActivity::calcNextDedupAll()
  2233. {
  2234. survivors.clear();
  2235. survivorIndex = 0;
  2236. OwnedRowArray group;
  2237. const void * next;
  2238. while((next = input->nextInGroup()) != NULL)
  2239. group.append(next);
  2240. if(group.ordinality() == 0)
  2241. return false;
  2242. unsigned max = group.ordinality();
  2243. if (primaryCompare)
  2244. {
  2245. //hard, if not impossible, to hit this code once optimisations in place
  2246. MemoryAttr indexbuff(max*sizeof(void *));
  2247. void ** temp = (void **)indexbuff.bufferBase();
  2248. void ** rows = (void * *)group.getArray();
  2249. msortvecstableinplace(rows, max, *primaryCompare, temp);
  2250. unsigned first = 0;
  2251. for (unsigned idx = 1; idx < max; idx++)
  2252. {
  2253. if (primaryCompare->docompare(rows[first], rows[idx]) != 0)
  2254. {
  2255. dedupRange(first, idx, group);
  2256. first = idx;
  2257. }
  2258. }
  2259. dedupRange(first, max, group);
  2260. for(unsigned idx2=0; idx2<max; ++idx2)
  2261. {
  2262. void * cur = rows[idx2];
  2263. if(cur)
  2264. {
  2265. LinkRoxieRow(cur);
  2266. survivors.append(cur);
  2267. }
  2268. }
  2269. }
  2270. else
  2271. {
  2272. dedupRange(0, max, group);
  2273. for(unsigned idx=0; idx<max; ++idx)
  2274. {
  2275. const void * cur = group.itemClear(idx);
  2276. if(cur)
  2277. survivors.append(cur);
  2278. }
  2279. }
  2280. return true;
  2281. }
  2282. void CHThorGroupDedupAllActivity::dedupRange(unsigned first, unsigned last, OwnedRowArray & group)
  2283. {
  2284. for (unsigned idxL = first; idxL < last; idxL++)
  2285. {
  2286. const void * left = group.item(idxL);
  2287. if (left)
  2288. {
  2289. for (unsigned idxR = first; idxR < last; idxR++)
  2290. {
  2291. const void * right = group.item(idxR);
  2292. if ((idxL != idxR) && right)
  2293. {
  2294. if (helper.matches(left, right))
  2295. {
  2296. if (keepLeft)
  2297. {
  2298. group.replace(NULL, idxR);
  2299. }
  2300. else
  2301. {
  2302. group.replace(NULL, idxL);
  2303. break;
  2304. }
  2305. }
  2306. }
  2307. }
  2308. }
  2309. }
  2310. }
  2311. const void *CHThorGroupDedupAllActivity::nextInGroup()
  2312. {
  2313. if (!firstDone)
  2314. {
  2315. firstDone = true;
  2316. calcNextDedupAll();
  2317. }
  2318. if(survivors.isItem(survivorIndex))
  2319. {
  2320. processed++;
  2321. return survivors.itemClear(survivorIndex++);
  2322. }
  2323. calcNextDedupAll();
  2324. return NULL;
  2325. }
  2326. //=====================================================================================================
  2327. bool HashDedupTable::insert(const void * row)
  2328. {
  2329. unsigned hash = helper.queryHash()->hash(row);
  2330. RtlDynamicRowBuilder keyRowBuilder(keyRowAllocator, true);
  2331. size32_t thisKeySize = helper.recordToKey(keyRowBuilder, row);
  2332. OwnedConstRoxieRow keyRow = keyRowBuilder.finalizeRowClear(thisKeySize);
  2333. if (find(hash, keyRow.get()))
  2334. return false;
  2335. addNew(new HashDedupElement(hash, keyRow.getClear()), hash);
  2336. return true;
  2337. }
  2338. CHThorHashDedupActivity::CHThorHashDedupActivity(IAgentContext & _agent, unsigned _activityId, unsigned _subgraphId, IHThorHashDedupArg & _arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg), table(_arg, activityId)
  2339. {
  2340. }
  2341. void CHThorHashDedupActivity::ready()
  2342. {
  2343. CHThorSimpleActivityBase::ready();
  2344. table.setRowAllocator(agent.queryCodeContext()->getRowAllocator(helper.queryKeySize(), activityId));
  2345. }
  2346. void CHThorHashDedupActivity::done()
  2347. {
  2348. table.kill();
  2349. CHThorSimpleActivityBase::done();
  2350. }
  2351. const void * CHThorHashDedupActivity::nextInGroup()
  2352. {
  2353. while(true)
  2354. {
  2355. OwnedConstRoxieRow next(input->nextInGroup());
  2356. if(!next)
  2357. {
  2358. table.kill();
  2359. return NULL;
  2360. }
  2361. if(table.insert(next))
  2362. return next.getClear();
  2363. }
  2364. }
  2365. //=====================================================================================================
  2366. CHThorSteppableActivityBase::CHThorSteppableActivityBase(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorArg & _help, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _help, _kind)
  2367. {
  2368. inputStepping = NULL;
  2369. stepCompare = NULL;
  2370. }
  2371. void CHThorSteppableActivityBase::setInput(unsigned index, IHThorInput *_input)
  2372. {
  2373. CHThorSimpleActivityBase::setInput(index, _input);
  2374. if (input && index == 0)
  2375. {
  2376. inputStepping = input->querySteppingMeta();
  2377. if (inputStepping)
  2378. stepCompare = inputStepping->queryCompare();
  2379. }
  2380. }
  2381. IInputSteppingMeta * CHThorSteppableActivityBase::querySteppingMeta()
  2382. {
  2383. return inputStepping;
  2384. }
  2385. //=====================================================================================================
  2386. CHThorFilterActivity::CHThorFilterActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorFilterArg &_arg, ThorActivityKind _kind) : CHThorSteppableActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  2387. {
  2388. }
  2389. void CHThorFilterActivity::ready()
  2390. {
  2391. CHThorSimpleActivityBase::ready();
  2392. anyThisGroup = false;
  2393. eof = !helper.canMatchAny();
  2394. }
  2395. const void * CHThorFilterActivity::nextInGroup()
  2396. {
  2397. if (eof)
  2398. return NULL;
  2399. loop
  2400. {
  2401. OwnedConstRoxieRow ret(input->nextInGroup());
  2402. if (!ret)
  2403. {
  2404. //stop returning two NULLs in a row.
  2405. if (anyThisGroup)
  2406. {
  2407. anyThisGroup = false;
  2408. return NULL;
  2409. }
  2410. ret.setown(input->nextInGroup());
  2411. if (!ret)
  2412. return NULL; // eof...
  2413. }
  2414. if (helper.isValid(ret))
  2415. {
  2416. anyThisGroup = true;
  2417. processed++;
  2418. return ret.getClear();
  2419. }
  2420. }
  2421. }
  2422. const void * CHThorFilterActivity::nextGE(const void * seek, unsigned numFields)
  2423. {
  2424. if (eof)
  2425. return NULL;
  2426. OwnedConstRoxieRow ret(input->nextGE(seek, numFields));
  2427. if (!ret)
  2428. return NULL;
  2429. if (helper.isValid(ret))
  2430. {
  2431. anyThisGroup = true;
  2432. processed++;
  2433. return ret.getClear();
  2434. }
  2435. return nextUngrouped();
  2436. }
  2437. bool CHThorFilterActivity::gatherConjunctions(ISteppedConjunctionCollector & collector)
  2438. {
  2439. return input->gatherConjunctions(collector);
  2440. }
  2441. void CHThorFilterActivity::resetEOF()
  2442. {
  2443. //Sometimes the smart stepping code returns a premature eof indicator (two nulls) and will
  2444. //therefore call resetEOF so the activity can reset its eof without resetting the activity itself.
  2445. //Note that resetEOF only needs to be implemented by activities that implement gatherConjunctions()
  2446. //and that cache eof.
  2447. eof = false;
  2448. anyThisGroup = false;
  2449. input->resetEOF();
  2450. }
  2451. //=====================================================================================================
  2452. CHThorFilterGroupActivity::CHThorFilterGroupActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorFilterGroupArg &_arg, ThorActivityKind _kind) : CHThorSteppableActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  2453. {
  2454. }
  2455. void CHThorFilterGroupActivity::ready()
  2456. {
  2457. CHThorSimpleActivityBase::ready();
  2458. eof = !helper.canMatchAny();
  2459. nextIndex = 0;
  2460. }
  2461. void CHThorFilterGroupActivity::done()
  2462. {
  2463. CHThorSimpleActivityBase::done();
  2464. pending.clear();
  2465. }
  2466. const void * CHThorFilterGroupActivity::nextInGroup()
  2467. {
  2468. loop
  2469. {
  2470. if (eof)
  2471. return NULL;
  2472. if (pending.ordinality())
  2473. {
  2474. if (pending.isItem(nextIndex))
  2475. {
  2476. processed++;
  2477. return pending.itemClear(nextIndex++);
  2478. }
  2479. nextIndex = 0;
  2480. pending.clear();
  2481. return NULL;
  2482. }
  2483. const void * ret = input->nextInGroup();
  2484. while (ret)
  2485. {
  2486. pending.append(ret);
  2487. ret = input->nextInGroup();
  2488. }
  2489. unsigned num = pending.ordinality();
  2490. if (num != 0)
  2491. {
  2492. if (!helper.isValid(num, (const void * *)pending.getArray()))
  2493. pending.clear(); // read next group
  2494. }
  2495. else
  2496. eof = true;
  2497. }
  2498. }
  2499. const void * CHThorFilterGroupActivity::nextGE(const void * seek, unsigned numFields)
  2500. {
  2501. if (eof)
  2502. return NULL;
  2503. if (pending.ordinality())
  2504. {
  2505. while (pending.isItem(nextIndex))
  2506. {
  2507. OwnedConstRoxieRow ret(pending.itemClear(nextIndex++));
  2508. if (stepCompare->docompare(ret, seek, numFields) >= 0)
  2509. {
  2510. processed++;
  2511. return ret.getClear();
  2512. }
  2513. }
  2514. nextIndex = 0;
  2515. pending.clear();
  2516. }
  2517. const void * ret = input->nextGE(seek, numFields);
  2518. while (ret)
  2519. {
  2520. pending.append(ret);
  2521. ret = input->nextInGroup();
  2522. }
  2523. unsigned num = pending.ordinality();
  2524. if (num != 0)
  2525. {
  2526. if (!helper.isValid(num, (const void * *)pending.getArray()))
  2527. pending.clear(); // read next group
  2528. }
  2529. else
  2530. eof = true;
  2531. return nextUngrouped();
  2532. }
  2533. //=====================================================================================================
  2534. CHThorLimitActivity::CHThorLimitActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorLimitArg &_arg, ThorActivityKind _kind) : CHThorSteppableActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  2535. {
  2536. }
  2537. void CHThorLimitActivity::ready()
  2538. {
  2539. CHThorSimpleActivityBase::ready();
  2540. rowLimit = helper.getRowLimit();
  2541. numGot = 0;
  2542. }
  2543. const void * CHThorLimitActivity::nextInGroup()
  2544. {
  2545. OwnedConstRoxieRow ret(input->nextInGroup());
  2546. if (ret)
  2547. {
  2548. if (++numGot > rowLimit)
  2549. {
  2550. if ( agent.queryCodeContext()->queryDebugContext())
  2551. agent.queryCodeContext()->queryDebugContext()->checkBreakpoint(DebugStateLimit, NULL, static_cast<IActivityBase *>(this));
  2552. helper.onLimitExceeded();
  2553. return NULL;
  2554. }
  2555. processed++;
  2556. }
  2557. return ret.getClear();
  2558. }
  2559. const void * CHThorLimitActivity::nextGE(const void * seek, unsigned numFields)
  2560. {
  2561. OwnedConstRoxieRow ret(input->nextGE(seek, numFields));
  2562. if (ret)
  2563. {
  2564. if (++numGot > rowLimit)
  2565. {
  2566. if ( agent.queryCodeContext()->queryDebugContext())
  2567. agent.queryCodeContext()->queryDebugContext()->checkBreakpoint(DebugStateLimit, NULL, static_cast<IActivityBase *>(this));
  2568. helper.onLimitExceeded();
  2569. return NULL;
  2570. }
  2571. processed++;
  2572. }
  2573. return ret.getClear();
  2574. }
  2575. //=====================================================================================================
  2576. CHThorSkipLimitActivity::CHThorSkipLimitActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorLimitArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  2577. {
  2578. }
  2579. void CHThorSkipLimitActivity::ready()
  2580. {
  2581. CHThorSimpleActivityBase::ready();
  2582. rowLimit = helper.getRowLimit();
  2583. }
  2584. void CHThorSkipLimitActivity::done()
  2585. {
  2586. CHThorSimpleActivityBase::done();
  2587. buffer.clear();
  2588. }
  2589. const void * CHThorSkipLimitActivity::nextInGroup()
  2590. {
  2591. if(!buffer)
  2592. {
  2593. buffer.setown(new CRowBuffer(input->queryOutputMeta(), true));
  2594. if(!buffer->pull(input, rowLimit))
  2595. {
  2596. if ( agent.queryCodeContext()->queryDebugContext())
  2597. agent.queryCodeContext()->queryDebugContext()->checkBreakpoint(DebugStateLimit, NULL, static_cast<IActivityBase *>(this));
  2598. onLimitExceeded();
  2599. }
  2600. }
  2601. const void * next = buffer->next();
  2602. if(next)
  2603. processed++;
  2604. return next;
  2605. }
  2606. //=====================================================================================================
  2607. CHThorCatchActivity::CHThorCatchActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorCatchArg &_arg, ThorActivityKind _kind) : CHThorSteppableActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  2608. {
  2609. }
  2610. const void * CHThorCatchActivity::nextInGroup()
  2611. {
  2612. try
  2613. {
  2614. OwnedConstRoxieRow ret(input->nextInGroup());
  2615. if (ret)
  2616. processed++;
  2617. return ret.getClear();
  2618. }
  2619. catch (IException *E)
  2620. {
  2621. E->Release();
  2622. helper.onExceptionCaught();
  2623. }
  2624. catch (...)
  2625. {
  2626. helper.onExceptionCaught();
  2627. }
  2628. throwUnexpected(); // onExceptionCaught should have thrown something
  2629. }
  2630. const void * CHThorCatchActivity::nextGE(const void * seek, unsigned numFields)
  2631. {
  2632. try
  2633. {
  2634. OwnedConstRoxieRow ret(input->nextGE(seek, numFields));
  2635. if (ret)
  2636. processed++;
  2637. return ret.getClear();
  2638. }
  2639. catch (IException *E)
  2640. {
  2641. E->Release();
  2642. helper.onExceptionCaught();
  2643. }
  2644. catch (...)
  2645. {
  2646. helper.onExceptionCaught();
  2647. }
  2648. throwUnexpected(); // onExceptionCaught should have thrown something
  2649. }
  2650. //=====================================================================================================
  2651. CHThorSkipCatchActivity::CHThorSkipCatchActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorCatchArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  2652. {
  2653. }
  2654. void CHThorSkipCatchActivity::done()
  2655. {
  2656. CHThorSimpleActivityBase::done();
  2657. buffer.clear();
  2658. }
  2659. void CHThorSkipCatchActivity::onException(IException *E)
  2660. {
  2661. buffer->clear();
  2662. if (kind == TAKcreaterowcatch)
  2663. {
  2664. createRowAllocator();
  2665. RtlDynamicRowBuilder rowBuilder(rowAllocator);
  2666. size32_t newSize = helper.transformOnExceptionCaught(rowBuilder, E);
  2667. if (newSize)
  2668. buffer->insert(rowBuilder.finalizeRowClear(newSize));
  2669. }
  2670. E->Release();
  2671. }
  2672. const void * CHThorSkipCatchActivity::nextInGroup()
  2673. {
  2674. if(!buffer)
  2675. {
  2676. buffer.setown(new CRowBuffer(input->queryOutputMeta(), true));
  2677. try
  2678. {
  2679. buffer->pull(input, (unsigned __int64) -1);
  2680. }
  2681. catch (IException *E)
  2682. {
  2683. onException(E);
  2684. }
  2685. catch (...)
  2686. {
  2687. onException(MakeStringException(2, "Unknown exception caught"));
  2688. }
  2689. }
  2690. const void * next = buffer->next();
  2691. if(next)
  2692. processed++;
  2693. return next;
  2694. }
  2695. //=====================================================================================================
  2696. CHThorOnFailLimitActivity::CHThorOnFailLimitActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorLimitArg &_arg, ThorActivityKind _kind) : CHThorSkipLimitActivity(_agent, _activityId, _subgraphId, _arg, _kind)
  2697. {
  2698. transformExtra = static_cast<IHThorLimitTransformExtra *>(helper.selectInterface(TAIlimittransformextra_1));
  2699. assertex(transformExtra);
  2700. }
  2701. void CHThorOnFailLimitActivity::onLimitExceeded()
  2702. {
  2703. buffer->clear();
  2704. RtlDynamicRowBuilder rowBuilder(rowAllocator);
  2705. size32_t newSize = transformExtra->transformOnLimitExceeded(rowBuilder);
  2706. if (newSize)
  2707. buffer->insert(rowBuilder.finalizeRowClear(newSize));
  2708. }
  2709. //=====================================================================================================
  2710. CHThorIfActivity::CHThorIfActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorIfArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  2711. {
  2712. inputTrue = NULL;
  2713. inputFalse = NULL;
  2714. selectedInput = NULL;
  2715. }
  2716. void CHThorIfActivity::done()
  2717. {
  2718. if (selectedInput)
  2719. selectedInput->done();
  2720. CHThorSimpleActivityBase::done();
  2721. }
  2722. void CHThorIfActivity::ready()
  2723. {
  2724. CHThorSimpleActivityBase::ready();
  2725. selectedInput = helper.getCondition() ? inputTrue : inputFalse;
  2726. if (selectedInput)
  2727. selectedInput->ready();
  2728. }
  2729. void CHThorIfActivity::setInput(unsigned index, IHThorInput *_input)
  2730. {
  2731. if (index==0)
  2732. inputTrue = _input;
  2733. else if (index == 1)
  2734. inputFalse = _input;
  2735. else
  2736. CHThorActivityBase::setInput(index, _input);
  2737. }
  2738. const void * CHThorIfActivity::nextInGroup()
  2739. {
  2740. if (!selectedInput)
  2741. return NULL;
  2742. const void *ret = selectedInput->nextInGroup();
  2743. if (ret)
  2744. processed++;
  2745. return ret;
  2746. }
  2747. //=====================================================================================================
  2748. CHThorCaseActivity::CHThorCaseActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorCaseArg &_arg, ThorActivityKind _kind) : CHThorMultiInputActivity(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  2749. {
  2750. }
  2751. void CHThorCaseActivity::ready()
  2752. {
  2753. //Evaluate the condition here to avoid calling ready() on the unused branch?
  2754. initialProcessed = processed;
  2755. selectedInput = NULL;
  2756. unsigned whichBranch = helper.getBranch();
  2757. if (whichBranch >= inputs.ordinality())
  2758. whichBranch = inputs.ordinality()-1;
  2759. selectedInput = inputs.item(whichBranch);
  2760. selectedInput->ready();
  2761. }
  2762. void CHThorCaseActivity::done()
  2763. {
  2764. if (selectedInput)
  2765. selectedInput->done();
  2766. }
  2767. const void *CHThorCaseActivity::nextInGroup()
  2768. {
  2769. if (!selectedInput)
  2770. return NULL;
  2771. const void *ret = selectedInput->nextInGroup();
  2772. if (ret)
  2773. processed++;
  2774. return ret;
  2775. }
  2776. //=====================================================================================================
  2777. CHThorSampleActivity::CHThorSampleActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorSampleArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  2778. {
  2779. }
  2780. void CHThorSampleActivity::ready()
  2781. {
  2782. CHThorSimpleActivityBase::ready();
  2783. numSamples = helper.getProportion();
  2784. whichSample = helper.getSampleNumber();
  2785. numToSkip = (whichSample ? whichSample-1 : 0);
  2786. anyThisGroup = false;
  2787. }
  2788. const void * CHThorSampleActivity::nextInGroup()
  2789. {
  2790. loop
  2791. {
  2792. OwnedConstRoxieRow ret(input->nextInGroup());
  2793. if (!ret)
  2794. {
  2795. //this does work with groups - may or may not be useful...
  2796. //reset the sample for each group.... probably best.
  2797. numToSkip = (whichSample ? whichSample-1 : 0);
  2798. if (anyThisGroup)
  2799. {
  2800. anyThisGroup = false;
  2801. return NULL;
  2802. }
  2803. ret.setown(input->nextInGroup());
  2804. if (!ret)
  2805. return NULL; // eof...
  2806. }
  2807. if (numToSkip == 0)
  2808. {
  2809. anyThisGroup = true;
  2810. numToSkip = numSamples-1;
  2811. processed++;
  2812. return ret.getClear();
  2813. }
  2814. numToSkip--;
  2815. }
  2816. }
  2817. //=====================================================================================================
  2818. CHThorAggregateActivity::CHThorAggregateActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorAggregateArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  2819. {
  2820. }
  2821. void CHThorAggregateActivity::ready()
  2822. {
  2823. CHThorSimpleActivityBase::ready();
  2824. eof = false;
  2825. }
  2826. const void * CHThorAggregateActivity::nextInGroup()
  2827. {
  2828. if (eof)
  2829. return NULL;
  2830. unsigned count = 0;
  2831. const void * next = input->nextInGroup();
  2832. if (!next && input->isGrouped())
  2833. {
  2834. eof = true;
  2835. return NULL;
  2836. }
  2837. RtlDynamicRowBuilder rowBuilder(rowAllocator);
  2838. helper.clearAggregate(rowBuilder);
  2839. if (next)
  2840. {
  2841. helper.processFirst(rowBuilder, next);
  2842. ReleaseRoxieRow(next);
  2843. bool abortEarly = (kind == TAKexistsaggregate) && !input->isGrouped();
  2844. if (!abortEarly)
  2845. {
  2846. loop
  2847. {
  2848. next = input->nextInGroup();
  2849. if (!next)
  2850. break;
  2851. helper.processNext(rowBuilder, next);
  2852. ReleaseRoxieRow(next);
  2853. }
  2854. }
  2855. }
  2856. if (!input->isGrouped()) // either read all, or aborted early
  2857. eof = true;
  2858. count++;
  2859. size32_t finalSize = outputMeta.getRecordSize(rowBuilder.getSelf());
  2860. return rowBuilder.finalizeRowClear(finalSize);
  2861. }
  2862. //=====================================================================================================
  2863. CHThorHashAggregateActivity::CHThorHashAggregateActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorHashAggregateArg &_arg, ThorActivityKind _kind, bool _isGroupedAggregate)
  2864. : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg),
  2865. isGroupedAggregate(_isGroupedAggregate),
  2866. aggregated(_arg, _arg)
  2867. {
  2868. }
  2869. void CHThorHashAggregateActivity::ready()
  2870. {
  2871. CHThorSimpleActivityBase::ready();
  2872. eof = false;
  2873. gathered = false;
  2874. }
  2875. void CHThorHashAggregateActivity::done()
  2876. {
  2877. aggregated.reset();
  2878. CHThorSimpleActivityBase::done();
  2879. }
  2880. const void * CHThorHashAggregateActivity::nextInGroup()
  2881. {
  2882. if (eof)
  2883. return NULL;
  2884. if (!gathered)
  2885. {
  2886. bool eog = true;
  2887. aggregated.start(rowAllocator);
  2888. loop
  2889. {
  2890. OwnedConstRoxieRow next(input->nextInGroup());
  2891. if (!next)
  2892. {
  2893. if (isGroupedAggregate)
  2894. {
  2895. if (eog)
  2896. eof = true;
  2897. break;
  2898. }
  2899. next.setown(input->nextInGroup());
  2900. if (!next)
  2901. break;
  2902. }
  2903. eog = false;
  2904. try
  2905. {
  2906. aggregated.addRow(next);
  2907. }
  2908. catch(IException * e)
  2909. {
  2910. throw makeWrappedException(e);
  2911. }
  2912. }
  2913. gathered = true;
  2914. }
  2915. Owned<AggregateRowBuilder> next = aggregated.nextResult();
  2916. if (next)
  2917. {
  2918. processed++;
  2919. return next->finalizeRowClear();
  2920. }
  2921. if (!isGroupedAggregate)
  2922. eof = true;
  2923. aggregated.reset();
  2924. gathered = false;
  2925. return NULL;
  2926. }
  2927. //=====================================================================================================
  2928. CHThorSelectNActivity::CHThorSelectNActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorSelectNArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  2929. {
  2930. }
  2931. const void * CHThorSelectNActivity::defaultRow()
  2932. {
  2933. if (!rowAllocator)
  2934. createRowAllocator(); //We delay as often not needed...
  2935. RtlDynamicRowBuilder rowBuilder(rowAllocator);
  2936. size32_t thisSize = helper.createDefault(rowBuilder);
  2937. return rowBuilder.finalizeRowClear(thisSize);
  2938. }
  2939. void CHThorSelectNActivity::ready()
  2940. {
  2941. CHThorSimpleActivityBase::ready();
  2942. finished = false;
  2943. }
  2944. const void * CHThorSelectNActivity::nextInGroup()
  2945. {
  2946. if (finished)
  2947. return NULL;
  2948. finished = true;
  2949. unsigned __int64 index = helper.getRowToSelect();
  2950. while (--index)
  2951. {
  2952. OwnedConstRoxieRow next(input->nextInGroup());
  2953. if (!next)
  2954. next.setown(input->nextInGroup());
  2955. if (!next)
  2956. {
  2957. processed++;
  2958. return defaultRow();
  2959. }
  2960. }
  2961. OwnedConstRoxieRow next(input->nextInGroup());
  2962. if (!next)
  2963. next.setown(input->nextInGroup());
  2964. if (!next)
  2965. next.setown(defaultRow());
  2966. processed++;
  2967. return next.getClear();
  2968. }
  2969. //=====================================================================================================
  2970. CHThorFirstNActivity::CHThorFirstNActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorFirstNArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  2971. {
  2972. grouped = outputMeta.isGrouped();
  2973. }
  2974. void CHThorFirstNActivity::ready()
  2975. {
  2976. CHThorSimpleActivityBase::ready();
  2977. skip = helper.numToSkip();
  2978. limit = helper.getLimit();
  2979. doneThisGroup = 0;
  2980. finished = (limit == 0);
  2981. if (limit + skip >= limit)
  2982. limit += skip;
  2983. }
  2984. const void * CHThorFirstNActivity::nextInGroup()
  2985. {
  2986. if (finished)
  2987. return NULL;
  2988. OwnedConstRoxieRow ret;
  2989. loop
  2990. {
  2991. ret.setown(input->nextInGroup());
  2992. if (!ret)
  2993. {
  2994. if (grouped)
  2995. {
  2996. if (doneThisGroup > skip)
  2997. {
  2998. doneThisGroup = 0;
  2999. return NULL;
  3000. }
  3001. doneThisGroup = 0;
  3002. }
  3003. ret.setown(input->nextInGroup());
  3004. if (!ret)
  3005. {
  3006. finished = true;
  3007. return NULL;
  3008. }
  3009. }
  3010. doneThisGroup++;
  3011. if (doneThisGroup > skip)
  3012. break;
  3013. }
  3014. if (doneThisGroup <= limit)
  3015. {
  3016. processed++;
  3017. return ret.getClear();
  3018. }
  3019. if (grouped)
  3020. {
  3021. ret.setown(input->nextInGroup());
  3022. while (ret)
  3023. ret.setown(input->nextInGroup());
  3024. doneThisGroup = 0;
  3025. }
  3026. else
  3027. finished = true;
  3028. return NULL;
  3029. }
  3030. //=====================================================================================================
  3031. CHThorChooseSetsActivity::CHThorChooseSetsActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorChooseSetsArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  3032. {
  3033. numSets = helper.getNumSets();
  3034. setCounts = new unsigned[numSets];
  3035. }
  3036. CHThorChooseSetsActivity::~CHThorChooseSetsActivity()
  3037. {
  3038. delete [] setCounts;
  3039. }
  3040. void CHThorChooseSetsActivity::ready()
  3041. {
  3042. CHThorSimpleActivityBase::ready();
  3043. finished = false;
  3044. memset(setCounts, 0, sizeof(unsigned)*numSets);
  3045. helper.setCounts(setCounts);
  3046. }
  3047. const void * CHThorChooseSetsActivity::nextInGroup()
  3048. {
  3049. if (finished)
  3050. return NULL;
  3051. loop
  3052. {
  3053. OwnedConstRoxieRow ret(input->nextInGroup());
  3054. if (!ret)
  3055. {
  3056. ret.setown(input->nextInGroup());
  3057. if (!ret)
  3058. return NULL;
  3059. }
  3060. processed++;
  3061. switch (helper.getRecordAction(ret))
  3062. {
  3063. case 2:
  3064. finished = true;
  3065. return ret.getClear();
  3066. case 1:
  3067. return ret.getClear();
  3068. }
  3069. }
  3070. }
  3071. //=====================================================================================================
  3072. CHThorChooseSetsExActivity::CHThorChooseSetsExActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorChooseSetsExArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  3073. {
  3074. numSets = helper.getNumSets();
  3075. setCounts = new unsigned[numSets];
  3076. memset(setCounts, 0, sizeof(unsigned)*numSets);
  3077. limits = (count_t *)checked_calloc(sizeof(count_t), numSets, "choose sets ex");
  3078. helper.getLimits(limits);
  3079. }
  3080. CHThorChooseSetsExActivity::~CHThorChooseSetsExActivity()
  3081. {
  3082. delete [] setCounts;
  3083. free(limits);
  3084. }
  3085. void CHThorChooseSetsExActivity::ready()
  3086. {
  3087. CHThorSimpleActivityBase::ready();
  3088. finished = false;
  3089. curIndex = 0;
  3090. memset(setCounts, 0, sizeof(unsigned)*numSets);
  3091. }
  3092. void CHThorChooseSetsExActivity::done()
  3093. {
  3094. gathered.clear();
  3095. CHThorSimpleActivityBase::done();
  3096. }
  3097. const void * CHThorChooseSetsExActivity::nextInGroup()
  3098. {
  3099. if (gathered.ordinality() == 0)
  3100. {
  3101. curIndex = 0;
  3102. const void * next = input->nextInGroup();
  3103. while(next)
  3104. {
  3105. gathered.append(next);
  3106. next = input->nextInGroup();
  3107. }
  3108. if(gathered.ordinality() == 0)
  3109. {
  3110. finished = true;
  3111. return NULL;
  3112. }
  3113. ForEachItemIn(idx1, gathered)
  3114. {
  3115. unsigned category = helper.getCategory(gathered.item(idx1));
  3116. if (category)
  3117. setCounts[category-1]++;
  3118. }
  3119. calculateSelection();
  3120. }
  3121. while (gathered.isItem(curIndex))
  3122. {
  3123. OwnedConstRoxieRow row(gathered.itemClear(curIndex++));
  3124. if (includeRow(row))
  3125. {
  3126. processed++;
  3127. return row.getClear();
  3128. }
  3129. }
  3130. gathered.clear();
  3131. return NULL;
  3132. }
  3133. //=====================================================================================================
  3134. CHThorChooseSetsLastActivity::CHThorChooseSetsLastActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorChooseSetsExArg &_arg, ThorActivityKind _kind) : CHThorChooseSetsExActivity(_agent, _activityId, _subgraphId, _arg, _kind)
  3135. {
  3136. numToSkip = (unsigned *)checked_calloc(sizeof(unsigned), numSets, "choose sets last");
  3137. }
  3138. CHThorChooseSetsLastActivity::~CHThorChooseSetsLastActivity()
  3139. {
  3140. free(numToSkip);
  3141. }
  3142. void CHThorChooseSetsLastActivity::ready()
  3143. {
  3144. CHThorChooseSetsExActivity::ready();
  3145. memset(numToSkip, 0, sizeof(unsigned) * numSets);
  3146. }
  3147. void CHThorChooseSetsLastActivity::calculateSelection()
  3148. {
  3149. for (unsigned idx=0; idx < numSets; idx++)
  3150. {
  3151. if (setCounts[idx] < limits[idx])
  3152. numToSkip[idx] = 0;
  3153. else
  3154. numToSkip[idx] = (unsigned)(setCounts[idx] - limits[idx]);
  3155. }
  3156. }
  3157. bool CHThorChooseSetsLastActivity::includeRow(const void * row)
  3158. {
  3159. unsigned category = helper.getCategory(row);
  3160. if (category)
  3161. {
  3162. if (numToSkip[category-1] == 0)
  3163. return true;
  3164. numToSkip[category-1]--;
  3165. }
  3166. return false;
  3167. }
  3168. //=====================================================================================================
  3169. CHThorChooseSetsEnthActivity::CHThorChooseSetsEnthActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorChooseSetsExArg &_arg, ThorActivityKind _kind) : CHThorChooseSetsExActivity(_agent, _activityId, _subgraphId, _arg, _kind)
  3170. {
  3171. counter = (unsigned __int64 *)checked_calloc(sizeof(unsigned __int64), numSets, "choose sets enth");
  3172. }
  3173. CHThorChooseSetsEnthActivity::~CHThorChooseSetsEnthActivity()
  3174. {
  3175. free(counter);
  3176. }
  3177. void CHThorChooseSetsEnthActivity::ready()
  3178. {
  3179. CHThorChooseSetsExActivity::ready();
  3180. memset(counter, 0, sizeof(unsigned __int64) * numSets);
  3181. }
  3182. void CHThorChooseSetsEnthActivity::calculateSelection()
  3183. {
  3184. }
  3185. bool CHThorChooseSetsEnthActivity::includeRow(const void * row)
  3186. {
  3187. unsigned category = helper.getCategory(row);
  3188. if (category)
  3189. {
  3190. counter[category-1] += limits[category-1];
  3191. if(counter[category-1] >= setCounts[category-1])
  3192. {
  3193. counter[category-1] -= setCounts[category-1];
  3194. return true;
  3195. }
  3196. }
  3197. return false;
  3198. }
  3199. //=====================================================================================================
  3200. CHThorDegroupActivity::CHThorDegroupActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorDegroupArg &_arg, ThorActivityKind _kind) : CHThorSteppableActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  3201. {
  3202. }
  3203. const void * CHThorDegroupActivity::nextInGroup()
  3204. {
  3205. const void * ret = input->nextUngrouped();
  3206. if (ret)
  3207. processed++;
  3208. return ret;
  3209. }
  3210. const void * CHThorDegroupActivity::nextGE(const void * seek, unsigned numFields)
  3211. {
  3212. const void * ret = input->nextGE(seek, numFields);
  3213. if (ret)
  3214. processed++;
  3215. return ret;
  3216. }
  3217. bool CHThorDegroupActivity::isGrouped()
  3218. {
  3219. return false;
  3220. }
  3221. //=====================================================================================================
  3222. CHThorGroupActivity::CHThorGroupActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorGroupArg &_arg, ThorActivityKind _kind) : CHThorSteppableActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  3223. {
  3224. }
  3225. bool CHThorGroupActivity::isGrouped()
  3226. {
  3227. return true;
  3228. }
  3229. void CHThorGroupActivity::ready()
  3230. {
  3231. CHThorSimpleActivityBase::ready();
  3232. next.clear();
  3233. endPending = false;
  3234. firstDone = false;
  3235. }
  3236. void CHThorGroupActivity::done()
  3237. {
  3238. CHThorSimpleActivityBase::done();
  3239. next.clear();
  3240. }
  3241. const void *CHThorGroupActivity::nextInGroup()
  3242. {
  3243. if (!firstDone)
  3244. {
  3245. firstDone = true;
  3246. next.setown(input->nextInGroup());
  3247. }
  3248. if (endPending)
  3249. {
  3250. endPending = false;
  3251. return NULL;
  3252. }
  3253. OwnedConstRoxieRow prev(next.getClear());
  3254. next.setown(input->nextInGroup());
  3255. if (!next) // skip incoming groups. (should it sub-group??)
  3256. next.setown(input->nextInGroup());
  3257. if (next)
  3258. {
  3259. assertex(prev); // If this fails, you have an initial empty group. That is not legal.
  3260. if (!helper.isSameGroup(prev, next))
  3261. endPending = true;
  3262. }
  3263. if (prev)
  3264. processed++;
  3265. return prev.getClear();
  3266. }
  3267. const void * CHThorGroupActivity::nextGE(const void * seek, unsigned numFields)
  3268. {
  3269. if (firstDone)
  3270. {
  3271. if (next)
  3272. {
  3273. if (stepCompare->docompare(next, seek, numFields) >= 0)
  3274. return nextInGroup();
  3275. }
  3276. }
  3277. next.setown(input->nextGE(seek, numFields));
  3278. firstDone = true;
  3279. return nextInGroup();
  3280. }
  3281. //=====================================================================================================
  3282. CHThorGroupSortActivity::CHThorGroupSortActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorSortArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  3283. {
  3284. gotSorted = false;
  3285. }
  3286. void CHThorGroupSortActivity::ready()
  3287. {
  3288. CHThorSimpleActivityBase::ready();
  3289. if(!sorter)
  3290. createSorter();
  3291. }
  3292. void CHThorGroupSortActivity::done()
  3293. {
  3294. if(sorter)
  3295. {
  3296. if(sorterIsConst)
  3297. sorter->killSorted();
  3298. else
  3299. sorter.clear();
  3300. }
  3301. gotSorted = false;
  3302. diskReader.clear();
  3303. CHThorSimpleActivityBase::done();
  3304. }
  3305. const void *CHThorGroupSortActivity::nextInGroup()
  3306. {
  3307. if(!gotSorted)
  3308. getSorted();
  3309. if(diskReader)
  3310. {
  3311. const void *row = diskReader->nextRow();
  3312. if (row)
  3313. return row;
  3314. diskReader.clear();
  3315. }
  3316. else
  3317. {
  3318. const void * ret = sorter->getNextSorted();
  3319. if(ret)
  3320. {
  3321. processed++;
  3322. return ret;
  3323. }
  3324. }
  3325. sorter->killSorted();
  3326. gotSorted = false;
  3327. return NULL;
  3328. }
  3329. void CHThorGroupSortActivity::createSorter()
  3330. {
  3331. IHThorAlgorithm * algo = static_cast<IHThorAlgorithm *>(helper.selectInterface(TAIalgorithm_1));
  3332. if(!algo)
  3333. {
  3334. sorter.setown(new CHeapSorter(helper.queryCompare(), queryRowManager(), InitialSortElements, CommitStep));
  3335. return;
  3336. }
  3337. unsigned flags = algo->getAlgorithmFlags();
  3338. sorterIsConst = ((flags & TAFconstant) != 0);
  3339. OwnedRoxieString algoname(algo->getAlgorithm());
  3340. if(!algoname)
  3341. {
  3342. if((flags & TAFunstable) != 0)
  3343. sorter.setown(new CQuickSorter(helper.queryCompare(), queryRowManager(), InitialSortElements, CommitStep));
  3344. else
  3345. sorter.setown(new CHeapSorter(helper.queryCompare(), queryRowManager(), InitialSortElements, CommitStep));
  3346. return;
  3347. }
  3348. if(stricmp(algoname, "quicksort") == 0)
  3349. {
  3350. if((flags & TAFstable) != 0)
  3351. sorter.setown(new CStableQuickSorter(helper.queryCompare(), queryRowManager(), InitialSortElements, CommitStep, this));
  3352. else
  3353. sorter.setown(new CQuickSorter(helper.queryCompare(), queryRowManager(), InitialSortElements, CommitStep));
  3354. }
  3355. else if(stricmp(algoname, "parquicksort") == 0)
  3356. {
  3357. if((flags & TAFstable) != 0)
  3358. sorter.setown(new CParallelStableQuickSorter(helper.queryCompare(), queryRowManager(), InitialSortElements, CommitStep, this));
  3359. else
  3360. sorter.setown(new CParallelQuickSorter(helper.queryCompare(), queryRowManager(), InitialSortElements, CommitStep));
  3361. }
  3362. else if(stricmp(algoname, "mergesort") == 0)
  3363. {
  3364. if((flags & TAFparallel) != 0)
  3365. sorter.setown(new CParallelStableMergeSorter(helper.queryCompare(), queryRowManager(), InitialSortElements, CommitStep, this));
  3366. else
  3367. sorter.setown(new CStableMergeSorter(helper.queryCompare(), queryRowManager(), InitialSortElements, CommitStep, this));
  3368. }
  3369. else if(stricmp(algoname, "parmergesort") == 0)
  3370. sorter.setown(new CParallelStableMergeSorter(helper.queryCompare(), queryRowManager(), InitialSortElements, CommitStep, this));
  3371. else if(stricmp(algoname, "heapsort") == 0)
  3372. sorter.setown(new CHeapSorter(helper.queryCompare(), queryRowManager(), InitialSortElements, CommitStep));
  3373. else if(stricmp(algoname, "insertionsort") == 0)
  3374. {
  3375. if((flags & TAFstable) != 0)
  3376. sorter.setown(new CStableInsertionSorter(helper.queryCompare(), queryRowManager(), InitialSortElements, CommitStep));
  3377. else
  3378. sorter.setown(new CInsertionSorter(helper.queryCompare(), queryRowManager(), InitialSortElements, CommitStep));
  3379. }
  3380. else
  3381. {
  3382. StringBuffer sb;
  3383. sb.appendf("Ignoring unsupported sort order algorithm '%s', using default", algoname.get());
  3384. agent.addWuException(sb.str(),WRN_UnsupportedAlgorithm,SeverityWarning,"hthor");
  3385. if((flags & TAFunstable) != 0)
  3386. sorter.setown(new CQuickSorter(helper.queryCompare(), queryRowManager(), InitialSortElements, CommitStep));
  3387. else
  3388. sorter.setown(new CHeapSorter(helper.queryCompare(), queryRowManager(), InitialSortElements, CommitStep));
  3389. }
  3390. sorter->setActivityId(activityId);
  3391. }
  3392. void CHThorGroupSortActivity::getSorted()
  3393. {
  3394. diskMerger.clear();
  3395. diskReader.clear();
  3396. queryRowManager()->addRowBuffer(this);//register for OOM callbacks
  3397. const void * next;
  3398. while((next = input->nextInGroup()) != NULL)
  3399. {
  3400. if (!sorter->addRow(next))
  3401. {
  3402. {
  3403. //Unlikely that this code will ever be executed but added for comfort
  3404. roxiemem::RoxieOutputRowArrayLock block(sorter->getRowArray());
  3405. sorter->flushRows();
  3406. sortAndSpillRows();
  3407. //Ensure new rows are written to the head of the array. It needs to be a separate call because
  3408. //performSort() cannot shift active row pointer since it can be called from any thread
  3409. sorter->flushRows();
  3410. }
  3411. if (!sorter->addRow(next))
  3412. {
  3413. ReleaseRoxieRow(next);
  3414. throw MakeStringException(0, "Insufficient memory to append sort row");
  3415. }
  3416. }
  3417. }
  3418. queryRowManager()->removeRowBuffer(this);//unregister for OOM callbacks
  3419. sorter->flushRows();
  3420. if(diskMerger)
  3421. {
  3422. sortAndSpillRows();
  3423. sorter->killSorted();
  3424. ICompare *compare = helper.queryCompare();
  3425. diskReader.setown(diskMerger->merge(compare));
  3426. }
  3427. else
  3428. {
  3429. sorter->performSort();
  3430. }
  3431. gotSorted = true;
  3432. }
  3433. //interface roxiemem::IBufferedRowCallback
  3434. unsigned CHThorGroupSortActivity::getSpillCost() const
  3435. {
  3436. return 10;
  3437. }
  3438. unsigned CHThorGroupSortActivity::getActivityId() const
  3439. {
  3440. return activityId;
  3441. }
  3442. bool CHThorGroupSortActivity::freeBufferedRows(bool critical)
  3443. {
  3444. roxiemem::RoxieOutputRowArrayLock block(sorter->getRowArray());
  3445. return sortAndSpillRows();
  3446. }
  3447. bool CHThorGroupSortActivity::sortAndSpillRows()
  3448. {
  3449. if (0 == sorter->numCommitted())
  3450. return false;
  3451. if(!diskMerger)
  3452. {
  3453. StringBuffer fbase;
  3454. agent.getTempfileBase(fbase).appendf(".spill_sort_%p", this);
  3455. PROGLOG("SORT: spilling to disk, filename base %s", fbase.str());
  3456. class CHThorRowLinkCounter : public CSimpleInterface, implements IRowLinkCounter
  3457. {
  3458. public:
  3459. IMPLEMENT_IINTERFACE_USING(CSimpleInterface);
  3460. virtual void releaseRow(const void *row)
  3461. {
  3462. ReleaseRoxieRow(row);
  3463. }
  3464. virtual void linkRow(const void *row)
  3465. {
  3466. LinkRoxieRow(row);
  3467. }
  3468. };
  3469. Owned<IRowLinkCounter> linker = new CHThorRowLinkCounter();
  3470. Owned<IRowInterfaces> rowInterfaces = createRowInterfaces(input->queryOutputMeta(), activityId, agent.queryCodeContext());
  3471. diskMerger.setown(createDiskMerger(rowInterfaces, linker, fbase.str()));
  3472. }
  3473. sorter->performSort();
  3474. sorter->spillSortedToDisk(diskMerger);
  3475. return true;
  3476. }
  3477. // Base for Quick sort and both Insertion sorts
  3478. void CSimpleSorterBase::spillSortedToDisk(IDiskMerger * merger)
  3479. {
  3480. Owned<IRowWriter> out = merger->createWriteBlock();
  3481. loop
  3482. {
  3483. const void *row = getNextSorted();
  3484. if (!row)
  3485. break;
  3486. out->putRow(row);
  3487. }
  3488. finger = 0;
  3489. out->flush();
  3490. rowsToSort.noteSpilled(rowsToSort.numCommitted());
  3491. }
  3492. // Quick sort
  3493. void CQuickSorter::performSort()
  3494. {
  3495. size32_t numRows = rowsToSort.numCommitted();
  3496. if (numRows)
  3497. {
  3498. const void * * rows = rowsToSort.getBlock(numRows);
  3499. qsortvec((void * *)rows, numRows, *compare);
  3500. finger = 0;
  3501. }
  3502. }
  3503. // Quick sort
  3504. void CParallelQuickSorter::performSort()
  3505. {
  3506. size32_t numRows = rowsToSort.numCommitted();
  3507. if (numRows)
  3508. {
  3509. const void * * rows = rowsToSort.getBlock(numRows);
  3510. parqsortvec((void * *)rows, numRows, *compare);
  3511. finger = 0;
  3512. }
  3513. }
  3514. // StableQuick sort
  3515. bool CStableSorter::addRow(const void * next)
  3516. {
  3517. roxiemem::rowidx_t nextRowCapacity = rowsToSort.rowCapacity() + 1;//increment capacity for the row we are about to add
  3518. if (nextRowCapacity > indexCapacity)
  3519. {
  3520. void *** newIndex = (void ***)rowManager->allocate(nextRowCapacity * sizeof(void*), activityId);//could force an OOM callback
  3521. if (newIndex)
  3522. {
  3523. roxiemem::RoxieOutputRowArrayLock block(getRowArray());//could force an OOM callback after index is freed but before index,indexCapacity is updated
  3524. ReleaseRoxieRow(index);
  3525. index = newIndex;
  3526. indexCapacity = RoxieRowCapacity(index) / sizeof(void*);
  3527. }
  3528. else
  3529. {
  3530. killSorted();
  3531. ReleaseRoxieRow(next);
  3532. throw MakeStringException(0, "Insufficient memory to allocate StableQuickSorter index");
  3533. }
  3534. }
  3535. return CSimpleSorterBase::addRow(next);
  3536. }
  3537. void CStableSorter::spillSortedToDisk(IDiskMerger * merger)
  3538. {
  3539. CSimpleSorterBase::spillSortedToDisk(merger);
  3540. ReleaseRoxieRow(index);
  3541. index = NULL;
  3542. indexCapacity = 0;
  3543. }
  3544. void CStableSorter::killSorted()
  3545. {
  3546. CSimpleSorterBase::killSorted();
  3547. ReleaseRoxieRow(index);
  3548. index = NULL;
  3549. indexCapacity = 0;
  3550. }
  3551. // StableQuick sort
  3552. void CStableQuickSorter::performSort()
  3553. {
  3554. size32_t numRows = rowsToSort.numCommitted();
  3555. if (numRows)
  3556. {
  3557. const void * * rows = rowsToSort.getBlock(numRows);
  3558. qsortvecstableinplace((void * *)rows, numRows, *compare, (void * *)index);
  3559. finger = 0;
  3560. }
  3561. }
  3562. void CParallelStableQuickSorter::performSort()
  3563. {
  3564. size32_t numRows = rowsToSort.numCommitted();
  3565. if (numRows)
  3566. {
  3567. const void * * rows = rowsToSort.getBlock(numRows);
  3568. parqsortvecstableinplace((void * *)rows, numRows, *compare, (void * *)index);
  3569. finger = 0;
  3570. }
  3571. }
  3572. // StableMerge sort
  3573. void CStableMergeSorter::performSort()
  3574. {
  3575. size32_t numRows = rowsToSort.numCommitted();
  3576. if (numRows)
  3577. {
  3578. const void * * rows = rowsToSort.getBlock(numRows);
  3579. msortvecstableinplace((void * *)rows, numRows, *compare, (void * *)index);
  3580. finger = 0;
  3581. }
  3582. }
  3583. void CParallelStableMergeSorter::performSort()
  3584. {
  3585. size32_t numRows = rowsToSort.numCommitted();
  3586. if (numRows)
  3587. {
  3588. const void * * rows = rowsToSort.getBlock(numRows);
  3589. parmsortvecstableinplace((void * *)rows, numRows, *compare, (void * *)index);
  3590. finger = 0;
  3591. }
  3592. }
  3593. // Heap sort
  3594. void CHeapSorter::performSort()
  3595. {
  3596. size32_t numRows = rowsToSort.numCommitted();
  3597. if (numRows)
  3598. {
  3599. const void * * rows = rowsToSort.getBlock(numRows);
  3600. heapsize = numRows;
  3601. for (unsigned i = 0; i < numRows; i++)
  3602. {
  3603. heap.append(i);
  3604. heap_push_up(i, heap.getArray(), rows, compare);
  3605. }
  3606. }
  3607. }
  3608. void CHeapSorter::spillSortedToDisk(IDiskMerger * merger)
  3609. {
  3610. CSimpleSorterBase::spillSortedToDisk(merger);
  3611. heap.kill();
  3612. heapsize = 0;
  3613. }
  3614. const void * CHeapSorter::getNextSorted()
  3615. {
  3616. if(heapsize)
  3617. {
  3618. size32_t numRows = rowsToSort.numCommitted();
  3619. if (numRows)
  3620. {
  3621. const void * * rows = rowsToSort.getBlock(numRows);
  3622. unsigned top = heap.item(0);
  3623. --heapsize;
  3624. heap.replace(heap.item(heapsize), 0);
  3625. heap_push_down(0, heapsize, heap.getArray(), rows, compare);
  3626. const void * row = rows[top];
  3627. rows[top] = NULL;
  3628. return row;
  3629. }
  3630. }
  3631. return NULL;
  3632. }
  3633. void CHeapSorter::killSorted()
  3634. {
  3635. CSimpleSorterBase::killSorted();
  3636. heap.kill();
  3637. heapsize = 0;
  3638. }
  3639. // Insertion sorts
  3640. void CInsertionSorter::performSort()
  3641. {
  3642. size32_t numRows = rowsToSort.numCommitted();
  3643. if (numRows)
  3644. {
  3645. const void * * rows = rowsToSort.getBlock(numRows);
  3646. for (unsigned i = 0; i < numRows; i++)
  3647. {
  3648. binary_vec_insert(rowsToSort.query(i), rows, i, *compare);
  3649. }
  3650. finger = 0;
  3651. }
  3652. }
  3653. void CStableInsertionSorter::performSort()
  3654. {
  3655. size32_t numRows = rowsToSort.numCommitted();
  3656. if (numRows)
  3657. {
  3658. const void * * rows = rowsToSort.getBlock(numRows);
  3659. for (unsigned i = 0; i < numRows; i++)
  3660. {
  3661. binary_vec_insert_stable(rowsToSort.query(i), rows, i, *compare);
  3662. }
  3663. finger = 0;
  3664. }
  3665. }
  3666. //=====================================================================================================
  3667. CHThorGroupedActivity::CHThorGroupedActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorGroupedArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  3668. {
  3669. }
  3670. void CHThorGroupedActivity::ready()
  3671. {
  3672. CHThorSimpleActivityBase::ready();
  3673. firstDone = false;
  3674. nextRowIndex = 0;
  3675. }
  3676. void CHThorGroupedActivity::done()
  3677. {
  3678. CHThorSimpleActivityBase::done();
  3679. next[0].clear();
  3680. next[1].clear();
  3681. next[2].clear();
  3682. }
  3683. const void *CHThorGroupedActivity::nextInGroup()
  3684. {
  3685. if (!firstDone)
  3686. {
  3687. next[0].setown(input->nextInGroup());
  3688. next[1].setown(input->nextInGroup());
  3689. nextRowIndex = 0;
  3690. }
  3691. unsigned nextToCompare = (nextRowIndex + 1) % 3;
  3692. unsigned nextToFill = (nextRowIndex + 2) % 3;
  3693. next[nextToFill].setown(input->nextInGroup());
  3694. OwnedConstRoxieRow ret(next[nextRowIndex].getClear());
  3695. if (ret)
  3696. {
  3697. if (next[nextToCompare])
  3698. {
  3699. if (!helper.isSameGroup(ret, next[nextToCompare]))
  3700. throw MakeStringException(100, "GROUPED(%u), expected a group break between adjacent rows (rows %" I64F "d, %" I64F "d) ", activityId, processed+1, processed+2);
  3701. }
  3702. else if (next[nextToFill])
  3703. {
  3704. if (helper.isSameGroup(ret, next[nextToFill]))
  3705. throw MakeStringException(100, "GROUPED(%u), unexpected group break found between rows %" I64F "d and %" I64F "d)", activityId, processed+1, processed+2);
  3706. }
  3707. processed++;
  3708. }
  3709. nextRowIndex = nextToCompare;
  3710. return ret.getClear();
  3711. }
  3712. //=====================================================================================================
  3713. CHThorSortedActivity::CHThorSortedActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorSortedArg &_arg, ThorActivityKind _kind) : CHThorSteppableActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  3714. {
  3715. //MORE: Should probably have a inter group and intra group sort functions
  3716. compare = helper.queryCompare();
  3717. }
  3718. void CHThorSortedActivity::ready()
  3719. {
  3720. CHThorSimpleActivityBase::ready();
  3721. firstDone = false;
  3722. }
  3723. void CHThorSortedActivity::done()
  3724. {
  3725. CHThorSimpleActivityBase::done();
  3726. next.clear();
  3727. }
  3728. const void *CHThorSortedActivity::nextInGroup()
  3729. {
  3730. if (!firstDone)
  3731. {
  3732. firstDone = true;
  3733. next.setown(input->nextInGroup());
  3734. }
  3735. OwnedConstRoxieRow prev(next.getClear());
  3736. next.setown(input->nextInGroup());
  3737. if (prev && next)
  3738. if (compare->docompare(prev, next) > 0)
  3739. throw MakeStringException(100, "SORTED(%u) detected incorrectly sorted rows (row %" I64F "d, %" I64F "d))", activityId, processed+1, processed+2);
  3740. if (prev)
  3741. processed++;
  3742. return prev.getClear();
  3743. }
  3744. const void * CHThorSortedActivity::nextGE(const void * seek, unsigned numFields)
  3745. {
  3746. if (next)
  3747. {
  3748. if (stepCompare->docompare(next, seek, numFields) >= 0)
  3749. return nextInGroup();
  3750. }
  3751. firstDone = true;
  3752. next.setown(input->nextGE(seek, numFields));
  3753. return nextInGroup();
  3754. }
  3755. //=====================================================================================================
  3756. CHThorTraceActivity::CHThorTraceActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorTraceArg &_arg, ThorActivityKind _kind)
  3757. : CHThorSteppableActivityBase(_agent, _activityId, _subgraphId, _arg, _kind),
  3758. helper(_arg), keepLimit(0), skip(0), sample(0), traceEnabled(false)
  3759. {
  3760. }
  3761. void CHThorTraceActivity::ready()
  3762. {
  3763. CHThorSimpleActivityBase::ready();
  3764. traceEnabled = agent.queryWorkUnit()->getDebugValueBool("traceEnabled", false);
  3765. if (traceEnabled && helper.canMatchAny())
  3766. {
  3767. keepLimit = helper.getKeepLimit();
  3768. if (keepLimit==(unsigned) -1)
  3769. keepLimit = agent.queryWorkUnit()->getDebugValueInt("traceLimit", 10);
  3770. skip = helper.getSkip();
  3771. sample = helper.getSample();
  3772. if (sample)
  3773. sample--;
  3774. name.setown(helper.getName());
  3775. if (!name)
  3776. name.set("Row");
  3777. }
  3778. else
  3779. keepLimit = 0;
  3780. }
  3781. void CHThorTraceActivity::done()
  3782. {
  3783. CHThorSimpleActivityBase::done();
  3784. name.clear();
  3785. }
  3786. const void *CHThorTraceActivity::nextInGroup()
  3787. {
  3788. OwnedConstRoxieRow ret(input->nextInGroup());
  3789. if (!ret)
  3790. return NULL;
  3791. onTrace(ret);
  3792. processed++;
  3793. return ret.getClear();
  3794. }
  3795. const void * CHThorTraceActivity::nextGE(const void * seek, unsigned numFields)
  3796. {
  3797. OwnedConstRoxieRow ret(input->nextGE(seek, numFields));
  3798. if (ret)
  3799. {
  3800. onTrace(ret);
  3801. processed++;
  3802. }
  3803. return ret.getClear();
  3804. }
  3805. void CHThorTraceActivity::onTrace(const void *row)
  3806. {
  3807. if (keepLimit && helper.isValid(row))
  3808. {
  3809. if (skip)
  3810. skip--;
  3811. else if (sample)
  3812. sample--;
  3813. else
  3814. {
  3815. CommonXmlWriter xmlwrite(XWFnoindent);
  3816. outputMeta.toXML((const byte *) row, xmlwrite);
  3817. DBGLOG("TRACE: <%s>%s<%s>", name.get(), xmlwrite.str(), name.get());
  3818. keepLimit--;
  3819. sample = helper.getSample();
  3820. if (sample)
  3821. sample--;
  3822. }
  3823. }
  3824. }
  3825. //=====================================================================================================
  3826. void getLimitType(unsigned flags, bool & limitFail, bool & limitOnFail)
  3827. {
  3828. if((flags & JFmatchAbortLimitSkips) != 0)
  3829. {
  3830. limitFail = false;
  3831. limitOnFail = false;
  3832. }
  3833. else
  3834. {
  3835. limitOnFail = ((flags & JFonfail) != 0);
  3836. limitFail = !limitOnFail;
  3837. }
  3838. }
  3839. CHThorJoinActivity::CHThorJoinActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorJoinArg &_arg, ThorActivityKind _kind)
  3840. : CHThorActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg), outBuilder(NULL)
  3841. {
  3842. }
  3843. void CHThorJoinActivity::ready()
  3844. {
  3845. CHThorActivityBase::ready();
  3846. input1->ready();
  3847. bool isStable = (helper.getJoinFlags() & JFunstable) == 0;
  3848. RoxieSortAlgorithm sortAlgorithm = isStable ? stableSpillingQuickSortAlgorithm : spillingQuickSortAlgorithm;
  3849. StringBuffer tempBase;
  3850. agent.getTempfileBase(tempBase);
  3851. if (helper.isLeftAlreadySorted())
  3852. sortedLeftInput.setown(createDegroupedInputReader(input));
  3853. else
  3854. sortedLeftInput.setown(createSortedInputReader(input, createSortAlgorithm(sortAlgorithm, helper.queryCompareLeft(), *queryRowManager(), input->queryOutputMeta(), agent.queryCodeContext(), tempBase, activityId)));
  3855. ICompare *compareRight = helper.queryCompareRight();
  3856. if (helper.isRightAlreadySorted())
  3857. groupedSortedRightInput.setown(createGroupedInputReader(input1, compareRight));
  3858. else
  3859. groupedSortedRightInput.setown(createSortedGroupedInputReader(input1, compareRight, createSortAlgorithm(sortAlgorithm, compareRight, *queryRowManager(), input1->queryOutputMeta(), agent.queryCodeContext(), tempBase, activityId)));
  3860. outBuilder.setAllocator(rowAllocator);
  3861. leftOuterJoin = (helper.getJoinFlags() & JFleftouter) != 0;
  3862. rightOuterJoin = (helper.getJoinFlags() & JFrightouter) != 0;
  3863. exclude = (helper.getJoinFlags() & JFexclude) != 0;
  3864. getLimitType(helper.getJoinFlags(), limitFail, limitOnFail);
  3865. if (rightOuterJoin && !defaultLeft)
  3866. createDefaultLeft();
  3867. if ((leftOuterJoin || limitOnFail) && !defaultRight)
  3868. createDefaultRight();
  3869. betweenjoin = ((helper.getJoinFlags() & JFslidingmatch) != 0);
  3870. assertex(!(betweenjoin && rightOuterJoin));
  3871. keepLimit = helper.getKeepLimit();
  3872. if (keepLimit == 0)
  3873. keepLimit = (unsigned)-1;
  3874. atmostLimit = helper.getJoinLimit();
  3875. if(atmostLimit == 0)
  3876. atmostLimit = (unsigned)-1;
  3877. else
  3878. assertex(!rightOuterJoin && !betweenjoin);
  3879. abortLimit = helper.getMatchAbortLimit();
  3880. if (abortLimit == 0)
  3881. abortLimit = (unsigned)-1;
  3882. assertex((helper.getJoinFlags() & (JFfirst | JFfirstleft | JFfirstright)) == 0); // no longer supported
  3883. if(betweenjoin)
  3884. {
  3885. collate = helper.queryCompareLeftRightLower();
  3886. collateupper = helper.queryCompareLeftRightUpper();
  3887. }
  3888. else
  3889. {
  3890. collate = collateupper = helper.queryCompareLeftRight();
  3891. }
  3892. rightIndex = 0;
  3893. joinCounter = 0;
  3894. failingLimit.clear();
  3895. state = JSfill;
  3896. if ((helper.getJoinFlags() & JFlimitedprefixjoin) && helper.getJoinLimit())
  3897. { //Limited Match Join (s[1..n])
  3898. limitedhelper.setown(createRHLimitedCompareHelper());
  3899. limitedhelper->init( helper.getJoinLimit(), groupedSortedRightInput, collate, helper.queryPrefixCompare() );
  3900. }
  3901. }
  3902. void CHThorJoinActivity::done()
  3903. {
  3904. outBuilder.clear();
  3905. right.clear();
  3906. left.clear();
  3907. pendingRight.clear();
  3908. sortedLeftInput.clear();
  3909. groupedSortedRightInput.clear();
  3910. CHThorActivityBase::done();
  3911. input1->done();
  3912. }
  3913. void CHThorJoinActivity::setInput(unsigned index, IHThorInput *_input)
  3914. {
  3915. if (index==1)
  3916. input1 = _input;
  3917. else
  3918. CHThorActivityBase::setInput(index, _input);
  3919. }
  3920. void CHThorJoinActivity::createDefaultLeft()
  3921. {
  3922. if (!defaultLeft)
  3923. {
  3924. if (!defaultLeftAllocator)
  3925. defaultLeftAllocator.setown(agent.queryCodeContext()->getRowAllocator(input->queryOutputMeta(), activityId));
  3926. RtlDynamicRowBuilder rowBuilder(defaultLeftAllocator);
  3927. size32_t thisSize = helper.createDefaultLeft(rowBuilder);
  3928. defaultLeft.setown(rowBuilder.finalizeRowClear(thisSize));
  3929. }
  3930. }
  3931. void CHThorJoinActivity::createDefaultRight()
  3932. {
  3933. if (!defaultRight)
  3934. {
  3935. if (!defaultRightAllocator)
  3936. defaultRightAllocator.setown(agent.queryCodeContext()->getRowAllocator(input1->queryOutputMeta(), activityId));
  3937. RtlDynamicRowBuilder rowBuilder(defaultRightAllocator);
  3938. size32_t thisSize = helper.createDefaultRight(rowBuilder);
  3939. defaultRight.setown(rowBuilder.finalizeRowClear(thisSize));
  3940. }
  3941. }
  3942. void CHThorJoinActivity::fillLeft()
  3943. {
  3944. matchedLeft = false;
  3945. left.setown(sortedLeftInput->nextInGroup()); // NOTE: already degrouped
  3946. if(betweenjoin && left && pendingRight && (collate->docompare(left, pendingRight) >= 0))
  3947. fillRight();
  3948. if (limitedhelper && 0==rightIndex)
  3949. {
  3950. rightIndex = 0;
  3951. joinCounter = 0;
  3952. right.clear();
  3953. matchedRight.kill();
  3954. if (left)
  3955. {
  3956. limitedhelper->getGroup(right,left);
  3957. ForEachItemIn(idx, right)
  3958. matchedRight.append(false);
  3959. }
  3960. }
  3961. }
  3962. void CHThorJoinActivity::fillRight()
  3963. {
  3964. if (limitedhelper)
  3965. return;
  3966. failingLimit.clear();
  3967. if(betweenjoin && left)
  3968. {
  3969. aindex_t start = 0;
  3970. while(right.isItem(start) && (collateupper->docompare(left, right.item(start)) > 0))
  3971. start++;
  3972. if(start>0)
  3973. right.clearPart(0, start);
  3974. }
  3975. else
  3976. right.clear();
  3977. rightIndex = 0;
  3978. joinCounter = 0;
  3979. unsigned groupCount = 0;
  3980. while(true)
  3981. {
  3982. OwnedConstRoxieRow next;
  3983. if(pendingRight)
  3984. {
  3985. next.setown(pendingRight.getClear());
  3986. }
  3987. else
  3988. {
  3989. next.setown(groupedSortedRightInput->nextInGroup());
  3990. }
  3991. if(!rightOuterJoin && next && (!left || (collateupper->docompare(left, next) > 0))) // if right is less than left, and not right outer, can skip group
  3992. {
  3993. while(next)
  3994. next.setown(groupedSortedRightInput->nextInGroup());
  3995. continue;
  3996. }
  3997. while(next)
  3998. {
  3999. if(groupCount==abortLimit)
  4000. {
  4001. if(limitFail)
  4002. failLimit();
  4003. if ( agent.queryCodeContext()->queryDebugContext())
  4004. agent.queryCodeContext()->queryDebugContext()->checkBreakpoint(DebugStateLimit, NULL, static_cast<IActivityBase *>(this));
  4005. if(limitOnFail)
  4006. {
  4007. assertex(!failingLimit);
  4008. try
  4009. {
  4010. failLimit();
  4011. }
  4012. catch(IException * except)
  4013. {
  4014. failingLimit.setown(except);
  4015. }
  4016. assertex(failingLimit);
  4017. }
  4018. right.append(next.getClear());
  4019. do
  4020. {
  4021. next.setown(groupedSortedRightInput->nextInGroup());
  4022. } while(next);
  4023. break;
  4024. }
  4025. else if(groupCount==atmostLimit)
  4026. {
  4027. right.clear();
  4028. groupCount = 0;
  4029. while(next)
  4030. {
  4031. next.setown(groupedSortedRightInput->nextInGroup());
  4032. }
  4033. }
  4034. else
  4035. {
  4036. right.append(next.getClear());
  4037. groupCount++;
  4038. }
  4039. next.setown(groupedSortedRightInput->nextInGroup());
  4040. }
  4041. // normally only want to read one right group, but if is between join and next right group is in window for left, need to continue
  4042. if(betweenjoin && left)
  4043. {
  4044. pendingRight.setown(groupedSortedRightInput->nextInGroup());
  4045. if(!pendingRight || (collate->docompare(left, pendingRight) < 0))
  4046. break;
  4047. }
  4048. else
  4049. break;
  4050. }
  4051. matchedRight.kill();
  4052. ForEachItemIn(idx, right)
  4053. matchedRight.append(false);
  4054. }
  4055. const void * CHThorJoinActivity::joinRecords(const void * curLeft, const void * curRight, unsigned counter)
  4056. {
  4057. try
  4058. {
  4059. outBuilder.ensureRow();
  4060. size32_t thisSize = helper.transform(outBuilder, curLeft, curRight, counter);
  4061. if(thisSize)
  4062. return outBuilder.finalizeRowClear(thisSize);
  4063. else
  4064. return NULL;
  4065. }
  4066. catch(IException * e)
  4067. {
  4068. throw makeWrappedException(e);
  4069. }
  4070. }
  4071. const void * CHThorJoinActivity::groupDenormalizeRecords(const void * curLeft, ConstPointerArray & rows)
  4072. {
  4073. try
  4074. {
  4075. outBuilder.ensureRow();
  4076. unsigned numRows = rows.ordinality();
  4077. const void * rhs = numRows ? rows.item(0) : defaultRight.get();
  4078. memsize_t thisSize = helper.transform(outBuilder, curLeft, rhs, numRows, (const void * *)rows.getArray());
  4079. if(thisSize)
  4080. return outBuilder.finalizeRowClear(thisSize);
  4081. else
  4082. return NULL;
  4083. }
  4084. catch(IException * e)
  4085. {
  4086. throw makeWrappedException(e);
  4087. }
  4088. }
  4089. const void * CHThorJoinActivity::joinException(const void * curLeft, IException * except)
  4090. {
  4091. try
  4092. {
  4093. outBuilder.ensureRow();
  4094. size32_t thisSize = helper.onFailTransform(outBuilder, curLeft, defaultRight, except);
  4095. if(thisSize)
  4096. return outBuilder.finalizeRowClear(thisSize);
  4097. else
  4098. return NULL;
  4099. }
  4100. catch(IException * e)
  4101. {
  4102. throw makeWrappedException(e);
  4103. }
  4104. }
  4105. void CHThorJoinActivity::failLimit()
  4106. {
  4107. helper.onMatchAbortLimitExceeded();
  4108. CommonXmlWriter xmlwrite(0);
  4109. if (input->queryOutputMeta() && input->queryOutputMeta()->hasXML())
  4110. {
  4111. input->queryOutputMeta()->toXML((byte *)left.get(), xmlwrite);
  4112. }
  4113. throw MakeStringException(0, "More than %d match candidates in join for row %s", abortLimit, xmlwrite.str());
  4114. }
  4115. const void *CHThorJoinActivity::nextInGroup()
  4116. {
  4117. loop
  4118. {
  4119. switch (state)
  4120. {
  4121. case JSfill:
  4122. fillLeft();
  4123. state = JSfillright;
  4124. break;
  4125. case JSfillright:
  4126. fillRight();
  4127. state = JScollate;
  4128. break;
  4129. case JSfillleft:
  4130. fillLeft();
  4131. state = JScollate;
  4132. break;
  4133. case JScollate:
  4134. if (right.ordinality() == 0)
  4135. {
  4136. if (!left)
  4137. return NULL;
  4138. state = JSleftonly;
  4139. }
  4140. else
  4141. {
  4142. if (!left)
  4143. state = JSrightonly;
  4144. else
  4145. {
  4146. int diff;
  4147. if(betweenjoin)
  4148. diff = ((collate->docompare(left, right.item(0)) < 0) ? -1 : ((collateupper->docompare(left, right.item(right.ordinality()-1)) > 0) ? +1 : 0));
  4149. else
  4150. diff = collate->docompare(left, right.item(0));
  4151. bool limitExceeded = right.ordinality()>abortLimit;
  4152. if (diff == 0)
  4153. {
  4154. if (limitExceeded)
  4155. {
  4156. const void * ret = NULL;
  4157. if(failingLimit)
  4158. {
  4159. if ( agent.queryCodeContext()->queryDebugContext())
  4160. agent.queryCodeContext()->queryDebugContext()->checkBreakpoint(DebugStateLimit, NULL, static_cast<IActivityBase *>(this));
  4161. ret = joinException(left, failingLimit);
  4162. }
  4163. left.clear();
  4164. state = JSfillleft;
  4165. ForEachItemIn(idx, right)
  4166. matchedRight.replace(true, idx);
  4167. if(ret)
  4168. {
  4169. processed++;
  4170. return ret;
  4171. }
  4172. }
  4173. else
  4174. {
  4175. state = JScompare;
  4176. joinLimit = keepLimit;
  4177. }
  4178. }
  4179. else if (diff < 0)
  4180. state = JSleftonly;
  4181. else if (limitExceeded)
  4182. {
  4183. // MORE - Roxie code seems to think there should be a destroyRowset(right) here....
  4184. state = JSfillright;
  4185. }
  4186. else
  4187. state = JSrightonly;
  4188. }
  4189. }
  4190. break;
  4191. case JSrightonly:
  4192. if (rightOuterJoin)
  4193. {
  4194. switch (kind)
  4195. {
  4196. case TAKjoin:
  4197. {
  4198. while (right.isItem(rightIndex))
  4199. {
  4200. if (!matchedRight.item(rightIndex))
  4201. {
  4202. const void * rhs = right.item(rightIndex++);
  4203. const void * ret = joinRecords(defaultLeft, rhs, 0);
  4204. if (ret)
  4205. {
  4206. processed++;
  4207. return ret;
  4208. }
  4209. }
  4210. else
  4211. rightIndex++;
  4212. }
  4213. break;
  4214. }
  4215. //Probably excessive to implement the following, but possibly useful
  4216. case TAKdenormalize:
  4217. {
  4218. OwnedConstRoxieRow newLeft(defaultLeft.getLink());
  4219. unsigned rowSize = 0;
  4220. unsigned leftCount = 0;
  4221. while (right.isItem(rightIndex))
  4222. {
  4223. if (!matchedRight.item(rightIndex))
  4224. {
  4225. const void * rhs = right.item(rightIndex);
  4226. try
  4227. {
  4228. RtlDynamicRowBuilder rowBuilder(rowAllocator);
  4229. size32_t thisSize = helper.transform(rowBuilder, newLeft, rhs, ++leftCount);
  4230. if (thisSize)
  4231. {
  4232. rowSize = thisSize;
  4233. newLeft.setown(rowBuilder.finalizeRowClear(rowSize));
  4234. }
  4235. }
  4236. catch(IException * e)
  4237. {
  4238. throw makeWrappedException(e);
  4239. }
  4240. }
  4241. rightIndex++;
  4242. }
  4243. state = JSfillright;
  4244. if (rowSize)
  4245. {
  4246. processed++;
  4247. return newLeft.getClear();
  4248. }
  4249. break;
  4250. }
  4251. case TAKdenormalizegroup:
  4252. {
  4253. filteredRight.kill();
  4254. while (right.isItem(rightIndex))
  4255. {
  4256. if (!matchedRight.item(rightIndex))
  4257. filteredRight.append(right.item(rightIndex));
  4258. rightIndex++;
  4259. }
  4260. state = JSfillright;
  4261. if (filteredRight.ordinality())
  4262. {
  4263. const void * ret = groupDenormalizeRecords(defaultLeft, filteredRight);
  4264. filteredRight.kill();
  4265. if (ret)
  4266. {
  4267. processed++;
  4268. return ret;
  4269. }
  4270. }
  4271. break;
  4272. }
  4273. default:
  4274. throwUnexpected();
  4275. }
  4276. }
  4277. state = JSfillright;
  4278. break;
  4279. case JSleftonly:
  4280. {
  4281. const void * ret = NULL;
  4282. if (!matchedLeft && leftOuterJoin)
  4283. {
  4284. switch (kind)
  4285. {
  4286. case TAKjoin:
  4287. ret = joinRecords(left, defaultRight, 0);
  4288. break;
  4289. case TAKdenormalize:
  4290. ret = left.getClear();
  4291. break;
  4292. case TAKdenormalizegroup:
  4293. filteredRight.kill();
  4294. ret = groupDenormalizeRecords(left, filteredRight);
  4295. break;
  4296. default:
  4297. throwUnexpected();
  4298. }
  4299. }
  4300. left.clear();
  4301. state = JSfillleft;
  4302. if (ret)
  4303. {
  4304. processed++;
  4305. return ret;
  4306. }
  4307. break;
  4308. }
  4309. case JScompare:
  4310. if (joinLimit != 0)
  4311. {
  4312. switch (kind)
  4313. {
  4314. case TAKjoin:
  4315. {
  4316. while (right.isItem(rightIndex))
  4317. {
  4318. const void * rhs = right.item(rightIndex++);
  4319. if (helper.match(left, rhs))
  4320. {
  4321. matchedRight.replace(true, rightIndex-1);
  4322. matchedLeft = true;
  4323. if (!exclude)
  4324. {
  4325. const void *ret = joinRecords(left, rhs, ++joinCounter);
  4326. if (ret)
  4327. {
  4328. processed++;
  4329. joinLimit--;
  4330. return ret;
  4331. }
  4332. }
  4333. }
  4334. }
  4335. break;
  4336. }
  4337. case TAKdenormalize:
  4338. {
  4339. OwnedConstRoxieRow newLeft;
  4340. newLeft.set(left);
  4341. unsigned rowSize = 0;
  4342. unsigned leftCount = 0;
  4343. while (right.isItem(rightIndex) && joinLimit)
  4344. {
  4345. const void * rhs = right.item(rightIndex++);
  4346. if (helper.match(left, rhs))
  4347. {
  4348. matchedRight.replace(true, rightIndex-1);
  4349. matchedLeft = true;
  4350. if (!exclude)
  4351. {
  4352. try
  4353. {
  4354. RtlDynamicRowBuilder rowBuilder(rowAllocator);
  4355. unsigned thisSize = helper.transform(rowBuilder, newLeft, rhs, ++leftCount);
  4356. if (thisSize)
  4357. {
  4358. rowSize = thisSize;
  4359. newLeft.setown(rowBuilder.finalizeRowClear(rowSize));
  4360. joinLimit--;
  4361. }
  4362. }
  4363. catch(IException * e)
  4364. {
  4365. throw makeWrappedException(e);
  4366. }
  4367. }
  4368. }
  4369. }
  4370. state = JSleftonly;
  4371. rightIndex = 0;
  4372. if (rowSize)
  4373. {
  4374. processed++;
  4375. return newLeft.getClear();
  4376. }
  4377. break;
  4378. }
  4379. case TAKdenormalizegroup:
  4380. {
  4381. filteredRight.kill();
  4382. while (right.isItem(rightIndex))
  4383. {
  4384. const void * rhs = right.item(rightIndex++);
  4385. if (helper.match(left, rhs))
  4386. {
  4387. matchedRight.replace(true, rightIndex-1);
  4388. filteredRight.append(rhs);
  4389. matchedLeft = true;
  4390. if (filteredRight.ordinality()==joinLimit)
  4391. break;
  4392. }
  4393. }
  4394. state = JSleftonly;
  4395. rightIndex = 0;
  4396. if (!exclude && filteredRight.ordinality())
  4397. {
  4398. const void * ret = groupDenormalizeRecords(left, filteredRight);
  4399. filteredRight.kill();
  4400. if (ret)
  4401. {
  4402. processed++;
  4403. return ret;
  4404. }
  4405. }
  4406. break;
  4407. }
  4408. default:
  4409. throwUnexpected();
  4410. }
  4411. }
  4412. state = JSleftonly;
  4413. rightIndex = 0;
  4414. joinCounter = 0;
  4415. break;
  4416. }
  4417. }
  4418. }
  4419. bool CHThorJoinActivity::isGrouped()
  4420. {
  4421. return false;
  4422. }
  4423. //=====================================================================================================
  4424. CHThorSelfJoinActivity::CHThorSelfJoinActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorJoinArg &_arg, ThorActivityKind _kind)
  4425. : CHThorActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg), outBuilder(NULL)
  4426. {
  4427. dualCacheInput = NULL;
  4428. }
  4429. void CHThorSelfJoinActivity::ready()
  4430. {
  4431. CHThorActivityBase::ready();
  4432. outBuilder.setAllocator(rowAllocator);
  4433. ICompare *compareLeft = helper.queryCompareLeft();
  4434. if (helper.isLeftAlreadySorted())
  4435. groupedInput.setown(createGroupedInputReader(input, compareLeft));
  4436. else
  4437. {
  4438. bool isStable = (helper.getJoinFlags() & JFunstable) == 0;
  4439. RoxieSortAlgorithm sortAlgorithm = isStable ? stableSpillingQuickSortAlgorithm : spillingQuickSortAlgorithm;
  4440. StringBuffer tempBase;
  4441. agent.getTempfileBase(tempBase);
  4442. groupedInput.setown(createSortedGroupedInputReader(input, compareLeft, createSortAlgorithm(sortAlgorithm, compareLeft, *queryRowManager(), input->queryOutputMeta(), agent.queryCodeContext(), tempBase, activityId)));
  4443. }
  4444. leftOuterJoin = (helper.getJoinFlags() & JFleftouter) != 0;
  4445. rightOuterJoin = (helper.getJoinFlags() & JFrightouter) != 0;
  4446. exclude = (helper.getJoinFlags() & JFexclude) != 0;
  4447. getLimitType(helper.getJoinFlags(), limitFail, limitOnFail);
  4448. if (rightOuterJoin && !defaultLeft)
  4449. {
  4450. if (!defaultAllocator)
  4451. defaultAllocator.setown(agent.queryCodeContext()->getRowAllocator(input->queryOutputMeta(), activityId));
  4452. RtlDynamicRowBuilder rowBuilder(defaultAllocator);
  4453. size32_t thisSize = helper.createDefaultLeft(rowBuilder);
  4454. defaultLeft.setown(rowBuilder.finalizeRowClear(thisSize));
  4455. }
  4456. if ((leftOuterJoin || limitOnFail) && !defaultRight)
  4457. {
  4458. if (!defaultAllocator)
  4459. defaultAllocator.setown(agent.queryCodeContext()->getRowAllocator(input->queryOutputMeta(), activityId));
  4460. RtlDynamicRowBuilder rowBuilder(defaultAllocator);
  4461. size32_t thisSize = helper.createDefaultRight(rowBuilder);
  4462. defaultRight.setown(rowBuilder.finalizeRowClear(thisSize));
  4463. }
  4464. if((helper.getJoinFlags() & JFslidingmatch) != 0)
  4465. throw MakeStringException(99, "Sliding self join not supported");
  4466. keepLimit = helper.getKeepLimit();
  4467. if(keepLimit == 0)
  4468. keepLimit = (unsigned)-1;
  4469. atmostLimit = helper.getJoinLimit();
  4470. if(atmostLimit == 0)
  4471. atmostLimit = (unsigned)-1;
  4472. else
  4473. assertex(!rightOuterJoin);
  4474. abortLimit = helper.getMatchAbortLimit();
  4475. if (abortLimit == 0)
  4476. abortLimit = (unsigned)-1;
  4477. assertex((helper.getJoinFlags() & (JFfirst | JFfirstleft | JFfirstright)) == 0); // no longer supported
  4478. collate = helper.queryCompareLeftRight();
  4479. eof = false;
  4480. doneFirstFill = false;
  4481. failingLimit.clear();
  4482. if ((helper.getJoinFlags() & JFlimitedprefixjoin) && helper.getJoinLimit())
  4483. { //Limited Match Join (s[1..n])
  4484. dualcache.setown(new CRHDualCache());
  4485. dualcache->init(groupedInput);
  4486. dualCacheInput = dualcache->queryOut1();
  4487. failingOuterAtmost = false;
  4488. matchedLeft = false;
  4489. leftIndex = 0;
  4490. rightOuterIndex = 0;
  4491. limitedhelper.setown(createRHLimitedCompareHelper());
  4492. limitedhelper->init( helper.getJoinLimit(), dualcache->queryOut2(), collate, helper.queryPrefixCompare() );
  4493. }
  4494. joinCounter = 0;
  4495. }
  4496. void CHThorSelfJoinActivity::done()
  4497. {
  4498. outBuilder.clear();
  4499. group.clear();
  4500. groupedInput.clear();
  4501. CHThorActivityBase::done();
  4502. }
  4503. bool CHThorSelfJoinActivity::fillGroup()
  4504. {
  4505. group.clear();
  4506. matchedLeft = false;
  4507. matchedRight.kill();
  4508. failingOuterAtmost = false;
  4509. OwnedConstRoxieRow next;
  4510. unsigned groupCount = 0;
  4511. next.setown(groupedInput->nextInGroup());
  4512. while(next)
  4513. {
  4514. if(groupCount==abortLimit)
  4515. {
  4516. if(limitFail)
  4517. failLimit(next);
  4518. if ( agent.queryCodeContext()->queryDebugContext())
  4519. agent.queryCodeContext()->queryDebugContext()->checkBreakpoint(DebugStateLimit, NULL, static_cast<IActivityBase *>(this));
  4520. if(limitOnFail)
  4521. {
  4522. assertex(!failingLimit);
  4523. try
  4524. {
  4525. failLimit(next);
  4526. }
  4527. catch(IException * except)
  4528. {
  4529. failingLimit.setown(except);
  4530. }
  4531. assertex(failingLimit);
  4532. group.append(next.getClear());
  4533. groupCount++;
  4534. break;
  4535. }
  4536. group.clear();
  4537. groupCount = 0;
  4538. while(next)
  4539. next.setown(groupedInput->nextInGroup());
  4540. }
  4541. else if(groupCount==atmostLimit)
  4542. {
  4543. if(leftOuterJoin)
  4544. {
  4545. group.append(next.getClear());
  4546. groupCount++;
  4547. failingOuterAtmost = true;
  4548. break;
  4549. }
  4550. else
  4551. {
  4552. group.clear();
  4553. groupCount = 0;
  4554. while(next)
  4555. next.setown(groupedInput->nextInGroup());
  4556. }
  4557. }
  4558. else
  4559. {
  4560. group.append(next.getClear());
  4561. groupCount++;
  4562. }
  4563. next.setown(groupedInput->nextInGroup());
  4564. }
  4565. if(group.ordinality()==0)
  4566. {
  4567. eof = true;
  4568. return false;
  4569. }
  4570. leftIndex = 0;
  4571. rightIndex = 0;
  4572. joinCounter = 0;
  4573. rightOuterIndex = 0;
  4574. joinLimit = keepLimit;
  4575. ForEachItemIn(idx, group)
  4576. matchedRight.append(false);
  4577. return true;
  4578. }
  4579. const void * CHThorSelfJoinActivity::nextInGroup()
  4580. {
  4581. if (limitedhelper) {
  4582. while(!eof) //limited match join
  4583. {
  4584. if (!group.isItem(rightIndex))
  4585. {
  4586. lhs.setown(dualCacheInput->nextInGroup());
  4587. if (lhs)
  4588. {
  4589. rightIndex = 0;
  4590. joinCounter = 0;
  4591. group.clear();
  4592. limitedhelper->getGroup(group,lhs);
  4593. }
  4594. else
  4595. eof = true;
  4596. }
  4597. if (group.isItem(rightIndex))
  4598. {
  4599. const void * rhs = group.item(rightIndex++);
  4600. if(helper.match(lhs, rhs))
  4601. {
  4602. const void * ret = joinRecords(lhs, rhs, ++joinCounter, NULL);
  4603. return ret;
  4604. }
  4605. }
  4606. }
  4607. return NULL;
  4608. }
  4609. if(!doneFirstFill)
  4610. {
  4611. fillGroup();
  4612. doneFirstFill = true;
  4613. }
  4614. while(!eof)
  4615. {
  4616. if(failingOuterAtmost)
  4617. while(group.isItem(leftIndex))
  4618. {
  4619. const void * ret = joinRecords(group.item(leftIndex++), defaultRight, 0, NULL);
  4620. if(ret)
  4621. {
  4622. processed++;
  4623. return ret;
  4624. }
  4625. }
  4626. if((joinLimit == 0) || !group.isItem(rightIndex))
  4627. {
  4628. if(leftOuterJoin && !matchedLeft && !failingLimit)
  4629. {
  4630. const void * ret = joinRecords(group.item(leftIndex), defaultRight, 0, NULL);
  4631. if(ret)
  4632. {
  4633. matchedLeft = true;
  4634. processed++;
  4635. return ret;
  4636. }
  4637. }
  4638. leftIndex++;
  4639. matchedLeft = false;
  4640. rightIndex = 0;
  4641. joinCounter = 0;
  4642. joinLimit = keepLimit;
  4643. }
  4644. if(!group.isItem(leftIndex))
  4645. {
  4646. if(failingLimit || failingOuterAtmost)
  4647. {
  4648. OwnedConstRoxieRow lhs(groupedInput->nextInGroup()); // dualCache never active here
  4649. while(lhs)
  4650. {
  4651. const void * ret = joinRecords(lhs, defaultRight, 0, failingLimit);
  4652. if(ret)
  4653. {
  4654. processed++;
  4655. return ret;
  4656. }
  4657. lhs.setown(groupedInput->nextInGroup());
  4658. }
  4659. failingLimit.clear();
  4660. }
  4661. if(rightOuterJoin && !failingLimit)
  4662. while(group.isItem(rightOuterIndex))
  4663. if(!matchedRight.item(rightOuterIndex++))
  4664. {
  4665. const void * ret = joinRecords(defaultLeft, group.item(rightOuterIndex-1), 0, NULL);
  4666. if(ret)
  4667. {
  4668. processed++;
  4669. return ret;
  4670. }
  4671. }
  4672. if(!fillGroup())
  4673. return NULL;
  4674. continue;
  4675. }
  4676. const void * lhs = group.item(leftIndex);
  4677. if(failingLimit)
  4678. {
  4679. leftIndex++;
  4680. const void * ret = joinRecords(lhs, defaultRight, 0, failingLimit);
  4681. if(ret)
  4682. {
  4683. processed++;
  4684. return ret;
  4685. }
  4686. }
  4687. else
  4688. {
  4689. const void * rhs = group.item(rightIndex++);
  4690. if(helper.match(lhs, rhs))
  4691. {
  4692. matchedLeft = true;
  4693. matchedRight.replace(true, rightIndex-1);
  4694. if(!exclude)
  4695. {
  4696. const void * ret = joinRecords(lhs, rhs, ++joinCounter, NULL);
  4697. if(ret)
  4698. {
  4699. processed++;
  4700. joinLimit--;
  4701. return ret;
  4702. }
  4703. }
  4704. }
  4705. }
  4706. }
  4707. return NULL;
  4708. }
  4709. const void * CHThorSelfJoinActivity::joinRecords(const void * curLeft, const void * curRight, unsigned counter, IException * except)
  4710. {
  4711. outBuilder.ensureRow();
  4712. try
  4713. {
  4714. size32_t thisSize = (except ? helper.onFailTransform(outBuilder, curLeft, curRight, except) : helper.transform(outBuilder, curLeft, curRight, counter));
  4715. if(thisSize){
  4716. return outBuilder.finalizeRowClear(thisSize);
  4717. }
  4718. else
  4719. return NULL;
  4720. }
  4721. catch(IException * e)
  4722. {
  4723. throw makeWrappedException(e);
  4724. }
  4725. }
  4726. void CHThorSelfJoinActivity::failLimit(const void * next)
  4727. {
  4728. helper.onMatchAbortLimitExceeded();
  4729. CommonXmlWriter xmlwrite(0);
  4730. if (input->queryOutputMeta() && input->queryOutputMeta()->hasXML())
  4731. {
  4732. input->queryOutputMeta()->toXML((byte *) next, xmlwrite);
  4733. }
  4734. throw MakeStringException(0, "More than %d match candidates in self-join for row %s", abortLimit, xmlwrite.str());
  4735. }
  4736. bool CHThorSelfJoinActivity::isGrouped()
  4737. {
  4738. return false;
  4739. }
  4740. //=====================================================================================================
  4741. CHThorLookupJoinActivity::LookupTable::LookupTable(unsigned _size, ICompare * _leftRightCompare, ICompare * _rightCompare, IHash * _leftHash, IHash * _rightHash, bool _dedupOnAdd)
  4742. : leftRightCompare(_leftRightCompare), rightCompare(_rightCompare), leftHash(_leftHash), rightHash(_rightHash), dedupOnAdd(_dedupOnAdd)
  4743. {
  4744. unsigned minsize = (4*_size)/3;
  4745. size = 2;
  4746. while((minsize >>= 1) > 0)
  4747. size <<= 1;
  4748. mask = size - 1;
  4749. table = new OwnedConstRoxieRow[size];
  4750. findex = BadIndex;
  4751. }
  4752. CHThorLookupJoinActivity::LookupTable::~LookupTable()
  4753. {
  4754. delete [] table;
  4755. }
  4756. bool CHThorLookupJoinActivity::LookupTable::add(const void * _right)
  4757. {
  4758. OwnedConstRoxieRow right(_right);
  4759. findex = BadIndex;
  4760. unsigned start = rightHash->hash(right) & mask;
  4761. unsigned index = start;
  4762. while(table[index])
  4763. {
  4764. if(dedupOnAdd && (rightCompare->docompare(table[index], right) == 0))
  4765. return false;
  4766. index++;
  4767. if(index==size)
  4768. index = 0;
  4769. if(index==start)
  4770. return false; //table is full, should never happen
  4771. }
  4772. table[index].setown(right.getClear());
  4773. return true;
  4774. }
  4775. const void * CHThorLookupJoinActivity::LookupTable::find(const void * left) const
  4776. {
  4777. fstart = leftHash->hash(left) & mask;
  4778. findex = fstart;
  4779. return doFind(left);
  4780. }
  4781. const void * CHThorLookupJoinActivity::LookupTable::findNext(const void * left) const
  4782. {
  4783. if(findex == BadIndex)
  4784. return NULL;
  4785. advance();
  4786. return doFind(left);
  4787. }
  4788. void CHThorLookupJoinActivity::LookupTable::advance() const
  4789. {
  4790. findex++;
  4791. if(findex==size)
  4792. findex = 0;
  4793. if(findex==fstart)
  4794. throw MakeStringException(0, "Internal error hthor lookup join activity (hash table full on lookup)");
  4795. }
  4796. const void * CHThorLookupJoinActivity::LookupTable::doFind(const void * left) const
  4797. {
  4798. while(table[findex])
  4799. {
  4800. if(leftRightCompare->docompare(left, table[findex]) == 0)
  4801. return table[findex];
  4802. advance();
  4803. }
  4804. findex = BadIndex;
  4805. return NULL;
  4806. }
  4807. CHThorLookupJoinActivity::CHThorLookupJoinActivity(IAgentContext & _agent, unsigned _activityId, unsigned _subgraphId, IHThorHashJoinArg &_arg, ThorActivityKind _kind) : CHThorActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg), table(0), outBuilder(NULL)
  4808. {
  4809. }
  4810. void CHThorLookupJoinActivity::ready()
  4811. {
  4812. CHThorActivityBase::ready();
  4813. input1->ready();
  4814. outBuilder.setAllocator(rowAllocator);
  4815. leftOuterJoin = (helper.getJoinFlags() & JFleftouter) != 0;
  4816. assertex((helper.getJoinFlags() & JFrightouter) == 0);
  4817. exclude = (helper.getJoinFlags() & JFexclude) != 0;
  4818. many = (helper.getJoinFlags() & JFmanylookup) != 0;
  4819. dedupRHS = (helper.getJoinFlags() & (JFmanylookup | JFmatchrequired | JFtransformMaySkip)) == 0; // optimisation: can implicitly dedup RHS unless is many lookup, or match required, or transform may skip
  4820. if((helper.getJoinFlags() & (JFfirst | JFfirstleft | JFfirstright | JFslidingmatch)) != 0)
  4821. throwUnexpected(); // compiler should have rejected
  4822. keepLimit = helper.getKeepLimit();
  4823. if(keepLimit==0)
  4824. keepLimit = static_cast<unsigned>(-1);
  4825. atmostLimit = helper.getJoinLimit();
  4826. limitLimit = helper.getMatchAbortLimit();
  4827. hasGroupLimit = ((atmostLimit > 0) || (limitLimit > 0));
  4828. if(atmostLimit==0)
  4829. atmostLimit = static_cast<unsigned>(-1);
  4830. if(limitLimit==0)
  4831. limitLimit = static_cast<unsigned>(-1);
  4832. isSmartJoin = (helper.getJoinFlags() & JFsmart) != 0;
  4833. getLimitType(helper.getJoinFlags(), limitFail, limitOnFail);
  4834. if((leftOuterJoin || limitOnFail) && !defaultRight)
  4835. createDefaultRight();
  4836. eog = false;
  4837. matchedGroup = false;
  4838. joinCounter = 0;
  4839. }
  4840. void CHThorLookupJoinActivity::done()
  4841. {
  4842. outBuilder.clear();
  4843. left.clear();
  4844. table.clear();
  4845. CHThorActivityBase::done();
  4846. input1->done();
  4847. }
  4848. void CHThorLookupJoinActivity::createDefaultRight()
  4849. {
  4850. if (!defaultRight)
  4851. {
  4852. if (!defaultRightAllocator)
  4853. defaultRightAllocator.setown(agent.queryCodeContext()->getRowAllocator(input1->queryOutputMeta(), activityId));
  4854. RtlDynamicRowBuilder rowBuilder(defaultRightAllocator);
  4855. size32_t thisSize = helper.createDefaultRight(rowBuilder);
  4856. defaultRight.setown(rowBuilder.finalizeRowClear(thisSize));
  4857. }
  4858. }
  4859. void CHThorLookupJoinActivity::loadRight()
  4860. {
  4861. OwnedRowArray rightset;
  4862. const void * next;
  4863. while(true)
  4864. {
  4865. next = input1->nextInGroup();
  4866. if(!next)
  4867. next = input1->nextInGroup();
  4868. if(!next)
  4869. break;
  4870. rightset.append(next);
  4871. }
  4872. unsigned rightord = rightset.ordinality();
  4873. table.setown(new LookupTable(rightord, helper.queryCompareLeftRight(), helper.queryCompareRight(), helper.queryHashLeft(), helper.queryHashRight(), dedupRHS));
  4874. unsigned i;
  4875. for(i=0; i<rightord; i++)
  4876. table->add(rightset.itemClear(i));
  4877. };
  4878. void CHThorLookupJoinActivity::setInput(unsigned index, IHThorInput * _input)
  4879. {
  4880. if (index==1)
  4881. input1 = _input;
  4882. else
  4883. CHThorActivityBase::setInput(index, _input);
  4884. }
  4885. //following are all copied from CHThorJoinActivity - should common up.
  4886. const void * CHThorLookupJoinActivity::joinRecords(const void * left, const void * right, unsigned counter)
  4887. {
  4888. try
  4889. {
  4890. outBuilder.ensureRow();
  4891. size32_t thisSize = helper.transform(outBuilder, left, right, counter);
  4892. if(thisSize)
  4893. return outBuilder.finalizeRowClear(thisSize);
  4894. else
  4895. return NULL;
  4896. }
  4897. catch(IException * e)
  4898. {
  4899. throw makeWrappedException(e);
  4900. }
  4901. }
  4902. const void * CHThorLookupJoinActivity::joinException(const void * left, IException * except)
  4903. {
  4904. try
  4905. {
  4906. outBuilder.ensureRow();
  4907. memsize_t thisSize = helper.onFailTransform(outBuilder, left, defaultRight, except);
  4908. if(thisSize)
  4909. return outBuilder.finalizeRowClear(thisSize);
  4910. else
  4911. return NULL;
  4912. }
  4913. catch(IException * e)
  4914. {
  4915. throw makeWrappedException(e);
  4916. }
  4917. }
  4918. const void * CHThorLookupJoinActivity::groupDenormalizeRecords(const void * left, ConstPointerArray & rows)
  4919. {
  4920. try
  4921. {
  4922. outBuilder.ensureRow();
  4923. unsigned numRows = rows.ordinality();
  4924. const void * right = numRows ? rows.item(0) : defaultRight.get();
  4925. memsize_t thisSize = helper.transform(outBuilder, left, right, numRows, (const void * *)rows.getArray());
  4926. if(thisSize)
  4927. return outBuilder.finalizeRowClear(thisSize);
  4928. else
  4929. return NULL;
  4930. }
  4931. catch(IException * e)
  4932. {
  4933. throw makeWrappedException(e);
  4934. }
  4935. }
  4936. const void * CHThorLookupJoinActivity::nextInGroup()
  4937. {
  4938. if(!table)
  4939. loadRight();
  4940. switch (kind)
  4941. {
  4942. case TAKlookupjoin:
  4943. case TAKsmartjoin:
  4944. return nextInGroupJoin();
  4945. case TAKlookupdenormalize:
  4946. case TAKlookupdenormalizegroup:
  4947. case TAKsmartdenormalize:
  4948. case TAKsmartdenormalizegroup:
  4949. return nextInGroupDenormalize();
  4950. }
  4951. throwUnexpected();
  4952. }
  4953. const void * CHThorLookupJoinActivity::nextInGroupJoin()
  4954. {
  4955. while(true)
  4956. {
  4957. const void * right = NULL;
  4958. if(!left)
  4959. {
  4960. left.setown(input->nextInGroup());
  4961. keepCount = keepLimit;
  4962. if(!left)
  4963. {
  4964. if (isSmartJoin)
  4965. left.setown(input->nextInGroup());
  4966. if(!left)
  4967. {
  4968. if(matchedGroup || eog)
  4969. {
  4970. matchedGroup = false;
  4971. eog = true;
  4972. return NULL;
  4973. }
  4974. eog = true;
  4975. continue;
  4976. }
  4977. }
  4978. eog = false;
  4979. gotMatch = false;
  4980. right = getRightFirst();
  4981. }
  4982. else
  4983. right = getRightNext();
  4984. const void * ret = NULL;
  4985. if(failingLimit)
  4986. {
  4987. ret = joinException(left, failingLimit);
  4988. }
  4989. else
  4990. {
  4991. while(right)
  4992. {
  4993. if(helper.match(left, right))
  4994. {
  4995. gotMatch = true;
  4996. if(exclude)
  4997. break;
  4998. ret = joinRecords(left, right, ++joinCounter);
  4999. if(ret)
  5000. break;
  5001. }
  5002. right = getRightNext();
  5003. ret = NULL;
  5004. }
  5005. if(leftOuterJoin && !gotMatch)
  5006. {
  5007. ret = joinRecords(left, defaultRight, 0);
  5008. gotMatch = true;
  5009. }
  5010. }
  5011. if(ret)
  5012. {
  5013. matchedGroup = true;
  5014. processed++;
  5015. if(!many || (--keepCount == 0) || failingLimit)
  5016. {
  5017. left.clear();
  5018. joinCounter = 0;
  5019. failingLimit.clear();
  5020. }
  5021. return ret;
  5022. }
  5023. left.clear();
  5024. joinCounter = 0;
  5025. }
  5026. }
  5027. const void * CHThorLookupJoinActivity::nextInGroupDenormalize()
  5028. {
  5029. while(true)
  5030. {
  5031. left.setown(input->nextInGroup());
  5032. if(!left)
  5033. {
  5034. if (!matchedGroup || isSmartJoin)
  5035. left.setown(input->nextInGroup());
  5036. if (!left)
  5037. {
  5038. matchedGroup = false;
  5039. return NULL;
  5040. }
  5041. }
  5042. gotMatch = false;
  5043. const void * right = getRightFirst();
  5044. const void * ret = NULL;
  5045. if (failingLimit)
  5046. ret = joinException(left, failingLimit);
  5047. else if (kind == TAKlookupdenormalize || kind == TAKsmartdenormalize)
  5048. {
  5049. OwnedConstRoxieRow newLeft(left.getLink());
  5050. unsigned rowSize = 0;
  5051. unsigned leftCount = 0;
  5052. keepCount = keepLimit;
  5053. while (right)
  5054. {
  5055. if (helper.match(left, right))
  5056. {
  5057. gotMatch = true;
  5058. if (exclude)
  5059. break;
  5060. try
  5061. {
  5062. RtlDynamicRowBuilder rowBuilder(rowAllocator);
  5063. unsigned thisSize = helper.transform(rowBuilder, newLeft, right, ++leftCount);
  5064. if (thisSize)
  5065. {
  5066. rowSize = thisSize;
  5067. newLeft.setown(rowBuilder.finalizeRowClear(rowSize));
  5068. }
  5069. }
  5070. catch(IException * e)
  5071. {
  5072. throw makeWrappedException(e);
  5073. }
  5074. if(!many || (--keepCount == 0))
  5075. break;
  5076. }
  5077. right = getRightNext();
  5078. }
  5079. //Is this rowSize test correct?? Is there any situation where it shouldn't just return newLeft?
  5080. if (rowSize)
  5081. ret = newLeft.getClear();
  5082. else if (leftOuterJoin && !gotMatch)
  5083. ret = left.getClear();
  5084. }
  5085. else
  5086. {
  5087. filteredRight.kill();
  5088. keepCount = keepLimit;
  5089. while (right)
  5090. {
  5091. if (helper.match(left, right))
  5092. {
  5093. gotMatch = true;
  5094. if(exclude)
  5095. break;
  5096. filteredRight.append(right);
  5097. if(!many || (--keepCount == 0))
  5098. break;
  5099. }
  5100. right = getRightNext();
  5101. }
  5102. if((filteredRight.ordinality() > 0) || (leftOuterJoin && !gotMatch))
  5103. ret = groupDenormalizeRecords(left, filteredRight);
  5104. filteredRight.kill();
  5105. }
  5106. left.clear();
  5107. failingLimit.clear();
  5108. if(ret)
  5109. {
  5110. matchedGroup = true;
  5111. processed++;
  5112. return ret;
  5113. }
  5114. }
  5115. }
  5116. bool CHThorLookupJoinActivity::isGrouped()
  5117. {
  5118. return input ? input->isGrouped() : false;
  5119. }
  5120. const void * CHThorLookupJoinActivity::fillRightGroup()
  5121. {
  5122. rightGroup.kill();
  5123. for(const void * right = table->find(left); right; right = table->findNext(left))
  5124. {
  5125. rightGroup.append(right);
  5126. if(rightGroup.ordinality() > limitLimit)
  5127. {
  5128. if(limitFail)
  5129. failLimit();
  5130. if ( agent.queryCodeContext()->queryDebugContext())
  5131. agent.queryCodeContext()->queryDebugContext()->checkBreakpoint(DebugStateLimit, NULL, static_cast<IActivityBase *>(this));
  5132. gotMatch = true;
  5133. if(limitOnFail)
  5134. {
  5135. assertex(!failingLimit);
  5136. try
  5137. {
  5138. failLimit();
  5139. }
  5140. catch(IException * e)
  5141. {
  5142. failingLimit.setown(e);
  5143. }
  5144. assertex(failingLimit);
  5145. }
  5146. else
  5147. {
  5148. rightGroup.kill();
  5149. }
  5150. break;
  5151. }
  5152. if(rightGroup.ordinality() > atmostLimit)
  5153. {
  5154. rightGroup.kill();
  5155. break;
  5156. }
  5157. }
  5158. rightGroupIndex = 0;
  5159. return readRightGroup();
  5160. }
  5161. void CHThorLookupJoinActivity::failLimit()
  5162. {
  5163. helper.onMatchAbortLimitExceeded();
  5164. CommonXmlWriter xmlwrite(0);
  5165. if(input->queryOutputMeta() && input->queryOutputMeta()->hasXML())
  5166. {
  5167. input->queryOutputMeta()->toXML(static_cast<const unsigned char *>(left.get()), xmlwrite);
  5168. }
  5169. throw MakeStringException(0, "More than %u match candidates in join for row %s", limitLimit, xmlwrite.str());
  5170. }
  5171. unsigned const CHThorLookupJoinActivity::LookupTable::BadIndex(static_cast<unsigned>(-1));
  5172. //=====================================================================================================
  5173. CHThorAllJoinActivity::CHThorAllJoinActivity(IAgentContext & _agent, unsigned _activityId, unsigned _subgraphId, IHThorAllJoinArg &_arg, ThorActivityKind _kind) : CHThorActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg), outBuilder(NULL)
  5174. {
  5175. }
  5176. void CHThorAllJoinActivity::ready()
  5177. {
  5178. CHThorActivityBase::ready();
  5179. input1->ready();
  5180. outBuilder.setAllocator(rowAllocator);
  5181. leftOuterJoin = (helper.getJoinFlags() & JFleftouter) != 0;
  5182. exclude = (helper.getJoinFlags() & JFexclude) != 0;
  5183. if(leftOuterJoin && !defaultRight)
  5184. createDefaultRight();
  5185. if((helper.getJoinFlags() & (JFrightouter | JFfirst | JFfirstleft | JFfirstright)) != 0)
  5186. throwUnexpected();
  5187. keepLimit = helper.getKeepLimit();
  5188. if(keepLimit==0)
  5189. keepLimit = (unsigned)-1;
  5190. started = false;
  5191. countForLeft = keepLimit;
  5192. matchedLeft = false;
  5193. matchedGroup = false;
  5194. eog = false;
  5195. eos = false;
  5196. }
  5197. void CHThorAllJoinActivity::done()
  5198. {
  5199. outBuilder.clear();
  5200. left.clear();
  5201. rightset.clear();
  5202. matchedRight.kill();
  5203. CHThorActivityBase::done();
  5204. input1->done();
  5205. }
  5206. void CHThorAllJoinActivity::createDefaultRight()
  5207. {
  5208. if (!defaultRight)
  5209. {
  5210. if (!defaultRightAllocator)
  5211. defaultRightAllocator.setown(agent.queryCodeContext()->getRowAllocator(input1->queryOutputMeta(), activityId));
  5212. RtlDynamicRowBuilder rowBuilder(defaultRightAllocator);
  5213. size32_t thisSize = helper.createDefaultRight(rowBuilder);
  5214. defaultRight.setown(rowBuilder.finalizeRowClear(thisSize));
  5215. }
  5216. }
  5217. void CHThorAllJoinActivity::loadRight()
  5218. {
  5219. const void * next;
  5220. while(true)
  5221. {
  5222. next = input1->nextInGroup();
  5223. if(!next)
  5224. next = input1->nextInGroup();
  5225. if(!next)
  5226. break;
  5227. rightset.append(next);
  5228. matchedRight.append(false);
  5229. }
  5230. rightIndex = 0;
  5231. joinCounter = 0;
  5232. rightOrdinality = rightset.ordinality();
  5233. }
  5234. const void * CHThorAllJoinActivity::joinRecords(const void * left, const void * right, unsigned counter)
  5235. {
  5236. try
  5237. {
  5238. outBuilder.ensureRow();
  5239. memsize_t thisSize = helper.transform(outBuilder, left, right, counter);
  5240. if(thisSize)
  5241. return outBuilder.finalizeRowClear(thisSize);
  5242. else
  5243. return NULL;
  5244. }
  5245. catch(IException * e)
  5246. {
  5247. throw makeWrappedException(e);
  5248. }
  5249. }
  5250. const void * CHThorAllJoinActivity::groupDenormalizeRecords(const void * curLeft, ConstPointerArray & rows)
  5251. {
  5252. try
  5253. {
  5254. outBuilder.ensureRow();
  5255. unsigned numRows = rows.ordinality();
  5256. const void * right = numRows ? rows.item(0) : defaultRight.get();
  5257. memsize_t thisSize = helper.transform(outBuilder, curLeft, right, numRows, (const void * *)rows.getArray());
  5258. if(thisSize)
  5259. return outBuilder.finalizeRowClear(thisSize);
  5260. else
  5261. return NULL;
  5262. }
  5263. catch(IException * e)
  5264. {
  5265. throw makeWrappedException(e);
  5266. }
  5267. }
  5268. void CHThorAllJoinActivity::setInput(unsigned index, IHThorInput * _input)
  5269. {
  5270. if (index==1)
  5271. input1 = _input;
  5272. else
  5273. {
  5274. CHThorActivityBase::setInput(index, _input);
  5275. leftIsGrouped = true; // input->isGrouped() is unreliable and it is just as good to always behave as if input is grouped
  5276. }
  5277. }
  5278. const void * CHThorAllJoinActivity::nextInGroup()
  5279. {
  5280. if(!started)
  5281. {
  5282. started = true;
  5283. left.setown(input->nextInGroup());
  5284. matchedLeft = false;
  5285. countForLeft = keepLimit;
  5286. if(!left)
  5287. {
  5288. eos = true;
  5289. return NULL;
  5290. }
  5291. loadRight();
  5292. }
  5293. const void * ret;
  5294. const void * right;
  5295. if(eos)
  5296. return NULL;
  5297. while(true)
  5298. {
  5299. ret = NULL;
  5300. if((rightIndex == rightOrdinality) || (countForLeft==0))
  5301. {
  5302. if(leftOuterJoin && left && !matchedLeft)
  5303. {
  5304. switch(kind)
  5305. {
  5306. case TAKalljoin:
  5307. ret = joinRecords(left, defaultRight, 0);
  5308. break;
  5309. case TAKalldenormalize:
  5310. ret = left.getClear();
  5311. break;
  5312. case TAKalldenormalizegroup:
  5313. filteredRight.kill();
  5314. ret = groupDenormalizeRecords(left, filteredRight);
  5315. break;
  5316. default:
  5317. throwUnexpected();
  5318. }
  5319. }
  5320. rightIndex = 0;
  5321. joinCounter = 0;
  5322. left.clear();
  5323. if(ret)
  5324. {
  5325. matchedGroup = true;
  5326. processed++;
  5327. return ret;
  5328. }
  5329. }
  5330. if(!left)
  5331. {
  5332. left.setown(input->nextInGroup());
  5333. matchedLeft = false;
  5334. countForLeft = keepLimit;
  5335. }
  5336. if(!left)
  5337. {
  5338. if(eog)
  5339. {
  5340. eos = true;
  5341. matchedGroup = false;
  5342. return NULL;
  5343. }
  5344. eog = true;
  5345. if(matchedGroup && leftIsGrouped)
  5346. {
  5347. matchedGroup = false;
  5348. return NULL;
  5349. }
  5350. matchedGroup = false;
  5351. continue;
  5352. }
  5353. eog = false;
  5354. switch(kind)
  5355. {
  5356. case TAKalljoin:
  5357. while(rightIndex < rightOrdinality)
  5358. {
  5359. right = rightset.item(rightIndex);
  5360. if(helper.match(left, right))
  5361. {
  5362. matchedLeft = true;
  5363. matchedRight.replace(true, rightIndex);
  5364. if(!exclude)
  5365. ret = joinRecords(left, right, ++joinCounter);
  5366. }
  5367. rightIndex++;
  5368. if(ret)
  5369. {
  5370. countForLeft--;
  5371. matchedGroup = true;
  5372. processed++;
  5373. return ret;
  5374. }
  5375. }
  5376. case TAKalldenormalize:
  5377. {
  5378. OwnedConstRoxieRow newLeft;
  5379. newLeft.set(left);
  5380. unsigned rowSize = 0;
  5381. unsigned leftCount = 0;
  5382. while((rightIndex < rightOrdinality) && countForLeft)
  5383. {
  5384. right = rightset.item(rightIndex);
  5385. if(helper.match(left, right))
  5386. {
  5387. matchedLeft = true;
  5388. matchedRight.replace(true, rightIndex);
  5389. if(!exclude)
  5390. {
  5391. try
  5392. {
  5393. RtlDynamicRowBuilder rowBuilder(rowAllocator);
  5394. unsigned thisSize = helper.transform(rowBuilder, newLeft, right, ++leftCount);
  5395. if(thisSize)
  5396. {
  5397. rowSize = thisSize;
  5398. newLeft.setown(rowBuilder.finalizeRowClear(rowSize));
  5399. --countForLeft;
  5400. }
  5401. }
  5402. catch(IException * e)
  5403. {
  5404. throw makeWrappedException(e);
  5405. }
  5406. }
  5407. }
  5408. rightIndex++;
  5409. }
  5410. if(rowSize)
  5411. {
  5412. processed++;
  5413. return newLeft.getClear();
  5414. }
  5415. }
  5416. break;
  5417. case TAKalldenormalizegroup:
  5418. filteredRight.kill();
  5419. while((rightIndex < rightOrdinality) && countForLeft)
  5420. {
  5421. right = rightset.item(rightIndex);
  5422. if(helper.match(left, right))
  5423. {
  5424. matchedLeft = true;
  5425. matchedRight.replace(true, rightIndex);
  5426. filteredRight.append(right);
  5427. --countForLeft;
  5428. }
  5429. ++rightIndex;
  5430. }
  5431. if(!exclude && filteredRight.ordinality())
  5432. {
  5433. const void * ret = groupDenormalizeRecords(left, filteredRight);
  5434. filteredRight.kill();
  5435. if(ret)
  5436. {
  5437. processed++;
  5438. return ret;
  5439. }
  5440. }
  5441. break;
  5442. default:
  5443. throwUnexpected();
  5444. }
  5445. }
  5446. }
  5447. bool CHThorAllJoinActivity::isGrouped()
  5448. {
  5449. return input ? input->isGrouped() : false;
  5450. }
  5451. //=====================================================================================================
  5452. //=====================================================================================================
  5453. CHThorWorkUnitWriteActivity::CHThorWorkUnitWriteActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorWorkUnitWriteArg &_arg, ThorActivityKind _kind)
  5454. : CHThorActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  5455. {
  5456. }
  5457. void CHThorWorkUnitWriteActivity::execute()
  5458. {
  5459. unsigned flags = helper.getFlags();
  5460. grouped = (POFgrouped & flags) != 0;
  5461. // In absense of OPT_OUTPUTLIMIT check pre 5.2 legacy name OPT_OUTPUTLIMIT_LEGACY
  5462. size32_t outputLimit = agent.queryWorkUnit()->getDebugValueInt(OPT_OUTPUTLIMIT, agent.queryWorkUnit()->getDebugValueInt(OPT_OUTPUTLIMIT_LEGACY, defaultDaliResultLimit));
  5463. if (flags & POFmaxsize)
  5464. outputLimit = helper.getMaxSize();
  5465. if (outputLimit>defaultDaliResultOutputMax)
  5466. throw MakeStringException(0, "Dali result outputs are restricted to a maximum of %d MB, the current limit is %d MB. A huge dali result usually indicates the ECL needs altering.", defaultDaliResultOutputMax, defaultDaliResultLimit);
  5467. assertex(outputLimit<=0x1000); // 32bit limit because MemoryBuffer/CMessageBuffers involved etc.
  5468. outputLimit *= 0x100000;
  5469. MemoryBuffer rowdata;
  5470. __int64 rows = 0;
  5471. IRecordSize * inputMeta = input->queryOutputMeta();
  5472. if (0 != (POFextend & helper.getFlags()))
  5473. {
  5474. WorkunitUpdate w = agent.updateWorkUnit();
  5475. Owned<IWUResult> result = updateWorkUnitResult(w, helper.queryName(), helper.getSequence());
  5476. rows = result->getResultRowCount();
  5477. }
  5478. __int64 initialRows = rows;
  5479. Owned<IOutputRowSerializer> rowSerializer;
  5480. if (input->queryOutputMeta()->getMetaFlags() & MDFneedserializedisk)
  5481. rowSerializer.setown( input->queryOutputMeta()->createDiskSerializer(agent.queryCodeContext(), activityId) );
  5482. int seq = helper.getSequence();
  5483. bool toStdout = (seq >= 0) && agent.queryWriteResultsToStdout();
  5484. Owned<SimpleOutputWriter> writer;
  5485. if (toStdout)
  5486. writer.setown(new SimpleOutputWriter);
  5487. if (agent.queryOutputFmt() == ofXML && seq >= 0)
  5488. {
  5489. StringBuffer sb;
  5490. const char *name = helper.queryName();
  5491. if (name && *name)
  5492. sb.appendf("<Dataset name='%s'>\n", name);
  5493. else
  5494. sb.appendf("<Dataset name='Result %d'>\n", seq+1);
  5495. agent.queryOutputSerializer()->fwrite(seq, (const void*)sb.str(), 1, sb.length());
  5496. }
  5497. loop
  5498. {
  5499. if ((unsigned __int64)rows >= agent.queryStopAfter())
  5500. break;
  5501. OwnedConstRoxieRow nextrec(input->nextInGroup());
  5502. if (grouped && (rows != initialRows))
  5503. rowdata.append(nextrec == NULL);
  5504. if (!nextrec)
  5505. {
  5506. nextrec.setown(input->nextInGroup());
  5507. if (!nextrec)
  5508. break;
  5509. }
  5510. size32_t thisSize = inputMeta->getRecordSize(nextrec);
  5511. if(outputLimit && ((rowdata.length() + thisSize) > outputLimit))
  5512. {
  5513. StringBuffer errMsg("Dataset too large to output to workunit (limit ");
  5514. errMsg.append(outputLimit/0x100000).append(" megabytes), in result (");
  5515. const char *name = helper.queryName();
  5516. if (name)
  5517. errMsg.append("name=").append(name);
  5518. else
  5519. errMsg.append("sequence=").append(helper.getSequence());
  5520. errMsg.append(")");
  5521. throw MakeStringExceptionDirect(0, errMsg.str());
  5522. }
  5523. if (rowSerializer)
  5524. {
  5525. CThorDemoRowSerializer serializerTarget(rowdata);
  5526. rowSerializer->serialize(serializerTarget, (const byte *) nextrec.get() );
  5527. }
  5528. else
  5529. rowdata.append(thisSize, nextrec);
  5530. if (toStdout && seq >= 0)
  5531. {
  5532. if (agent.queryOutputFmt() == ofSTD)
  5533. {
  5534. helper.serializeXml((byte *) nextrec.get(), *writer);
  5535. writer->newline();
  5536. agent.queryOutputSerializer()->fwrite(seq, (const void*)writer->str(), 1, writer->length());
  5537. writer->clear();
  5538. }
  5539. else if (agent.queryOutputFmt() == ofXML)
  5540. {
  5541. CommonXmlWriter xmlwrite(0,1);
  5542. xmlwrite.outputBeginNested(DEFAULTXMLROWTAG, false);
  5543. helper.serializeXml((byte *) nextrec.get(), xmlwrite);
  5544. xmlwrite.outputEndNested(DEFAULTXMLROWTAG);
  5545. agent.queryOutputSerializer()->fwrite(seq, (const void*)xmlwrite.str(), 1, xmlwrite.length());
  5546. }
  5547. }
  5548. rows++;
  5549. }
  5550. WorkunitUpdate w = agent.updateWorkUnit();
  5551. Owned<IWUResult> result = updateWorkUnitResult(w, helper.queryName(), helper.getSequence());
  5552. if (0 != (POFextend & helper.getFlags()))
  5553. result->addResultRaw(rowdata.length(), rowdata.toByteArray(), ResultFormatRaw);
  5554. else
  5555. result->setResultRaw(rowdata.length(), rowdata.toByteArray(), ResultFormatRaw);
  5556. result->setResultStatus(ResultStatusCalculated);
  5557. result->setResultRowCount(rows);
  5558. result->setResultTotalRowCount(rows); // Is this right??
  5559. if (toStdout && seq >= 0)
  5560. {
  5561. if (agent.queryOutputFmt() == ofXML)
  5562. {
  5563. StringBuffer sb;
  5564. sb.appendf(DEFAULTXMLFOOTER).newline();
  5565. agent.queryOutputSerializer()->fwrite(seq, (const void*)sb.str(), 1, sb.length());
  5566. }
  5567. else if (agent.queryOutputFmt() != ofSTD)
  5568. agent.outputFormattedResult(helper.queryName(), seq, false);
  5569. if (!(POFextend & helper.getFlags()))//POextend results will never get closed, so wont flush until serializer dtor
  5570. agent.queryOutputSerializer()->close(seq, false);
  5571. }
  5572. }
  5573. //=====================================================================================================
  5574. CHThorDictionaryWorkUnitWriteActivity::CHThorDictionaryWorkUnitWriteActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorDictionaryWorkUnitWriteArg &_arg, ThorActivityKind _kind)
  5575. : CHThorActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  5576. {
  5577. }
  5578. void CHThorDictionaryWorkUnitWriteActivity::execute()
  5579. {
  5580. int sequence = helper.getSequence();
  5581. const char *storedName = helper.queryName();
  5582. assertex(storedName && *storedName);
  5583. assertex(sequence < 0);
  5584. RtlLinkedDictionaryBuilder builder(rowAllocator, helper.queryHashLookupInfo());
  5585. loop
  5586. {
  5587. const void *row = input->nextInGroup();
  5588. if (!row)
  5589. {
  5590. row = input->nextInGroup();
  5591. if (!row)
  5592. break;
  5593. }
  5594. builder.appendOwn(row);
  5595. processed++;
  5596. }
  5597. unsigned __int64 usedCount = rtlDictionaryCount(builder.getcount(), builder.queryrows());
  5598. // In absense of OPT_OUTPUTLIMIT check pre 5.2 legacy name OPT_OUTPUTLIMIT_LEGACY
  5599. size32_t outputLimit = agent.queryWorkUnit()->getDebugValueInt(OPT_OUTPUTLIMIT, agent.queryWorkUnit()->getDebugValueInt(OPT_OUTPUTLIMIT_LEGACY, defaultDaliResultLimit)) * 0x100000;
  5600. MemoryBuffer rowdata;
  5601. CThorDemoRowSerializer out(rowdata);
  5602. Owned<IOutputRowSerializer> serializer = input->queryOutputMeta()->createDiskSerializer(agent.queryCodeContext(), activityId);
  5603. rtlSerializeDictionary(out, serializer, builder.getcount(), builder.queryrows());
  5604. if(outputLimit && (rowdata.length() > outputLimit))
  5605. {
  5606. StringBuffer errMsg("Dictionary too large to output to workunit (limit ");
  5607. errMsg.append(outputLimit/0x100000).append(" megabytes), in result (");
  5608. const char *name = helper.queryName();
  5609. if (name)
  5610. errMsg.append("name=").append(name);
  5611. else
  5612. errMsg.append("sequence=").append(helper.getSequence());
  5613. errMsg.append(")");
  5614. throw MakeStringExceptionDirect(0, errMsg.str());
  5615. }
  5616. WorkunitUpdate w = agent.updateWorkUnit();
  5617. Owned<IWUResult> result = updateWorkUnitResult(w, helper.queryName(), helper.getSequence());
  5618. result->setResultRaw(rowdata.length(), rowdata.toByteArray(), ResultFormatRaw);
  5619. result->setResultStatus(ResultStatusCalculated);
  5620. result->setResultRowCount(usedCount);
  5621. result->setResultTotalRowCount(usedCount); // Is this right??
  5622. }
  5623. //=====================================================================================================
  5624. CHThorRemoteResultActivity::CHThorRemoteResultActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorRemoteResultArg &_arg, ThorActivityKind _kind)
  5625. : CHThorActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  5626. {
  5627. }
  5628. void CHThorRemoteResultActivity::execute()
  5629. {
  5630. OwnedConstRoxieRow result(input->nextInGroup());
  5631. helper.sendResult(result);
  5632. }
  5633. //=====================================================================================================
  5634. CHThorInlineTableActivity::CHThorInlineTableActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorInlineTableArg &_arg, ThorActivityKind _kind) :
  5635. CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  5636. {
  5637. }
  5638. void CHThorInlineTableActivity::ready()
  5639. {
  5640. CHThorSimpleActivityBase::ready();
  5641. curRow = 0;
  5642. numRows = helper.numRows();
  5643. }
  5644. const void *CHThorInlineTableActivity::nextInGroup()
  5645. {
  5646. // Filtering empty rows, returns the next valid row
  5647. while (curRow < numRows)
  5648. {
  5649. RtlDynamicRowBuilder rowBuilder(rowAllocator);
  5650. size32_t size = helper.getRow(rowBuilder, curRow++);
  5651. if (size)
  5652. {
  5653. processed++;
  5654. return rowBuilder.finalizeRowClear(size);
  5655. }
  5656. }
  5657. return NULL;
  5658. }
  5659. //=====================================================================================================
  5660. CHThorNullActivity::CHThorNullActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  5661. {
  5662. }
  5663. const void *CHThorNullActivity::nextInGroup()
  5664. {
  5665. return NULL;
  5666. }
  5667. //=====================================================================================================
  5668. CHThorActionActivity::CHThorActionActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorActionArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  5669. {
  5670. }
  5671. void CHThorActionActivity::execute()
  5672. {
  5673. helper.action();
  5674. }
  5675. const void *CHThorActionActivity::nextInGroup()
  5676. {
  5677. return NULL;
  5678. }
  5679. //=====================================================================================================
  5680. CHThorSideEffectActivity::CHThorSideEffectActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorSideEffectArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  5681. {
  5682. }
  5683. const void *CHThorSideEffectActivity::nextInGroup()
  5684. {
  5685. try
  5686. {
  5687. helper.action();
  5688. }
  5689. catch(IException * e)
  5690. {
  5691. throw makeWrappedException(e);
  5692. }
  5693. return NULL;
  5694. }
  5695. //=====================================================================================================
  5696. CHThorDummyActivity::CHThorDummyActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind)
  5697. {
  5698. }
  5699. void CHThorDummyActivity::execute()
  5700. {
  5701. }
  5702. const void *CHThorDummyActivity::nextInGroup()
  5703. {
  5704. return input ? input->nextInGroup() : NULL;
  5705. }
  5706. //=====================================================================================================
  5707. CHThorWhenActionActivity::CHThorWhenActionActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorArg &_arg, ThorActivityKind _kind, EclGraphElement * _graphElement)
  5708. : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), graphElement(_graphElement)
  5709. {
  5710. }
  5711. void CHThorWhenActionActivity::ready()
  5712. {
  5713. CHThorSimpleActivityBase::ready();
  5714. graphElement->executeDependentActions(agent, NULL, WhenBeforeId);
  5715. graphElement->executeDependentActions(agent, NULL, WhenParallelId);
  5716. }
  5717. void CHThorWhenActionActivity::execute()
  5718. {
  5719. graphElement->executeDependentActions(agent, NULL, 1);
  5720. }
  5721. const void * CHThorWhenActionActivity::nextInGroup()
  5722. {
  5723. return input->nextInGroup();
  5724. }
  5725. void CHThorWhenActionActivity::done()
  5726. {
  5727. graphElement->executeDependentActions(agent, NULL, WhenSuccessId);
  5728. CHThorSimpleActivityBase::done();
  5729. }
  5730. //=====================================================================================================
  5731. CHThorMultiInputActivity::CHThorMultiInputActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind)
  5732. {
  5733. }
  5734. void CHThorMultiInputActivity::ready()
  5735. {
  5736. CHThorSimpleActivityBase::ready();
  5737. ForEachItemIn(idx, inputs)
  5738. inputs.item(idx)->ready();
  5739. }
  5740. void CHThorMultiInputActivity::done()
  5741. {
  5742. CHThorSimpleActivityBase::done();
  5743. ForEachItemIn(idx, inputs)
  5744. inputs.item(idx)->done();
  5745. }
  5746. void CHThorMultiInputActivity::setInput(unsigned index, IHThorInput *_input)
  5747. {
  5748. if (index==inputs.length())
  5749. {
  5750. inputs.append(_input);
  5751. }
  5752. else
  5753. {
  5754. while (!inputs.isItem(index))
  5755. inputs.append(NULL);
  5756. inputs.replace(_input, index);
  5757. }
  5758. }
  5759. void CHThorMultiInputActivity::updateProgress(IStatisticGatherer &progress) const
  5760. {
  5761. CHThorSimpleActivityBase::updateProgress(progress);
  5762. ForEachItemIn(idx, inputs)
  5763. {
  5764. IHThorInput *i = inputs.item(idx);
  5765. if (i)
  5766. i->updateProgress(progress);
  5767. }
  5768. }
  5769. //=====================================================================================================
  5770. CHThorConcatActivity::CHThorConcatActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorFunnelArg &_arg, ThorActivityKind _kind) : CHThorMultiInputActivity(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  5771. {
  5772. }
  5773. void CHThorConcatActivity::ready()
  5774. {
  5775. grouped = helper.queryOutputMeta()->isGrouped();
  5776. inputIdx = 0;
  5777. curInput = inputs.item(inputIdx);
  5778. eogSeen = false;
  5779. anyThisGroup = false;
  5780. CHThorMultiInputActivity::ready();
  5781. }
  5782. const void *CHThorConcatActivity::nextInGroup()
  5783. {
  5784. if (!curInput)
  5785. return NULL; // eof
  5786. const void * next = curInput->nextInGroup();
  5787. if (next)
  5788. {
  5789. anyThisGroup = true;
  5790. eogSeen = false;
  5791. processed++;
  5792. return next;
  5793. }
  5794. else if (!eogSeen)
  5795. {
  5796. eogSeen = true;
  5797. if (grouped)
  5798. {
  5799. if (anyThisGroup)
  5800. {
  5801. anyThisGroup = false;
  5802. return NULL;
  5803. }
  5804. else
  5805. return nextInGroup();
  5806. }
  5807. else
  5808. return nextInGroup();
  5809. }
  5810. else if (inputIdx < inputs.length()-1)
  5811. {
  5812. inputIdx++;
  5813. curInput = inputs.item(inputIdx);
  5814. eogSeen = false;
  5815. anyThisGroup = false;
  5816. return nextInGroup();
  5817. }
  5818. else
  5819. {
  5820. curInput = NULL;
  5821. return NULL;
  5822. }
  5823. }
  5824. //=====================================================================================================
  5825. CHThorNonEmptyActivity::CHThorNonEmptyActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorNonEmptyArg &_arg, ThorActivityKind _kind) : CHThorMultiInputActivity(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  5826. {
  5827. }
  5828. void CHThorNonEmptyActivity::ready()
  5829. {
  5830. grouped = helper.queryOutputMeta()->isGrouped();
  5831. selectedInput = NULL;
  5832. CHThorMultiInputActivity::ready();
  5833. }
  5834. const void *CHThorNonEmptyActivity::nextInGroup()
  5835. {
  5836. if (!selectedInput)
  5837. {
  5838. ForEachItemIn(i, inputs)
  5839. {
  5840. IHThorInput * cur = inputs.item(i);
  5841. const void * next = cur->nextInGroup();
  5842. if (next)
  5843. {
  5844. selectedInput = cur;
  5845. processed++;
  5846. return next;
  5847. }
  5848. }
  5849. return NULL;
  5850. }
  5851. const void * next = selectedInput->nextInGroup();
  5852. if (next)
  5853. processed++;
  5854. return next;
  5855. }
  5856. //=====================================================================================================
  5857. CHThorRegroupActivity::CHThorRegroupActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorRegroupArg &_arg, ThorActivityKind _kind) : CHThorMultiInputActivity(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  5858. {
  5859. }
  5860. void CHThorRegroupActivity::ready()
  5861. {
  5862. inputIndex = 0;
  5863. eof = false;
  5864. numProcessedLastGroup = processed;
  5865. CHThorMultiInputActivity::ready();
  5866. }
  5867. const void * CHThorRegroupActivity::nextFromInputs()
  5868. {
  5869. unsigned initialInput = inputIndex;
  5870. while (inputs.isItem(inputIndex))
  5871. {
  5872. OwnedConstRoxieRow next(inputs.item(inputIndex)->nextInGroup());
  5873. if (next)
  5874. {
  5875. if ((inputIndex != initialInput) && (inputIndex != initialInput+1))
  5876. {
  5877. throw MakeStringException(100, "Mismatched groups supplied to regroup %u", activityId);
  5878. }
  5879. return next.getClear();
  5880. }
  5881. inputIndex++;
  5882. }
  5883. if ((initialInput != 0) && (initialInput+1 != inputs.ordinality()))
  5884. throw MakeStringException(100, "Mismatched groups supplied to Regroup Activity(%u)", activityId);
  5885. inputIndex = 0;
  5886. return NULL;
  5887. }
  5888. const void * CHThorRegroupActivity::nextInGroup()
  5889. {
  5890. if (eof)
  5891. return NULL;
  5892. const void * ret = nextFromInputs();
  5893. if (ret)
  5894. {
  5895. processed++;
  5896. return ret;
  5897. }
  5898. if (numProcessedLastGroup != processed)
  5899. {
  5900. numProcessedLastGroup = processed;
  5901. return NULL;
  5902. }
  5903. eof = true;
  5904. return NULL;
  5905. }
  5906. //=====================================================================================================
  5907. CHThorRollupGroupActivity::CHThorRollupGroupActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorRollupGroupArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  5908. {
  5909. }
  5910. void CHThorRollupGroupActivity::ready()
  5911. {
  5912. CHThorSimpleActivityBase::ready();
  5913. eof = false;
  5914. }
  5915. const void * CHThorRollupGroupActivity::nextInGroup()
  5916. {
  5917. if (eof)
  5918. return NULL;
  5919. loop
  5920. {
  5921. OwnedRowArray group;
  5922. loop
  5923. {
  5924. const void * in = input->nextInGroup();
  5925. if (!in)
  5926. break;
  5927. group.append(in);
  5928. }
  5929. if (group.ordinality() == 0)
  5930. {
  5931. eof = true;
  5932. return NULL;
  5933. }
  5934. try
  5935. {
  5936. RtlDynamicRowBuilder rowBuilder(rowAllocator);
  5937. size32_t outSize = helper.transform(rowBuilder, group.ordinality(), (const void * *)group.getArray());
  5938. if (outSize)
  5939. {
  5940. processed++;
  5941. return rowBuilder.finalizeRowClear(outSize);
  5942. }
  5943. }
  5944. catch(IException * e)
  5945. {
  5946. throw makeWrappedException(e);
  5947. }
  5948. }
  5949. }
  5950. //=====================================================================================================
  5951. CHThorCombineActivity::CHThorCombineActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorCombineArg &_arg, ThorActivityKind _kind) : CHThorMultiInputActivity(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  5952. {
  5953. }
  5954. void CHThorCombineActivity::ready()
  5955. {
  5956. numProcessedLastGroup = processed;
  5957. CHThorMultiInputActivity::ready();
  5958. }
  5959. void CHThorCombineActivity::nextInputs(OwnedRowArray & out)
  5960. {
  5961. ForEachItemIn(i, inputs)
  5962. {
  5963. const void * next = inputs.item(i)->nextInGroup();
  5964. if (next)
  5965. out.append(next);
  5966. }
  5967. }
  5968. const void *CHThorCombineActivity::nextInGroup()
  5969. {
  5970. loop
  5971. {
  5972. OwnedRowArray group;
  5973. nextInputs(group);
  5974. if ((group.ordinality() == 0) && (numProcessedLastGroup == processed))
  5975. nextInputs(group);
  5976. if (group.ordinality() == 0)
  5977. {
  5978. numProcessedLastGroup = processed;
  5979. return NULL;
  5980. }
  5981. else if (group.ordinality() != inputs.ordinality())
  5982. {
  5983. throw MakeStringException(101, "Mismatched group input for Combine Activity(%u)", activityId);
  5984. }
  5985. try
  5986. {
  5987. RtlDynamicRowBuilder rowBuilder(rowAllocator);
  5988. size32_t outSize = helper.transform(rowBuilder, group.ordinality(), (const void * *)group.getArray());
  5989. if (outSize)
  5990. {
  5991. processed++;
  5992. return rowBuilder.finalizeRowClear(outSize);
  5993. }
  5994. }
  5995. catch(IException * e)
  5996. {
  5997. throw makeWrappedException(e);
  5998. }
  5999. }
  6000. }
  6001. //=====================================================================================================
  6002. CHThorCombineGroupActivity::CHThorCombineGroupActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorCombineGroupArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  6003. {
  6004. }
  6005. void CHThorCombineGroupActivity::ready()
  6006. {
  6007. numProcessedLastGroup = processed;
  6008. CHThorSimpleActivityBase::ready();
  6009. input1->ready();
  6010. }
  6011. void CHThorCombineGroupActivity::done()
  6012. {
  6013. CHThorSimpleActivityBase::done();
  6014. input1->done();
  6015. }
  6016. void CHThorCombineGroupActivity::setInput(unsigned index, IHThorInput *_input)
  6017. {
  6018. if (index==1)
  6019. input1 = _input;
  6020. else
  6021. CHThorSimpleActivityBase::setInput(index, _input);
  6022. }
  6023. const void *CHThorCombineGroupActivity::nextInGroup()
  6024. {
  6025. loop
  6026. {
  6027. OwnedConstRoxieRow left(input->nextInGroup());
  6028. if (!left && (numProcessedLastGroup == processed))
  6029. left.setown(input->nextInGroup());
  6030. if (!left)
  6031. {
  6032. if (numProcessedLastGroup == processed)
  6033. {
  6034. OwnedConstRoxieRow nextRight(input1->nextInGroup());
  6035. if (nextRight)
  6036. throw MakeStringException(101, "Missing LEFT record for Combine group Activity(%u)", activityId);
  6037. }
  6038. else
  6039. numProcessedLastGroup = processed;
  6040. return NULL;
  6041. }
  6042. OwnedRowArray group;
  6043. loop
  6044. {
  6045. const void * in = input1->nextInGroup();
  6046. if (!in)
  6047. break;
  6048. group.append(in);
  6049. }
  6050. if (group.ordinality() == 0)
  6051. {
  6052. throw MakeStringException(101, "Missing RIGHT group for Combine Group Activity(%u)", activityId);
  6053. }
  6054. try
  6055. {
  6056. RtlDynamicRowBuilder rowBuilder(rowAllocator);
  6057. size32_t outSize = helper.transform(rowBuilder, left, group.ordinality(), (const void * *)group.getArray());
  6058. if (outSize)
  6059. {
  6060. processed++;
  6061. return rowBuilder.finalizeRowClear(outSize);
  6062. }
  6063. }
  6064. catch(IException * e)
  6065. {
  6066. throw makeWrappedException(e);
  6067. }
  6068. }
  6069. }
  6070. //=====================================================================================================
  6071. CHThorApplyActivity::CHThorApplyActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorApplyArg &_arg, ThorActivityKind _kind) : CHThorActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  6072. {
  6073. }
  6074. void CHThorApplyActivity::execute()
  6075. {
  6076. try
  6077. {
  6078. helper.start();
  6079. loop
  6080. {
  6081. OwnedConstRoxieRow next(input->nextInGroup());
  6082. if (!next)
  6083. {
  6084. next.setown(input->nextInGroup());
  6085. if (!next)
  6086. break;
  6087. }
  6088. helper.apply(next);
  6089. }
  6090. helper.end();
  6091. }
  6092. catch (IException *e)
  6093. {
  6094. throw makeWrappedException(e);
  6095. }
  6096. }
  6097. //=====================================================================================================
  6098. CHThorDistributionActivity::CHThorDistributionActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorDistributionArg &_arg, ThorActivityKind _kind)
  6099. : CHThorActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  6100. {
  6101. }
  6102. void CHThorDistributionActivity::execute()
  6103. {
  6104. MemoryAttr ma;
  6105. IDistributionTable * * accumulator = (IDistributionTable * *)ma.allocate(helper.queryInternalRecordSize()->getMinRecordSize());
  6106. helper.clearAggregate(accumulator);
  6107. OwnedConstRoxieRow nextrec(input->nextInGroup());
  6108. loop
  6109. {
  6110. if (!nextrec)
  6111. {
  6112. nextrec.setown(input->nextInGroup());
  6113. if (!nextrec)
  6114. break;
  6115. }
  6116. helper.process(accumulator, nextrec);
  6117. nextrec.setown(input->nextInGroup());
  6118. }
  6119. StringBuffer result;
  6120. result.append("<XML>");
  6121. helper.gatherResult(accumulator, result);
  6122. result.append("</XML>");
  6123. helper.sendResult(result.length(), result.str());
  6124. helper.destruct(accumulator);
  6125. }
  6126. //---------------------------------------------------------------------------
  6127. CHThorWorkunitReadActivity::CHThorWorkunitReadActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorWorkunitReadArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  6128. {
  6129. first = true;
  6130. bufferStream.setown(createMemoryBufferSerialStream(resultBuffer));
  6131. deserializer.setStream(bufferStream);
  6132. }
  6133. CHThorWorkunitReadActivity::~CHThorWorkunitReadActivity()
  6134. {
  6135. }
  6136. void CHThorWorkunitReadActivity::ready()
  6137. {
  6138. CHThorSimpleActivityBase::ready();
  6139. rowDeserializer.setown(rowAllocator->createDiskDeserializer(agent.queryCodeContext()));
  6140. if(first)
  6141. {
  6142. checkForDiskRead();
  6143. first = false;
  6144. }
  6145. if(diskread)
  6146. {
  6147. diskread->ready();
  6148. return;
  6149. }
  6150. grouped = outputMeta.isGrouped();
  6151. unsigned lenData;
  6152. void * tempData;
  6153. OwnedRoxieString fromWuid(helper.getWUID());
  6154. ICsvToRowTransformer * csvTransformer = helper.queryCsvTransformer();
  6155. IXmlToRowTransformer * xmlTransformer = helper.queryXmlTransformer();
  6156. if (fromWuid)
  6157. agent.queryCodeContext()->getExternalResultRaw(lenData, tempData, fromWuid, helper.queryName(), helper.querySequence(), xmlTransformer, csvTransformer);
  6158. else
  6159. agent.queryCodeContext()->getResultRaw(lenData, tempData, helper.queryName(), helper.querySequence(), xmlTransformer, csvTransformer);
  6160. resultBuffer.setBuffer(lenData, tempData, true);
  6161. eogPending = false;
  6162. }
  6163. void CHThorWorkunitReadActivity::checkForDiskRead()
  6164. {
  6165. StringBuffer diskFilename;
  6166. OwnedRoxieString fromWuid(helper.getWUID());
  6167. if (agent.getWorkunitResultFilename(diskFilename, fromWuid, helper.queryName(), helper.querySequence()))
  6168. {
  6169. diskreadHelper.setown(createWorkUnitReadArg(diskFilename.str(), &helper));
  6170. try
  6171. {
  6172. diskreadHelper->onCreate(agent.queryCodeContext(), NULL, NULL);
  6173. }
  6174. catch(IException * e)
  6175. {
  6176. throw makeWrappedException(e);
  6177. }
  6178. diskread.setown(new CHThorDiskReadActivity(agent, activityId, subgraphId, *diskreadHelper, TAKdiskread));
  6179. }
  6180. }
  6181. void CHThorWorkunitReadActivity::done()
  6182. {
  6183. if(diskread)
  6184. diskread->done();
  6185. resultBuffer.resetBuffer();
  6186. CHThorSimpleActivityBase::done();
  6187. }
  6188. const void *CHThorWorkunitReadActivity::nextInGroup()
  6189. {
  6190. if(diskread)
  6191. {
  6192. const void * ret = diskread->nextInGroup();
  6193. processed = diskread->queryProcessed();
  6194. return ret;
  6195. }
  6196. if (deserializer.eos())
  6197. return NULL;
  6198. if (eogPending)
  6199. {
  6200. eogPending = false;
  6201. return NULL;
  6202. }
  6203. RtlDynamicRowBuilder rowBuilder(rowAllocator);
  6204. size32_t newSize = rowDeserializer->deserialize(rowBuilder, deserializer);
  6205. if (grouped)
  6206. deserializer.read(sizeof(bool), &eogPending);
  6207. processed++;
  6208. return rowBuilder.finalizeRowClear(newSize);
  6209. }
  6210. //=====================================================================================================
  6211. CHThorParseActivity::CHThorParseActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorParseArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  6212. {
  6213. //DebugBreak();
  6214. anyThisGroup = false;
  6215. curSearchTextLen = 0;
  6216. curSearchText = NULL;
  6217. algorithm = createThorParser(agent.queryCodeContext(), helper);
  6218. parser = algorithm->createParser(agent.queryCodeContext(), activityId, helper.queryHelper(), &helper);
  6219. rowIter = parser->queryResultIter();
  6220. }
  6221. CHThorParseActivity::~CHThorParseActivity()
  6222. {
  6223. if (curSearchText && helper.searchTextNeedsFree())
  6224. rtlFree(curSearchText);
  6225. parser->Release();
  6226. algorithm->Release();
  6227. }
  6228. void CHThorParseActivity::ready()
  6229. {
  6230. CHThorSimpleActivityBase::ready();
  6231. anyThisGroup = false;
  6232. parser->reset();
  6233. }
  6234. void CHThorParseActivity::done()
  6235. {
  6236. CHThorSimpleActivityBase::done();
  6237. if (curSearchText && helper.searchTextNeedsFree())
  6238. rtlFree(curSearchText);
  6239. curSearchText = NULL;
  6240. in.clear();
  6241. }
  6242. bool CHThorParseActivity::processRecord(const void * in)
  6243. {
  6244. if (curSearchText && helper.searchTextNeedsFree())
  6245. rtlFree(curSearchText);
  6246. curSearchTextLen = 0;
  6247. curSearchText = NULL;
  6248. helper.getSearchText(curSearchTextLen, curSearchText, in);
  6249. return parser->performMatch(*this, in, curSearchTextLen, curSearchText);
  6250. }
  6251. unsigned CHThorParseActivity::onMatch(ARowBuilder & self, const void * curRecord, IMatchedResults * results, IMatchWalker * walker)
  6252. {
  6253. try
  6254. {
  6255. return helper.transform(self, curRecord, results, walker);
  6256. }
  6257. catch(IException * e)
  6258. {
  6259. throw makeWrappedException(e);
  6260. }
  6261. }
  6262. const void * CHThorParseActivity::nextInGroup()
  6263. {
  6264. loop
  6265. {
  6266. if (rowIter->isValid())
  6267. {
  6268. anyThisGroup = true;
  6269. OwnedConstRoxieRow out = rowIter->getRow();
  6270. rowIter->next();
  6271. processed++;
  6272. return out.getClear();
  6273. }
  6274. in.setown(input->nextInGroup());
  6275. if (!in)
  6276. {
  6277. if (anyThisGroup)
  6278. {
  6279. anyThisGroup = false;
  6280. return NULL;
  6281. }
  6282. in.setown(input->nextInGroup());
  6283. if (!in)
  6284. return NULL;
  6285. }
  6286. processRecord(in);
  6287. rowIter->first();
  6288. }
  6289. }
  6290. //=====================================================================================================
  6291. CHThorEnthActivity::CHThorEnthActivity(IAgentContext & _agent, unsigned _activityId, unsigned _subgraphId, IHThorEnthArg & _arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg), outBuilder(NULL)
  6292. {
  6293. }
  6294. void CHThorEnthActivity::ready()
  6295. {
  6296. CHThorSimpleActivityBase::ready();
  6297. outBuilder.setAllocator(rowAllocator);
  6298. numerator = helper.getProportionNumerator();
  6299. denominator = helper.getProportionDenominator();
  6300. started = false;
  6301. }
  6302. void CHThorEnthActivity::done()
  6303. {
  6304. outBuilder.clear();
  6305. }
  6306. void CHThorEnthActivity::start()
  6307. {
  6308. if(denominator == 0) denominator = 1;
  6309. counter = (helper.getSampleNumber()-1) * greatestCommonDivisor(numerator, denominator);
  6310. if (counter >= denominator)
  6311. counter %= denominator;
  6312. started = true;
  6313. }
  6314. const void * CHThorEnthActivity::nextInGroup()
  6315. {
  6316. if(!started)
  6317. start();
  6318. OwnedConstRoxieRow ret;
  6319. loop
  6320. {
  6321. ret.setown(input->nextInGroup());
  6322. if(!ret) //end of group
  6323. ret.setown(input->nextInGroup());
  6324. if(!ret) //eof
  6325. return NULL;
  6326. if (wanted())
  6327. {
  6328. processed++;
  6329. return ret.getClear();
  6330. }
  6331. }
  6332. }
  6333. //=====================================================================================================
  6334. CHThorTopNActivity::CHThorTopNActivity(IAgentContext & _agent, unsigned _activityId, unsigned _subgraphId, IHThorTopNArg & _arg, ThorActivityKind _kind)
  6335. : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg), compare(*helper.queryCompare())
  6336. {
  6337. hasBest = helper.hasBest();
  6338. grouped = outputMeta.isGrouped();
  6339. curIndex = 0;
  6340. sortedCount = 0;
  6341. limit = 0;
  6342. sorted = NULL;
  6343. }
  6344. CHThorTopNActivity::~CHThorTopNActivity()
  6345. {
  6346. roxiemem::ReleaseRoxieRowRange(sorted, curIndex, sortedCount);
  6347. free(sorted);
  6348. }
  6349. void CHThorTopNActivity::ready()
  6350. {
  6351. CHThorSimpleActivityBase::ready();
  6352. limit = helper.getLimit();
  6353. assertex(limit == (size_t)limit);
  6354. sorted = (const void * *)checked_calloc((size_t)(limit+1), sizeof(void *), "topn");
  6355. sortedCount = 0;
  6356. curIndex = 0;
  6357. eof = false;
  6358. eoi = false;
  6359. }
  6360. void CHThorTopNActivity::done()
  6361. {
  6362. CHThorSimpleActivityBase::done();
  6363. roxiemem::ReleaseRoxieRowRange(sorted, curIndex, sortedCount);
  6364. free(sorted);
  6365. sorted = NULL;
  6366. curIndex = 0;
  6367. sortedCount = 0;
  6368. }
  6369. const void * CHThorTopNActivity::nextInGroup()
  6370. {
  6371. if(eof)
  6372. return NULL;
  6373. if(curIndex >= sortedCount)
  6374. {
  6375. bool eog = sortedCount != 0;
  6376. getSorted();
  6377. if(sortedCount == 0)
  6378. {
  6379. eof = true;
  6380. return NULL;
  6381. }
  6382. if (eog)
  6383. return NULL;
  6384. }
  6385. processed++;
  6386. return sorted[curIndex++];
  6387. }
  6388. bool CHThorTopNActivity::abortEarly()
  6389. {
  6390. if (hasBest && (sortedCount == limit))
  6391. {
  6392. int compare = helper.compareBest(sorted[sortedCount-1]);
  6393. if (compare == 0)
  6394. {
  6395. if (grouped)
  6396. {
  6397. //MORE: This would be more efficient if we had a away of skipping to the end of the incomming group.
  6398. OwnedConstRoxieRow next;
  6399. do
  6400. {
  6401. next.setown(input->nextInGroup());
  6402. } while(next);
  6403. }
  6404. else
  6405. eoi = true;
  6406. return true;
  6407. }
  6408. //This only checks the lowest element - we could check all elements inserted, but it would increase the number of compares
  6409. if (compare < 0)
  6410. throw MakeStringException(0, "TOPN: row found that exceeds the best value");
  6411. }
  6412. return false;
  6413. }
  6414. void CHThorTopNActivity::getSorted()
  6415. {
  6416. curIndex = 0;
  6417. sortedCount = 0;
  6418. if (eoi)
  6419. return;
  6420. OwnedConstRoxieRow next(input->nextInGroup());
  6421. while(next)
  6422. {
  6423. if(sortedCount < limit)
  6424. {
  6425. binary_vec_insert_stable(next.getClear(), sorted, sortedCount, compare);
  6426. sortedCount++;
  6427. if (abortEarly())
  6428. return;
  6429. }
  6430. else
  6431. {
  6432. // do not bother with insertion sort if we know next will fall off the end
  6433. if(limit && compare.docompare(sorted[sortedCount-1], next) > 0)
  6434. {
  6435. binary_vec_insert_stable(next.getClear(), sorted, sortedCount, compare);
  6436. ReleaseRoxieRow(sorted[sortedCount]);
  6437. if (abortEarly())
  6438. return;
  6439. }
  6440. }
  6441. next.setown(input->nextInGroup());
  6442. }
  6443. }
  6444. //=====================================================================================================
  6445. CHThorXmlParseActivity::CHThorXmlParseActivity(IAgentContext & _agent, unsigned _activityId, unsigned _subgraphId, IHThorXmlParseArg & _arg, ThorActivityKind _kind)
  6446. : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  6447. {
  6448. srchStrNeedsFree = helper.searchTextNeedsFree();
  6449. srchStr = NULL;
  6450. }
  6451. CHThorXmlParseActivity::~CHThorXmlParseActivity()
  6452. {
  6453. if(srchStrNeedsFree) rtlFree(srchStr);
  6454. }
  6455. void CHThorXmlParseActivity::ready()
  6456. {
  6457. CHThorSimpleActivityBase::ready();
  6458. numProcessedLastGroup = processed;
  6459. }
  6460. void CHThorXmlParseActivity::done()
  6461. {
  6462. CHThorSimpleActivityBase::done();
  6463. if(srchStrNeedsFree) rtlFree(srchStr);
  6464. srchStr = NULL;
  6465. in.clear();
  6466. }
  6467. const void * CHThorXmlParseActivity::nextInGroup()
  6468. {
  6469. loop
  6470. {
  6471. if(xmlParser)
  6472. {
  6473. loop
  6474. {
  6475. bool gotNext = false;
  6476. try
  6477. {
  6478. gotNext = xmlParser->next();
  6479. }
  6480. catch(IException * e)
  6481. {
  6482. throw makeWrappedException(e);
  6483. }
  6484. if(!gotNext)
  6485. {
  6486. if(srchStrNeedsFree)
  6487. {
  6488. rtlFree(srchStr);
  6489. srchStr = NULL;
  6490. }
  6491. xmlParser.clear();
  6492. break;
  6493. }
  6494. if(lastMatch)
  6495. {
  6496. try
  6497. {
  6498. RtlDynamicRowBuilder rowBuilder(rowAllocator);
  6499. unsigned sizeGot = helper.transform(rowBuilder, in, lastMatch);
  6500. lastMatch.clear();
  6501. if (sizeGot)
  6502. {
  6503. processed++;
  6504. return rowBuilder.finalizeRowClear(sizeGot);
  6505. }
  6506. }
  6507. catch(IException * e)
  6508. {
  6509. throw makeWrappedException(e);
  6510. }
  6511. }
  6512. }
  6513. }
  6514. in.setown(input->nextInGroup());
  6515. if(!in)
  6516. {
  6517. if(numProcessedLastGroup == processed)
  6518. in.setown(input->nextInGroup());
  6519. if(!in)
  6520. {
  6521. numProcessedLastGroup = processed;
  6522. return NULL;
  6523. }
  6524. }
  6525. size32_t srchLen;
  6526. helper.getSearchText(srchLen, srchStr, in);
  6527. OwnedRoxieString xmlIteratorPath(helper.getXmlIteratorPath());
  6528. xmlParser.setown(createXMLParse(srchStr, srchLen, xmlIteratorPath, *this, ptr_noRoot, helper.requiresContents()));
  6529. }
  6530. }
  6531. //=====================================================================================================
  6532. class CHThorMergeActivity : public CHThorMultiInputActivity
  6533. {
  6534. protected:
  6535. IHThorMergeArg &helper;
  6536. CHThorStreamMerger merger;
  6537. public:
  6538. CHThorMergeActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorMergeArg &_arg, ThorActivityKind _kind) : CHThorMultiInputActivity(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  6539. {
  6540. merger.init(helper.queryCompare(), helper.dedup(), NULL); // can mass null for range because merger.nextGE() never called
  6541. }
  6542. ~CHThorMergeActivity()
  6543. {
  6544. merger.cleanup();
  6545. }
  6546. virtual void ready()
  6547. {
  6548. CHThorMultiInputActivity::ready();
  6549. merger.initInputs(inputs.length(), inputs.getArray());
  6550. }
  6551. virtual void done()
  6552. {
  6553. merger.done();
  6554. CHThorMultiInputActivity::done();
  6555. }
  6556. virtual const void * nextInGroup()
  6557. {
  6558. const void * ret = merger.nextRow();
  6559. if (ret)
  6560. processed++;
  6561. return ret;
  6562. }
  6563. };
  6564. //=====================================================================================================
  6565. //Web Service Call base
  6566. CHThorWSCBaseActivity::CHThorWSCBaseActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorWebServiceCallArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  6567. {
  6568. callHelper = &_arg;
  6569. init();
  6570. }
  6571. CHThorWSCBaseActivity::CHThorWSCBaseActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorWebServiceCallActionArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  6572. {
  6573. callHelper = NULL;
  6574. init();
  6575. }
  6576. void CHThorWSCBaseActivity::done()
  6577. {
  6578. WSChelper.clear();//doesn't return until helper threads terminate
  6579. CHThorSimpleActivityBase::done();
  6580. }
  6581. void CHThorWSCBaseActivity::init()
  6582. {
  6583. // Build authentication token
  6584. StringBuffer uidpair;
  6585. IUserDescriptor *userDesc = agent.queryCodeContext()->queryUserDescriptor();
  6586. if (userDesc)//NULL if standalone
  6587. {
  6588. userDesc->getUserName(uidpair);
  6589. uidpair.append(":");
  6590. userDesc->getPassword(uidpair);
  6591. JBASE64_Encode(uidpair.str(), uidpair.length(), authToken);
  6592. }
  6593. soapTraceLevel = agent.queryWorkUnit()->getDebugValueInt("soapTraceLevel", 1);
  6594. }
  6595. //---------------------------------------------------------------------------
  6596. CHThorWSCRowCallActivity::CHThorWSCRowCallActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorWebServiceCallArg &_arg, ThorActivityKind _kind) : CHThorWSCBaseActivity(_agent, _activityId, _subgraphId, _arg, _kind)
  6597. {
  6598. }
  6599. const void *CHThorWSCRowCallActivity::nextInGroup()
  6600. {
  6601. try
  6602. {
  6603. assertex(WSChelper);
  6604. OwnedConstRoxieRow ret = WSChelper->getRow();
  6605. if (!ret)
  6606. return NULL;
  6607. ++processed;
  6608. return ret.getClear();
  6609. }
  6610. catch(IException * e)
  6611. {
  6612. throw makeWrappedException(e);
  6613. }
  6614. }
  6615. //---------------------------------------------------------------------------
  6616. const void *CHThorHttpRowCallActivity::nextInGroup()
  6617. {
  6618. try
  6619. {
  6620. if (WSChelper == NULL)
  6621. {
  6622. WSChelper.setown(createHttpCallHelper(this, rowAllocator, authToken.str(), SCrow, NULL, queryDummyContextLogger(),NULL));
  6623. WSChelper->start();
  6624. }
  6625. return CHThorWSCRowCallActivity::nextInGroup();
  6626. }
  6627. catch(IException * e)
  6628. {
  6629. throw makeWrappedException(e);
  6630. }
  6631. }
  6632. //---------------------------------------------------------------------------
  6633. const void *CHThorSoapRowCallActivity::nextInGroup()
  6634. {
  6635. try
  6636. {
  6637. if (WSChelper == NULL)
  6638. {
  6639. WSChelper.setown(createSoapCallHelper(this, rowAllocator, authToken.str(), SCrow, NULL, queryDummyContextLogger(),NULL));
  6640. WSChelper->start();
  6641. }
  6642. return CHThorWSCRowCallActivity::nextInGroup();
  6643. }
  6644. catch(IException * e)
  6645. {
  6646. throw makeWrappedException(e);
  6647. }
  6648. }
  6649. //---------------------------------------------------------------------------
  6650. //---------------------------------------------------------------------------
  6651. //---------------------------------------------------------------------------
  6652. CHThorSoapRowActionActivity::CHThorSoapRowActionActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorSoapActionArg &_arg, ThorActivityKind _kind) : CHThorWSCBaseActivity(_agent, _activityId, _subgraphId, _arg, _kind)
  6653. {
  6654. }
  6655. void CHThorSoapRowActionActivity::execute()
  6656. {
  6657. try
  6658. {
  6659. WSChelper.setown(createSoapCallHelper(this, NULL, authToken.str(), SCrow, NULL, queryDummyContextLogger(),NULL));
  6660. WSChelper->start();
  6661. WSChelper->waitUntilDone();
  6662. }
  6663. catch(IException * e)
  6664. {
  6665. throw makeWrappedException(e);
  6666. }
  6667. IException *e = WSChelper->getError();
  6668. if(e)
  6669. throw makeWrappedException(e);
  6670. }
  6671. //---------------------------------------------------------------------------
  6672. CHThorSoapDatasetCallActivity::CHThorSoapDatasetCallActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorSoapCallArg &_arg, ThorActivityKind _kind) : CHThorWSCBaseActivity(_agent, _activityId, _subgraphId, _arg, _kind)
  6673. {
  6674. }
  6675. const void * CHThorSoapDatasetCallActivity::nextInGroup()
  6676. {
  6677. try
  6678. {
  6679. if (WSChelper == NULL)
  6680. {
  6681. WSChelper.setown(createSoapCallHelper(this, rowAllocator, authToken.str(), SCdataset, NULL, queryDummyContextLogger(),NULL));
  6682. WSChelper->start();
  6683. }
  6684. OwnedConstRoxieRow ret = WSChelper->getRow();
  6685. if (!ret)
  6686. return NULL;
  6687. ++processed;
  6688. return ret.getClear();
  6689. }
  6690. catch(IException * e)
  6691. {
  6692. throw makeWrappedException(e);
  6693. }
  6694. }
  6695. const void * CHThorSoapDatasetCallActivity::getNextRow()
  6696. {
  6697. CriticalBlock b(crit);
  6698. const void *nextrec = input->nextInGroup();
  6699. if (!nextrec)
  6700. {
  6701. nextrec = input->nextInGroup();
  6702. }
  6703. return nextrec;
  6704. };
  6705. //---------------------------------------------------------------------------
  6706. CHThorSoapDatasetActionActivity::CHThorSoapDatasetActionActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorSoapActionArg &_arg, ThorActivityKind _kind) : CHThorWSCBaseActivity(_agent, _activityId, _subgraphId, _arg, _kind)
  6707. {
  6708. }
  6709. void CHThorSoapDatasetActionActivity::execute()
  6710. {
  6711. try
  6712. {
  6713. WSChelper.setown(createSoapCallHelper(this, NULL, authToken.str(), SCdataset, NULL, queryDummyContextLogger(),NULL));
  6714. WSChelper->start();
  6715. WSChelper->waitUntilDone();
  6716. }
  6717. catch(IException * e)
  6718. {
  6719. throw makeWrappedException(e);
  6720. }
  6721. IException *e = WSChelper->getError();
  6722. if(e)
  6723. throw makeWrappedException(e);
  6724. }
  6725. const void * CHThorSoapDatasetActionActivity::getNextRow()
  6726. {
  6727. CriticalBlock b(crit);
  6728. const void *nextrec = input->nextInGroup();
  6729. if (!nextrec)
  6730. {
  6731. nextrec = input->nextInGroup();
  6732. }
  6733. if (nextrec)
  6734. {
  6735. processed++;
  6736. }
  6737. return nextrec;
  6738. };
  6739. //=====================================================================================================
  6740. CHThorResultActivity::CHThorResultActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorArg &_arg, ThorActivityKind _kind)
  6741. : CHThorActivityBase(_agent, _activityId, _subgraphId, _arg, _kind)
  6742. {
  6743. }
  6744. void CHThorResultActivity::extractResult(unsigned & retSize, void * & ret)
  6745. {
  6746. unsigned len = rowdata.length();
  6747. retSize = len;
  6748. if (len)
  6749. {
  6750. void * temp = rtlMalloc(len);
  6751. memcpy(temp, rowdata.toByteArray(), len);
  6752. ret = temp;
  6753. }
  6754. else
  6755. ret = NULL;
  6756. }
  6757. //=====================================================================================================
  6758. CHThorDatasetResultActivity::CHThorDatasetResultActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorDatasetResultArg &_arg, ThorActivityKind _kind)
  6759. : CHThorResultActivity(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  6760. {
  6761. }
  6762. void CHThorDatasetResultActivity::execute()
  6763. {
  6764. rowdata.clear();
  6765. IRecordSize * inputMeta = input->queryOutputMeta();
  6766. loop
  6767. {
  6768. OwnedConstRoxieRow nextrec(input->nextInGroup());
  6769. if (!nextrec)
  6770. {
  6771. nextrec.setown(input->nextInGroup());
  6772. if (!nextrec)
  6773. break;
  6774. }
  6775. rowdata.append(inputMeta->getRecordSize(nextrec), nextrec);
  6776. }
  6777. }
  6778. //=====================================================================================================
  6779. CHThorRowResultActivity::CHThorRowResultActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorRowResultArg &_arg, ThorActivityKind _kind)
  6780. : CHThorResultActivity(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  6781. {
  6782. }
  6783. void CHThorRowResultActivity::execute()
  6784. {
  6785. OwnedConstRoxieRow nextrec(input->nextInGroup());
  6786. assertex(nextrec);
  6787. IRecordSize * inputMeta = input->queryOutputMeta();
  6788. unsigned length = inputMeta->getRecordSize(nextrec);
  6789. rowdata.clear().append(length, nextrec);
  6790. }
  6791. //=====================================================================================================
  6792. CHThorChildIteratorActivity::CHThorChildIteratorActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorChildIteratorArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  6793. {
  6794. }
  6795. const void *CHThorChildIteratorActivity::nextInGroup()
  6796. {
  6797. if (eof)
  6798. return NULL;
  6799. bool ok;
  6800. if (!started)
  6801. {
  6802. ok = helper.first();
  6803. started = true;
  6804. }
  6805. else
  6806. ok = helper.next();
  6807. try
  6808. {
  6809. while(ok)
  6810. {
  6811. RtlDynamicRowBuilder rowBuilder(rowAllocator);
  6812. size32_t outSize = helper.transform(rowBuilder);
  6813. if(outSize)
  6814. {
  6815. processed++;
  6816. return rowBuilder.finalizeRowClear(outSize);
  6817. }
  6818. ok = helper.next();
  6819. }
  6820. }
  6821. catch(IException * e)
  6822. {
  6823. throw makeWrappedException(e);
  6824. }
  6825. eof = true;
  6826. return NULL;
  6827. }
  6828. void CHThorChildIteratorActivity::ready()
  6829. {
  6830. CHThorSimpleActivityBase::ready();
  6831. started = false;
  6832. eof = false;
  6833. }
  6834. //=====================================================================================================
  6835. CHThorLinkedRawIteratorActivity::CHThorLinkedRawIteratorActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorLinkedRawIteratorArg &_arg, ThorActivityKind _kind)
  6836. : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  6837. {
  6838. }
  6839. const void *CHThorLinkedRawIteratorActivity::nextInGroup()
  6840. {
  6841. const void *ret =helper.next();
  6842. if (ret)
  6843. {
  6844. LinkRoxieRow(ret);
  6845. processed++;
  6846. }
  6847. return ret;
  6848. }
  6849. //=====================================================================================================
  6850. //=====================================================================================================
  6851. //== New implementations - none are currently used, created or tested =================================
  6852. //=====================================================================================================
  6853. CHThorChildNormalizeActivity::CHThorChildNormalizeActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorChildNormalizeArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  6854. {
  6855. }
  6856. const void *CHThorChildNormalizeActivity::nextInGroup()
  6857. {
  6858. if (eof)
  6859. return NULL;
  6860. bool ok;
  6861. if (!started)
  6862. {
  6863. ok = helper.first();
  6864. started = true;
  6865. }
  6866. else
  6867. ok = helper.next();
  6868. try
  6869. {
  6870. if (ok)
  6871. {
  6872. RtlDynamicRowBuilder rowBuilder(rowAllocator);
  6873. do {
  6874. unsigned thisSize = helper.transform(rowBuilder);
  6875. if (thisSize)
  6876. {
  6877. processed++;
  6878. return rowBuilder.finalizeRowClear(thisSize);
  6879. }
  6880. ok = helper.next();
  6881. }
  6882. while (ok);
  6883. }
  6884. }
  6885. catch(IException * e)
  6886. {
  6887. throw makeWrappedException(e);
  6888. }
  6889. eof = true;
  6890. return NULL;
  6891. }
  6892. void CHThorChildNormalizeActivity::ready()
  6893. {
  6894. CHThorSimpleActivityBase::ready();
  6895. started = false;
  6896. eof = false;
  6897. }
  6898. //=====================================================================================================
  6899. CHThorChildAggregateActivity::CHThorChildAggregateActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorChildAggregateArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  6900. {
  6901. }
  6902. const void *CHThorChildAggregateActivity::nextInGroup()
  6903. {
  6904. if (eof)
  6905. return NULL;
  6906. eof = true;
  6907. processed++;
  6908. try
  6909. {
  6910. RtlDynamicRowBuilder rowBuilder(rowAllocator);
  6911. helper.clearAggregate(rowBuilder);
  6912. helper.processRows(rowBuilder);
  6913. size32_t finalSize = outputMeta.getRecordSize(rowBuilder.getSelf());
  6914. return rowBuilder.finalizeRowClear(finalSize);
  6915. }
  6916. catch(IException * e)
  6917. {
  6918. throw makeWrappedException(e);
  6919. }
  6920. }
  6921. void CHThorChildAggregateActivity::ready()
  6922. {
  6923. CHThorSimpleActivityBase::ready();
  6924. eof = false;
  6925. }
  6926. //=====================================================================================================
  6927. CHThorChildGroupAggregateActivity::CHThorChildGroupAggregateActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorChildGroupAggregateArg &_arg, ThorActivityKind _kind)
  6928. : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind),
  6929. helper(_arg),
  6930. aggregated(_arg, _arg)
  6931. {
  6932. }
  6933. void CHThorChildGroupAggregateActivity::ready()
  6934. {
  6935. CHThorSimpleActivityBase::ready();
  6936. eof = false;
  6937. gathered = false;
  6938. aggregated.start(rowAllocator);
  6939. }
  6940. void CHThorChildGroupAggregateActivity::done()
  6941. {
  6942. aggregated.reset();
  6943. CHThorSimpleActivityBase::done();
  6944. }
  6945. void CHThorChildGroupAggregateActivity::processRow(const void * next)
  6946. {
  6947. aggregated.addRow(next);
  6948. }
  6949. const void * CHThorChildGroupAggregateActivity::nextInGroup()
  6950. {
  6951. if (eof)
  6952. return NULL;
  6953. if (!gathered)
  6954. {
  6955. helper.processRows(this);
  6956. gathered = true;
  6957. }
  6958. Owned<AggregateRowBuilder> next = aggregated.nextResult();
  6959. if (next)
  6960. {
  6961. processed++;
  6962. return next->finalizeRowClear();
  6963. }
  6964. eof = true;
  6965. return NULL;
  6966. }
  6967. //=====================================================================================================
  6968. CHThorChildThroughNormalizeActivity::CHThorChildThroughNormalizeActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorChildThroughNormalizeArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg), outBuilder(NULL)
  6969. {
  6970. }
  6971. void CHThorChildThroughNormalizeActivity::done()
  6972. {
  6973. outBuilder.clear();
  6974. lastInput.clear();
  6975. CHThorSimpleActivityBase::done();
  6976. }
  6977. void CHThorChildThroughNormalizeActivity::ready()
  6978. {
  6979. CHThorSimpleActivityBase::ready();
  6980. outBuilder.setAllocator(rowAllocator);
  6981. numProcessedLastGroup = processed;
  6982. ok = false;
  6983. }
  6984. const void *CHThorChildThroughNormalizeActivity::nextInGroup()
  6985. {
  6986. try
  6987. {
  6988. loop
  6989. {
  6990. if (ok)
  6991. ok = helper.next();
  6992. while (!ok)
  6993. {
  6994. lastInput.setown(input->nextInGroup());
  6995. if (!lastInput)
  6996. {
  6997. if (numProcessedLastGroup != processed)
  6998. {
  6999. numProcessedLastGroup = processed;
  7000. return NULL;
  7001. }
  7002. lastInput.setown(input->nextInGroup());
  7003. if (!lastInput)
  7004. return NULL;
  7005. }
  7006. ok = helper.first(lastInput);
  7007. }
  7008. outBuilder.ensureRow();
  7009. do
  7010. {
  7011. size32_t thisSize = helper.transform(outBuilder);
  7012. if (thisSize)
  7013. {
  7014. processed++;
  7015. return outBuilder.finalizeRowClear(thisSize);
  7016. }
  7017. ok = helper.next();
  7018. } while (ok);
  7019. }
  7020. }
  7021. catch(IException * e)
  7022. {
  7023. throw makeWrappedException(e);
  7024. }
  7025. }
  7026. //=====================================================================================================
  7027. CHThorDiskReadBaseActivity::CHThorDiskReadBaseActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorDiskReadBaseArg &_arg, ThorActivityKind _kind) : CHThorActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  7028. {
  7029. helper.setCallback(this);
  7030. }
  7031. CHThorDiskReadBaseActivity::~CHThorDiskReadBaseActivity()
  7032. {
  7033. close();
  7034. }
  7035. void CHThorDiskReadBaseActivity::ready()
  7036. {
  7037. CHThorActivityBase::ready();
  7038. grouped = false;
  7039. recordsize = 0;
  7040. fixedDiskRecordSize = 0;
  7041. eofseen = false;
  7042. opened = false;
  7043. compressed = false;
  7044. rowcompressed = false;
  7045. blockcompressed = false;
  7046. persistent = false;
  7047. localOffset = 0;
  7048. offsetOfPart = 0;
  7049. partNum = (unsigned)-1;
  7050. resolve();
  7051. }
  7052. void CHThorDiskReadBaseActivity::done()
  7053. {
  7054. close();
  7055. CHThorActivityBase::done();
  7056. }
  7057. void CHThorDiskReadBaseActivity::resolve()
  7058. {
  7059. OwnedRoxieString fileName(helper.getFileName());
  7060. mangleHelperFileName(mangledHelperFileName, fileName, agent.queryWuid(), helper.getFlags());
  7061. if (helper.getFlags() & (TDXtemporary | TDXjobtemp))
  7062. {
  7063. StringBuffer mangledFilename;
  7064. mangleLocalTempFilename(mangledFilename, mangledHelperFileName.str());
  7065. tempFileName.set(agent.queryTemporaryFile(mangledFilename.str()));
  7066. logicalFileName.set(tempFileName);
  7067. gatherInfo(NULL);
  7068. }
  7069. else
  7070. {
  7071. ldFile.setown(agent.resolveLFN(mangledHelperFileName.str(), "Read", 0 != (helper.getFlags() & TDRoptional)));
  7072. if ( mangledHelperFileName.charAt(0) == '~')
  7073. logicalFileName.set(mangledHelperFileName.str()+1);
  7074. else
  7075. logicalFileName.set(mangledHelperFileName.str());
  7076. if (ldFile)
  7077. {
  7078. Owned<IFileDescriptor> fdesc;
  7079. fdesc.setown(ldFile->getFileDescriptor());
  7080. gatherInfo(fdesc);
  7081. IDistributedFile *dFile = ldFile->queryDistributedFile();
  7082. if (dFile) //only makes sense for distributed (non local) files
  7083. {
  7084. persistent = dFile->queryAttributes().getPropBool("@persistent");
  7085. dfsParts.setown(dFile->getIterator());
  7086. if (helper.getFlags() & TDRfilenamecallback)
  7087. {
  7088. IDistributedSuperFile *super = dFile->querySuperFile();
  7089. if (super)
  7090. {
  7091. unsigned numsubs = super->numSubFiles(true);
  7092. unsigned s=0;
  7093. for (; s<numsubs; s++)
  7094. {
  7095. IDistributedFile &subfile = super->querySubFile(s, true);
  7096. subfileLogicalFilenames.append(subfile.queryLogicalName());
  7097. }
  7098. assertex(fdesc);
  7099. superfile.set(fdesc->querySuperFileDescriptor());
  7100. assertex(superfile);
  7101. }
  7102. }
  7103. if((helper.getFlags() & (TDXtemporary | TDXjobtemp)) == 0)
  7104. agent.logFileAccess(dFile, "HThor", "READ");
  7105. if(!agent.queryWorkUnit()->getDebugValueBool("skipFileFormatCrcCheck", false) && !(helper.getFlags() & TDRnocrccheck))
  7106. verifyRecordFormatCrc();
  7107. }
  7108. }
  7109. if (!ldFile)
  7110. {
  7111. StringBuffer buff;
  7112. buff.appendf("Input file '%s' was missing but declared optional", mangledHelperFileName.str());
  7113. WARNLOG("%s", buff.str());
  7114. agent.addWuException(buff.str(), WRN_SkipMissingOptFile, SeverityInformation, "hthor");
  7115. }
  7116. }
  7117. }
  7118. void CHThorDiskReadBaseActivity::gatherInfo(IFileDescriptor * fileDesc)
  7119. {
  7120. if(fileDesc)
  7121. {
  7122. if (!agent.queryResolveFilesLocally())
  7123. {
  7124. grouped = fileDesc->isGrouped();
  7125. if(grouped != ((helper.getFlags() & TDXgrouped) != 0))
  7126. {
  7127. StringBuffer msg;
  7128. msg.append("DFS and code generated group info. differs: DFS(").append(grouped ? "grouped" : "ungrouped").append("), CodeGen(").append(grouped ? "ungrouped" : "grouped").append("), using DFS info");
  7129. WARNLOG("%s", msg.str());
  7130. agent.addWuException(msg.str(), WRN_MismatchGroupInfo, SeverityError, "hthor");
  7131. }
  7132. }
  7133. else
  7134. grouped = ((helper.getFlags() & TDXgrouped) != 0);
  7135. }
  7136. else
  7137. {
  7138. grouped = ((helper.getFlags() & TDXgrouped) != 0);
  7139. }
  7140. diskMeta.set(helper.queryDiskRecordSize()->querySerializedDiskMeta());
  7141. if (grouped)
  7142. diskMeta.setown(new CSuffixedOutputMeta(+1, diskMeta));
  7143. if (outputMeta.isFixedSize())
  7144. {
  7145. recordsize = outputMeta.getFixedSize();
  7146. if (grouped)
  7147. recordsize++;
  7148. }
  7149. else
  7150. recordsize = 0;
  7151. calcFixedDiskRecordSize();
  7152. if(fileDesc)
  7153. {
  7154. compressed = fileDesc->isCompressed(&blockcompressed); //try new decompression, fall back to old unless marked as block
  7155. if(fixedDiskRecordSize)
  7156. {
  7157. size32_t dfsSize = fileDesc->queryProperties().getPropInt("@recordSize");
  7158. if(!((dfsSize == 0) || (dfsSize == fixedDiskRecordSize) || (grouped && (dfsSize+1 == fixedDiskRecordSize)))) //third option for backwards compatibility, as hthor used to publish @recordSize not including the grouping byte
  7159. throw MakeStringException(0, "Published record size %d for file %s does not match coded record size %d", dfsSize, mangledHelperFileName.str(), fixedDiskRecordSize);
  7160. if (!compressed && (((helper.getFlags() & TDXcompress) != 0) && (fixedDiskRecordSize >= MIN_ROWCOMPRESS_RECSIZE)))
  7161. {
  7162. StringBuffer msg;
  7163. msg.append("Ignoring compression attribute on file ").append(mangledHelperFileName.str()).append(", which is not published as compressed");
  7164. WARNLOG("%s", msg.str());
  7165. agent.addWuException(msg.str(), WRN_MismatchCompressInfo, SeverityWarning, "hthor");
  7166. compressed = true;
  7167. }
  7168. }
  7169. }
  7170. else
  7171. {
  7172. compressed = checkIsCompressed(helper.getFlags(), fixedDiskRecordSize, false);//grouped=FALSE because fixedDiskRecordSize already includes grouped
  7173. }
  7174. void *k;
  7175. size32_t kl;
  7176. helper.getEncryptKey(kl,k);
  7177. encryptionkey.setOwn(kl,k);
  7178. if (encryptionkey.length()!=0)
  7179. {
  7180. blockcompressed = true;
  7181. compressed = true;
  7182. }
  7183. }
  7184. void CHThorDiskReadBaseActivity::close()
  7185. {
  7186. closepart();
  7187. tempFileName.clear();
  7188. dfsParts.clear();
  7189. if(ldFile)
  7190. {
  7191. IDistributedFile * dFile = ldFile->queryDistributedFile();
  7192. if(dFile)
  7193. dFile->setAccessed();
  7194. ldFile.clear();
  7195. }
  7196. }
  7197. unsigned __int64 CHThorDiskReadBaseActivity::getFilePosition(const void * row)
  7198. {
  7199. return localOffset + offsetOfPart;
  7200. }
  7201. unsigned __int64 CHThorDiskReadBaseActivity::getLocalFilePosition(const void * row)
  7202. {
  7203. return makeLocalFposOffset(partNum-1, localOffset);
  7204. }
  7205. void CHThorDiskReadBaseActivity::closepart()
  7206. {
  7207. inputstream.clear();
  7208. inputfileio.clear();
  7209. inputfile.clear();
  7210. }
  7211. bool CHThorDiskReadBaseActivity::openNext()
  7212. {
  7213. offsetOfPart += localOffset;
  7214. localOffset = 0;
  7215. saveOpenExc.clear();
  7216. if (dfsParts||ldFile)
  7217. {
  7218. // open next part of a multipart, if there is one
  7219. while ((dfsParts&&dfsParts->isValid())||
  7220. (!dfsParts&&(partNum<ldFile->numParts())))
  7221. {
  7222. IDistributedFilePart * curPart = dfsParts?&dfsParts->query():NULL;
  7223. unsigned numCopies = curPart?curPart->numCopies():ldFile->numPartCopies(partNum);
  7224. //MORE: Order of copies should be optimized at this point....
  7225. StringBuffer file, filelist;
  7226. closepart();
  7227. if (dfsParts && superfile && curPart)
  7228. {
  7229. unsigned subfile;
  7230. unsigned lnum;
  7231. if (superfile->mapSubPart(partNum, subfile, lnum))
  7232. logicalFileName.set(subfileLogicalFilenames.item(subfile));
  7233. }
  7234. for (unsigned copy=0; copy < numCopies; copy++)
  7235. {
  7236. RemoteFilename rfilename;
  7237. if (curPart)
  7238. curPart->getFilename(rfilename,copy);
  7239. else
  7240. ldFile->getPartFilename(rfilename,partNum,copy);
  7241. rfilename.getPath(file.clear());
  7242. filelist.append('\n').append(file);
  7243. try
  7244. {
  7245. inputfile.setown(createIFile(rfilename));
  7246. if(compressed)
  7247. {
  7248. Owned<IExpander> eexp;
  7249. if (encryptionkey.length()!=0)
  7250. eexp.setown(createAESExpander256((size32_t)encryptionkey.length(),encryptionkey.bufferBase()));
  7251. inputfileio.setown(createCompressedFileReader(inputfile,eexp));
  7252. if(!inputfileio && !blockcompressed) //fall back to old decompression, unless dfs marked as new
  7253. {
  7254. inputfileio.setown(inputfile->open(IFOread));
  7255. if(inputfileio)
  7256. rowcompressed = true;
  7257. }
  7258. }
  7259. else
  7260. inputfileio.setown(inputfile->open(IFOread));
  7261. if (inputfileio)
  7262. break;
  7263. }
  7264. catch (IException *E)
  7265. {
  7266. if (saveOpenExc.get())
  7267. E->Release();
  7268. else
  7269. saveOpenExc.setown(E);
  7270. }
  7271. closepart();
  7272. }
  7273. if (dfsParts)
  7274. dfsParts->next();
  7275. partNum++;
  7276. if (checkOpenedFile(file.str(), filelist.str()))
  7277. {
  7278. opened = true;
  7279. return true;
  7280. }
  7281. }
  7282. return false;
  7283. }
  7284. else if (!tempFileName.isEmpty())
  7285. {
  7286. StringBuffer file(tempFileName.get());
  7287. tempFileName.clear();
  7288. closepart();
  7289. try
  7290. {
  7291. inputfile.setown(createIFile(file.str()));
  7292. if(compressed)
  7293. {
  7294. Owned<IExpander> eexp;
  7295. if (encryptionkey.length())
  7296. eexp.setown(createAESExpander256((size32_t) encryptionkey.length(),encryptionkey.bufferBase()));
  7297. inputfileio.setown(createCompressedFileReader(inputfile,eexp));
  7298. if(!inputfileio && !blockcompressed) //fall back to old decompression, unless dfs marked as new
  7299. {
  7300. inputfileio.setown(inputfile->open(IFOread));
  7301. if(inputfileio)
  7302. rowcompressed = true;
  7303. }
  7304. }
  7305. else
  7306. inputfileio.setown(inputfile->open(IFOread));
  7307. }
  7308. catch (IException *E)
  7309. {
  7310. closepart();
  7311. StringBuffer msg;
  7312. WARNLOG("%s", E->errorMessage(msg).str());
  7313. if (saveOpenExc.get())
  7314. E->Release();
  7315. else
  7316. saveOpenExc.setown(E);
  7317. }
  7318. partNum++;
  7319. if (checkOpenedFile(file.str(), NULL))
  7320. {
  7321. opened = true;
  7322. return true;
  7323. }
  7324. }
  7325. return false;
  7326. }
  7327. bool CHThorDiskReadBaseActivity::checkOpenedFile(char const * filename, char const * filenamelist)
  7328. {
  7329. unsigned __int64 filesize = 0;
  7330. if (!inputfileio)
  7331. {
  7332. if (!(helper.getFlags() & TDRoptional))
  7333. {
  7334. StringBuffer s;
  7335. if(filenamelist) {
  7336. if (saveOpenExc.get())
  7337. {
  7338. if (strstr(mangledHelperFileName.str(),"::>")!=NULL) // if a 'special' filename just use saved exception
  7339. saveOpenExc->errorMessage(s);
  7340. else
  7341. {
  7342. s.append("Could not open logical file ").append(mangledHelperFileName.str()).append(" in any of these locations:").append(filenamelist).append(" (");
  7343. saveOpenExc->errorMessage(s).append(")");
  7344. }
  7345. }
  7346. else
  7347. s.append("Could not open logical file ").append(mangledHelperFileName.str()).append(" in any of these locations:").append(filenamelist).append(" (").append((unsigned)GetLastError()).append(")");
  7348. }
  7349. else
  7350. s.append("Could not open local physical file ").append(filename).append(" (").append((unsigned)GetLastError()).append(")");
  7351. agent.fail(1, s.str());
  7352. }
  7353. }
  7354. else
  7355. filesize = inputfileio->size();
  7356. saveOpenExc.clear();
  7357. if (filesize)
  7358. {
  7359. if (!compressed && fixedDiskRecordSize && (filesize % fixedDiskRecordSize) != 0)
  7360. {
  7361. StringBuffer s;
  7362. s.append("File ").append(filename).append(" size is ").append(filesize).append(" which is not a multiple of ").append(fixedDiskRecordSize);
  7363. agent.fail(1, s.str());
  7364. }
  7365. unsigned readBufferSize = queryReadBufferSize();
  7366. inputstream.setown(createFileSerialStream(inputfileio, 0, filesize, readBufferSize));
  7367. StringBuffer report("Reading file ");
  7368. report.append(inputfile->queryFilename());
  7369. agent.reportProgress(report.str());
  7370. }
  7371. return (filesize != 0);
  7372. }
  7373. void CHThorDiskReadBaseActivity::open()
  7374. {
  7375. assertex(!opened);
  7376. partNum = 0;
  7377. if (dfsParts)
  7378. eofseen = !dfsParts->first() || !openNext();
  7379. else if (ldFile||tempFileName.length())
  7380. eofseen = !openNext();
  7381. else
  7382. eofseen = true;
  7383. opened = true;
  7384. }
  7385. //=====================================================================================================
  7386. CHThorBinaryDiskReadBase::CHThorBinaryDiskReadBase(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorDiskReadBaseArg &_arg, IHThorCompoundBaseArg & _segHelper, ThorActivityKind _kind)
  7387. : CHThorDiskReadBaseActivity(_agent, _activityId, _subgraphId, _arg, _kind), segHelper(_segHelper), prefetchBuffer(NULL)
  7388. {
  7389. }
  7390. void CHThorBinaryDiskReadBase::calcFixedDiskRecordSize()
  7391. {
  7392. fixedDiskRecordSize = diskMeta->getFixedSize();
  7393. }
  7394. void CHThorBinaryDiskReadBase::append(IKeySegmentMonitor *segment)
  7395. {
  7396. if (segment->isWild())
  7397. segment->Release();
  7398. else
  7399. segMonitors.append(*segment);
  7400. }
  7401. void CHThorBinaryDiskReadBase::setMergeBarrier(unsigned barrierOffset)
  7402. {
  7403. // nothing to do - we don't merge...
  7404. }
  7405. unsigned CHThorBinaryDiskReadBase::ordinality() const
  7406. {
  7407. return segMonitors.length();
  7408. }
  7409. IKeySegmentMonitor *CHThorBinaryDiskReadBase::item(unsigned idx) const
  7410. {
  7411. if (segMonitors.isItem(idx))
  7412. return &segMonitors.item(idx);
  7413. else
  7414. return NULL;
  7415. }
  7416. void CHThorBinaryDiskReadBase::ready()
  7417. {
  7418. CHThorDiskReadBaseActivity::ready();
  7419. if (!diskMeta)
  7420. diskMeta.set(outputMeta);
  7421. segMonitors.kill();
  7422. segHelper.createSegmentMonitors(this);
  7423. prefetcher.setown(diskMeta->createDiskPrefetcher(agent.queryCodeContext(), activityId));
  7424. deserializer.setown(diskMeta->createDiskDeserializer(agent.queryCodeContext(), activityId));
  7425. }
  7426. bool CHThorBinaryDiskReadBase::openNext()
  7427. {
  7428. if (CHThorDiskReadBaseActivity::openNext())
  7429. {
  7430. if(rowcompressed && fixedDiskRecordSize)
  7431. {
  7432. throwUnexpected();
  7433. //MORE: What happens here
  7434. PROGLOG("Disk read falling back to legacy decompression routine");
  7435. //in.setown(createRowCompReadSeq(*inputfileiostream, 0, fixedDiskRecordSize));
  7436. }
  7437. //Only one of these will actually be used.
  7438. prefetchBuffer.setStream(inputstream);
  7439. deserializeSource.setStream(inputstream);
  7440. return true;
  7441. }
  7442. return false;
  7443. }
  7444. void CHThorBinaryDiskReadBase::closepart()
  7445. {
  7446. prefetchBuffer.clearStream();
  7447. deserializeSource.clearStream();
  7448. CHThorDiskReadBaseActivity::closepart();
  7449. }
  7450. unsigned CHThorBinaryDiskReadBase::queryReadBufferSize()
  7451. {
  7452. return hthorReadBufferSize;
  7453. }
  7454. void CHThorBinaryDiskReadBase::open()
  7455. {
  7456. if (!segHelper.canMatchAny())
  7457. {
  7458. eofseen = true;
  7459. opened = true;
  7460. }
  7461. else
  7462. CHThorDiskReadBaseActivity::open();
  7463. }
  7464. //=====================================================================================================
  7465. CHThorDiskReadActivity::CHThorDiskReadActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorDiskReadArg &_arg, ThorActivityKind _kind) : CHThorBinaryDiskReadBase(_agent, _activityId, _subgraphId, _arg, _arg, _kind), helper(_arg), outBuilder(NULL)
  7466. {
  7467. needTransform = false;
  7468. eogPending = 0;
  7469. lastGroupProcessed = 0;
  7470. }
  7471. void CHThorDiskReadActivity::ready()
  7472. {
  7473. PARENT::ready();
  7474. outBuilder.setAllocator(rowAllocator);
  7475. eogPending = false;
  7476. lastGroupProcessed = processed;
  7477. needTransform = helper.needTransform() || segMonitors.length();
  7478. limit = helper.getRowLimit();
  7479. if (helper.getFlags() & TDRlimitskips)
  7480. limit = (unsigned __int64) -1;
  7481. stopAfter = helper.getChooseNLimit();
  7482. }
  7483. void CHThorDiskReadActivity::done()
  7484. {
  7485. outBuilder.clear();
  7486. PARENT::done();
  7487. }
  7488. const void *CHThorDiskReadActivity::nextInGroup()
  7489. {
  7490. if (!opened) open();
  7491. if (eogPending && (lastGroupProcessed != processed))
  7492. {
  7493. eogPending = false;
  7494. lastGroupProcessed = processed;
  7495. return NULL;
  7496. }
  7497. try
  7498. {
  7499. if (needTransform || grouped)
  7500. {
  7501. while (!eofseen && ((stopAfter == 0) || ((processed - initialProcessed) < stopAfter)))
  7502. {
  7503. queryUpdateProgress();
  7504. while (!prefetchBuffer.eos())
  7505. {
  7506. queryUpdateProgress();
  7507. prefetcher->readAhead(prefetchBuffer);
  7508. const byte * next = prefetchBuffer.queryRow();
  7509. size32_t sizeRead = prefetchBuffer.queryRowSize();
  7510. size32_t thisSize;
  7511. if (segMonitorsMatch(next))
  7512. {
  7513. thisSize = helper.transform(outBuilder.ensureRow(), next);
  7514. }
  7515. else
  7516. thisSize = 0;
  7517. bool eog = grouped && next[sizeRead-1];
  7518. prefetchBuffer.finishedRow();
  7519. localOffset += sizeRead;
  7520. if (thisSize)
  7521. {
  7522. if (grouped)
  7523. eogPending = eog;
  7524. if ((processed - initialProcessed) >=limit)
  7525. {
  7526. outBuilder.clear();
  7527. if ( agent.queryCodeContext()->queryDebugContext())
  7528. agent.queryCodeContext()->queryDebugContext()->checkBreakpoint(DebugStateLimit, NULL, static_cast<IActivityBase *>(this));
  7529. helper.onLimitExceeded();
  7530. return NULL;
  7531. }
  7532. processed++;
  7533. return outBuilder.finalizeRowClear(thisSize);
  7534. }
  7535. if (eog && (lastGroupProcessed != processed))
  7536. {
  7537. lastGroupProcessed = processed;
  7538. return NULL;
  7539. }
  7540. }
  7541. eofseen = !openNext();
  7542. }
  7543. }
  7544. else
  7545. {
  7546. assertex(outputMeta == diskMeta);
  7547. while(!eofseen && ((stopAfter == 0) || (processed - initialProcessed) < stopAfter))
  7548. {
  7549. queryUpdateProgress();
  7550. if (!inputstream->eos())
  7551. {
  7552. size32_t sizeRead = deserializer->deserialize(outBuilder.ensureRow(), deserializeSource);
  7553. //In this case size read from disk == size created in memory
  7554. localOffset += sizeRead;
  7555. if ((processed - initialProcessed)>=limit)
  7556. {
  7557. outBuilder.clear();
  7558. if ( agent.queryCodeContext()->queryDebugContext())
  7559. agent.queryCodeContext()->queryDebugContext()->checkBreakpoint(DebugStateLimit, NULL, static_cast<IActivityBase *>(this));
  7560. helper.onLimitExceeded();
  7561. return NULL;
  7562. }
  7563. processed++;
  7564. return outBuilder.finalizeRowClear(sizeRead);
  7565. }
  7566. eofseen = !openNext();
  7567. }
  7568. }
  7569. close();
  7570. }
  7571. catch(IException * e)
  7572. {
  7573. throw makeWrappedException(e);
  7574. }
  7575. return NULL;
  7576. }
  7577. //=====================================================================================================
  7578. CHThorDiskNormalizeActivity::CHThorDiskNormalizeActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorDiskNormalizeArg &_arg, ThorActivityKind _kind) : CHThorBinaryDiskReadBase(_agent, _activityId, _subgraphId, _arg, _arg, _kind), helper(_arg), outBuilder(NULL)
  7579. {
  7580. }
  7581. void CHThorDiskNormalizeActivity::done()
  7582. {
  7583. outBuilder.clear();
  7584. PARENT::done();
  7585. }
  7586. void CHThorDiskNormalizeActivity::ready()
  7587. {
  7588. PARENT::ready();
  7589. outBuilder.setAllocator(rowAllocator);
  7590. limit = helper.getRowLimit();
  7591. if (helper.getFlags() & TDRlimitskips)
  7592. limit = (unsigned __int64) -1;
  7593. stopAfter = helper.getChooseNLimit();
  7594. lastSizeRead = 0;
  7595. expanding = false;
  7596. }
  7597. void CHThorDiskNormalizeActivity::gatherInfo(IFileDescriptor * fd)
  7598. {
  7599. PARENT::gatherInfo(fd);
  7600. assertex(!grouped);
  7601. }
  7602. const void *CHThorDiskNormalizeActivity::nextInGroup()
  7603. {
  7604. if (!opened) open();
  7605. loop
  7606. {
  7607. if (eofseen || (stopAfter && (processed - initialProcessed) >= stopAfter))
  7608. break;
  7609. loop
  7610. {
  7611. if (expanding)
  7612. {
  7613. loop
  7614. {
  7615. expanding = helper.next();
  7616. if (!expanding)
  7617. break;
  7618. const void * ret = createNextRow();
  7619. if (ret)
  7620. return ret;
  7621. }
  7622. }
  7623. localOffset += lastSizeRead;
  7624. prefetchBuffer.finishedRow();
  7625. if (inputstream->eos())
  7626. {
  7627. lastSizeRead = 0;
  7628. break;
  7629. }
  7630. prefetcher->readAhead(prefetchBuffer);
  7631. const byte * next = prefetchBuffer.queryRow();
  7632. lastSizeRead = prefetchBuffer.queryRowSize();
  7633. queryUpdateProgress();
  7634. if (segMonitorsMatch(next))
  7635. {
  7636. try
  7637. {
  7638. expanding = helper.first(next);
  7639. }
  7640. catch(IException * e)
  7641. {
  7642. throw makeWrappedException(e);
  7643. }
  7644. if (expanding)
  7645. {
  7646. const void * ret = createNextRow();
  7647. if (ret)
  7648. return ret;
  7649. }
  7650. }
  7651. }
  7652. eofseen = !openNext();
  7653. }
  7654. close();
  7655. return NULL;
  7656. }
  7657. const void * CHThorDiskNormalizeActivity::createNextRow()
  7658. {
  7659. try
  7660. {
  7661. size32_t thisSize = helper.transform(outBuilder.ensureRow());
  7662. if (thisSize == 0)
  7663. return NULL;
  7664. if ((processed - initialProcessed) >=limit)
  7665. {
  7666. outBuilder.clear();
  7667. if ( agent.queryCodeContext()->queryDebugContext())
  7668. agent.queryCodeContext()->queryDebugContext()->checkBreakpoint(DebugStateLimit, NULL, static_cast<IActivityBase *>(this));
  7669. helper.onLimitExceeded();
  7670. return NULL;
  7671. }
  7672. processed++;
  7673. return outBuilder.finalizeRowClear(thisSize);
  7674. }
  7675. catch(IException * e)
  7676. {
  7677. throw makeWrappedException(e);
  7678. }
  7679. }
  7680. //=====================================================================================================
  7681. CHThorDiskAggregateActivity::CHThorDiskAggregateActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorDiskAggregateArg &_arg, ThorActivityKind _kind) : CHThorBinaryDiskReadBase(_agent, _activityId, _subgraphId, _arg, _arg, _kind), helper(_arg), outBuilder(NULL)
  7682. {
  7683. }
  7684. void CHThorDiskAggregateActivity::done()
  7685. {
  7686. outBuilder.clear();
  7687. PARENT::done();
  7688. }
  7689. void CHThorDiskAggregateActivity::ready()
  7690. {
  7691. PARENT::ready();
  7692. outBuilder.setAllocator(rowAllocator);
  7693. finished = false;
  7694. }
  7695. void CHThorDiskAggregateActivity::gatherInfo(IFileDescriptor * fd)
  7696. {
  7697. PARENT::gatherInfo(fd);
  7698. assertex(!grouped);
  7699. }
  7700. const void *CHThorDiskAggregateActivity::nextInGroup()
  7701. {
  7702. if (finished) return NULL;
  7703. try
  7704. {
  7705. if (!opened) open();
  7706. outBuilder.ensureRow();
  7707. helper.clearAggregate(outBuilder);
  7708. while (!eofseen)
  7709. {
  7710. while (!inputstream->eos())
  7711. {
  7712. queryUpdateProgress();
  7713. prefetcher->readAhead(prefetchBuffer);
  7714. const byte * next = prefetchBuffer.queryRow();
  7715. size32_t sizeRead = prefetchBuffer.queryRowSize();
  7716. if (segMonitorsMatch(next))
  7717. helper.processRow(outBuilder, next);
  7718. prefetchBuffer.finishedRow();
  7719. localOffset += sizeRead;
  7720. }
  7721. eofseen = !openNext();
  7722. }
  7723. close();
  7724. processed++;
  7725. finished = true;
  7726. unsigned retSize = outputMeta.getRecordSize(outBuilder.getSelf());
  7727. return outBuilder.finalizeRowClear(retSize);
  7728. }
  7729. catch(IException * e)
  7730. {
  7731. throw makeWrappedException(e);
  7732. }
  7733. }
  7734. //=====================================================================================================
  7735. CHThorDiskCountActivity::CHThorDiskCountActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorDiskCountArg &_arg, ThorActivityKind _kind) : CHThorBinaryDiskReadBase(_agent, _activityId, _subgraphId, _arg, _arg, _kind), helper(_arg)
  7736. {
  7737. finished = true;
  7738. }
  7739. CHThorDiskCountActivity::~CHThorDiskCountActivity()
  7740. {
  7741. }
  7742. void CHThorDiskCountActivity::ready()
  7743. {
  7744. PARENT::ready();
  7745. finished = false;
  7746. stopAfter = helper.getChooseNLimit();
  7747. }
  7748. void CHThorDiskCountActivity::gatherInfo(IFileDescriptor * fd)
  7749. {
  7750. PARENT::gatherInfo(fd);
  7751. assertex(!grouped);
  7752. }
  7753. const void *CHThorDiskCountActivity::nextInGroup()
  7754. {
  7755. if (finished) return NULL;
  7756. unsigned __int64 totalCount = 0;
  7757. if ((segMonitors.ordinality() == 0) && !helper.hasFilter() && (fixedDiskRecordSize != 0) && !(helper.getFlags() & (TDXtemporary | TDXjobtemp))
  7758. && !((helper.getFlags() & TDXcompress) && agent.queryResolveFilesLocally()) )
  7759. {
  7760. resolve();
  7761. if (segHelper.canMatchAny() && ldFile)
  7762. {
  7763. unsigned __int64 size = ldFile->getFileSize();
  7764. if (size % fixedDiskRecordSize)
  7765. throw MakeStringException(0, "Physical file %s has size %" I64F "d which is not a multiple of record size %d", ldFile->queryLogicalName(), size, fixedDiskRecordSize);
  7766. totalCount = size / fixedDiskRecordSize;
  7767. }
  7768. }
  7769. else
  7770. {
  7771. if (!opened) open();
  7772. loop
  7773. {
  7774. if (eofseen)
  7775. break;
  7776. while (!inputstream->eos())
  7777. {
  7778. queryUpdateProgress();
  7779. prefetcher->readAhead(prefetchBuffer);
  7780. const byte * next = prefetchBuffer.queryRow();
  7781. size32_t sizeRead = prefetchBuffer.queryRowSize();
  7782. if (segMonitorsMatch(next))
  7783. totalCount += helper.numValid(next);
  7784. prefetchBuffer.finishedRow();
  7785. localOffset += sizeRead;
  7786. if (totalCount > stopAfter)
  7787. break;
  7788. }
  7789. if (totalCount > stopAfter)
  7790. break;
  7791. eofseen = !openNext();
  7792. }
  7793. close();
  7794. }
  7795. if (totalCount > stopAfter)
  7796. totalCount = stopAfter;
  7797. finished = true;
  7798. processed++;
  7799. size32_t outSize = outputMeta.getFixedSize();
  7800. void * ret = rowAllocator->createRow();
  7801. if (outSize == 1)
  7802. {
  7803. assertex(stopAfter == 1);
  7804. *(byte *)ret = (byte)totalCount;
  7805. }
  7806. else
  7807. {
  7808. assertex(outSize == sizeof(unsigned __int64));
  7809. *(unsigned __int64 *)ret = totalCount;
  7810. }
  7811. return rowAllocator->finalizeRow(outSize, ret, outSize);
  7812. }
  7813. //=====================================================================================================
  7814. CHThorDiskGroupAggregateActivity::CHThorDiskGroupAggregateActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorDiskGroupAggregateArg &_arg, ThorActivityKind _kind)
  7815. : CHThorBinaryDiskReadBase(_agent, _activityId, _subgraphId, _arg, _arg, _kind),
  7816. helper(_arg),
  7817. aggregated(_arg, _arg)
  7818. {
  7819. }
  7820. void CHThorDiskGroupAggregateActivity::ready()
  7821. {
  7822. PARENT::ready();
  7823. eof = false;
  7824. gathered = false;
  7825. }
  7826. void CHThorDiskGroupAggregateActivity::gatherInfo(IFileDescriptor * fd)
  7827. {
  7828. PARENT::gatherInfo(fd);
  7829. assertex(!grouped);
  7830. aggregated.start(rowAllocator);
  7831. }
  7832. void CHThorDiskGroupAggregateActivity::processRow(const void * next)
  7833. {
  7834. aggregated.addRow(next);
  7835. }
  7836. const void *CHThorDiskGroupAggregateActivity::nextInGroup()
  7837. {
  7838. if (eof)
  7839. return NULL;
  7840. try
  7841. {
  7842. if (!gathered)
  7843. {
  7844. if (!opened) open();
  7845. while (!eofseen)
  7846. {
  7847. while (!inputstream->eos())
  7848. {
  7849. queryUpdateProgress();
  7850. prefetcher->readAhead(prefetchBuffer);
  7851. const byte * next = prefetchBuffer.queryRow();
  7852. size32_t sizeRead = prefetchBuffer.queryRowSize();
  7853. //helper.processRows(sizeRead, next, this);
  7854. helper.processRow(next, this);
  7855. prefetchBuffer.finishedRow();
  7856. localOffset += sizeRead;
  7857. }
  7858. eofseen = !openNext();
  7859. }
  7860. close();
  7861. gathered = true;
  7862. }
  7863. }
  7864. catch(IException * e)
  7865. {
  7866. throw makeWrappedException(e);
  7867. }
  7868. Owned<AggregateRowBuilder> next = aggregated.nextResult();
  7869. if (next)
  7870. {
  7871. processed++;
  7872. return next->finalizeRowClear();
  7873. }
  7874. eof = true;
  7875. return NULL;
  7876. }
  7877. //=====================================================================================================
  7878. CHThorCsvReadActivity::CHThorCsvReadActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorCsvReadArg &_arg, ThorActivityKind _kind) : CHThorDiskReadBaseActivity(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  7879. {
  7880. maxRowSize = agent.queryWorkUnit()->getDebugValueInt(OPT_MAXCSVROWSIZE, defaultMaxCsvRowSize) * 1024 * 1024;
  7881. }
  7882. CHThorCsvReadActivity::~CHThorCsvReadActivity()
  7883. {
  7884. }
  7885. void CHThorCsvReadActivity::ready()
  7886. {
  7887. PARENT::ready();
  7888. }
  7889. void CHThorCsvReadActivity::done()
  7890. {
  7891. csvSplitter.reset();
  7892. PARENT::done();
  7893. }
  7894. void CHThorCsvReadActivity::gatherInfo(IFileDescriptor * fd)
  7895. {
  7896. PARENT::gatherInfo(fd);
  7897. ICsvParameters * csvInfo = helper.queryCsvParameters();
  7898. headerLines = csvInfo->queryHeaderLen();
  7899. maxDiskSize = csvInfo->queryMaxSize();
  7900. limit = helper.getRowLimit();
  7901. if (helper.getFlags() & TDRlimitskips)
  7902. limit = (unsigned __int64) -1;
  7903. stopAfter = helper.getChooseNLimit();
  7904. const char * quotes = NULL;
  7905. const char * separators = NULL;
  7906. const char * terminators = NULL;
  7907. const char * escapes = NULL;
  7908. IDistributedFile * dFile = ldFile?ldFile->queryDistributedFile():NULL;
  7909. if (dFile) //only makes sense for distributed (non local) files
  7910. {
  7911. IPropertyTree & options = dFile->queryAttributes();
  7912. quotes = options.queryProp("@csvQuote");
  7913. separators = options.queryProp("@csvSeparate");
  7914. terminators = options.queryProp("@csvTerminate");
  7915. escapes = options.queryProp("@csvEscape");
  7916. }
  7917. csvSplitter.init(helper.getMaxColumns(), csvInfo, quotes, separators, terminators, escapes);
  7918. }
  7919. void CHThorCsvReadActivity::calcFixedDiskRecordSize()
  7920. {
  7921. fixedDiskRecordSize = 0;
  7922. }
  7923. const void *CHThorCsvReadActivity::nextInGroup()
  7924. {
  7925. while (!stopAfter || (processed - initialProcessed) < stopAfter)
  7926. {
  7927. checkOpenNext();
  7928. if (eofseen)
  7929. break;
  7930. if (!inputstream->eos())
  7931. {
  7932. size32_t rowSize = 4096; // MORE - make configurable
  7933. size32_t thisLineLength;
  7934. loop
  7935. {
  7936. size32_t avail;
  7937. const void *peek = inputstream->peek(rowSize, avail);
  7938. thisLineLength = csvSplitter.splitLine(avail, (const byte *)peek);
  7939. if (thisLineLength < rowSize || avail < rowSize)
  7940. break;
  7941. if (rowSize == maxRowSize)
  7942. {
  7943. OwnedRoxieString fileName(helper.getFileName());
  7944. throw MakeStringException(99, "File %s contained a line of length greater than %d bytes.", fileName.get(), rowSize);
  7945. }
  7946. if (rowSize >= maxRowSize/2)
  7947. rowSize = maxRowSize;
  7948. else
  7949. rowSize += rowSize;
  7950. }
  7951. RtlDynamicRowBuilder rowBuilder(rowAllocator);
  7952. unsigned thisSize;
  7953. try
  7954. {
  7955. thisSize = helper.transform(rowBuilder, csvSplitter.queryLengths(), (const char * *)csvSplitter.queryData());
  7956. }
  7957. catch(IException * e)
  7958. {
  7959. throw makeWrappedException(e);
  7960. }
  7961. inputstream->skip(thisLineLength);
  7962. localOffset += thisLineLength;
  7963. if (thisSize)
  7964. {
  7965. OwnedConstRoxieRow ret = rowBuilder.finalizeRowClear(thisSize);
  7966. if ((processed - initialProcessed) >= limit)
  7967. {
  7968. if ( agent.queryCodeContext()->queryDebugContext())
  7969. agent.queryCodeContext()->queryDebugContext()->checkBreakpoint(DebugStateLimit, NULL, static_cast<IActivityBase *>(this));
  7970. helper.onLimitExceeded();
  7971. return NULL;
  7972. }
  7973. processed++;
  7974. return ret.getClear();
  7975. }
  7976. }
  7977. }
  7978. close();
  7979. return NULL;
  7980. }
  7981. bool CHThorCsvReadActivity::openNext()
  7982. {
  7983. if (CHThorDiskReadBaseActivity::openNext())
  7984. {
  7985. unsigned lines = headerLines;
  7986. while (lines-- && !inputstream->eos())
  7987. {
  7988. size32_t numAvailable;
  7989. const void * next = inputstream->peek(maxDiskSize, numAvailable);
  7990. inputstream->skip(csvSplitter.splitLine(numAvailable, (const byte *)next));
  7991. }
  7992. // only skip header in the first file - since spray doesn't duplicate the header.
  7993. headerLines = 0;
  7994. return true;
  7995. }
  7996. return false;
  7997. }
  7998. void CHThorCsvReadActivity::checkOpenNext()
  7999. {
  8000. agent.reportProgress(NULL);
  8001. if (!opened)
  8002. {
  8003. agent.reportProgress(NULL);
  8004. if (!helper.canMatchAny())
  8005. {
  8006. eofseen = true;
  8007. opened = true;
  8008. }
  8009. else
  8010. open();
  8011. }
  8012. loop
  8013. {
  8014. if (eofseen || !inputstream->eos())
  8015. return;
  8016. eofseen = !openNext();
  8017. }
  8018. }
  8019. //=====================================================================================================
  8020. CHThorXmlReadActivity::CHThorXmlReadActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorXmlReadArg &_arg, ThorActivityKind _kind) : CHThorDiskReadBaseActivity(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  8021. {
  8022. }
  8023. void CHThorXmlReadActivity::ready()
  8024. {
  8025. CHThorDiskReadBaseActivity::ready();
  8026. rowTransformer.set(helper.queryTransformer());
  8027. localOffset = 0;
  8028. limit = helper.getRowLimit();
  8029. if (helper.getFlags() & TDRlimitskips)
  8030. limit = (unsigned __int64) -1;
  8031. stopAfter = helper.getChooseNLimit();
  8032. }
  8033. void CHThorXmlReadActivity::done()
  8034. {
  8035. xmlParser.clear();
  8036. CHThorDiskReadBaseActivity::done();
  8037. }
  8038. void CHThorXmlReadActivity::gatherInfo(IFileDescriptor * fd)
  8039. {
  8040. PARENT::gatherInfo(fd);
  8041. }
  8042. void CHThorXmlReadActivity::calcFixedDiskRecordSize()
  8043. {
  8044. fixedDiskRecordSize = 0;
  8045. }
  8046. const void *CHThorXmlReadActivity::nextInGroup()
  8047. {
  8048. if(!opened) open();
  8049. while (!eofseen && (!stopAfter || (processed - initialProcessed) < stopAfter))
  8050. {
  8051. agent.reportProgress(NULL);
  8052. //call to next() will callback on the IXmlSelect interface
  8053. bool gotNext = false;
  8054. try
  8055. {
  8056. gotNext = xmlParser->next();
  8057. }
  8058. catch(IException * e)
  8059. {
  8060. throw makeWrappedException(e, inputfile->queryFilename());
  8061. }
  8062. if(!gotNext)
  8063. eofseen = !openNext();
  8064. else if (lastMatch)
  8065. {
  8066. RtlDynamicRowBuilder rowBuilder(rowAllocator);
  8067. unsigned sizeGot;
  8068. try
  8069. {
  8070. sizeGot = rowTransformer->transform(rowBuilder, lastMatch, this);
  8071. }
  8072. catch(IException * e)
  8073. {
  8074. throw makeWrappedException(e);
  8075. }
  8076. lastMatch.clear();
  8077. localOffset = 0;
  8078. if (sizeGot)
  8079. {
  8080. OwnedConstRoxieRow ret = rowBuilder.finalizeRowClear(sizeGot);
  8081. if ((processed - initialProcessed) >= limit)
  8082. {
  8083. if ( agent.queryCodeContext()->queryDebugContext())
  8084. agent.queryCodeContext()->queryDebugContext()->checkBreakpoint(DebugStateLimit, NULL, static_cast<IActivityBase *>(this));
  8085. helper.onLimitExceeded();
  8086. return NULL;
  8087. }
  8088. processed++;
  8089. return ret.getClear();
  8090. }
  8091. }
  8092. }
  8093. return NULL;
  8094. }
  8095. bool CHThorXmlReadActivity::openNext()
  8096. {
  8097. if (inputfileio)
  8098. offsetOfPart += inputfileio->size();
  8099. localOffset = 0;
  8100. if (CHThorDiskReadBaseActivity::openNext())
  8101. {
  8102. unsigned readBufferSize = queryReadBufferSize();
  8103. OwnedIFileIOStream inputfileiostream;
  8104. if(readBufferSize)
  8105. inputfileiostream.setown(createBufferedIOStream(inputfileio, readBufferSize));
  8106. else
  8107. inputfileiostream.setown(createIOStream(inputfileio));
  8108. OwnedRoxieString xmlIterator(helper.getXmlIteratorPath());
  8109. if (kind==TAKjsonread)
  8110. xmlParser.setown(createJSONParse(*inputfileiostream, xmlIterator, *this, (0 != (TDRxmlnoroot & helper.getFlags()))?ptr_noRoot:ptr_none, (helper.getFlags() & TDRusexmlcontents) != 0));
  8111. else
  8112. xmlParser.setown(createXMLParse(*inputfileiostream, xmlIterator, *this, (0 != (TDRxmlnoroot & helper.getFlags()))?ptr_noRoot:ptr_none, (helper.getFlags() & TDRusexmlcontents) != 0));
  8113. return true;
  8114. }
  8115. return false;
  8116. }
  8117. void CHThorXmlReadActivity::closepart()
  8118. {
  8119. xmlParser.clear();
  8120. CHThorDiskReadBaseActivity::closepart();
  8121. }
  8122. //---------------------------------------------------------------------------
  8123. CHThorLocalResultReadActivity::CHThorLocalResultReadActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorLocalResultReadArg &_arg, ThorActivityKind _kind, __int64 graphId) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  8124. {
  8125. physicalRecordSize = outputMeta;
  8126. grouped = outputMeta.isGrouped();
  8127. graph = resolveLocalQuery(graphId);
  8128. result = NULL;
  8129. }
  8130. void CHThorLocalResultReadActivity::ready()
  8131. {
  8132. CHThorSimpleActivityBase::ready();
  8133. result = graph->queryResult(helper.querySequence());
  8134. curRow = 0;
  8135. }
  8136. const void *CHThorLocalResultReadActivity::nextInGroup()
  8137. {
  8138. const void * next = result->queryRow(curRow++);
  8139. if (next)
  8140. {
  8141. processed++;
  8142. LinkRoxieRow(next);
  8143. return next;
  8144. }
  8145. return NULL;
  8146. }
  8147. //=====================================================================================================
  8148. CHThorLocalResultWriteActivity::CHThorLocalResultWriteActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorLocalResultWriteArg &_arg, ThorActivityKind _kind, __int64 graphId)
  8149. : CHThorActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  8150. {
  8151. graph = resolveLocalQuery(graphId);
  8152. }
  8153. void CHThorLocalResultWriteActivity::execute()
  8154. {
  8155. IHThorGraphResult * result = graph->createResult(helper.querySequence(), LINK(rowAllocator));
  8156. loop
  8157. {
  8158. const void *nextrec = input->nextInGroup();
  8159. if (!nextrec)
  8160. {
  8161. nextrec = input->nextInGroup();
  8162. if (!nextrec)
  8163. break;
  8164. result->addRowOwn(NULL);
  8165. }
  8166. result->addRowOwn(nextrec);
  8167. }
  8168. }
  8169. //=====================================================================================================
  8170. CHThorDictionaryResultWriteActivity::CHThorDictionaryResultWriteActivity (IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorDictionaryResultWriteArg &_arg, ThorActivityKind _kind, __int64 graphId)
  8171. : CHThorActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  8172. {
  8173. graph = resolveLocalQuery(graphId);
  8174. }
  8175. void CHThorDictionaryResultWriteActivity::execute()
  8176. {
  8177. RtlLinkedDictionaryBuilder builder(rowAllocator, helper.queryHashLookupInfo());
  8178. loop
  8179. {
  8180. const void *row = input->nextInGroup();
  8181. if (!row)
  8182. {
  8183. row = input->nextInGroup();
  8184. if (!row)
  8185. break;
  8186. }
  8187. builder.appendOwn(row);
  8188. }
  8189. IHThorGraphResult * result = graph->createResult(helper.querySequence(), LINK(rowAllocator));
  8190. size32_t dictSize = builder.getcount();
  8191. byte ** dictRows = builder.queryrows();
  8192. for (size32_t row = 0; row < dictSize; row++)
  8193. {
  8194. byte *thisRow = dictRows[row];
  8195. if (thisRow)
  8196. LinkRoxieRow(thisRow);
  8197. result->addRowOwn(thisRow);
  8198. }
  8199. }
  8200. //=====================================================================================================
  8201. CHThorLocalResultSpillActivity::CHThorLocalResultSpillActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorLocalResultSpillArg &_arg, ThorActivityKind _kind, __int64 graphId)
  8202. : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  8203. {
  8204. result = NULL;
  8205. nullPending = false;
  8206. graph = resolveLocalQuery(graphId);
  8207. assertex(graph);
  8208. }
  8209. void CHThorLocalResultSpillActivity::ready()
  8210. {
  8211. CHThorSimpleActivityBase::ready();
  8212. result = graph->createResult(helper.querySequence(), LINK(rowAllocator));
  8213. nullPending = false;
  8214. }
  8215. const void * CHThorLocalResultSpillActivity::nextInGroup()
  8216. {
  8217. const void * ret = input->nextInGroup();
  8218. if (ret)
  8219. {
  8220. if (nullPending)
  8221. {
  8222. result->addRowOwn(NULL);
  8223. nullPending = false;
  8224. }
  8225. LinkRoxieRow(ret);
  8226. result->addRowOwn(ret);
  8227. processed++;
  8228. }
  8229. else
  8230. nullPending = true;
  8231. return ret;
  8232. }
  8233. void CHThorLocalResultSpillActivity::done()
  8234. {
  8235. loop
  8236. {
  8237. const void * ret = input->nextInGroup();
  8238. if (!ret)
  8239. {
  8240. if (nullPending)
  8241. break;
  8242. nullPending = true;
  8243. }
  8244. else
  8245. {
  8246. if (nullPending)
  8247. {
  8248. result->addRowOwn(NULL);
  8249. nullPending = false;
  8250. }
  8251. result->addRowOwn(ret);
  8252. }
  8253. }
  8254. CHThorSimpleActivityBase::done();
  8255. }
  8256. //=====================================================================================================
  8257. CHThorLoopActivity::CHThorLoopActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorLoopArg &_arg, ThorActivityKind _kind)
  8258. : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  8259. {
  8260. flags = helper.getFlags();
  8261. maxIterations = 0;
  8262. }
  8263. CHThorLoopActivity::~CHThorLoopActivity()
  8264. {
  8265. ForEachItemIn(idx, loopPending)
  8266. ReleaseRoxieRow(loopPending.item(idx));
  8267. }
  8268. void CHThorLoopActivity::ready()
  8269. {
  8270. curInput = input;
  8271. eof = false;
  8272. loopCounter = 1;
  8273. CHThorSimpleActivityBase::ready();
  8274. maxIterations = helper.numIterations();
  8275. if ((int)maxIterations < 0) maxIterations = 0;
  8276. finishedLooping = ((kind == TAKloopcount) && (maxIterations == 0));
  8277. if ((flags & IHThorLoopArg::LFnewloopagain) && !helper.loopFirstTime())
  8278. finishedLooping = true;
  8279. extractBuilder.clear();
  8280. helper.createParentExtract(extractBuilder);
  8281. }
  8282. const void * CHThorLoopActivity::nextInGroup()
  8283. {
  8284. if (eof)
  8285. return NULL;
  8286. unsigned emptyIterations = 0;
  8287. loop
  8288. {
  8289. loop
  8290. {
  8291. const void * ret = curInput->nextInGroup();
  8292. if (!ret)
  8293. {
  8294. ret = curInput->nextInGroup(); // more cope with groups somehow....
  8295. if (!ret)
  8296. {
  8297. if (finishedLooping)
  8298. {
  8299. eof = true;
  8300. return NULL;
  8301. }
  8302. break;
  8303. }
  8304. }
  8305. if (finishedLooping ||
  8306. ((flags & IHThorLoopArg::LFfiltered) && !helper.sendToLoop(loopCounter, ret)))
  8307. {
  8308. processed++;
  8309. return ret;
  8310. }
  8311. loopPending.append(ret);
  8312. }
  8313. switch (kind)
  8314. {
  8315. case TAKloopdataset:
  8316. {
  8317. if (!(flags & IHThorLoopArg::LFnewloopagain))
  8318. {
  8319. if (!helper.loopAgain(loopCounter, loopPending.ordinality(), (const void * *)loopPending.getArray()))
  8320. {
  8321. if (loopPending.ordinality() == 0)
  8322. {
  8323. eof = true;
  8324. return NULL;
  8325. }
  8326. arrayInput.init(&loopPending);
  8327. curInput = &arrayInput;
  8328. finishedLooping = true;
  8329. continue; // back to the input loop again
  8330. }
  8331. }
  8332. break;
  8333. }
  8334. case TAKlooprow:
  8335. if (loopPending.empty())
  8336. {
  8337. finishedLooping = true;
  8338. eof = true;
  8339. return NULL;
  8340. }
  8341. break;
  8342. }
  8343. if (loopPending.ordinality())
  8344. emptyIterations = 0;
  8345. else
  8346. {
  8347. //note: any outputs which didn't go around the loop again, would return the record, reinitializing emptyIterations
  8348. emptyIterations++;
  8349. if (emptyIterations > EMPTY_LOOP_LIMIT)
  8350. throw MakeStringException(0, "Executed LOOP with empty input and output %u times", emptyIterations);
  8351. if (emptyIterations % 32 == 0)
  8352. DBGLOG("Executing LOOP with empty input and output %u times", emptyIterations);
  8353. }
  8354. void * counterRow = NULL;
  8355. if (flags & IHThorLoopArg::LFcounter)
  8356. {
  8357. counterRow = queryRowManager()->allocate(sizeof(thor_loop_counter_t), activityId);
  8358. *((thor_loop_counter_t *)counterRow) = loopCounter;
  8359. }
  8360. Owned<IHThorGraphResults> curResults = loopGraph->execute(counterRow, loopPending, extractBuilder.getbytes());
  8361. if (flags & IHThorLoopArg::LFnewloopagain)
  8362. {
  8363. IHThorGraphResult * result = curResults->queryResult(helper.loopAgainResult());
  8364. assertex(result);
  8365. const void * row = result->queryRow(0);
  8366. assertex(row);
  8367. //Result is a row which contains a single boolean field.
  8368. if (!((const bool *)row)[0])
  8369. finishedLooping = true;
  8370. }
  8371. resultInput.init(curResults->queryResult(0));
  8372. curInput = &resultInput;
  8373. loopCounter++;
  8374. if ((kind == TAKloopcount) && (loopCounter > maxIterations))
  8375. finishedLooping = true;
  8376. }
  8377. }
  8378. void CHThorLoopActivity::done()
  8379. {
  8380. ForEachItemIn(idx, loopPending)
  8381. ReleaseRoxieRow(loopPending.item(idx));
  8382. loopPending.kill();
  8383. CHThorSimpleActivityBase::done();
  8384. }
  8385. //---------------------------------------------------------------------------
  8386. CHThorGraphLoopResultReadActivity::CHThorGraphLoopResultReadActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorGraphLoopResultReadArg &_arg, ThorActivityKind _kind, __int64 graphId) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(&_arg)
  8387. {
  8388. physicalRecordSize = outputMeta;
  8389. grouped = outputMeta.isGrouped();
  8390. result = NULL;
  8391. graph = resolveLocalQuery(graphId);
  8392. }
  8393. CHThorGraphLoopResultReadActivity::CHThorGraphLoopResultReadActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorArg & _arg, ThorActivityKind _kind, __int64 graphId, unsigned _sequence, bool _grouped) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(NULL)
  8394. {
  8395. physicalRecordSize = outputMeta;
  8396. sequence = _sequence;
  8397. grouped = _grouped;
  8398. result = NULL;
  8399. graph = resolveLocalQuery(graphId);
  8400. }
  8401. void CHThorGraphLoopResultReadActivity::ready()
  8402. {
  8403. CHThorSimpleActivityBase::ready();
  8404. if (helper)
  8405. sequence = helper->querySequence();
  8406. if ((int)sequence >= 0)
  8407. result = graph->queryGraphLoopResult(sequence);
  8408. else
  8409. result = NULL;
  8410. curRow = 0;
  8411. }
  8412. const void *CHThorGraphLoopResultReadActivity::nextInGroup()
  8413. {
  8414. if (result)
  8415. {
  8416. const void * next = result->queryRow(curRow++);
  8417. if (next)
  8418. {
  8419. processed++;
  8420. LinkRoxieRow(next);
  8421. return (void *)next;
  8422. }
  8423. }
  8424. return NULL;
  8425. }
  8426. //=====================================================================================================
  8427. CHThorGraphLoopResultWriteActivity::CHThorGraphLoopResultWriteActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorGraphLoopResultWriteArg &_arg, ThorActivityKind _kind, __int64 graphId)
  8428. : CHThorActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  8429. {
  8430. graph = resolveLocalQuery(graphId);
  8431. }
  8432. void CHThorGraphLoopResultWriteActivity::execute()
  8433. {
  8434. IHThorGraphResult * result = graph->createGraphLoopResult(LINK(rowAllocator));
  8435. loop
  8436. {
  8437. const void *nextrec = input->nextInGroup();
  8438. if (!nextrec)
  8439. {
  8440. nextrec = input->nextInGroup();
  8441. if (!nextrec)
  8442. break;
  8443. result->addRowOwn(NULL);
  8444. }
  8445. result->addRowOwn(nextrec);
  8446. }
  8447. }
  8448. //=====================================================================================================
  8449. class CCounterMeta : public CInterface, implements IOutputMetaData
  8450. {
  8451. public:
  8452. IMPLEMENT_IINTERFACE
  8453. virtual size32_t getRecordSize(const void *rec) { return sizeof(thor_loop_counter_t); }
  8454. virtual size32_t getMinRecordSize() const { return sizeof(thor_loop_counter_t); }
  8455. virtual size32_t getFixedSize() const { return sizeof(thor_loop_counter_t); }
  8456. virtual void toXML(const byte * self, IXmlWriter & out) { }
  8457. virtual unsigned getVersion() const { return OUTPUTMETADATA_VERSION; }
  8458. virtual unsigned getMetaFlags() { return 0; }
  8459. virtual void destruct(byte * self) {}
  8460. virtual IOutputRowSerializer * createDiskSerializer(ICodeContext * ctx, unsigned activityId) { return NULL; }
  8461. virtual IOutputRowDeserializer * createDiskDeserializer(ICodeContext * ctx, unsigned activityId) { return NULL; }
  8462. virtual ISourceRowPrefetcher * createDiskPrefetcher(ICodeContext * ctx, unsigned activityId) { return NULL; }
  8463. virtual IOutputMetaData * querySerializedDiskMeta() { return this; }
  8464. virtual IOutputRowSerializer * createInternalSerializer(ICodeContext * ctx, unsigned activityId) { return NULL; }
  8465. virtual IOutputRowDeserializer * createInternalDeserializer(ICodeContext * ctx, unsigned activityId) { return NULL; }
  8466. virtual void walkIndirectMembers(const byte * self, IIndirectMemberVisitor & visitor) {}
  8467. virtual IOutputMetaData * queryChildMeta(unsigned i) { return NULL; }
  8468. };
  8469. //=====================================================================================================
  8470. CHThorGraphLoopActivity::CHThorGraphLoopActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorGraphLoopArg &_arg, ThorActivityKind _kind)
  8471. : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  8472. {
  8473. flags = helper.getFlags();
  8474. maxIterations = 0;
  8475. counterMeta.setown(new CCounterMeta);
  8476. }
  8477. void CHThorGraphLoopActivity::ready()
  8478. {
  8479. executed = false;
  8480. resultIndex = 0;
  8481. CHThorSimpleActivityBase::ready();
  8482. maxIterations = helper.numIterations();
  8483. if ((int)maxIterations < 0) maxIterations = 0;
  8484. loopResults.setown(agent.createGraphLoopResults());
  8485. extractBuilder.clear();
  8486. helper.createParentExtract(extractBuilder);
  8487. rowAllocator.setown(agent.queryCodeContext()->getRowAllocator(queryOutputMeta(), activityId));
  8488. rowAllocatorCounter.setown(agent.queryCodeContext()->getRowAllocator(counterMeta, activityId));
  8489. }
  8490. const void * CHThorGraphLoopActivity::nextInGroup()
  8491. {
  8492. if (!executed)
  8493. {
  8494. executed = true;
  8495. IHThorGraphResult * inputResult = loopResults->createResult(0, LINK(rowAllocator));
  8496. loop
  8497. {
  8498. const void * ret = input->nextInGroup();
  8499. if (!ret)
  8500. {
  8501. ret = input->nextInGroup();
  8502. if (!ret)
  8503. break;
  8504. inputResult->addRowOwn(NULL);
  8505. }
  8506. inputResult->addRowOwn(ret);
  8507. }
  8508. for (unsigned loopCounter = 1; loopCounter <= maxIterations; loopCounter++)
  8509. {
  8510. void * counterRow = NULL;
  8511. if (flags & IHThorGraphLoopArg::GLFcounter)
  8512. {
  8513. counterRow = rowAllocatorCounter->createRow();
  8514. *((thor_loop_counter_t *)counterRow) = loopCounter;
  8515. counterRow = rowAllocatorCounter->finalizeRow(sizeof(thor_loop_counter_t), counterRow, sizeof(thor_loop_counter_t));
  8516. }
  8517. loopGraph->execute(counterRow, loopResults, extractBuilder.getbytes());
  8518. }
  8519. int iNumResults = loopResults->ordinality();
  8520. finalResult = loopResults->queryResult(iNumResults-1); //Get the last result, which isnt necessarily 'maxIterations'
  8521. }
  8522. const void * next = finalResult->getOwnRow(resultIndex++);
  8523. if (next)
  8524. processed++;
  8525. return next;
  8526. }
  8527. void CHThorGraphLoopActivity::done()
  8528. {
  8529. rowAllocator.clear();
  8530. finalResult = NULL;
  8531. loopResults.clear();
  8532. CHThorSimpleActivityBase::done();
  8533. }
  8534. //=====================================================================================================
  8535. CHThorParallelGraphLoopActivity::CHThorParallelGraphLoopActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorGraphLoopArg &_arg, ThorActivityKind _kind)
  8536. : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  8537. {
  8538. flags = helper.getFlags();
  8539. maxIterations = 0;
  8540. }
  8541. void CHThorParallelGraphLoopActivity::ready()
  8542. {
  8543. executed = false;
  8544. resultIndex = 0;
  8545. CHThorSimpleActivityBase::ready();
  8546. maxIterations = helper.numIterations();
  8547. if ((int)maxIterations < 0) maxIterations = 0;
  8548. loopResults.setown(agent.createGraphLoopResults());
  8549. extractBuilder.clear();
  8550. helper.createParentExtract(extractBuilder);
  8551. rowAllocator.setown(agent.queryCodeContext()->getRowAllocator(queryOutputMeta(), activityId));
  8552. }
  8553. const void * CHThorParallelGraphLoopActivity::nextInGroup()
  8554. {
  8555. if (!executed)
  8556. {
  8557. executed = true;
  8558. IHThorGraphResult * inputResult = loopResults->createResult(0, LINK(rowAllocator));
  8559. loop
  8560. {
  8561. const void * ret = input->nextInGroup();
  8562. if (!ret)
  8563. {
  8564. ret = input->nextInGroup();
  8565. if (!ret)
  8566. break;
  8567. inputResult->addRowOwn(NULL);
  8568. }
  8569. inputResult->addRowOwn(ret);
  8570. }
  8571. // The lack of separation between pre-creation and creation means this would require cloning lots of structures.
  8572. // not implemented for the moment.
  8573. // loopGraph->executeParallel(loopResults, extractBuilder.getbytes(), maxIterations);
  8574. finalResult = loopResults->queryResult(maxIterations);
  8575. }
  8576. const void * next = finalResult->getOwnRow(resultIndex++);
  8577. if (next)
  8578. processed++;
  8579. return next;
  8580. }
  8581. void CHThorParallelGraphLoopActivity::done()
  8582. {
  8583. rowAllocator.clear();
  8584. finalResult = NULL;
  8585. loopResults.clear();
  8586. CHThorSimpleActivityBase::done();
  8587. }
  8588. //=====================================================================================================
  8589. LibraryCallOutput::LibraryCallOutput(CHThorLibraryCallActivity * _owner, unsigned _output, IOutputMetaData * _meta) : owner(_owner), output(_output), meta(_meta)
  8590. {
  8591. processed = 0;
  8592. }
  8593. const void * LibraryCallOutput::nextInGroup()
  8594. {
  8595. if (!gotRows)
  8596. {
  8597. result.set(owner->getResultRows(output));
  8598. gotRows = true;
  8599. }
  8600. const void * ret = result->getOwnRow(curRow++);
  8601. if (ret)
  8602. processed++;
  8603. return ret;
  8604. }
  8605. bool LibraryCallOutput::isGrouped()
  8606. {
  8607. return meta->isGrouped();
  8608. }
  8609. IOutputMetaData * LibraryCallOutput::queryOutputMeta() const
  8610. {
  8611. return meta;
  8612. }
  8613. void LibraryCallOutput::ready()
  8614. {
  8615. owner->ready();
  8616. gotRows = false;
  8617. result.clear();
  8618. curRow = 0;
  8619. }
  8620. void LibraryCallOutput::done()
  8621. {
  8622. owner->done();
  8623. result.clear();
  8624. }
  8625. void LibraryCallOutput::updateProgress(IStatisticGatherer &progress) const
  8626. {
  8627. owner->updateOutputProgress(progress, *this, processed);
  8628. }
  8629. CHThorLibraryCallActivity::CHThorLibraryCallActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorLibraryCallArg &_arg, ThorActivityKind _kind, IPropertyTree * node)
  8630. : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  8631. {
  8632. libraryName.set(node->queryProp("att[@name=\"libname\"]/@value"));
  8633. interfaceHash = node->getPropInt("att[@name=\"_interfaceHash\"]/@value", 0);
  8634. bool embedded = node->getPropBool("att[@name=\"embedded\"]/@value", false) ;
  8635. if (embedded)
  8636. {
  8637. embeddedGraphName.set(node->queryProp("att[@name=\"graph\"]/@value"));
  8638. if (!embeddedGraphName)
  8639. embeddedGraphName.set(libraryName);
  8640. }
  8641. Owned<IPropertyTreeIterator> iter = node->getElements("att[@name=\"_outputUsed\"]");
  8642. ForEach(*iter)
  8643. {
  8644. unsigned whichOutput = iter->query().getPropInt("@value");
  8645. IOutputMetaData * meta = helper.queryOutputMeta(whichOutput);
  8646. outputs.append(*new LibraryCallOutput(this, whichOutput, meta));
  8647. }
  8648. state = StateCreated;
  8649. }
  8650. IHThorGraphResult * CHThorLibraryCallActivity::getResultRows(unsigned whichOutput)
  8651. {
  8652. CriticalBlock procedure(cs);
  8653. if (!results)
  8654. {
  8655. if (libraryName.length() == 0)
  8656. libraryName.setown(helper.getLibraryName());
  8657. helper.createParentExtract(extractBuilder);
  8658. results.setown(agent.executeLibraryGraph(libraryName, interfaceHash, activityId, embeddedGraphName, extractBuilder.getbytes()));
  8659. }
  8660. return results->queryResult(whichOutput);
  8661. }
  8662. IHThorInput * CHThorLibraryCallActivity::queryOutput(unsigned idx)
  8663. {
  8664. assert(outputs.isItem(idx));
  8665. return &outputs.item(idx);
  8666. }
  8667. void CHThorLibraryCallActivity::updateOutputProgress(IStatisticGatherer &progress, const LibraryCallOutput & _output, unsigned __int64 numProcessed) const
  8668. {
  8669. LibraryCallOutput & output = const_cast<LibraryCallOutput &>(_output);
  8670. updateProgressForOther(progress, activityId, subgraphId, outputs.find(output), numProcessed);
  8671. }
  8672. void CHThorLibraryCallActivity::ready()
  8673. {
  8674. CriticalBlock procedure(cs);
  8675. if (state != StateReady)
  8676. {
  8677. results.clear();
  8678. CHThorSimpleActivityBase::ready();
  8679. state = StateReady;
  8680. }
  8681. }
  8682. const void * CHThorLibraryCallActivity::nextInGroup()
  8683. {
  8684. throwUnexpected();
  8685. }
  8686. void CHThorLibraryCallActivity::done()
  8687. {
  8688. CriticalBlock procedure(cs);
  8689. if (state != StateDone)
  8690. {
  8691. results.clear();
  8692. CHThorSimpleActivityBase::done();
  8693. }
  8694. }
  8695. //=====================================================================================================
  8696. class CHThorNWayInputActivity : public CHThorSimpleActivityBase, implements IHThorNWayInput
  8697. {
  8698. IHThorNWayInputArg & helper;
  8699. InputArrayType inputs;
  8700. InputArrayType selectedInputs;
  8701. public:
  8702. CHThorNWayInputActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorNWayInputArg &_arg, ThorActivityKind _kind) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  8703. {
  8704. }
  8705. virtual void ready()
  8706. {
  8707. bool selectionIsAll;
  8708. size32_t selectionLen;
  8709. rtlDataAttr selection;
  8710. helper.getInputSelection(selectionIsAll, selectionLen, selection.refdata());
  8711. selectedInputs.kill();
  8712. if (selectionIsAll)
  8713. {
  8714. ForEachItemIn(i, inputs)
  8715. selectedInputs.append(inputs.item(i));
  8716. }
  8717. else
  8718. {
  8719. const size32_t * selections = (const size32_t *)selection.getdata();
  8720. unsigned max = selectionLen/sizeof(size32_t);
  8721. for (unsigned i = 0; i < max; i++)
  8722. {
  8723. unsigned nextIndex = selections[i];
  8724. //Check there are no duplicates..... Assumes there are a fairly small number of inputs, so n^2 search is ok.
  8725. for (unsigned j=i+1; j < max; j++)
  8726. {
  8727. if (nextIndex == selections[j])
  8728. throw MakeStringException(100, "Selection list for nway input can not contain duplicates");
  8729. }
  8730. if (!inputs.isItem(nextIndex-1))
  8731. throw MakeStringException(100, "Index %d in RANGE selection list is out of range", nextIndex);
  8732. selectedInputs.append(inputs.item(nextIndex-1));
  8733. }
  8734. }
  8735. ForEachItemIn(i2, selectedInputs)
  8736. selectedInputs.item(i2)->ready();
  8737. }
  8738. virtual void setInput(unsigned idx, IHThorInput *_in)
  8739. {
  8740. assertex(idx == inputs.ordinality());
  8741. inputs.append(_in);
  8742. }
  8743. virtual const void * nextInGroup()
  8744. {
  8745. throwUnexpected();
  8746. }
  8747. virtual void updateProgress(IStatisticGatherer &progress) const
  8748. {
  8749. // CHThorSimpleActivityBase::updateProgress(progress);
  8750. ForEachItemIn(i, inputs)
  8751. inputs.item(i)->updateProgress(progress);
  8752. }
  8753. virtual unsigned numConcreteOutputs() const
  8754. {
  8755. return selectedInputs.ordinality();
  8756. }
  8757. virtual IHThorInput * queryConcreteInput(unsigned idx) const
  8758. {
  8759. if (selectedInputs.isItem(idx))
  8760. return selectedInputs.item(idx);
  8761. return NULL;
  8762. }
  8763. };
  8764. //=====================================================================================================
  8765. class CHThorNWayGraphLoopResultReadActivity : public CHThorSimpleActivityBase, implements IHThorNWayInput
  8766. {
  8767. IHThorNWayGraphLoopResultReadArg & helper;
  8768. CIArrayOf<CHThorActivityBase> inputs;
  8769. __int64 graphId;
  8770. bool grouped;
  8771. public:
  8772. CHThorNWayGraphLoopResultReadActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorNWayGraphLoopResultReadArg &_arg, ThorActivityKind _kind, __int64 _graphId) : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  8773. {
  8774. grouped = helper.isGrouped();
  8775. graphId = _graphId;
  8776. }
  8777. virtual bool isGrouped()
  8778. {
  8779. return grouped;
  8780. }
  8781. virtual void ready()
  8782. {
  8783. bool selectionIsAll;
  8784. size32_t selectionLen;
  8785. rtlDataAttr selection;
  8786. helper.getInputSelection(selectionIsAll, selectionLen, selection.refdata());
  8787. if (selectionIsAll)
  8788. throw MakeStringException(100, "ALL not yet supported for NWay graph inputs");
  8789. unsigned max = selectionLen / sizeof(size32_t);
  8790. const size32_t * selections = (const size32_t *)selection.getdata();
  8791. for (unsigned i = 0; i < max; i++)
  8792. {
  8793. CHThorActivityBase * resultInput = new CHThorGraphLoopResultReadActivity(agent, activityId, subgraphId, helper, kind, graphId, selections[i], grouped);
  8794. inputs.append(*resultInput);
  8795. resultInput->ready();
  8796. }
  8797. }
  8798. virtual void done()
  8799. {
  8800. inputs.kill();
  8801. }
  8802. virtual void setInput(unsigned idx, IHThorInput *_in)
  8803. {
  8804. throwUnexpected();
  8805. }
  8806. virtual const void * nextInGroup()
  8807. {
  8808. throwUnexpected();
  8809. }
  8810. virtual unsigned numConcreteOutputs() const
  8811. {
  8812. return inputs.ordinality();
  8813. }
  8814. virtual IHThorInput * queryConcreteInput(unsigned idx) const
  8815. {
  8816. if (inputs.isItem(idx))
  8817. return &inputs.item(idx);
  8818. return NULL;
  8819. }
  8820. };
  8821. //=====================================================================================================
  8822. CHThorNWaySelectActivity::CHThorNWaySelectActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorNWaySelectArg &_arg, ThorActivityKind _kind) : CHThorMultiInputActivity(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  8823. {
  8824. selectedInput = NULL;
  8825. }
  8826. void CHThorNWaySelectActivity::done()
  8827. {
  8828. selectedInput = NULL;
  8829. CHThorMultiInputActivity::done();
  8830. }
  8831. void CHThorNWaySelectActivity::ready()
  8832. {
  8833. CHThorMultiInputActivity::ready();
  8834. unsigned whichInput = helper.getInputIndex();
  8835. selectedInput = NULL;
  8836. if (whichInput--)
  8837. {
  8838. ForEachItemIn(i, inputs)
  8839. {
  8840. IHThorInput * cur = inputs.item(i);
  8841. IHThorNWayInput * nWayInput = dynamic_cast<IHThorNWayInput *>(cur);
  8842. if (nWayInput)
  8843. {
  8844. unsigned numRealInputs = nWayInput->numConcreteOutputs();
  8845. if (whichInput < numRealInputs)
  8846. selectedInput = nWayInput->queryConcreteInput(whichInput);
  8847. whichInput -= numRealInputs;
  8848. }
  8849. else
  8850. {
  8851. if (whichInput == 0)
  8852. selectedInput = cur;
  8853. whichInput -= 1;
  8854. }
  8855. if (selectedInput)
  8856. break;
  8857. }
  8858. }
  8859. }
  8860. const void * CHThorNWaySelectActivity::nextInGroup()
  8861. {
  8862. if (!selectedInput)
  8863. return NULL;
  8864. return selectedInput->nextInGroup();
  8865. }
  8866. const void * CHThorNWaySelectActivity::nextGE(const void * seek, unsigned numFields)
  8867. {
  8868. if (!selectedInput)
  8869. return NULL;
  8870. return selectedInput->nextGE(seek, numFields);
  8871. }
  8872. IInputSteppingMeta * CHThorNWaySelectActivity::querySteppingMeta()
  8873. {
  8874. if (selectedInput)
  8875. return selectedInput->querySteppingMeta();
  8876. return NULL;
  8877. }
  8878. //=====================================================================================================
  8879. CHThorStreamedIteratorActivity::CHThorStreamedIteratorActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorStreamedIteratorArg &_arg, ThorActivityKind _kind)
  8880. : CHThorSimpleActivityBase(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg)
  8881. {
  8882. }
  8883. void CHThorStreamedIteratorActivity::ready()
  8884. {
  8885. CHThorSimpleActivityBase::ready();
  8886. rows.setown(helper.createInput());
  8887. }
  8888. const void *CHThorStreamedIteratorActivity::nextInGroup()
  8889. {
  8890. assertex(rows);
  8891. const void * next = rows->nextRow();
  8892. if (next)
  8893. processed++;
  8894. return next;
  8895. }
  8896. void CHThorStreamedIteratorActivity::done()
  8897. {
  8898. if (rows)
  8899. {
  8900. rows->stop();
  8901. rows.clear();
  8902. }
  8903. }
  8904. //=====================================================================================================
  8905. CHThorExternalActivity::CHThorExternalActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorExternalArg &_arg, ThorActivityKind _kind, IPropertyTree * _graphNode)
  8906. : CHThorMultiInputActivity(_agent, _activityId, _subgraphId, _arg, _kind), helper(_arg), graphNode(_graphNode)
  8907. {
  8908. }
  8909. void CHThorExternalActivity::ready()
  8910. {
  8911. CHThorMultiInputActivity::ready();
  8912. //must be called after onStart()
  8913. processor.setown(helper.createProcessor());
  8914. processor->onCreate(agent.queryCodeContext(), graphNode);
  8915. ForEachItemIn(idx, inputs)
  8916. {
  8917. Owned<CHThorInputAdaptor> adaptedInput = new CHThorInputAdaptor(inputs.item(idx));
  8918. processor->addInput(idx, adaptedInput);
  8919. }
  8920. processor->start();
  8921. if (outputMeta.getMinRecordSize() > 0)
  8922. rows.setown(processor->createOutput(0));
  8923. }
  8924. const void *CHThorExternalActivity::nextInGroup()
  8925. {
  8926. assertex(rows);
  8927. const void * next = rows->nextRow();
  8928. if (next)
  8929. processed++;
  8930. return next;
  8931. }
  8932. void CHThorExternalActivity::execute()
  8933. {
  8934. assertex(!rows);
  8935. processor->execute();
  8936. }
  8937. void CHThorExternalActivity::reset()
  8938. {
  8939. rows.clear();
  8940. processor->reset();
  8941. processor.clear();
  8942. }
  8943. void CHThorExternalActivity::done()
  8944. {
  8945. if (rows)
  8946. {
  8947. rows->stop();
  8948. rows.clear();
  8949. }
  8950. processor->stop();
  8951. }
  8952. //=====================================================================================================
  8953. MAKEFACTORY(DiskWrite);
  8954. MAKEFACTORY(Iterate);
  8955. MAKEFACTORY(Filter);
  8956. MAKEFACTORY(Aggregate);
  8957. MAKEFACTORY(Rollup);
  8958. MAKEFACTORY(Project);
  8959. MAKEFACTORY(PrefetchProject);
  8960. MAKEFACTORY(FilterProject);
  8961. extern HTHOR_API IHThorActivity * createGroupDedupActivity(IAgentContext & _agent, unsigned _activityId, unsigned _subgraphId, IHThorDedupArg & arg, ThorActivityKind kind)
  8962. {
  8963. if(arg.compareAll())
  8964. return new CHThorGroupDedupAllActivity(_agent, _activityId, _subgraphId, arg, kind);
  8965. else if (arg.keepLeft())
  8966. return new CHThorGroupDedupKeepLeftActivity(_agent, _activityId, _subgraphId, arg, kind);
  8967. else
  8968. return new CHThorGroupDedupKeepRightActivity(_agent, _activityId, _subgraphId, arg, kind);
  8969. }
  8970. MAKEFACTORY(HashDedup);
  8971. MAKEFACTORY(Group);
  8972. MAKEFACTORY(Degroup);
  8973. MAKEFACTORY_ARG(GroupSort, Sort);
  8974. MAKEFACTORY(Join);
  8975. MAKEFACTORY_ARG(SelfJoin, Join);
  8976. MAKEFACTORY_ARG(LookupJoin, HashJoin);
  8977. MAKEFACTORY(AllJoin);
  8978. MAKEFACTORY(WorkUnitWrite);
  8979. MAKEFACTORY(DictionaryWorkUnitWrite);
  8980. MAKEFACTORY(FirstN);
  8981. MAKEFACTORY(InlineTable);
  8982. MAKEFACTORY_ARG(Concat, Funnel);
  8983. MAKEFACTORY(Apply);
  8984. MAKEFACTORY(Sample);
  8985. MAKEFACTORY(Normalize);
  8986. MAKEFACTORY(NormalizeChild);
  8987. MAKEFACTORY(NormalizeLinkedChild);
  8988. MAKEFACTORY(Distribution);
  8989. MAKEFACTORY(RemoteResult);
  8990. MAKEFACTORY(ChooseSets);
  8991. MAKEFACTORY_ARG(ChooseSetsLast, ChooseSetsEx);
  8992. MAKEFACTORY_ARG(ChooseSetsEnth, ChooseSetsEx);
  8993. MAKEFACTORY(WorkunitRead);
  8994. MAKEFACTORY(PipeRead);
  8995. MAKEFACTORY(PipeWrite);
  8996. MAKEFACTORY(CsvWrite);
  8997. MAKEFACTORY(XmlWrite);
  8998. MAKEFACTORY(PipeThrough);
  8999. MAKEFACTORY(If);
  9000. extern HTHOR_API IHThorActivity *createChildIfActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorIfArg &arg, ThorActivityKind kind)
  9001. {
  9002. return new CHThorIfActivity(_agent, _activityId, _subgraphId, arg, kind);
  9003. }
  9004. extern HTHOR_API IHThorActivity *createHashAggregateActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorHashAggregateArg &arg, ThorActivityKind kind, bool _isGroupedAggregate)
  9005. {
  9006. return new CHThorHashAggregateActivity(_agent, _activityId, _subgraphId, arg, kind, _isGroupedAggregate);
  9007. }
  9008. MAKEFACTORY(Null);
  9009. MAKEFACTORY(SideEffect);
  9010. MAKEFACTORY(Action);
  9011. MAKEFACTORY(SelectN);
  9012. MAKEFACTORY(Spill);
  9013. MAKEFACTORY(Limit);
  9014. MAKEFACTORY_ARG(SkipLimit, Limit);
  9015. MAKEFACTORY_ARG(OnFailLimit, Limit);
  9016. MAKEFACTORY(Catch);
  9017. MAKEFACTORY_ARG(SkipCatch, Catch);
  9018. MAKEFACTORY(CountProject);
  9019. MAKEFACTORY(IndexWrite);
  9020. MAKEFACTORY(Parse);
  9021. MAKEFACTORY(Enth);
  9022. MAKEFACTORY(TopN);
  9023. MAKEFACTORY(XmlParse);
  9024. MAKEFACTORY(Merge);
  9025. MAKEFACTORY_ARG(HttpRowCall, HttpCall);
  9026. MAKEFACTORY_ARG(SoapRowCall, SoapCall);
  9027. MAKEFACTORY_ARG(SoapRowAction, SoapAction);
  9028. MAKEFACTORY_ARG(SoapDatasetCall, SoapCall);
  9029. MAKEFACTORY_ARG(SoapDatasetAction, SoapAction);
  9030. MAKEFACTORY(DatasetResult);
  9031. MAKEFACTORY(RowResult);
  9032. MAKEFACTORY(ChildIterator);
  9033. extern HTHOR_API IHThorActivity *createDummyActivity(IAgentContext &_agent, unsigned _activityId, unsigned _subgraphId, IHThorArg &arg, ThorActivityKind kind)
  9034. {
  9035. return new CHThorDummyActivity(_agent, _activityId, _subgraphId, arg, kind);
  9036. }
  9037. MAKEFACTORY_EXTRA(WhenAction,EclGraphElement *)
  9038. MAKEFACTORY_EXTRA(LibraryCall, IPropertyTree *)
  9039. MAKEFACTORY(ChildNormalize)
  9040. MAKEFACTORY(ChildAggregate)
  9041. MAKEFACTORY(ChildGroupAggregate)
  9042. MAKEFACTORY(ChildThroughNormalize)
  9043. MAKEFACTORY(DiskRead)
  9044. MAKEFACTORY(DiskNormalize)
  9045. MAKEFACTORY(DiskAggregate)
  9046. MAKEFACTORY(DiskCount)
  9047. MAKEFACTORY(DiskGroupAggregate)
  9048. MAKEFACTORY(CsvRead)
  9049. MAKEFACTORY(XmlRead)
  9050. MAKEFACTORY_EXTRA(LocalResultRead, __int64)
  9051. MAKEFACTORY_EXTRA(LocalResultWrite, __int64)
  9052. MAKEFACTORY_EXTRA(DictionaryResultWrite, __int64)
  9053. MAKEFACTORY_EXTRA(LocalResultSpill, __int64)
  9054. MAKEFACTORY_EXTRA(GraphLoopResultRead, __int64)
  9055. MAKEFACTORY_EXTRA(GraphLoopResultWrite, __int64)
  9056. MAKEFACTORY_EXTRA(NWayGraphLoopResultRead, __int64)
  9057. MAKEFACTORY(Combine)
  9058. MAKEFACTORY(RollupGroup)
  9059. MAKEFACTORY(Regroup)
  9060. MAKEFACTORY(CombineGroup)
  9061. MAKEFACTORY(Case)
  9062. MAKEFACTORY(LinkedRawIterator)
  9063. MAKEFACTORY(GraphLoop)
  9064. MAKEFACTORY(Loop)
  9065. MAKEFACTORY(Process)
  9066. MAKEFACTORY(Grouped)
  9067. MAKEFACTORY(Sorted)
  9068. MAKEFACTORY(Trace)
  9069. MAKEFACTORY(NWayInput)
  9070. MAKEFACTORY(NWaySelect)
  9071. MAKEFACTORY(NonEmpty)
  9072. MAKEFACTORY(FilterGroup);
  9073. MAKEFACTORY(StreamedIterator);
  9074. MAKEFACTORY_EXTRA(External, IPropertyTree *);
  9075. IHThorException * makeHThorException(ThorActivityKind kind, unsigned activityId, unsigned subgraphId, int code, char const * format, ...)
  9076. {
  9077. va_list args;
  9078. va_start(args, format);
  9079. IHThorException * ret = new CHThorException(code, format, args, MSGAUD_user, kind, activityId, subgraphId);
  9080. va_end(args);
  9081. return ret;
  9082. }
  9083. IHThorException * makeHThorException(ThorActivityKind kind, unsigned activityId, unsigned subgraphId, IException * exc)
  9084. {
  9085. return new CHThorException(exc, kind, activityId, subgraphId);
  9086. }
  9087. IHThorException * makeHThorException(ThorActivityKind kind, unsigned activityId, unsigned subgraphId, IException * exc, char const * extra)
  9088. {
  9089. return new CHThorException(exc, extra, kind, activityId, subgraphId);
  9090. }