function GTGenerate_ProcessChunk($wpName, $queries, $attMap) { $allPassthrough = []; $allSynth = []; foreach ($queries as $query => $info) { $pass = $info['pass']; foreach ($pass as $attr) { if (!in_array($attr, $allPassthrough)) { $allPassthrough[] = $attr; } } $output = $info['output']; foreach ($output as $attr) { if (!in_array($attr, $allSynth)) { $allSynth[] = $attr; } } } $gtVars = []; ?> //+{"kind":"WPF", "name":"Process Chunk", "action":"start"} extern "C" int GTProcessChunkWorkFunc_<?php echo $wpName; ?> (WorkDescription & workDescription, ExecEngineData & result) { GTProcessChunkWD myWork; myWork.swap(workDescription); Chunk & input = myWork.get_chunkToProcess(); QueryToGLAStateMap & gtStates = myWork.get_gtStates(); QueryToGLAStateMap & constStates = myWork.get_constStates(); QueryIDSet queriesToRun = QueryExitsToQueries( myWork.get_whichQueryExits() ); FATALIF(queriesToRun.IsEmpty(), "Attempted to process chunk with no queries to run."); <?php cgDeclareQueryIDs($queries); ?> QueryIDSet queriesAvailable; <?php foreach ($queries as $query => $info) { ?> queriesAvailable.Union(<?php echo queryName($query); ?> ); <?php } // for each query ?> QueryIDSet queriesCovered = queriesToRun; queriesCovered.Intersect(queriesAvailable); FATALIF( queriesCovered.IsEmpty(), "Queries being run do not overlap queries known by this waypoint" ); PROFILING2_START; // Set up the output chunk Chunk output; // Defining the GT states needed. // For each one we will look for an existing state, if we find none, we // create a new state from scratch. <?php foreach ($queries as $query => $info) { $gt = $info['gt']; $gtVar = 'state_' . queryName($query); $gtVars[$query] = $gtVar; $cstArgs = []; if ($gt->configurable()) { echo ' // JSON Configuration for query ' . queryName($query) . PHP_EOL; $carg = $info['cargs']; $carg->init(); $cstArgs[] = $carg->name(); echo PHP_EOL; } if ($gt->has_state()) { $cstArgs[] = '*constState'; } if (\count($cstArgs) > 0) { $cstStr = '(' . implode(', ', $cstArgs) . ')'; } else { $cstStr = ''; } ?> <?php echo $gt; ?> * <?php echo $gtVar; ?> = nullptr; if( queriesToRun.Overlaps(<?php echo queryName($query); ?> ) ) { if( gtStates.IsThere(<?php echo queryName($query); ?> ) ) { // Extract from container GLAPtr tState; GLAState& state = gtStates.Find(<?php echo queryName($query); ?> ); tState.swap(state); // Check type FATALIF( tState.get_glaType() != <?php echo $gt->cHash(); ?> , "Got different type than expected for GT of type <?php echo $gt; ?> "); // Extract pointer <?php echo $gtVar; ?> = (<?php echo $gt; ?> *) tState.get_glaPtr(); // Return container tState.swap(state); } // if we already have a state available else { // We don't have a state, create a new one <?php if ($gt->has_state()) { ?> // Extract the constant state, so we can use it to initialize // the GT const <?php echo $gt->state(); ?> * constState = nullptr; GLAPtr constStatePtr; // Extract from container FATALIF( !constStates.IsThere(<?php echo queryName($query); ?> ), "No constant state found for query (<?php echo queryName($query); ?> ) that requires a constant state"); GLAState & tempState = constStates.Find(<?php echo queryName($query); ?> ); constStatePtr.swap(tempState); // Check validity FATALIF( constStatePtr.get_glaType() != <?php echo $gt->state()->cHash(); ?> , "Got different type than expected for constant state of type <?php echo $gt->state(); ?> "); // Get pointer constState = (const <?php echo $gt->state(); ?> *) constStatePtr.get_glaPtr(); // Put back in container constStatePtr.swap(tempState); <?php } // if GT has a constant state ?> // Construct new GT <?php echo $gtVar; ?> = new <?php echo $gt; echo $cstStr; ?> ; // Play into container, so we can reuse it. GLAPtr newPtr( <?php echo $gt->cHash(); ?> , <?php echo $gtVar; ?> ); QueryIDSet qry = <?php echo queryName($query); ?> ; gtStates.Insert(qry, newPtr); } // if we had to create a state } // if query <?php echo queryName($query); ?> is running <?php } // foreach query ?> // Prepare output bitstring iterator MMappedStorage queries_out_store; Column queries_out_col( queries_out_store ); BStringIterator queries_out(queries_out_col, queriesCovered); // Prepare output for all passthrough attributes <?php cgConstructColumns($allPassthrough, '_out'); ?> // Prepare output for synthesized attributes <?php cgConstructColumns($allSynth, '_out'); ?> // Queries Covered by each passthrough attribute <?php foreach ($allPassthrough as $attr) { $type = $attr->type(); $nullable = $type->is('nullable'); $cstr = ""; if ($nullable) { $cstr = "(GrokitNull::Value)"; } ?> <?php echo $type; ?> <?php echo $attr->name(); ?> _out_default<?php echo $cstr; ?> ; QueryIDSet <?php echo $attr->name(); ?> _out_queries; <?php foreach ($queries as $query => $info) { if (in_array($attr, $info['pass'])) { ?> <?php echo $attr->name(); ?> _out_queries.Union(<?php echo queryName($query); ?> ); <?php } // if attribute is part of this query } // foreach query } // foreach passthrough attribute ?> // Queries covered by each synthesized attribute <?php foreach ($allSynth as $attr) { $type = $attr->type(); $nullable = $type->is('nullable'); $cstr = ""; if ($nullable) { $cstr = "(GrokitNull::Value)"; } ?> <?php echo $type; ?> <?php echo $attr->name(); ?> _out_default<?php echo $cstr; ?> ; QueryIDSet <?php echo $attr->name(); ?> _out_queries; <?php foreach ($queries as $query => $info) { if (in_array($attr, $info['output'])) { ?> <?php echo $attr->name(); ?> _out_queries.Union(<?php echo queryName($query); ?> ); <?php } // if attribute is part of this query } // foreach query } // foreach passthrough attribute ?> // Define constants used in expressions <?php foreach ($queries as $query => $info) { $input = $info['expressions']; cgDeclareConstants($input); } // foreach query ?> // Profiling information int64_t numTuplesIn = 0; int64_t numTuplesOut = 0; #ifdef PER_QUERY_PROFILE <?php foreach ($queries as $query => $info) { ?> int64_t numTuplesIn_<?php echo queryName($query); ?> = 0; int64_t numTuplesOut_<?php echo queryName($query); ?> = 0; <?php } // foreach query ?> #endif // PER_QUERY_PROFILE // Define should_iterate and is_done for each query <?php $iterVars = []; foreach ($queries as $query => $info) { $iterVar = 'should_process_' . queryName($query); $iterVars[] = $iterVar; ?> bool <?php echo $iterVar; ?> = true; <?php } $iterExpr = implode(' || ', $iterVars); ?> <?php foreach ($queries as $query => $info) { // Call StartChunk() on iterable GTs $gt = $info['gt']; $gtVar = $gtVars[$query]; if ($gt->iterable()) { ?> if (queriesToRun.Overlaps(<?php echo queryName($query); ?> )) { <?php echo $gtVar; ?> ->StartChunk(); } <?php } } ?> do { <?php cgAccessColumns($attMap, 'input', $wpName); ?> // Prepare input bitstring iterator BStringIterator queries_in; input.SwapBitmap(queries_in); numTuplesIn = 0; #ifdef PER_QUERY_PROFILE <?php foreach ($queries as $query => $info) { ?> numTuplesIn_<?php echo queryName($query); ?> = 0; <?php } // foreach query ?> #endif // PER_QUERY_PROFILE // Begin processing tuples while( !queries_in.AtEndOfColumn() ) { numTuplesIn++; QueryIDSet qry = queries_in.GetCurrent(); qry.Intersect(queriesToRun); queries_in.Advance(); <?php cgAccessAttributes($attMap); foreach ($queries as $query => $info) { $gt = $info['gt']; $input = $info['expressions']; $output = $info['output']; $iterVar = 'should_process_' . queryName($query); $gtVar = $gtVars[$query]; $outputVars = []; foreach ($output as $attr) { $outputVars[] = $attr->name() . '_out'; } $inputVals = []; foreach ($input as $expr) { $inputVals[] = $expr->value(); } // Prepare the output text ob_start(); ?> // Insert synthesized attributes <?php foreach ($allSynth as $attr) { ?> if( queriesToRun.Overlaps(<?php echo $attr->name(); ?> _out_queries) ) { <?php echo $attr->name(); ?> _out_Column_Out.Insert(<?php echo $attr->name(); ?> _out); } else { <?php echo $attr->name(); ?> _out_Column_Out.Insert(<?php echo $attr->name(); ?> _out_default); } <?php echo $attr->name(); ?> _out_Column_Out.Advance(); <?php } // foreach synthesized attribute ?> // Insert passthrough attributes <?php foreach ($allPassthrough as $attr) { ?> if( queriesToRun.Overlaps(<?php echo $attr->name(); ?> _out_queries) ) { <?php echo $attr->name(); ?> _out_Column_Out.Insert(<?php echo $attr->name(); ?> ); } else { <?php echo $attr->name(); ?> _out_Column_Out.Insert(<?php echo $attr->name(); ?> _out_default); } <?php echo $attr->name(); ?> _out_Column_Out.Advance(); <?php } // foreach synthesized attribute ?> queries_out.Insert(<?php echo queryName($query); ?> ); queries_out.Advance(); numTuplesOut++; #ifdef PER_QUERY_PROFILE numTuplesOut_<?php echo queryName($query); ?> ++; #endif // PER_QUERY_PROFILE <?php $outputText = ob_get_clean(); ?> // Do Query [<?php echo queryName($query); ?> ] if( <?php echo $iterVar; ?> && qry.Overlaps(<?php echo queryName($query); ?> ) ) { #ifdef PER_QUERY_PROFILE numTuplesIn_<?php echo queryName($query); ?> ++; #endif // PER_QUERY_PROFILE <?php cgDeclarePreprocessing($input, 3); ?> <?php if ($gt->result_type() == 'single') { ?> if( <?php echo $gtVar; ?> ->ProcessTuple(<?php echo implode(', ', $inputVals); ?> , <?php echo implode(', ', $outputVars); ?> ) ) { <?php echo $outputText; ?> } // if GT produced output for this tuple <?php } else { // if gt result type is single ?> <?php echo $gtVar; ?> ->ProcessTuple(<?php echo implode(', ', $inputVals); ?> ); while( <?php echo $gtVar; ?> ->GetNextResult(<?php echo implode(', ', $outputVars); ?> ) ) { <?php echo $outputText; ?> } // while GT has output for this tuple <?php } // if gt result type is multi ?> } // if <?php echo queryName($query); ?> active in tuple <?php } // foreach query cgAdvanceAttributes($attMap, 2); ?> } // while we have tuples to process <?php foreach ($queries as $query => $info) { $gt = $info['gt']; $iterVar = 'should_process_' . queryName($query); $gtVar = $gtVars[$query]; if ($gt->iterable()) { ?> if (<?php echo $iterVar; ?> ) { <?php echo $iterVar; ?> = <?php echo $gtVar; ?> ->ShouldIterate(); } <?php } else { ?> <?php echo $iterVar; ?> = false; <?php } } //foreach query ?> // Put columns back into chunk <?php cgPutbackColumns($attMap, 'input', $wpName); ?> // Put bitmap back into chunk queries_in.Done(); input.SwapBitmap(queries_in); } while(<?php echo $iterExpr; ?> ); // Tell GTs that need to know about the chunk boundary <?php foreach ($queries as $query => $info) { $gt = $info['gt']; $gtVar = $gtVars[$query]; if ($gt->chunk_boundary()) { ?> <?php echo $gtVar; ?> ->ChunkBoundary(); <?php } // if GT cares about chunk boundaries } // foreach query ?> // Finalize the output iterators and put the columns into the output chunk queries_out.Done(); output.SwapBitmap(queries_out); <?php foreach ($allPassthrough as $attr) { ?> if( queriesToRun.Overlaps(<?php echo $attr->name(); ?> _out_queries) ) { Column temp; <?php echo $attr->name(); ?> _out_Column_Out.Done(temp); output.SwapColumn(temp, <?php echo $attr->slot(); ?> ); } <?php } // foreach passthrough attribute ?> <?php foreach ($allSynth as $attr) { ?> if( queriesToRun.Overlaps(<?php echo $attr->name(); ?> _out_queries) ) { Column temp; <?php echo $attr->name(); ?> _out_Column_Out.Done(temp); output.SwapColumn(temp, <?php echo $attr->slot(); ?> ); } <?php } // foreach passthrough attribute ?> PROFILING2_END; // Profiling PCounterList counterList; PCounter totalCntIn("tpi", numTuplesIn, "<?php echo $wpName; ?> "); counterList.Append(totalCntIn); PCounter totalCntOut("tpo", numTuplesOut, "<?php echo $wpName; ?> "); counterList.Append(totalCntOut); #ifdef PER_QUERY_PROFILE <?php foreach ($queries as $query => $info) { ?> if( queriesToRun.Overlaps(<?php echo queryName($query); ?> ) ) { PCounter cntIn("tpi <?php echo queryName($query); ?> ", numTuplesIn_<?php echo queryName($query); ?> , "<?php echo $wpName; ?> "); counterList.Append(cntIn); PCounter cntOut("tpo <?php echo queryName($query); ?> ", numTuplesOut_<?php echo queryName($query); ?> , "<?php echo $wpName; ?> "); counterList.Append(cntOut); } <?php } // foreach query ?> #endif // PER_QUERY_PROFILE PROFILING2_SET(counterList, "<?php echo $wpName; ?> "); // Return result and exit GTProcessChunkRez gtRez(gtStates, output); result.swap(gtRez); return WP_PROCESS_CHUNK; } //+{"kind":"WPF", "name":"Process Chunk", "action":"end"} <?php }
function GLAGenerate_ProcessChunk($wpName, $queries, $attMap) { ?> #ifndef PER_QUERY_PROFILE #define PER_QUERY_PROFILE #endif #include <map> #include <sstream> //+{"kind":"WPF", "name":"Process Chunk", "action":"start"} extern "C" int GLAProcessChunkWorkFunc_<?php echo $wpName; ?> (WorkDescription &workDescription, ExecEngineData &result) { GLAProcessChunkWD myWork; myWork.swap(workDescription); Chunk &input = myWork.get_chunkToProcess (); QueryToGLAStateMap& glaStates = myWork.get_glaStates(); QueryToGLAStateMap& constStates = myWork.get_constStates(); QueryToGLAStateMap& garbageStates = myWork.get_garbageStates(); PROFILING2_START; QueryIDSet queriesToRun = QueryExitsToQueries( myWork.get_whichQueryExits() ); FATALIF(queriesToRun.IsEmpty(), "Why are we processing a chunk with no queries to run?"); <?php cgDeclareQueryIDs($queries); ?> QueryIDSet queriesAvailable; <?php foreach ($queries as $query => $info) { ?> queriesAvailable.Union(<?php echo queryName($query); ?> ); <?php } // for each query ?> QueryIDSet queriesCovered = queriesToRun; queriesCovered.Intersect(queriesAvailable); FATALIF( queriesCovered.IsEmpty(), "Queries being run do not overlap queries known by this waypoint!" ); <?php cgAccessColumns($attMap, 'input', $wpName); ?> // prepare bitstring iterator BStringIterator queries; input.SwapBitmap (queries); // Garbage collect old states, if there are any. <?php foreach ($queries as $query => $info) { $gla = $info['gla']; ?> if( garbageStates.IsThere( <?php echo queryName($query); ?> ) ) { QueryID curID = <?php echo queryName($query); ?> ; QueryID key; GLAState state; garbageStates.Remove( curID, key, state ); GLAPtr curPtr; curPtr.swap(state); <?php echo $gla; ?> * garbage = (<?php echo $gla; ?> *) curPtr.get_glaPtr(); delete garbage; } <?php } // foreach query ?> // Defining the GLA states needed. // For each one we will look for an existing state, if we find none, we // create a state from scratch. <?php $glaVars = []; foreach ($queries as $query => $info) { $gla = $info['gla']; $glaVar = 'state_' . queryName($query); $glaVars[$query] = $glaVar; // Create the pointer to the GLA $cstArgs = []; if ($gla->configurable()) { echo ' // JSON Configuration for query ' . queryName($query) . PHP_EOL; $carg = $info['cargs']; $carg->init(); $cstArgs[] = $carg->name(); echo PHP_EOL; } if ($gla->has_state()) { $cstArgs[] = '*constState'; } if (\count($cstArgs) > 0) { $cstStr = '(' . implode(', ', $cstArgs) . ')'; } else { $cstStr = ''; } ?> <?php echo $gla; ?> * <?php echo $glaVar; ?> = NULL; if( queriesToRun.Overlaps(<?php echo queryName($query); ?> ) ) { if( glaStates.IsThere(<?php echo queryName($query); ?> ) ) { // We already have a state, just extract it. GLAPtr tState; GLAState& state = glaStates.Find(<?php echo queryName($query); ?> ); tState.swap(state); FATALIF( tState.get_glaType() != <?php echo $gla->cHash(); ?> , "Got different type than expected for GLA of type <?php echo $gla; ?> "); <?php echo $glaVar; ?> = (<?php echo $gla; ?> *) tState.get_glaPtr(); tState.swap(state); } else { // We don't have a state, create a new one. <?php if ($gla->has_state()) { ?> // Extract the constant state, so we can use it to initialize // the GLA const <?php echo $gla->state(); ?> * constState = nullptr; GLAPtr constStatePtr; // Extract from container FATALIF( !constStates.IsThere(<?php echo queryName($query); ?> ), "No constant state found for query (<?php echo queryName($query); ?> ) that requires a constant state"); GLAState & tempState = constStates.Find(<?php echo queryName($query); ?> ); constStatePtr.swap(tempState); // Check validity FATALIF( constStatePtr.get_glaType() != <?php echo $gla->state()->cHash(); ?> , "Got different type than expected for constant state of type <?php echo $gla->state(); ?> "); // Get pointer constState = (const <?php echo $gla->state(); ?> *) constStatePtr.get_glaPtr(); // Put back in container constStatePtr.swap(tempState); <?php } // if gla has a constant state ?> // Construct new GLA <?php echo $glaVar; ?> = new <?php echo $gla; echo $cstStr; ?> ; // Place into container, so we can reuse it. GLAPtr newPtr( <?php echo $gla->cHash(); ?> , <?php echo $glaVar; ?> ); QueryIDSet qry = <?php echo queryName($query); ?> ; glaStates.Insert(qry, newPtr); } // else don't have a GLA state already } // if queriesToRun overlaps <?php echo queryName($query); ?> . <?php } // foreach query // Define constants used in expressions foreach ($queries as $query => $info) { $input = $info['expressions']; cgDeclareConstants($input); // Per-query profile ?> #ifdef PER_QUERY_PROFILE int64_t numTuples_<?php echo queryName($query); ?> = 0; #endif // PER_QUERY_PROFILE <?php } // foreach query ?> int64_t numTuples = 0; while( !queries.AtEndOfColumn() ) { ++numTuples; QueryIDSet qry; qry = queries.GetCurrent(); qry.Intersect(queriesToRun); queries.Advance(); <?php cgAccessAttributes($attMap); foreach ($queries as $query => $info) { $gla = $info['gla']; $input = $info['expressions']; $output = $info['output']; $glaVar = $glaVars[$query]; ?> // Do query <?php echo queryName($query); ?> : if( qry.Overlaps(<?php echo queryName($query); ?> ) ) { <?php // Declare preprocessing variables cgDeclarePreprocessing($input, 3); ?> <?php echo $glaVar; ?> ->AddItem( <?php echo implode(', ', $input); ?> ); #ifdef PER_QUERY_PROFILE numTuples_<?php echo queryName($query); ?> ++; #endif // PER_QUERY_PROFILE } // if query overlaps <?php echo queryName($query); ?> . <?php } // foreach query cgAdvanceAttributes($attMap, 2); ?> } // while not at end of input <?php // Tell GLAs that wish to know about the chunk boundary. foreach ($queries as $query => $info) { $gla = $info['gla']; $glaVar = $glaVars[$query]; if ($gla->chunk_boundary()) { ?> <?php echo $glaVar; ?> ->ChunkBoundary(); <?php } // if GLA wishes to know about chunk boundary } // foreach query ?> PROFILING2_END; PCounterList counterList; PCounter totalCnt("tpi", numTuples, "<?php echo $wpName; ?> "); counterList.Append(totalCnt); #ifdef PER_QUERY_PROFILE // Add tuple counters to list <?php foreach ($queries as $query => $info) { ?> PCounter cnt("tpi <?php echo queryName($query); ?> ", numTuples_<?php echo queryName($query); ?> , "<?php echo $wpName; ?> "); counterList.Append(cnt); <?php } //foreach query ?> #endif // PER_QUERY_PROFILE PROFILING2_SET(counterList, "<?php echo $wpName; ?> "); <?php cgPutbackColumns($attMap, 'input', $wpName); ?> // Finish bitstring iterator queries.Done(); input.SwapBitmap(queries); GLAProcessRez glaResult(glaStates, input); result.swap(glaResult); return WP_PROCESS_CHUNK; // for processchunk } //+{"kind":"WPF", "name":"Process Chunk", "action":"end"} <?php }
function SelectionGenerate($wpName, $queries, $attMap) { //echo PHP_EOL . '/*' . PHP_EOL; //print_r($wpName); //print_r($queries); //print_r($attMap); //echo PHP_EOL . '*/' . PHP_EOL; ?> // module specific headers to allow separate compilation #include "GLAData.h" #include "Errors.h" //+{"kind":"WPF", "name":"Pre-Processing", "action":"start"} extern "C" int SelectionPreProcessWorkFunc_<?php echo $wpName; ?> (WorkDescription& workDescription, ExecEngineData& result) { SelectionPreProcessWD myWork; myWork.swap(workDescription); QueryExitContainer& queries = myWork.get_whichQueryExits(); QueryToGLASContMap & requiredStates = myWork.get_requiredStates(); QueryToGLAStateMap constStates; <?php cgDeclareQueryIDs($queries); ?> <?php foreach ($queries as $query => $info) { $gf = $info['gf']; if (!is_null($gf) && $gf->has_state()) { $state = $gf->state(); if ($state->configurable()) { $carg = $info['cargs']; echo ' // JSON Configuration for query ' . queryName($query) . PHP_EOL; $carg->init(); echo PHP_EOL; } // if gf const state is configurable } // if gf has state } //foreach query ?> FOREACH_TWL(iter, queries) { <?php foreach ($queries as $query => $val) { ?> if( iter.query == <?php echo queryName($query); ?> ) { <?php if ($val['gf'] !== null) { // This is a generalized filter $gf = $val['gf']; $given_states = $val['states']; if ($gf->has_state()) { $cstArgs = []; $state = $gf->state(); // If the state is configurable, give it the JSON carg if ($state->configurable()) { $carg = $query['cargs']; $cstArgs[] = $carg->name(); } // if gf state is configurable if (\count($given_states) > 0) { ?> FATALIF(!requiredStates.IsThere(<?php echo queryName($query); ?> ), "No required states received for query that declared required states"); GLAStateContainer& givenStates = requiredStates.Find(<?php echo queryName($query); ?> ); givenStates.MoveToStart(); GLAPtr reqTemp; <?php foreach ($givenStates as $gs) { $cstArgs[] = $gs->name(); ?> // Extract state from waypoint[<?php echo $gs->waypoint(); ?> ] <?php echo $gs->type(); ?> * <?php echo $gs->name(); ?> = nullptr; reqTemp.Swap(givenStates.Current()); FATALIF( reqTemp.get_glaType() != <?php echo $gs->type()->cHash(); ?> , "Got different type than expected for required state of type <?php echo $gs > type(); ?> "); <?php echo $gs->name(); ?> = (<?php echo $gs->type(); ?> *) reqTemp.get_glaPtr(); reqTemp.swap(givenStates.Current()); givenStates.Advance(); <?php } // foreach given state } // if we have given states $cstStr = \count($cstArgs) > 0 ? '(' . implode(', ', $cstArgs) . ')' : ''; ?> <?php echo $state; ?> * temp = new <?php echo $state; echo $cstStr; ?> ; GLAPtr newPtr( <?php echo $state->cHash(); ?> , (void *) temp ); QueryID qryID = <?php echo queryName($query); ?> ; constStates.Insert(qryID, newPtr); <?php } // if gf has state } // if( $val['gf'] !== null ) ?> } // if <?php echo queryName($query); ?> is current query <?php } // foreach query ?> } END_FOREACH; SelectionPreProcessRez myRez( constStates ); myRez.swap(result); return WP_PREPROCESSING; // for PreProcess } //+{"kind":"WPF", "name":"Pre-Processing", "action":"end"} //+{"kind":"WPF", "name":"Process Chunk", "action":"start"} extern "C" int SelectionProcessChunkWorkFunc_<?php echo $wpName; ?> (WorkDescription &workDescription, ExecEngineData &result) { // go to the work description and get the input chunk SelectionProcessChunkWD myWork; myWork.swap (workDescription); Chunk &input = myWork.get_chunkToProcess (); QueryToGLAStateMap& constStates = myWork.get_constStates(); PROFILING2_START; QueryIDSet queriesToRun = QueryExitsToQueries(myWork.get_whichQueryExits ()); <?php cgDeclareQueryIDs($queries); cgAccessColumns($attMap, 'input', $wpName); // Declare the constants needed by the filters and synth expressions. foreach ($queries as $query => $val) { ?> // Constants for query <?php echo queryName($query); ?> : <?php $filters = $val['filters']; $synths = $val['synths']; cgDeclareConstants($filters); cgDeclareConstants($synths); } // foreach query ?> // prepare bitstring iterator Column inBitCol; BStringIterator queries; input.SwapBitmap (queries); // creating storage for syhthesized attributes <?php foreach ($queries as $query => $val) { $synList = $val['synths']; foreach ($synList as $att => $syn) { ?> MMappedStorage <?php echo attStorage($att); ?> ; Column <?php echo attCol($att); ?> (<?php echo attStorage($att); ?> ); <?php echo attIteratorType($att); ?> colI_<?php echo $att; ?> (<?php echo attCol($att); ?> ); <?php echo attType($att); ?> <?php echo $att; ?> ; <?php } // foreach synthesized attribute } // foreach query ?> <?php foreach ($queries as $query => $val) { $givenStates = $val['states']; $gf = $val['gf']; $cargs = $val['cargs']; grokit_assert($gf !== null || count($givenStates) == 0, 'We were given states for query ' . $query . ' when we have no GF!'); if (!is_null($gf) && $gf->has_state()) { $state = $gf->state(); $stateName = 'cst_state_' . queryName($query); $constMod = $state->mutable() ? '' : 'const '; ?> // Extracting constant state for query <?php echo queryName($query); ?> FATALIF(!constStates.IsThere(<?php echo queryName($query); ?> ), "No constant state found for query <?php echo queryName($query); ?> ."); <?php echo $constMod; echo $state; ?> * <?php echo $stateName; ?> = nullptr; { GLAState& curState = constStates.Find(<?php echo queryName($query); ?> ); GLAPtr tmp; tmp.swap(curState); FATALIF( tmp.get_glaType() != <?php echo $state->cHash(); ?> , "Got different type than expected for constant state of type <?php echo $state; ?> "); <?php echo $stateName; ?> = (<?php echo $constMod; echo $state; ?> *) tmp.get_glaPtr(); tmp.swap(curState); } <?php } // if gf requires constant state if ($gf !== null) { $ctrArgs = []; if ($gf->configurable()) { echo ' // JSON initialiser for query ' . queryName($query) . PHP_EOL; $cargs->init(); echo PHP_EOL; $ctrArgs[] = $cargs->name(); } if ($gf->has_state()) { $ctrArgs[] = '*' . $stateName; } $ctrStr = \count($ctrArgs) > 0 ? '(' . implode(', ', $ctrArgs) . ')' : ''; ?> // Construct GF for query <?php echo queryName($query); ?> <?php echo $gf->value(); ?> <?php echo queryName($query); ?> _state<?php echo $ctrStr; ?> ; <?php } // if we have a GF } // foreach query ?> MMappedStorage bitStore; Column outBitCol(bitStore); BStringIterator outQueries (outBitCol, queriesToRun); #ifdef PER_QUERY_PROFILE <?php foreach ($queries as $query => $val) { ?> int64_t n_tuples_<?php echo queryName($query); ?> = 0; <?php } // foreach query ?> #endif // PER_QUERY_PROFILE int64_t numTuples = 0; while (!queries.AtEndOfColumn ()) { ++numTuples; QueryIDSet qry; qry = queries.GetCurrent(); qry.Intersect(queriesToRun); queries.Advance(); //selection code for all the predicates <?php cgAccessAttributes($attMap); foreach ($queries as $query => $val) { $gf = $val['gf']; $filters = $val['filters']; $synths = $val['synths']; $stateName = queryName($query) . '_state'; $filterVals = array_map(function ($expr) { return '(' . $expr . ')'; }, $filters); if ($gf === null) { // Simple set of expressions. if (\count($filterVals) > 0) { $selExpr = implode(' && ', $filterVals); } else { $selExpr = 'true'; } } else { // We have a GF $selExpr = "{$stateName}.Filter(" . implode(', ', $filterVals) . ")"; } ?> // do <?php echo queryName($query); ?> : <?php foreach ($synths as $att => $syn) { ?> <?php echo attType($att); ?> <?php echo $att; ?> ; <?php } // foreach synthesized attribute ?> if( qry.Overlaps(<?php echo queryName($query); ?> ) ) { #ifdef PER_QUERY_PROFILE ++numTuples_<?php echo queryName($query); ?> ; #endif // PER_QUERY_PROFILE <?php cgDeclarePreprocessing($filters, 2); ?> if( <?php echo $selExpr; ?> ) { // compute synthesized <?php cgDeclarePreprocessing($synths, 3); foreach ($synths as $att => $expr) { ?> <?php echo $att; ?> = <?php echo $expr; ?> ; <?php } //foreach synthesized attribute ?> } else { qry.Difference(<?php echo queryName($query); ?> ); } } <?php foreach ($synths as $att => $syn) { ?> colI_<?php echo $att; ?> .Insert(<?php echo $att; ?> ); colI_<?php echo $att; ?> .Advance(); <?php } // foreach synthesized attribute } // foreach query ?> outQueries.Insert(qry); outQueries.Advance(); <?php cgAdvanceAttributes($attMap); ?> } // while we still have tuples remaining // finally, if there were any results, put the data back in the chunk <?php cgPutbackColumns($attMap, 'input', $wpName); foreach ($queries as $query => $val) { $synths = $val['synths']; ?> if (<?php echo queryName($query); ?> .Overlaps(queriesToRun)) { <?php foreach ($synths as $att => $expr) { ?> colI_<?php echo $att; ?> .Done(<?php echo attCol($att); ?> ); input.SwapColumn(<?php echo attCol($att); ?> , <?php echo attSlot($att); ?> ); <?php } //foreach synthesized attribute ?> } // If <?php echo queryName($query); ?> overlaps queriesToRun <?php } // foreach query ?> // put in the output bitmap outQueries.Done (); input.SwapBitmap (outQueries); // Finish performance counters PROFILING2_END; PCounterList counterList; PCounter totalCnt("tpi", numTuples, "<?php echo $wpName; ?> "); counterList.Append(totalCnt); PCounter tplOutCnt("tpo", numTuples, "<?php echo $wpName; ?> "); counterList.Append(tplOutCnt); #ifdef PER_QUERY_PROFILE <?php foreach ($queries as $query => $val) { $filters = $val['filters']; ?> if( <?php echo queryName($query); ?> .Overlaps(queriesToRun)) { PCounter cnt("<?php echo queryName($query); ?> ", numTuples_<?php echo queryName($query); ?> , "<?php echo $wpName; ?> "); counterList.Append(cnt); } <?php } // foreach query ?> #endif // PER_QUERY_PROFILE PROFILING2_SET(counterList, "<?php echo $wpName; ?> "); ChunkContainer tempResult (input); tempResult.swap (result); return WP_PROCESS_CHUNK; // For Process Chunk } //+{"kind":"WPF", "name":"Process Chunk", "action":"end"} <?php }