-/* ------------------------------------------------
-Copyright 2014 AT&T Intellectual Property
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ------------------------------------------- */
-
-#include <string>
-#include <stdio.h>
-#include <stdlib.h>
-//#include <algo.h>
-#include<algorithm>
-
-#include "parse_fta.h"
-#include "parse_schema.h"
-#include "analyze_fta.h"
-#include "generate_utils.h"
-#include "query_plan.h"
-#include "generate_lfta_code.h"
-#include "generate_nic_code.h"
-
-using namespace std;
-
-extern int DEFAULT_LFTA_HASH_TABLE_SIZE;
-
-// default value for correlation between the interface card and
-// the system clock
-#define DEFAULT_TIME_CORR 16
-
-
-// For fast hashing
-//#define NRANDS 100
-extern string hash_nums[NRANDS];
-/*
-= {
-"12916008961267169387ull", "13447227858232756685ull",
-"15651770379918602919ull", "1154671861688431608ull",
-"6777078091984849858ull", "14217205709582564356ull",
-"4955408621820609982ull", "15813680319165523695ull",
-"9897969721407807129ull", "5799700135519793083ull",
-"3446529189623437397ull", "2766403683465910630ull",
-"3759321430908793328ull", "6569396511892890354ull",
-"11124853911180290924ull", "17425412145238035549ull",
-"6879931585355039943ull", "16598635011539670441ull",
-"9615975578494811651ull", "4378135509538422740ull",
-"741282195344332574ull", "17368612862906255584ull",
-"17294299200556814618ull", "518343398779663051ull",
-"3861893449302272757ull", "8951107288843549591ull",
-"15785139392894559409ull", "5917810836789601602ull",
-"16169988133001117004ull", "9792861259254509262ull",
-"5089058010244872136ull", "2130075224835397689ull",
-"844136788226150435ull", "1303298091153875333ull",
-"3579898206894361183ull", "7529542662845336496ull",
-"13151949992653382522ull", "2145333536541545660ull",
-"11258221828939586934ull", "3741808146124570279ull",
-"16272841626371307089ull", "12174572036188391283ull",
-"9749343496254107661ull", "9141275584134508830ull",
-"10134192232065698216ull", "12944268412561423018ull",
-"17499725811865666340ull", "5281482378159088661ull",
-"13254803486023572607ull", "4526762838498717025ull",
-"15990846379668494011ull", "10680949816169027468ull",
-"7116154096012931030ull", "5296740689865236632ull",
-"5222427027515795922ull", "6893215299448261251ull",
-"10164707755932877485ull", "15325979189512082255ull",
-"3713267224148573289ull", "12292682741753167354ull",
-"4098115959960163588ull", "16095675565885113990ull",
-"11391590846210510720ull", "8432889531466002673ull",
-"7146668520368482523ull", "7678169991822407997ull",
-"9882712513525031447ull", "13904414563513869160ull",
-"1080076724395768626ull", "8448147843172150388ull",
-"17633093729608185134ull", "10044622457050142303ull",
-"4128911859292425737ull", "30642269109444395ull",
-"16124215396922640581ull", "15444089895060081110ull",
-"16437006538696302944ull", "800338649777443426ull",
-"5355794945275091932ull", "11656354278827687117ull",
-"1110873718944691255ull", "10829576045617693977ull",
-"3846916616884579955ull", "17055821716837625668ull",
-"13418968402643535758ull", "11671612594828802128ull",
-"11597298928184328586ull", "13196028510862205499ull",
-"16539578557089782373ull", "3182048322921507591ull",
-"10016080431267550241ull", "148751875162592690ull",
-"10400930266590768572ull", "4023803397139127870ull",
-"17766462746879108920ull", "14807761432134600873ull",
-"13521540421053792403ull", "13980983198941385205ull",
-"16257584414193564367ull", "1760484796451765024ull"
-};
-*/
-
-
-// ----------------------------------------------
-// Data extracted from the query plan node
-// for use by code generation.
-
-static cplx_lit_table *complex_literals; //Table of literals with constructors.
-static vector<handle_param_tbl_entry *> param_handle_table;
-static param_table *param_tbl; // Table of all referenced parameters.
-
-static vector<scalarexp_t *> sl_list;
-static vector<cnf_elem *> where;
-
-static gb_table *gb_tbl; // Table of all group-by attributes.
-static aggregate_table *aggr_tbl; // Table of all referenced aggregates.
-
-static bool packed_return; // unpack using structyure, not fcns
-static nic_property *nicprop; // nic properties for this interface.
-static int global_id;
-
-
-// The partial_fcns vector can now refer to
-// partial functions, or expensive functions
-// which can be cached (if there are multiple refs). A couple
-// of int vectors distinguish the cases.
-static vector<scalarexp_t *> partial_fcns;
-static vector<int> fcn_ref_cnt;
-static vector<bool> is_partial_fcn;
-int sl_fcns_start = 0, sl_fcns_end = 0;
-int wh_fcns_start = 0, wh_fcns_end = 0;
-int gb_fcns_start = 0, gb_fcns_end = 0;
-int ag_fcns_start = 0, ag_fcns_end = 0;
-
-
-// These vectors are for combinable predicates.
-static vector<int> pred_class; // identifies the group
-static vector<int> pred_pos; // position in the group.
-
-
-
-static char tmpstr[1000];
-
-//////////////////////////////////////////////////////////////////////
-/// Various utilities
-
-string generate_fta_name(string node_name){
- string ret = normalize_name(node_name);
- if(ret == ""){
- ret = "default";
- }
- ret += "_fta";
-
- return(ret);
-}
-
-
-string generate_aggr_struct_name(string node_name){
- string ret = normalize_name(node_name);
- if(ret == ""){
- ret = "default";
- }
- ret += "_aggr_struct";
-
- return(ret);
-}
-
-string generate_fj_struct_name(string node_name){
- string ret = normalize_name(node_name);
- if(ret == ""){
- ret = "default";
- }
- ret += "_fj_struct";
-
- return(ret);
-}
-
-string generate_unpack_code(int tblref, int schref, string field, table_list *schema, string node_name, string end_goto = string("end")){
- string ret;
- if(! packed_return){
- sprintf(tmpstr,"\tretval = %s(p, &unpack_var_%s_%d);\n",
- schema->get_fcn(schref,field).c_str(), field.c_str(), tblref);
- ret += tmpstr;
- if(!schema->get_modifier_list(schref,field)->contains_key("required"))
- ret += "\tif(retval) goto "+end_goto+";\n";
-
- }else{
-// TODO: ntoh xforms (aug 2010 : removing ntoh, hton)
- data_type dt(schema->get_type_name(schref,field), schema->get_modifier_list(schref,field));
- if(dt.is_buffer_type()){
- if(dt.get_type() != v_str_t){
- ret += "\tif(sizeof(struct "+node_name+"_input_struct)+"+node_name+"_input_struct_var->unpack_var_"+field+".length+int("+node_name+"_input_struct_var->unpack_var_"+field+".data) > sz)\n";
- ret += "\t\tgoto "+end_goto+";\n";
- ret+= "\t\t"+node_name+"_input_struct_var->unpack_var_"+field+".data += "+node_name+"_input_struct_var->unpack_var_"+field+".length;\n";
- ret += "\tunpack_var_"+field+"_"+int_to_string(tblref)+
- " = "+node_name+"_input_struct_var->unpack_var_"+field+";+\n";
- }else{
- fprintf(stderr,"INTERNAL ERROR buffer type not string type in generate_lfta_code.cc:generate_unpack_code\n");
- exit(1);
- }
- }else{
- ret += "\tunpack_var_"+field+"_"+int_to_string(tblref)+
- " = "+node_name+"_input_struct_var->unpack_var_"+field+";\n";
- }
- }
- return ret;
-}
-
-string generate_aggr_struct(string node_name, gb_table *gb_tbl, aggregate_table *aggr_tbl){
- string ret = "struct " + generate_aggr_struct_name(node_name) + "{\n";
-
- int g;
- for(g=0;g<gb_tbl->size();g++){
- sprintf(tmpstr,"gb_var%d",g);
- ret += "\t"+gb_tbl->get_data_type(g)->make_cvar(tmpstr)+";\n";
- }
-
- int a;
- for(a=0;a<aggr_tbl->size();a++){
- ret += "\t";
- sprintf(tmpstr,"aggr_var%d",a);
- if(aggr_tbl->is_builtin(a))
- ret+="\t"+aggr_tbl->get_data_type(a)->make_cvar(tmpstr)+";\n";
- else
- ret+="\t"+aggr_tbl->get_storage_type(a)->make_cvar(tmpstr)+";\n";
- }
-
-/*
- ret += "\tstruct "+generate_aggr_struct_name(node_name)+" *next;\n";
-*/
-
- ret += "};\n\n";
-
- return(ret);
-}
-
-
-string generate_fj_struct(filter_join_qpn *fs, string node_name ){
- string ret;
-
- if(fs->use_bloom == false){ // uses hash table instead
- ret = "struct " + generate_fj_struct_name(node_name) + "{\n";
- int k;
- for(k=0;k<fs->hash_eq.size();++k){
- sprintf(tmpstr,"key_var%d",k);
- ret += "\t"+fs->hash_eq[k]->pr->get_left_se()->get_data_type()->make_cvar(tmpstr)+";\n";
- }
- ret += "\tlong long int ts;\n";
- ret += "};\n\n";
- }
-
- return(ret);
-}
-
-
-
-
-string generate_fta_struct(string node_name, gb_table *gb_tbl,
- aggregate_table *aggr_tbl, param_table *param_tbl,
- cplx_lit_table *complex_literals,
- vector<handle_param_tbl_entry *> ¶m_handle_table,
- bool is_aggr_query, bool is_fj, bool uses_bloom,
- table_list *schema){
-
- string ret = "struct " + generate_fta_name(node_name) + "{\n";
- ret += "\tstruct FTA f;\n";
-
-//-------------------------------------------------------------
-// Aggregate-specific fields
-
- if(is_aggr_query){
-/*
- ret += "\tstruct "+generate_aggr_struct_name(node_name)+" *aggr_head, *flush_head;\n";
-*/
- ret+="\tstruct "+generate_aggr_struct_name(node_name)+" *aggr_table; // the groups\n";
- ret+="\tgs_uint32_t *aggr_table_hashmap; // hash val, plus control info.\n";
-// ret+="\tint bitmap_size;\n";
- ret += "\tint n_aggrs; // # of non-empty slots in aggr_table\n";
- ret += "\tint max_aggrs; // size of aggr_table and its hashmap.\n";
- ret += "\tint max_windows; // max number of open windows.\n";
- ret += "\tunsigned int generation; // initially zero, increment on\n";
- ret += "\t // every hash table flush - whether regular or induced.\n";
- ret += "\t // Old groups are identified by a generation mismatch.\n";
- ret += "\tunsigned int flush_pos; // next aggr_table entry to examine\n";
- ret += "\tunsigned int flush_ctr; // control slow flushing\n";
-
-
-
- int g;
- bool uses_temporal_flush = false;
- for(g=0;g<gb_tbl->size();g++){
- data_type *dt = gb_tbl->get_data_type(g);
- if(dt->is_temporal()){
-/*
- fprintf(stderr,"group by attribute %s is temporal, ",
- gb_tbl->get_name(g).c_str());
- if(dt->is_increasing()){
- fprintf(stderr,"increasing.\n");
- }else{
- fprintf(stderr,"decreasing.\n");
- }
-*/
- data_type *gdt = gb_tbl->get_data_type(g);
- if(gdt->is_buffer_type()){
- fprintf(stderr, "\t but temporal BUFFER types are not supported, skipping.\n");
- }else{
- sprintf(tmpstr,"\t%s last_gb_%d;\n",gdt->get_cvar_type().c_str(),g);
- ret += tmpstr;
- sprintf(tmpstr,"\t%s flush_start_gb_%d;\n",gdt->get_cvar_type().c_str(),g);
- ret += tmpstr;
- sprintf(tmpstr,"\t%s last_flushed_gb_%d;\n",gdt->get_cvar_type().c_str(),g);
- ret += tmpstr;
- uses_temporal_flush = true;
- }
-
- }
-
- }
- if(! uses_temporal_flush){
- fprintf(stderr,"Warning: no temporal flush.\n");
- }
- }
-
-// ---------------------------------------------------------
-// Filter-join specific fields
-
- if(is_fj){
- if(uses_bloom){
- ret +=
-"\tunsigned char * bf_table; //array of bloom filters with layout \n"
-"\t\t// bit 0 bf 0| bit 0 bf 1| bit 0 bf 2| bit 1 bf 0| bit 1 bf 1|.....\n"
-"\tint first_exec;\n"
-"\tlong long int last_bin;\n"
-"\tint last_bloom_pos;\n"
-"\n"
-;
- }else{ // limited hash table
- ret +=
-" struct "+generate_fj_struct_name(node_name)+" *join_table;\n"
-"\n"
-;
- }
-
- }
-
-//--------------------------------------------------------
-// Common fields
-
-// Create places to hold the parameters.
- int p;
- vector<string> param_vec = param_tbl->get_param_names();
- for(p=0;p<param_vec.size();p++){
- data_type *dt = param_tbl->get_data_type(param_vec[p]);
- sprintf(tmpstr,"\t%s param_%s;\n",dt->get_cvar_type().c_str(),
- param_vec[p].c_str());
- ret += tmpstr;
- if(param_tbl->handle_access(param_vec[p])){
- ret += "\tstruct search_handle *param_handle_"+param_vec[p]+";\n";
- }
- }
-
-// Create places to hold complex literals.
- int cl;
- for(cl=0;cl<complex_literals->size();cl++){
- literal_t *l = complex_literals->get_literal(cl);
- data_type *dtl = new data_type( l->get_type() );
- sprintf(tmpstr,"\t%s complex_literal_%d;\n",dtl->get_cvar_type().c_str(),cl);
- ret += tmpstr;
- }
-
-// Create places to hold the pass-by-handle parameters.
- for(p=0;p<param_handle_table.size();++p){
- sprintf(tmpstr,"\tgs_param_handle_t handle_param_%d;\n",p);
- ret += tmpstr;
- }
-
-// Create places to hold the last values of temporal
-// attributes referenced in select clause
-// we also need to store values of the temoral attributed
-// of last flushed tuple in aggr queries
-// to make sure we generate the cirrect temporal tuple
-// in the presense of slow flushes
-
-
- col_id_set temp_cids; // col ids of temp attributes in select clause
-
- int s;
- col_id_set::iterator csi;
-
- for(s=0;s<sl_list.size();s++){
- data_type *sdt = sl_list[s]->get_data_type();
- if (sdt->is_temporal()) {
- gather_se_col_ids(sl_list[s],temp_cids, gb_tbl);
- }
- }
-
- for(csi=temp_cids.begin(); csi != temp_cids.end();++csi){
- int tblref = (*csi).tblvar_ref;
- int schref = (*csi).schema_ref;
- string field = (*csi).field;
- data_type dt(schema->get_type_name(schref,field), schema->get_modifier_list(schref,field));
- sprintf(tmpstr,"\t%s last_%s_%d;\n", dt.get_cvar_type().c_str(), field.c_str(), tblref);
- ret += tmpstr;
- }
-
- ret += "\tgs_uint64_t trace_id;\n\n";
-
-// Fields to store the runtime stats
-
- ret += "\tgs_uint32_t in_tuple_cnt;\n";
- ret += "\tgs_uint32_t out_tuple_cnt;\n";
- ret += "\tgs_uint32_t out_tuple_sz;\n";
- ret += "\tgs_uint32_t accepted_tuple_cnt;\n";
- ret += "\tgs_uint64_t cycle_cnt;\n";
- ret += "\tgs_uint32_t collision_cnt;\n";
- ret += "\tgs_uint32_t eviction_cnt;\n";
- ret += "\tgs_float_t sampling_rate;\n";
-
-
-
- ret += "};\n\n";
-
- return(ret);
-}
-
-//------------------------------------------------------------
-// Set colref tblvars to 0..
-// (special processing for join-like operators in an lfta).
-
-void reset_se_col_ids_tblvars(scalarexp_t *se, gb_table *gtbl){
- vector<scalarexp_t *> operands;
- int o;
-
- if(! se)
- return;
-
- switch(se->get_operator_type()){
- case SE_LITERAL:
- case SE_PARAM:
- case SE_IFACE_PARAM:
- return;
- case SE_UNARY_OP:
- reset_se_col_ids_tblvars(se->get_left_se(),gtbl);
- return;
- case SE_BINARY_OP:
- reset_se_col_ids_tblvars(se->get_left_se(),gtbl);
- reset_se_col_ids_tblvars(se->get_right_se(),gtbl);
- return;
- case SE_COLREF:
- if(! se->is_gb() ){
- se->get_colref()->set_tablevar_ref(0);
- }else{
- if(gtbl==NULL){
- fprintf(stderr,"INTERNAL ERROR: gbvar ref in gather_se_col_ids, but gtbl is NULL.\n");
- exit(1);
- }
- reset_se_col_ids_tblvars(gtbl->get_def(se->get_gb_ref()),gtbl);
- }
- return;
- case SE_AGGR_STAR:
- return;
- case SE_AGGR_SE:
- reset_se_col_ids_tblvars(se->get_left_se(),gtbl);
- return;
- case SE_FUNC:
- operands = se->get_operands();
- for(o=0;o<operands.size();o++){
- reset_se_col_ids_tblvars(operands[o], gtbl);
- }
- return;
- default:
- fprintf(stderr,"INTERNAL ERROR in reset_se_col_ids_tblvars, line %d, character %d: unknown operator type %d\n",
- se->get_lineno(), se->get_charno(),se->get_operator_type());
- exit(1);
- }
-}
-
-
-// reset column tblvars accessed in this pr.
-
-void reset_pr_col_ids_tblvars(predicate_t *pr, gb_table *gtbl){
- vector<scalarexp_t *> op_list;
- int o;
-
- switch(pr->get_operator_type()){
- case PRED_IN:
- reset_se_col_ids_tblvars(pr->get_left_se(), gtbl);
- return;
- case PRED_COMPARE:
- reset_se_col_ids_tblvars(pr->get_left_se(),gtbl) ;
- reset_se_col_ids_tblvars(pr->get_right_se(),gtbl) ;
- return;
- case PRED_UNARY_OP:
- reset_pr_col_ids_tblvars(pr->get_left_pr(),gtbl) ;
- return;
- case PRED_BINARY_OP:
- reset_pr_col_ids_tblvars(pr->get_left_pr(),gtbl) ;
- reset_pr_col_ids_tblvars(pr->get_right_pr(),gtbl) ;
- return;
- case PRED_FUNC:
- op_list = pr->get_op_list();
- for(o=0;o<op_list.size();++o){
- reset_se_col_ids_tblvars(op_list[o],gtbl) ;
- }
- return;
- default:
- fprintf(stderr,"INTERNAL ERROR in reset_pr_col_ids_tblvars, line %d, character %d, unknown predicate operator type %d\n",
- pr->get_lineno(), pr->get_charno(), pr->get_operator_type() );
- }
-}
-
-
-
-
-// Generate code that makes reference
-// to the tuple, and not to any aggregates.
-static string generate_se_code(scalarexp_t *se,table_list *schema){
- string ret;
- data_type *ldt, *rdt;
- int o;
- vector<scalarexp_t *> operands;
-
-
- switch(se->get_operator_type()){
- case SE_LITERAL:
- if(se->is_handle_ref()){
- sprintf(tmpstr,"t->handle_param_%d",se->get_handle_ref() );
- ret = tmpstr;
- return(ret);
- }
- if(se->get_literal()->is_cpx_lit()){
- sprintf(tmpstr,"t->complex_literal_%d",se->get_literal()->get_cpx_lit_ref() );
- ret = tmpstr;
- return(ret);
- }
- return(se->get_literal()->to_C_code("")); // not complex, no constructor
- case SE_PARAM:
- if(se->is_handle_ref()){
- sprintf(tmpstr,"t->handle_param_%d",se->get_handle_ref() );
- ret = tmpstr;
- return(ret);
- }
- ret += "t->param_";
- ret += se->get_param_name();
- return(ret);
- case SE_UNARY_OP:
- ldt = se->get_left_se()->get_data_type();
- if(ldt->complex_operator(se->get_op()) ){
- ret += ldt->get_complex_operator(se->get_op());
- ret += "(";
- ret += generate_se_code(se->get_left_se(),schema);
- ret += ")";
- }else{
- ret += "(";
- ret += se->get_op();
- ret += generate_se_code(se->get_left_se(),schema);
- ret += ")";
- }
- return(ret);
- case SE_BINARY_OP:
- ldt = se->get_left_se()->get_data_type();
- rdt = se->get_right_se()->get_data_type();
-
- if(ldt->complex_operator(rdt, se->get_op()) ){
- ret += ldt->get_complex_operator(rdt, se->get_op());
- ret += "(";
- ret += generate_se_code(se->get_left_se(),schema);
- ret += ", ";
- ret += generate_se_code(se->get_right_se(),schema);
- ret += ")";
- }else{
- ret += "(";
- ret += generate_se_code(se->get_left_se(),schema);
- ret += se->get_op();
- ret += generate_se_code(se->get_right_se(),schema);
- ret += ")";
- }
- return(ret);
- case SE_COLREF:
- if(se->is_gb()){ // OK to ref gb attrs, but they're not yet unpacked ...
- // so return the defining code.
- ret = generate_se_code(gb_tbl->get_def(se->get_gb_ref()), schema );
-
- }else{
- sprintf(tmpstr,"unpack_var_%s_%d",
- se->get_colref()->get_field().c_str(), se->get_colref()->get_tablevar_ref() );
- ret = tmpstr;
- }
- return(ret);
- case SE_FUNC:
-// Should not be ref'ing any aggr here.
- if(se->get_aggr_ref() >= 0){
- fprintf(stderr,"INTERNAL ERROR, UDAF reference in generate_se_code.\n");
- return("ERROR in generate_se_code");
- }
-
- if(se->is_partial()){
- sprintf(tmpstr,"partial_fcn_result_%d",se->get_partial_ref());
- ret = tmpstr;
- }else{
- ret += se->op + "(";
- operands = se->get_operands();
- for(o=0;o<operands.size();o++){
- if(o>0) ret += ", ";
- if(operands[o]->get_data_type()->is_buffer_type() && (! (operands[o]->is_handle_ref()) ) )
- ret += "&";
- ret += generate_se_code(operands[o], schema);
- }
- ret += ")";
- }
- return(ret);
- default:
- fprintf(stderr,"INTERNAL ERROR in generate_se_code (lfta), line %d, character %d: unknown operator type %d\n",
- se->get_lineno(), se->get_charno(),se->get_operator_type());
- return("ERROR in generate_se_code");
- }
-}
-
-// generate code that refers only to aggregate data and constants.
-static string generate_se_code_fm_aggr(scalarexp_t *se, string var, table_list *schema){
-
- string ret;
- data_type *ldt, *rdt;
- int o;
- vector<scalarexp_t *> operands;
-
-
- switch(se->get_operator_type()){
- case SE_LITERAL:
- if(se->is_handle_ref()){
- sprintf(tmpstr,"t->handle_param_%d",se->get_handle_ref() );
- ret = tmpstr;
- return(ret);
- }
- if(se->get_literal()->is_cpx_lit()){
- sprintf(tmpstr,"t->complex_literal_%d",se->get_literal()->get_cpx_lit_ref() );
- ret = tmpstr;
- return(ret);
- }
- return(se->get_literal()->to_C_code("")); // not complex no constructor
- case SE_PARAM:
- if(se->is_handle_ref()){
- sprintf(tmpstr,"t->handle_param_%d",se->get_handle_ref() );
- ret = tmpstr;
- return(ret);
- }
- ret += "t->param_";
- ret += se->get_param_name();
- return(ret);
- case SE_UNARY_OP:
- ldt = se->get_left_se()->get_data_type();
- if(ldt->complex_operator(se->get_op()) ){
- ret += ldt->get_complex_operator(se->get_op());
- ret += "(";
- ret += generate_se_code_fm_aggr(se->get_left_se(),var,schema);
- ret += ")";
- }else{
- ret += "(";
- ret += se->get_op();
- ret += generate_se_code_fm_aggr(se->get_left_se(),var,schema);
- ret += ")";
- }
- return(ret);
- case SE_BINARY_OP:
- ldt = se->get_left_se()->get_data_type();
- rdt = se->get_right_se()->get_data_type();
-
- if(ldt->complex_operator(rdt, se->get_op()) ){
- ret += ldt->get_complex_operator(rdt, se->get_op());
- ret += "(";
- ret += generate_se_code_fm_aggr(se->get_left_se(),var,schema);
- ret += ", ";
- ret += generate_se_code_fm_aggr(se->get_right_se(),var,schema);
- ret += ")";
- }else{
- ret += "(";
- ret += generate_se_code_fm_aggr(se->get_left_se(),var,schema);
- ret += se->get_op();
- ret += generate_se_code_fm_aggr(se->get_right_se(),var,schema);
- ret += ")";
- }
- return(ret);
- case SE_COLREF:
- if(se->is_gb()){ // OK to ref gb attrs, but they're not yet
- // unpacked ... so return the defining code.
- sprintf(tmpstr,"%sgb_var%d",var.c_str(),se->get_gb_ref());
- ret = tmpstr;
-
- }else{
- fprintf(stderr,"ERROR reference to non-GB column ref not permitted here,"
- "error in generate_se_code_fm_aggr, line %d, character %d.\n",
- se->get_lineno(), se->get_charno());
- ret = tmpstr;
- }
- return(ret);
- case SE_AGGR_STAR:
- case SE_AGGR_SE:
- sprintf(tmpstr,"%saggr_var%d",var.c_str(),se->get_aggr_ref());
- ret = tmpstr;
- return(ret);
- case SE_FUNC:
-// Is it a UDAF?
- if(se->get_aggr_ref() >= 0){
- sprintf(tmpstr,"udaf_ret%d",se->get_aggr_ref());
- ret = tmpstr;
- return(ret);
- }
-
- if(se->is_partial()){
- sprintf(tmpstr,"partial_fcn_result_%d",se->get_partial_ref());
- ret = tmpstr;
- }else{
- ret += se->op + "(";
- operands = se->get_operands();
- for(o=0;o<operands.size();o++){
- if(o>0) ret += ", ";
- if(operands[o]->get_data_type()->is_buffer_type() && (! (operands[o]->is_handle_ref()) ) )
- ret += "&";
- ret += generate_se_code_fm_aggr(operands[o], var, schema);
- }
- ret += ")";
- }
- return(ret);
- default:
- fprintf(stderr,"INTERNAL ERROR in generate_lfta_code.cc::generate_se_code_fm_aggr, line %d, character %d: unknown operator type %d\n",
- se->get_lineno(), se->get_charno(),se->get_operator_type());
- return("ERROR in generate_se_code");
- }
-
-}
-
-
-static string unpack_partial_fcn_fm_aggr(scalarexp_t *se, int pfn_id, string var, table_list *schema){
- string ret;
- int o;
- vector<scalarexp_t *> operands;
-
-
- if(se->get_operator_type() != SE_FUNC || se->get_aggr_ref() >= 0){
- fprintf(stderr,"INTERNAL ERROR, non-function SE passed to unpack_partial_fcn_fm_aggr. line %d, character %d\n",
- se->get_lineno(), se->get_charno());
- return("ERROR in generate_se_code");
- }
-
- ret = "\tretval = " + se->get_op() + "( ";
- sprintf(tmpstr, "&partial_fcn_result_%d",pfn_id);
- ret += tmpstr;
-
- operands = se->get_operands();
- for(o=0;o<operands.size();o++){
- ret += ", ";
- if(operands[o]->get_data_type()->is_buffer_type() && (! (operands[o]->is_handle_ref()) ) )
- ret += "&";
- ret += generate_se_code_fm_aggr(operands[o], var, schema);
- }
- ret += ");\n";
-
- return(ret);
-}
-
-static string generate_cached_fcn(scalarexp_t *se, table_list *schema){
- string ret;
- int o;
- vector<scalarexp_t *> operands;
-
- if(se->get_operator_type() != SE_FUNC || se->get_aggr_ref() >= 0){
- fprintf(stderr,"INTERNAL ERROR, non-function SE passed to generate_cached_fcn. line %d, character %d\n",
- se->get_lineno(), se->get_charno());
- return("ERROR in generate_se_code");
- }
-
- ret = se->get_op() + "( ";
-
- operands = se->get_operands();
- for(o=0;o<operands.size();o++){
- if(o) ret += ", ";
- if(operands[o]->get_data_type()->is_buffer_type() && (! (operands[o]->is_handle_ref()) ) )
- ret += "&";
- ret += generate_se_code(operands[o], schema);
- }
- ret += ");\n";
-
- return(ret);
-}
-
-
-
-static string unpack_partial_fcn(scalarexp_t *se, int pfn_id, table_list *schema){
- string ret;
- int o;
- vector<scalarexp_t *> operands;
-
-
- if(se->get_operator_type() != SE_FUNC || se->get_aggr_ref() >= 0){
- fprintf(stderr,"INTERNAL ERROR, non-function SE passed to unpack_partial_fcn. line %d, character %d\n",
- se->get_lineno(), se->get_charno());
- return("ERROR in generate_se_code");
- }
-
- ret = "\tretval = " + se->get_op() + "( ",
- sprintf(tmpstr, "&partial_fcn_result_%d",pfn_id);
- ret += tmpstr;
-
- operands = se->get_operands();
- for(o=0;o<operands.size();o++){
- ret += ", ";
- if(operands[o]->get_data_type()->is_buffer_type() && (! (operands[o]->is_handle_ref()) ) )
- ret += "&";
- ret += generate_se_code(operands[o], schema);
- }
- ret += ");\n";
-
- return(ret);
-}
-
-
-
-
-
-static string generate_C_comparison_op(string op){
- if(op == "=") return("==");
- if(op == "<>") return("!=");
- return(op);
-}
-
-static string generate_C_boolean_op(string op){
- if( (op == "AND") || (op == "And") || (op == "and") ){
- return("&&");
- }
- if( (op == "OR") || (op == "Or") || (op == "or") ){
- return("||");
- }
- if( (op == "NOT") || (op == "Not") || (op == "not") ){
- return("!");
- }
-
- fprintf(stderr,"INTERNAL ERROR: unknown boolean operator %s\n",op.c_str());
- return("ERROR UNKNOWN BOOLEAN OPERATOR :"+op);
-}
-
-
-static string generate_predicate_code(predicate_t *pr,table_list *schema){
- string ret;
- vector<literal_t *> litv;
- int i;
- data_type *ldt, *rdt;
- vector<scalarexp_t *> op_list;
- int o,cref,ppos;
- unsigned int bitmask;
-
- switch(pr->get_operator_type()){
- case PRED_IN:
- ldt = pr->get_left_se()->get_data_type();
-
- ret += "( ";
- litv = pr->get_lit_vec();
- for(i=0;i<litv.size();i++){
- if(i>0) ret += " || ";
- ret += "( ";
-
- if(ldt->complex_comparison(ldt) ){
- ret += ldt->get_comparison_fcn(ldt) ;
- ret += "( ";
- if(ldt->is_buffer_type() ) ret += "&";
- ret += generate_se_code(pr->get_left_se(), schema);
- ret += ", ";
- if(ldt->is_buffer_type() ) ret += "&";
- if(litv[i]->is_cpx_lit()){
- sprintf(tmpstr,"t->complex_literal_%d",litv[i]->get_cpx_lit_ref() );
- ret += tmpstr;
- }else{
- ret += litv[i]->to_C_code("");
- }
- ret += ") == 0";
- }else{
- ret += generate_se_code(pr->get_left_se(), schema);
- ret += " == ";
- ret += litv[i]->to_C_code("");
- }
-
- ret += " )";
- }
- ret += " )";
- return(ret);
-
- case PRED_COMPARE:
- ldt = pr->get_left_se()->get_data_type();
- rdt = pr->get_right_se()->get_data_type();
-
- ret += "( ";
- if(ldt->complex_comparison(rdt) ){
- ret += ldt->get_comparison_fcn(rdt);
- ret += "(";
- if(ldt->is_buffer_type() ) ret += "&";
- ret += generate_se_code(pr->get_left_se(),schema);
- ret += ", ";
- if(rdt->is_buffer_type() ) ret += "&";
- ret += generate_se_code(pr->get_right_se(),schema);
- ret += ") ";
- ret += generate_C_comparison_op(pr->get_op());
- ret += "0";
- }else{
- ret += generate_se_code(pr->get_left_se(),schema);
- ret += generate_C_comparison_op(pr->get_op());
- ret += generate_se_code(pr->get_right_se(),schema);
- }
- ret += " )";
- return(ret);
- case PRED_UNARY_OP:
- ret += "( ";
- ret += generate_C_boolean_op(pr->get_op());
- ret += generate_predicate_code(pr->get_left_pr(),schema);
- ret += " )";
- return(ret);
- case PRED_BINARY_OP:
- ret += "( ";
- ret += generate_predicate_code(pr->get_left_pr(),schema);
- ret += generate_C_boolean_op(pr->get_op());
- ret += generate_predicate_code(pr->get_right_pr(),schema);
- ret += " )";
- return(ret);
- case PRED_FUNC:
- op_list = pr->get_op_list();
- cref = pr->get_combinable_ref();
- if(cref >= 0){ // predicate is a combinable pred reference
- // Trust, but verify
- if(pred_class.size() >= cref && pred_class[cref] >= 0){
- ppos = pred_pos[cref];
- bitmask = 1 << ppos % 32;
- sprintf(tmpstr,"(pref_common_pred_val_%d_%d & %u)",pred_class[cref],ppos/32,bitmask);
- ret = tmpstr;
- return ret;
- }
- }
-
- ret = pr->get_op() + "(";
- if (pr->is_sampling_fcn) {
- ret += "t->sampling_rate";
- if (!op_list.empty())
- ret += ", ";
- }
- for(o=0;o<op_list.size();++o){
- if(o>0) ret += ", ";
- if(op_list[o]->get_data_type()->is_buffer_type() && (! (op_list[o]->is_handle_ref()) ) )
- ret += "&";
- ret += generate_se_code(op_list[o],schema);
- }
- ret += " )";
- return(ret);
- default:
- fprintf(stderr,"INTERNAL ERROR in generate_predicate_code, line %d, character %d, unknown predicate operator type %d\n",
- pr->get_lineno(), pr->get_charno(), pr->get_operator_type() );
- return("ERROR in generate_predicate_code");
- }
-}
-
-
-static string generate_equality_test(string &lhs_op, string &rhs_op, data_type *dt){
- string ret;
-
- if(dt->complex_comparison(dt) ){
- ret += dt->get_comparison_fcn(dt);
- ret += "(";
- if(dt->is_buffer_type() ) ret += "&";
- ret += lhs_op;
- ret += ", ";
- if(dt->is_buffer_type() ) ret += "&";
- ret += rhs_op;
- ret += ") == 0";
- }else{
- ret += lhs_op;
- ret += " == ";
- ret += rhs_op;
- }
-
- return(ret);
-}
-
-static string generate_comparison(string &lhs_op, string &rhs_op, data_type *dt){
- string ret;
-
- if(dt->complex_comparison(dt) ){
- ret += dt->get_comparison_fcn(dt);
- ret += "(";
- if(dt->is_buffer_type() ) ret += "&";
- ret += lhs_op;
- ret += ", ";
- if(dt->is_buffer_type() ) ret += "&";
- ret += rhs_op;
- ret += ") == 0";
- }else{
- ret += lhs_op;
- ret += " == ";
- ret += rhs_op;
- }
-
- return(ret);
-}
-
-// Here I assume that only MIN and MAX aggregates can be computed
-// over BUFFER data types.
-
-static string generate_aggr_update(string var, aggregate_table *atbl,int aidx, table_list *schema){
- string retval = "\t\t";
- string op = atbl->get_op(aidx);
-
-// Is it a UDAF
- if(! atbl->is_builtin(aidx)) {
- int o;
- retval += op+"_LFTA_AGGR_UPDATE_(";
- if(atbl->get_storage_type(aidx)->get_type() != fstring_t) retval+="&";
- retval+="("+var+")";
- vector<scalarexp_t *> opl = atbl->get_operand_list(aidx);
- for(o=0;o<opl.size();++o){
- retval += ",";
- if(opl[o]->get_data_type()->is_buffer_type() && (! (opl[o]->is_handle_ref()) ) )
- retval.append("&");
- retval += generate_se_code(opl[o], schema);
- }
- retval += ");\n";
-
- return retval;
- }
-
-// Built-in aggregate processing.
-
- data_type *dt = atbl->get_data_type(aidx);
-
- if(op == "COUNT"){
- retval.append(var);
- retval.append("++;\n");
- return(retval);
- }
- if(op == "SUM"){
- retval.append(var);
- retval.append(" += ");
- retval.append(generate_se_code(atbl->get_aggr_se(aidx), schema) );
- retval.append(";\n");
- return(retval);
- }
- if(op == "MIN"){
- sprintf(tmpstr,"aggr_tmp_%d = %s;\n",aidx,generate_se_code(atbl->get_aggr_se(aidx), schema ).c_str() );
- retval.append(tmpstr);
- if(dt->complex_comparison(dt)){
- if(dt->is_buffer_type())
- sprintf(tmpstr,"\t\tif(%s(&aggr_tmp_%d,&(%s)) < 0)\n",dt->get_comparison_fcn(dt).c_str(), aidx, var.c_str());
- else
- sprintf(tmpstr,"\t\tif(%s(aggr_tmp_%d,%s) < 0)\n",dt->get_comparison_fcn(dt).c_str(), aidx, var.c_str());
- }else{
- sprintf(tmpstr,"\t\tif(aggr_tmp_%d < %s)\n",aidx,var.c_str());
- }
- retval.append(tmpstr);
- if(dt->is_buffer_type()){
- sprintf(tmpstr,"\t\t\t%s(f,&(%s),&aggr_tmp_%d);\n",dt->get_buffer_replace().c_str(),var.c_str(),aidx);
- }else{
- sprintf(tmpstr,"\t\t\t%s = aggr_tmp_%d;\n",var.c_str(),aidx);
- }
- retval.append(tmpstr);
-
- return(retval);
- }
- if(op == "MAX"){
- sprintf(tmpstr,"aggr_tmp_%d = %s;\n",aidx,generate_se_code(atbl->get_aggr_se(aidx), schema ).c_str() );
- retval.append(tmpstr);
- if(dt->complex_comparison(dt)){
- if(dt->is_buffer_type())
- sprintf(tmpstr,"\t\tif(%s(&aggr_tmp_%d,&(%s)) > 0)\n",dt->get_comparison_fcn(dt).c_str(), aidx, var.c_str());
- else
- sprintf(tmpstr,"\t\tif(%s(aggr_tmp_%d,%s) > 0)\n",dt->get_comparison_fcn(dt).c_str(), aidx, var.c_str());
- }else{
- sprintf(tmpstr,"\t\tif(aggr_tmp_%d > %s)\n",aidx,var.c_str());
- }
- retval.append(tmpstr);
- if(dt->is_buffer_type()){
- sprintf(tmpstr,"\t\t\t%s(f,&(%s),&aggr_tmp_%d);\n",dt->get_buffer_replace().c_str(),var.c_str(),aidx);
- }else{
- sprintf(tmpstr,"\t\t\t%s = aggr_tmp_%d;\n",var.c_str(),aidx);
- }
- retval.append(tmpstr);
-
- return(retval);
-
- }
- if(op == "AND_AGGR"){
- retval.append(var);
- retval.append(" &= ");
- retval.append(generate_se_code(atbl->get_aggr_se(aidx), schema) );
- retval.append(";\n");
- return(retval);
- }
- if(op == "OR_AGGR"){
- retval.append(var);
- retval.append(" |= ");
- retval.append(generate_se_code(atbl->get_aggr_se(aidx), schema) );
- retval.append(";\n");
- return(retval);
- }
- if(op == "XOR_AGGR"){
- retval.append(var);
- retval.append(" ^= ");
- retval.append(generate_se_code(atbl->get_aggr_se(aidx), schema) );
- retval.append(";\n");
- return(retval);
- }
- fprintf(stderr,"INTERNAL ERROR : aggregate %s not recognized in generate_aggr_update.\n",op.c_str());
- return("ERROR: aggregate not recognized: "+op);
-
-}
-
-
-
-static string generate_aggr_init(string var, aggregate_table *atbl,int aidx, table_list *schema){
- string retval;
- string op = atbl->get_op(aidx);
-
-// Is it a UDAF
- if(! atbl->is_builtin(aidx)) {
- int o;
- retval += "\t\t"+op+"_LFTA_AGGR_INIT_(";
- if(atbl->get_storage_type(aidx)->get_type() != fstring_t) retval+="&";
- retval+="("+var+"));\n";
-// Add 1st tupl
- retval += "\t"+atbl->get_op(aidx)+"_LFTA_AGGR_UPDATE_(";
- if(atbl->get_storage_type(aidx)->get_type() != fstring_t) retval+="&";
- retval+="("+var+")";
- vector<scalarexp_t *> opl = atbl->get_operand_list(aidx);
- for(o=0;o<opl.size();++o){
- retval += ",";
- if(opl[o]->get_data_type()->is_buffer_type() && (! (opl[o]->is_handle_ref()) ) )
- retval.append("&");
- retval += generate_se_code(opl[o],schema);
- }
- retval += ");\n";
- return(retval);
- }
-
-// Built-in aggregate processing.
-
-
- data_type *dt = atbl->get_data_type(aidx);
-
- if(op == "COUNT"){
- retval = "\t\t"+var;
- retval.append(" = 1;\n");
- return(retval);
- }
-
- if(op == "SUM" || op == "MIN" || op == "MAX" || op == "AND_AGGR" ||
- op == "OR_AGGR" || op == "XOR_AGGR"){
- if(dt->is_buffer_type()){
- sprintf(tmpstr,"\t\taggr_tmp_%d = %s;\n",aidx,generate_se_code(atbl->get_aggr_se(aidx), schema ).c_str() );
- retval.append(tmpstr);
- sprintf(tmpstr,"\t\t%s(f,&(%s),&aggr_tmp_%d);\n",dt->get_buffer_assign_copy().c_str(),var.c_str(),aidx);
- retval.append(tmpstr);
- }else{
- retval = "\t\t"+var;
- retval += " = ";
- retval.append(generate_se_code(atbl->get_aggr_se(aidx), schema));
- retval.append(";\n");
- }
- return(retval);
- }
-
- fprintf(stderr,"INTERNAL ERROR : aggregate %s not recognized in generate_aggr_init.\n",op.c_str());
- return("ERROR: aggregate not recognized: "+op);
-}
-
-
-////////////////////////////////////////////////////////////
-
-
-string generate_preamble(table_list *schema, //map<string,string> &int_fcn_defs,
- std::string &node_name, std::string &schema_embed_str){
-// Include these only once, not once per lfta
-// string ret = "#include \"rts.h\"\n";
-// ret += "#include \"fta.h\"\n\n");
-
- string ret = "#ifndef LFTA_IN_NIC\n";
- ret += "char *"+generate_schema_string_name(node_name)+" = " +schema_embed_str+";\n";
- ret += "#include<stdio.h>\n";
- ret += "#include <limits.h>\n";
- ret += "#include <float.h>\n";
- ret += "#include \"rdtsc.h\"\n";
- ret += "#endif\n";
-
-
-
- return(ret);
-}
-
-
-string generate_tuple_from_aggr(string node_name, table_list *schema, string idx){
- int a,p,s;
-// need to create and output the tuple.
- string ret = "/*\t\tCreate an output tuple for the aggregate being kicked out \t*/\n";
-// Check for any UDAFs with LFTA_BAILOUT
- ret += "\tlfta_bailout = 0;\n";
- for(a=0;a<aggr_tbl->size();a++){
- if(aggr_tbl->has_bailout(a)){
- ret += "\tlfta_bailout+="+aggr_tbl->get_op(a)+"_LFTA_AGGR_BAILOUT_(";
- if(aggr_tbl->get_storage_type(a)->get_type() != fstring_t) ret+="&";
- ret+="(t->aggr_table["+idx+"].aggr_var"+int_to_string(a)+"));\n";
- }
- }
- ret += "\tif(! lfta_bailout){\n";
-
-// First, compute the size of the tuple.
-
-// Unpack UDAF return values
- for(a=0;a<aggr_tbl->size();a++){
- if(! aggr_tbl->is_builtin(a)){
- ret += "\t"+aggr_tbl->get_op(a)+"_LFTA_AGGR_OUTPUT_(&(udaf_ret"+int_to_string(a)+"),";
- if(aggr_tbl->get_storage_type(a)->get_type() != fstring_t) ret+="&";
- ret+="(t->aggr_table["+idx+"].aggr_var"+int_to_string(a)+"));\n";
-
- }
- }
-
-
-// Unpack partial fcns ref'd by the select clause.
- if(sl_fcns_start != sl_fcns_end){
- ret += "\t\tunpack_failed = 0;\n";
- for(p=sl_fcns_start;p<sl_fcns_end;p++){
- if(is_partial_fcn[p]){
- ret += "\t" + unpack_partial_fcn_fm_aggr(partial_fcns[p], p,
- "t->aggr_table["+idx+"].",schema);
- ret += "\t\tif(retval) unpack_failed = 1;\n";
- }
- }
- // BEGIN don't allocate tuple if
- ret += "\t\tif( unpack_failed == 0 ){\n"; // unpack failed.
- }
-
-// Unpack any BUFFER type selections into temporaries
-// so that I can compute their size and not have
-// to recompute their value during tuple packing.
-// I can use regular assignment here because
-// these temporaries are non-persistent.
-
- for(s=0;s<sl_list.size();s++){
- data_type *sdt = sl_list[s]->get_data_type();
- if(sdt->is_buffer_type()){
- sprintf(tmpstr,"\t\t\tselvar_%d = ",s);
- ret += tmpstr;
- ret += generate_se_code_fm_aggr(sl_list[s],"t->aggr_table["+idx+"].",schema);
- ret += ";\n";
- }
- }
-
-
-// The size of the tuple is the size of the tuple struct plus the
-// size of the buffers to be copied in.
-
- ret += "\t\t\ttuple_size = sizeof( struct ";
- ret += generate_tuple_name(node_name);
- ret += ")";
- for(s=0;s<sl_list.size();s++){
- data_type *sdt = sl_list[s]->get_data_type();
- if(sdt->is_buffer_type()){
- sprintf(tmpstr," + %s(&selvar_%d)", sdt->get_buffer_size().c_str(),s);
- ret += tmpstr;
- }
- }
- ret += ";\n";
-
-
- ret += "\t\t\ttuple = allocate_tuple(f, tuple_size );\n";
- ret += "\t\t\tif( tuple != NULL){\n";
-
-
-// Test passed, make assignments to the tuple.
-
- ret += "\t\t\t\ttuple_pos = sizeof( struct ";
- ret += generate_tuple_name(node_name) ;
- ret += ");\n";
-
-// Mark tuple as REGULAR_TUPLE
- ret += "\n\t\t\t\ttuple->tuple_type = REGULAR_TUPLE;\n";
-
- for(s=0;s<sl_list.size();s++){
- data_type *sdt = sl_list[s]->get_data_type();
- if(sdt->is_buffer_type()){
- sprintf(tmpstr,"\t\t\t\t%s(&(tuple->tuple_var%d), &selvar_%d, (char *)tuple, ((char *)tuple)+tuple_pos);\n", sdt->get_buffer_tuple_copy().c_str(),s, s);
- ret += tmpstr;
- sprintf(tmpstr,"\t\t\t\ttuple_pos += %s(&selvar_%d);\n", sdt->get_buffer_size().c_str(), s);
- ret += tmpstr;
- }else{
- sprintf(tmpstr,"\t\t\t\ttuple->tuple_var%d = ",s);
- ret += tmpstr;
-// if(sdt->needs_hn_translation())
-// ret += sdt->hton_translation() +"( ";
- ret += generate_se_code_fm_aggr(sl_list[s],"t->aggr_table["+idx+"].",schema);
-// if(sdt->needs_hn_translation())
-// ret += ") ";
- ret += ";\n";
- }
- }
-
-// Generate output.
- ret += "\t\t\t\tpost_tuple(tuple);\n";
- ret += "\t\t\t\t#ifdef LFTA_STATS\n";
- ret+="\t\t\t\tt->out_tuple_cnt++;\n";
- ret+="\t\t\t\tt->out_tuple_sz+=tuple_size;\n";
- ret += "\t\t\t\t#endif\n\n";
- ret += "\t\t\t}\n";
-
- if(sl_fcns_start != sl_fcns_end) // END don't allocate tuple if
- ret += "\t\t}\n"; // unpack failed.
- ret += "\t}\n";
-
-// Need to release memory held by BUFFER types.
- int g;
-
- for(g=0;g<gb_tbl->size();g++){
- data_type *gdt = gb_tbl->get_data_type(g);
- if(gdt->is_buffer_type()){
- sprintf(tmpstr,"\t\t\t%s(&(t->aggr_table[%s].gb_var%d));\n",gdt->get_buffer_destroy().c_str(),idx.c_str(),g);
- ret += tmpstr;
- }
- }
- for(a=0;a<aggr_tbl->size();a++){
- if(aggr_tbl->is_builtin(a)){
- data_type *adt = aggr_tbl->get_data_type(a);
- if(adt->is_buffer_type()){
- sprintf(tmpstr,"\t\t\t%s(&(t->aggr_table[%s].aggr_var%d));\n",adt->get_buffer_destroy().c_str(),idx.c_str(),a);
- ret += tmpstr;
- }
- }else{
- ret += "\t\t"+aggr_tbl->get_op(a)+"_LFTA_AGGR_DESTROY_(";
- if(aggr_tbl->get_storage_type(a)->get_type() != fstring_t) ret+="&";
- ret+="(t->aggr_table["+idx+"].aggr_var"+int_to_string(a)+"));\n";
- }
- }
-
- ret += "\t\tt->n_aggrs--;\n";
-
- return(ret);
-
-}
-
-string generate_gb_match_test(string idx){
- int g;
- string ret="\tif (IS_FILLED(t->aggr_table_bitmap, "+idx+") && IS_NEW(t->aggr_table_bitmap,"+idx+")";
- if(gb_tbl->size()>0){
- ret+="\n\t/* \t\tcheck if the grouping variables are equal */\n";
- ret+="\t\t";
-
-// Next, scan list for a match on the group-by attributes.
- string rhs_op, lhs_op;
- for(g=0;g<gb_tbl->size();g++){
- ret += " && ";
- ret += "(";
- sprintf(tmpstr,"gb_attr_%d",g); lhs_op = tmpstr;
- sprintf(tmpstr,"t->aggr_table[%s].gb_var%d",idx.c_str(),g); rhs_op = tmpstr;
- ret += generate_equality_test(lhs_op, rhs_op, gb_tbl->get_data_type(g) );
- ret += ")";
- }
- }
-
- ret += "){\n";
-
- return ret;
-}
-
-string generate_gb_update(string node_name, table_list *schema, string idx, bool has_udaf){
- int g;
- string ret;
-
- ret += "/*\t\tMatch found : update in place.\t*/\n";
- int a;
- has_udaf = false;
- for(a=0;a<aggr_tbl->size();a++){
- sprintf(tmpstr,"t->aggr_table[%s].aggr_var%d",idx.c_str(),a);
- ret += generate_aggr_update(tmpstr,aggr_tbl,a, schema);
- if(! aggr_tbl->is_builtin(a)) has_udaf = true;
- }
-
-// garbage collect copied buffer type gb attrs.
- for(g=0;g<gb_tbl->size();g++){
- data_type *gdt = gb_tbl->get_data_type(g);
- if(gdt->is_buffer_type()){
- sprintf(tmpstr,"\t\t\t%s(&(gb_attr_%d));\n",gdt->get_buffer_destroy().c_str(),g);
- ret+=tmpstr;
- }
- }
-
-
-
- bool first_udaf = true;
- if(has_udaf){
- ret += "\t\tif(";
- for(a=0;a<aggr_tbl->size();a++){
- if(! aggr_tbl->is_builtin(a)){
- if(! first_udaf)ret += " || ";
- else first_udaf = false;
- ret += aggr_tbl->get_op(a)+"_LFTA_AGGR_FLUSHME_(";
- if(aggr_tbl->get_storage_type(a)->get_type() != fstring_t) ret+="&";
- ret+="(t->aggr_table["+idx+"].aggr_var"+int_to_string(a)+"))";
- }
- }
- ret+="){\n";
- ret+=" fta_aggr_flush_old_"+node_name+"(f,t->max_aggrs);\n";
- ret += generate_tuple_from_aggr(node_name,schema,idx);
- ret += "\t\tt->aggr_table_hashmap["+idx+"] &= ~SLOT_FILLED;\n";
- ret+="\t\t}\n";
- }
- return ret;
-}
-
-
-string generate_init_group( table_list *schema, string idx){
- int g,a;
- string ret="\t\t\tt->aggr_table_hashmap["+idx+"] = hash2 | SLOT_FILLED | gen_val;\n";
-// Fill up the aggregate block.
- for(g=0;g<gb_tbl->size();g++){
- sprintf(tmpstr,"\t\t\tt->aggr_table[%s].gb_var%d = gb_attr_%d;\n",idx.c_str(),g,g);
- ret += tmpstr;
- }
- for(a=0;a<aggr_tbl->size();a++){
- sprintf(tmpstr,"t->aggr_table[%s].aggr_var%d",idx.c_str(),a);
- ret += generate_aggr_init(tmpstr, aggr_tbl,a, schema);
- }
- ret+="\t\tt->n_aggrs++;\n";
- return ret;
-}
-
-
-string generate_fta_flush(string node_name, table_list *schema,
- ext_fcn_list *Ext_fcns){
-
- string ret;
- string select_var_defs ;
- int s, p;
-
-// Flush from previous epoch
-
- ret+="static void fta_aggr_flush_old_"+node_name+"(struct FTA *f, unsigned int nflush){\n";
-
- ret += "\tgs_int32_t tuple_size, tuple_pos;\n";
- ret += "\tstruct "+generate_tuple_name(node_name)+" *tuple;\n";
- ret += "\tint i, lfta_bailout;\n";
- ret += "\tunsigned int gen_val;\n";
-
- ret += "\tstruct "+generate_fta_name(node_name)+" * t = (struct ";
- ret += generate_fta_name(node_name)+" *) f;\n";
-
- ret += "\n";
-
-
-// Variables needed to store selected attributes of BUFFER type
-// temporarily, in order to compute their size for storage
-// in an output tuple.
-
- select_var_defs = "";
- for(s=0;s<sl_list.size();s++){
- data_type *sdt = sl_list[s]->get_data_type();
- if(sdt->is_buffer_type()){
- sprintf(tmpstr,"\t%s selvar_%d;\n",sdt->get_cvar_type().c_str(),s);
- select_var_defs.append(tmpstr);
- }
- }
- if(select_var_defs != ""){
- ret += "/*\t\tTemporaries for computing buffer sizes.\t*/\n";
- ret += select_var_defs;
- }
-
-
-// Variables to store results of partial functions.
- if(sl_fcns_start != sl_fcns_end){
- ret += "/*\t\tVariables to store the results of partial functions.\t*/\n";
- for(p=sl_fcns_start;p<sl_fcns_end;p++){
- sprintf(tmpstr,"\t%s partial_fcn_result_%d;\n",
- partial_fcns[p]->get_data_type()->get_cvar_type().c_str(), p);
- ret += tmpstr;
- }
- ret += "\tgs_retval_t retval = 0;\n\tint unpack_failed = 0;\n;";
- }
-
-// Variables for udaf output temporaries
- bool no_udaf = true;
- int a;
- for(a=0;a<aggr_tbl->size();a++){
- if(! aggr_tbl->is_builtin(a)){
- if(no_udaf){
- ret+="/*\t\tUDAF output vars.\t*/\n";
- no_udaf = false;
- }
- int afcn_id = aggr_tbl->get_fcn_id(a);
- data_type *adt = Ext_fcns->get_fcn_dt(afcn_id);
- sprintf(tmpstr,"udaf_ret%d", a);
- ret+="\t"+adt->make_cvar(tmpstr)+";\n";
- }
- }
-
-
-// ret+="\tt->flush_finished=1; /* flush will be completed */\n";
- ret+="\n";
- ret+="\tgen_val = t->generation & SLOT_GEN_BITS;\n";
- ret+="\tfor (i=t->flush_pos; (i < t->max_aggrs) && t->n_aggrs && nflush>0; ++i){\n";
- ret+="\t\tif ( (t->aggr_table_hashmap[i] & SLOT_FILLED) && (((t->aggr_table_hashmap[i] & SLOT_GEN_BITS) != gen_val ) || (";
- bool first_g=true;
- int g;
- for(g=0;g<gb_tbl->size();g++){
- data_type *gdt = gb_tbl->get_data_type(g);
- if(gdt->is_temporal()){
- if(first_g) first_g=false; else ret+=" || ";
- ret += "t->last_gb_"+int_to_string(g)+" > t->aggr_table[i].gb_var"+int_to_string(g)+" ";
- }
- }
- ret += "))) {\n";
- ret+="\t\t\tt->aggr_table_hashmap[i] = 0;\n";
- ret+=
-"#ifdef LFTA_STATS\n"
-"\t\t\tt->eviction_cnt++;\n"
-"#endif\n"
-;
-
-
- ret+=generate_tuple_from_aggr(node_name,schema,"i");
-
-// ret+="\t\t\tt->n_aggrs--;\n"; // done in generate_tuple_from_aggr
- ret+="\t\t\tnflush--;\n";
- ret+="\t\t}\n";
- ret+="\t}\n";
- ret+="\tt->flush_pos=i;\n";
- ret+="\tif(t->n_aggrs == 0) {\n";
- ret+="\t\tt->flush_pos = t->max_aggrs;\n";
- ret += "\t}\n\n";
-
- ret+="\tif(t->flush_pos == t->max_aggrs) {\n";
-
- for(int g=0;g<gb_tbl->size();g++){
- data_type *dt = gb_tbl->get_data_type(g);
- if(dt->is_temporal()){
- data_type *gdt = gb_tbl->get_data_type(g);
- if(!gdt->is_buffer_type()){
- sprintf(tmpstr,"\t\tt->last_flushed_gb_%d = t->flush_start_gb_%d;\n",g,g);
- ret += tmpstr;
- }
- }
- }
- ret += "\t}\n}\n\n";
-
- return(ret);
-}
-
-// TODO Remove sprintf to perform string catenation
-string generate_fta_load_params(string node_name){
- int p;
- vector<string> param_names = param_tbl->get_param_names();
-
- string ret = "static int load_params_"+node_name+"(struct "+generate_fta_name(node_name);
- ret += " *t, int sz, void *value, int initial_call){\n";
- ret += "\tint pos=0;\n";
- ret += "\tint data_pos;\n";
-
- for(p=0;p<param_names.size();p++){
- data_type *dt = param_tbl->get_data_type(param_names[p]);
- if(dt->is_buffer_type()){
- sprintf(tmpstr,"\t%s tmp_var_%s;\n",dt->get_cvar_type().c_str(), param_names[p].c_str() );
- ret += tmpstr;
- sprintf(tmpstr,"\t%s access_var_%s;\n",dt->get_tuple_cvar_type().c_str(), param_names[p].c_str() );
- ret += tmpstr;
- }
- }
-
-
-
- ret += "\n\tdata_pos = ";
- for(p=0;p<param_names.size();p++){
- if(p>0) ret += " + ";
- data_type *dt = param_tbl->get_data_type(param_names[p]);
- ret += "sizeof( ";
- ret += dt->get_tuple_cvar_type();
- ret += " )";
- }
- ret += ";\n";
- ret += "\tif(data_pos > sz) return 1;\n\n";
-
-
- for(p=0;p<param_names.size();p++){
- data_type *dt = param_tbl->get_data_type(param_names[p]);
- if(dt->is_buffer_type()){
- sprintf(tmpstr,"\taccess_var_%s = *( (%s *)((char *)value+pos) );\n",param_names[p].c_str(), dt->get_tuple_cvar_type().c_str() );
- ret += tmpstr;
- switch( dt->get_type() ){
- case v_str_t:
-// ret += "\ttmp_var_"+param_names[p]+".data = ntohl( tmp_var_"+param_names[p]+".data );\n"; // ntoh conversion
-// ret += "\ttmp_var_"+param_names[p]+".length = ntohl( tmp_var_"+param_names[p]+".length );\n"; // ntoh conversion
- sprintf(tmpstr,"\tif( (access_var_%s.offset) + access_var_%s.length > sz) return 1;\n",param_names[p].c_str(), param_names[p].c_str() );
- ret += tmpstr;
- sprintf(tmpstr,"\ttmp_var_%s.data = (gs_sp_t)(value) + access_var_%s.offset ;\n",param_names[p].c_str(), param_names[p].c_str() );
- ret += tmpstr;
- sprintf(tmpstr,"\ttmp_var_%s.length = access_var_%s.length ;\n",param_names[p].c_str(), param_names[p].c_str() );
- ret += tmpstr;
- break;
- default:
- fprintf(stderr,"ERROR: parameter %s is of type %s, a buffered type, but I don't know how to unpack it as a parameter.\n",param_names[p].c_str(), dt->get_type_str().c_str() );
- exit(1);
- break;
- }
-// First, destroy the old
- ret += "\tif(! initial_call)\n";
- sprintf(tmpstr,"\t\t%s(&(t->param_%s));\n",dt->get_buffer_destroy().c_str(),param_names[p].c_str());
- ret += tmpstr;
-// Next, create the new.
- sprintf(tmpstr,"\t%s((struct FTA *)t, &(t->param_%s), &tmp_var_%s);\n", dt->get_buffer_assign_copy().c_str(), param_names[p].c_str(), param_names[p].c_str() );
- ret += tmpstr;
- }else{
-// if(dt->needs_hn_translation()){
-// sprintf(tmpstr,"\tt->param_%s = %s( *( (%s *)( (char *)value+pos) ) );\n",
-// param_names[p].c_str(), dt->ntoh_translation().c_str(), dt->get_cvar_type().c_str() );
-// }else{
- sprintf(tmpstr,"\tt->param_%s = *( (%s *)( (char *)value+pos) );\n",
- param_names[p].c_str(), dt->get_cvar_type().c_str() );
-// }
- ret += tmpstr;
- }
- sprintf(tmpstr,"\tpos += sizeof( %s );\n",dt->get_cvar_type().c_str() );
- ret += tmpstr;
- }
-
-// Register the pass-by-handle parameters
-
- ret += "/* register and de-register the pass-by-handle parameters */\n";
-
- int ph;
- for(ph=0;ph<param_handle_table.size();++ph){
- data_type pdt(param_handle_table[ph]->type_name);
- switch(param_handle_table[ph]->val_type){
- case cplx_lit_e:
- break;
- case litval_e:
- break;
- case param_e:
- ret += "\tif(! initial_call)\n";
- sprintf(tmpstr, "\t\t%s(t->handle_param_%d);\n",
- param_handle_table[ph]->lfta_deregistration_fcn().c_str(),ph);
- ret += tmpstr;
- sprintf(tmpstr,"\tt->handle_param_%d = %s((struct FTA *)t,",ph,param_handle_table[ph]->lfta_registration_fcn().c_str());
- ret += tmpstr;
-
- if(pdt.is_buffer_type()) ret += "&(";
- ret += "t->param_"+param_handle_table[ph]->param_name;
- if(pdt.is_buffer_type()) ret += ")";
- ret += ");\n";
- break;
- default:
- sprintf(tmpstr, "INTERNAL ERROR unknown case (%d) found when processing pass-by-handle parameter table.",param_handle_table[ph]->val_type);
- fprintf(stderr,"%s\n",tmpstr);
- ret+=tmpstr;
- }
- }
-
- ret+="\treturn 0;\n";
- ret += "}\n\n";
-
- return(ret);
-}
-
-
-
-
-string generate_fta_free(string node_name, bool is_aggr_query){
-
- string ret="static gs_retval_t free_fta_"+node_name+"(struct FTA *f, gs_uint32_t recursive){\n";
- ret+= "\tstruct "+generate_fta_name(node_name)+
- " * t = (struct "+generate_fta_name(node_name)+" *) f;\n";
- ret += "\tint i;\n";
-
- if(is_aggr_query){
- ret+="\tfta_aggr_flush_old_" + node_name+"(f,t->max_aggrs);\n";
- ret+="\t/* \t\tmark all groups as old */\n";
- ret+="\tt->generation++;\n";
- ret+="\tt->flush_pos = 0;\n";
- ret+="\tfta_aggr_flush_old_" + node_name+"(f,t->max_aggrs);\n";
- }
-
-// Deregister the pass-by-handle parameters
- ret += "/* de-register the pass-by-handle parameters */\n";
- int ph;
- for(ph=0;ph<param_handle_table.size();++ph){
- sprintf(tmpstr, "\t%s(t->handle_param_%d);\n",
- param_handle_table[ph]->lfta_deregistration_fcn().c_str(),ph);
- ret += tmpstr;
- }
-
-
- ret += "\treturn 0;\n}\n\n";
- return(ret);
-}
-
-
-string generate_fta_control(string node_name, table_list *schema, bool is_aggr_query){
- string ret="static gs_retval_t control_fta_"+node_name+"(struct FTA *f, gs_int32_t command, gs_int32_t sz, void *value){\n";
- ret += "\tstruct "+generate_fta_name(node_name)+" * t = (struct ";
- ret += generate_fta_name(node_name)+" *) f;\n\n";
- ret+="\tint i;\n";
-
-
- ret += "\t/* temp status tuple */\n";
- ret += "\tstruct "+generate_tuple_name(node_name)+" *tuple;\n";
- ret += "\tgs_int32_t tuple_size;\n";
-
-
- if(is_aggr_query){
- ret+="\tif(command == FTA_COMMAND_FLUSH){\n";
-
- ret+="\t\tif (!t->n_aggrs) {\n";
- ret+="\t\t\ttuple = allocate_tuple(f, 0);\n";
- ret+="\t\t\tif( tuple != NULL)\n";
- ret+="\t\t\t\tpost_tuple(tuple);\n";
-
- ret+="\t\t}else{\n";
-
- ret+="\t\t\tfta_aggr_flush_old_" + node_name+"(f,t->max_aggrs);\n";
- ret+="\t\t\t/* \t\tmark all groups as old */\n";
- ret +="\t\tt->generation++;\n";
- ret += "//\tmarking groups old should happen implicitly by advancing the generation.\n";
- ret+="//\t\t\tfor (i = 0; i < t->bitmap_size; ++i)\n";
- ret+="//\t\t\t\tt->aggr_table_bitmap[i] &= 0xAAAAAAAA;\n";
- ret+="\t\t\tt->flush_pos = 0;\n";
- ret+="\t\t\tfta_aggr_flush_old_" + node_name+"(f,t->max_aggrs);\n";
- ret+="\t\t}\n";
-
- ret+="\t}\n";
- }
- if(param_tbl->size() > 0){
- ret+=
-"\tif(command == FTA_COMMAND_LOAD_PARAMS){\n"
-"\t\tif(load_params_"+node_name+"(t, sz, value, 0))\n"
-"#ifndef LFTA_IN_NIC\n"
-"\t\t\tfprintf(stderr,\"WARNING: parameter passed to lfta "+node_name+" is too small, ignored.\\n\");\n"
-"#else\n"
-"\t\t{}\n"
-"#endif\n"
-"\t}\n";
- }
- ret+=
-"\tif(command == FTA_COMMAND_SET_SAMPLING_RATE){\n"
-"\t\tmemcpy(&t->sampling_rate, value, sizeof(gs_float_t));\n"
-"\t}\n\n";
-
-
- ret += "\tif(command == FTA_COMMAND_FILE_DONE ){\n";
-
- if(is_aggr_query){
- ret+="\t\tif (t->n_aggrs) {\n";
- ret+="\t\t\tfta_aggr_flush_old_" + node_name+"(f,t->max_aggrs);\n";
- ret+="\t\t\t/* \t\tmark all groups as old */\n";
- ret +="\t\tt->generation++;\n";
- ret += "//\tmarking groups old should happen implicitly by advancing the generation.\n";
- ret+="//\t\t\tfor (i = 0; i < t->bitmap_size; ++i)\n";
- ret+="//\t\t\t\tt->aggr_table_bitmap[i] &= 0xAAAAAAAA;\n";
- ret+="\t\t\tt->flush_pos = 0;\n";
- ret+="\t\t\tfta_aggr_flush_old_" + node_name+"(f,t->max_aggrs);\n";
- ret+="\t\t}\n";
- }
-
- ret += "\t\ttuple_size = sizeof( struct "+generate_tuple_name(node_name)+");\n";
- ret += "\t\ttuple = allocate_tuple(f, tuple_size );\n";
- ret += "\t\tif( tuple == NULL)\n\t\treturn 1;\n";
-
- /* mark tuple as EOF_TUPLE */
- ret += "\n\t\t/* Mark tuple as eof_tuple */\n";
- ret += "\t\ttuple->tuple_type = EOF_TUPLE;\n";
- ret += "\t\tpost_tuple(tuple);\n";
- ret += "\t}\n";
-
- ret += "\treturn 0;\n}\n\n";
-
- return(ret);
-}
-
-string generate_fta_clock(string node_name, table_list *schema, unsigned time_corr, bool is_aggr_query){
- string ret="static gs_retval_t clock_fta_"+node_name+"(struct FTA *f){\n";
- ret += "\tstruct "+generate_fta_name(node_name)+" * t = (struct ";
- ret += generate_fta_name(node_name)+" *) f;\n\n";
-
- ret += "\t/* Create a temp status tuple */\n";
- ret += "\tstruct "+generate_tuple_name(node_name)+" *tuple;\n";
- ret += "\tgs_int32_t tuple_size;\n";
- ret += "\tunsigned int i;\n";
- ret += "\ttime_t cur_time;\n";
- ret += "\tint time_advanced;\n";
- ret += "\tstruct fta_stat stats;\n";
-
-
-
- /* copy the last seen values of temporal attributes */
- col_id_set temp_cids; // col ids of temp attributes in select clause
-
-
- /* HACK: in order to reuse the SE generation code, we need to copy
- * the last values of the temp attributes into new variables
- * which have names unpack_var_XXX_XXX
- */
-
- int s, g;
- col_id_set::iterator csi;
-
- for(s=0;s<sl_list.size();s++){
- data_type *sdt = sl_list[s]->get_data_type();
- if (sdt->is_temporal()) {
- gather_se_col_ids(sl_list[s],temp_cids, gb_tbl);
- }
- }
-
- for(csi=temp_cids.begin(); csi != temp_cids.end();++csi){
- int tblref = (*csi).tblvar_ref;
- int schref = (*csi).schema_ref;
- string field = (*csi).field;
- data_type dt(schema->get_type_name(schref,field), schema->get_modifier_list(schref,field));
- sprintf(tmpstr,"\t%s unpack_var_%s_%d;\n", dt.get_cvar_type().c_str(), field.c_str(), tblref);
- ret += tmpstr;
- }
-
- if (is_aggr_query) {
- for(g=0;g<gb_tbl->size();g++){
- data_type *gdt = gb_tbl->get_data_type(g);
- if(gdt->is_temporal()){
- sprintf(tmpstr,"\t%s gb_attr_%d;\n",gb_tbl->get_data_type(g)->get_cvar_type().c_str(),g);
- ret += tmpstr;
- data_type *gdt = gb_tbl->get_data_type(g);
- if(gdt->is_buffer_type()){
- sprintf(tmpstr,"\t%s gb_attr_tmp%d;\n",gb_tbl->get_data_type(g)->get_cvar_type().c_str(),g);
- ret += tmpstr;
- }
- }
- }
- }
- ret += "\n";
-
- ret += "\ttime_advanced = 0;\n";
-
- for(csi=temp_cids.begin(); csi != temp_cids.end();++csi){
- int tblref = (*csi).tblvar_ref;
- int schref = (*csi).schema_ref;
- string field = (*csi).field;
- data_type dt(schema->get_type_name(schref,field), schema->get_modifier_list(schref,field));
-
- // update last seen value with the value seen
- ret += "\t#ifdef PREFILTER_DEFINED\n";
- sprintf(tmpstr,"\tif (prefilter_temp_vars.unpack_var_%s_%d > t->last_%s_%d) {\n\t\tt->last_%s_%d = prefilter_temp_vars.unpack_var_%s_%d;\n",
- field.c_str(), tblref, field.c_str(), tblref, field.c_str(), tblref, field.c_str(), tblref);
- ret += tmpstr;
- ret += "\t\ttime_advanced = 1;\n\t}\n";
- ret += "\t#endif\n";
-
- // we need to pay special attention to time fields
- if (field == "time" || field == "timestamp"){
- ret += "\tcur_time = time(&cur_time);\n";
-
- if (field == "time") {
- sprintf(tmpstr,"\tif (!gscp_blocking_mode() && (t->last_time_%d < (cur_time - %d))) {\n",
- tblref, time_corr);
- ret += tmpstr;
- sprintf(tmpstr,"\t\tunpack_var_%s_%d = t->last_%s_%d = cur_time - %d;\n",
- field.c_str(), tblref, field.c_str(), tblref, time_corr);
- } else {
- sprintf(tmpstr,"\tif (!gscp_blocking_mode() && ((gs_uint32_t)(t->last_%s_%d>>32) < (cur_time - %d))) {\n",
- field.c_str(), tblref, time_corr);
- ret += tmpstr;
- sprintf(tmpstr,"\t\tunpack_var_%s_%d = t->last_%s_%d = ((gs_uint64_t)(cur_time - %d))<<32;\n",
- field.c_str(), tblref, field.c_str(), tblref, time_corr);
- }
- ret += tmpstr;
-
- ret += "\t\ttime_advanced = 1;\n";
- ret += "\t}\n";
-
- sprintf(tmpstr,"\telse\n\t\tunpack_var_%s_%d = t->last_%s_%d;\n",
- field.c_str(), tblref, field.c_str(), tblref);
- ret += tmpstr;
- } else {
- sprintf(tmpstr,"\tunpack_var_%s_%d = t->last_%s_%d;\n",
- field.c_str(), tblref, field.c_str(), tblref);
- ret += tmpstr;
- }
- }
-
- // for aggregation lftas we need to check if the time was advanced beyond the current epoch
- if (is_aggr_query) {
-
- string change_test;
- bool first_one = true;
- for(g=0;g<gb_tbl->size();g++){
- data_type *gdt = gb_tbl->get_data_type(g);
- if(gdt->is_temporal()){
-// To perform the test, first need to compute the value
-// of the temporal gb attrs.
- if(gdt->is_buffer_type()){
- // NOTE : if the SE defining the gb is anything
- // other than a ref to a variable, this will generate
- // illegal code. To be resolved with Spatch.
- sprintf(tmpstr,"\tgb_attr_tmp%d = %s;\n",
- g, generate_se_code(gb_tbl->get_def(g),schema).c_str() );
- ret+=tmpstr;
- sprintf(tmpstr,"\t%s(f, &gb_attr_%d, &gb_attr_tmp%d);\n",
- gdt->get_buffer_assign_copy().c_str(), g, g);
- }else{
- sprintf(tmpstr,"\tgb_attr_%d = %s;\n",g,generate_se_code(gb_tbl->get_def(g),schema).c_str());
- }
- ret += tmpstr;
-
- sprintf(tmpstr,"t->last_gb_%d",g); string lhs_op = tmpstr;
- sprintf(tmpstr,"gb_attr_%d",g); string rhs_op = tmpstr;
- if(first_one){first_one = false;} else {change_test.append(") && (");}
- change_test.append(generate_equality_test(lhs_op, rhs_op, gdt));
- }
- }
-
- ret += "\n\tif( time_advanced && !( (";
- ret += change_test;
- ret += ") ) ){\n";
-
- ret += "\n/*\t\tFlush the aggregates if the temporal gb attrs have changed.\t*/\n";
- ret += "\t\tif(t->flush_pos<t->max_aggrs) \n";
- ret += "\t\t\tfta_aggr_flush_old_"+node_name+"(f,t->max_aggrs);\n";
-
- ret += "\t\t/* \t\tmark all groups as old */\n";
- ret +="\t\tt->generation++;\n";
- ret += "//\tmarking groups old should happen implicitly by advancing the generation.\n";
- ret += "//\t\tfor (i = 0; i < t->bitmap_size; ++i)\n";
- ret += "//\t\t\tt->aggr_table_bitmap[i] &= 0xAAAAAAAA;\n";
- ret += "\t\tt->flush_pos = 0;\n";
-
- for(g=0;g<gb_tbl->size();g++){
- data_type *gdt = gb_tbl->get_data_type(g);
- if(gdt->is_temporal()){
- sprintf(tmpstr,"\t\tt->flush_start_gb_%d = gb_attr_%d;\n",g,g); ret += tmpstr;
- sprintf(tmpstr,"\t\tt->last_gb_%d = gb_attr_%d;\n",g,g); ret += tmpstr;
- }
- }
- ret += "\t}\n\n";
-
- }
-
- ret += "\ttuple_size = sizeof( struct "+generate_tuple_name(node_name)+") + sizeof(gs_uint64_t) + sizeof(struct fta_stat);\n";
- ret += "\ttuple = allocate_tuple(f, tuple_size );\n";
- ret += "\tif( tuple == NULL)\n\t\treturn 1;\n";
-
-
- for(s=0;s<sl_list.size();s++){
- data_type *sdt = sl_list[s]->get_data_type();
- if(sdt->is_temporal()){
-
- if (sl_list[s]->is_gb()) {
- sprintf(tmpstr,"\tt->last_flushed_gb_%d = (t->n_aggrs) ? t->last_flushed_gb_%d : %s;\n",sl_list[s]->get_gb_ref(), sl_list[s]->get_gb_ref(), generate_se_code(sl_list[s],schema).c_str());
- ret += tmpstr;
- }
-
- sprintf(tmpstr,"\ttuple->tuple_var%d = ",s);
- ret += tmpstr;
-// if(sdt->needs_hn_translation())
-// ret += sdt->hton_translation() +"( ";
- if (sl_list[s]->is_gb()) {
- sprintf(tmpstr, "t->last_flushed_gb_%d",sl_list[s]->get_gb_ref());
- ret += tmpstr;
- } else{
- ret += generate_se_code(sl_list[s],schema);
- }
-// if(sdt->needs_hn_translation())
-// ret += " )";
- ret += ";\n";
- }
- }
-
- /* mark tuple as temporal */
- ret += "\n\t/* Mark tuple as temporal */\n";
- ret += "\ttuple->tuple_type = TEMPORAL_TUPLE;\n";
-
- ret += "\n\t/* Copy trace id */\n";
- ret += "\tmemcpy((gs_sp_t)tuple+sizeof( struct "+generate_tuple_name(node_name)+"), &t->trace_id, sizeof(gs_uint64_t));\n\n";
-
- ret += "\n\t/* Populate runtime stats */\n";
- ret += "\tstats.ftaid = f->ftaid;\n";
- ret += "\tstats.in_tuple_cnt = t->in_tuple_cnt;\n";
- ret += "\tstats.out_tuple_cnt = t->out_tuple_cnt;\n";
- ret += "\tstats.out_tuple_sz = t->out_tuple_sz;\n";
- ret += "\tstats.accepted_tuple_cnt = t->accepted_tuple_cnt;\n";
- ret += "\tstats.cycle_cnt = t->cycle_cnt;\n";
- ret += "\tstats.collision_cnt = t->collision_cnt;\n";
- ret += "\tstats.eviction_cnt = t->eviction_cnt;\n";
- ret += "\tstats.sampling_rate = t->sampling_rate;\n";
-
- ret += "\n#ifdef LFTA_PROFILE\n";
- ret += "\n\t/* Print stats */\n";
- ret += "\tfprintf(stderr, \"STATS " + node_name + " \");\n";
- ret += "\tfprintf(stderr, \"in_tuple_cnt= %u \", t->in_tuple_cnt);\n";
- ret += "\tfprintf(stderr, \"out_tuple_cnt= %u \", t->out_tuple_cnt);\n";
- ret += "\tfprintf(stderr, \"out_tuple_sz= %u \", t->out_tuple_sz);\n";
- ret += "\tfprintf(stderr, \"accepted_tuple_cnt= %u \", t->accepted_tuple_cnt);\n";
- ret += "\tfprintf(stderr, \"cycle_cnt= %llu \", t->cycle_cnt);\n";
- ret += "\tfprintf(stderr, \"cycle_per_in_tuple= %lf \", ((double)t->cycle_cnt)/((double)t->in_tuple_cnt));\n";
- ret += "\tfprintf(stderr, \"collision_cnt= %d\\n\", t->collision_cnt);\n\n";
- ret += "\tfprintf(stderr, \"eviction_cnt= %d\\n\", t->eviction_cnt);\n\n";
- ret += "\n#endif\n";
-
-
- ret += "\n\t/* Copy stats */\n";
- ret += "\tmemcpy((gs_sp_t)tuple+sizeof( struct "+generate_tuple_name(node_name)+") + sizeof(gs_uint64_t), &stats, sizeof(fta_stat));\n\n";
- ret+="\tpost_tuple(tuple);\n";
-
- ret += "\n\t/* Send a heartbeat message to clearinghouse */\n";
- ret += "\tfta_heartbeat(f->ftaid, t->trace_id++, 1, &stats);\n";
-
- ret += "\n\t/* Reset runtime stats */\n";
- ret += "\tt->in_tuple_cnt = 0;\n";
- ret += "\tt->out_tuple_cnt = 0;\n";
- ret += "\tt->out_tuple_sz = 0;\n";
- ret += "\tt->accepted_tuple_cnt = 0;\n";
- ret += "\tt->cycle_cnt = 0;\n";
- ret += "\tt->collision_cnt = 0;\n";
- ret += "\tt->eviction_cnt = 0;\n";
-
- ret += "\treturn 0;\n}\n\n";
-
- return(ret);
-}
-
-
-// accept processing before the where clause,
-// do flush processwing.
-string generate_aggr_accept_prelim(qp_node *fs, string node_name, table_list *schema, col_id_set &unpacked_cids, string &temporal_flush){
- int s;
-
-// Slow flush
- string ret="\n/*\tslow flush\t*/\n";
- string slow_flush_str = fs->get_val_of_def("slow_flush");
- int n_slow_flush = atoi(slow_flush_str.c_str());
- if(n_slow_flush <= 0) n_slow_flush = 2;
- if(n_slow_flush > 1){
- ret += "\tt->flush_ctr++;\n";
- ret += "\tif(t->flush_ctr >= "+int_to_string(n_slow_flush)+"){\n";
- ret += "\t\tt->flush_ctr = 0;\n";
- ret+="\t\tif(t->flush_pos<t->max_aggrs) fta_aggr_flush_old_"+node_name+"(f,1);\n";
- ret += "\t}\n\n";
- }else{
- ret+="\tif(t->flush_pos<t->max_aggrs) fta_aggr_flush_old_"+node_name+"(f,1);\n\n";
- }
-
-
- string change_test;
- bool first_one = true;
- int g;
- col_id_set flush_cids; // col ids accessed when computing flush variables.
- // unpack them at temporal flush test time.
- temporal_flush = "";
-
-
- for(g=0;g<gb_tbl->size();g++){
- data_type *gdt = gb_tbl->get_data_type(g);
- if(gdt->is_temporal()){
- gather_se_col_ids(gb_tbl->get_def(g), flush_cids, gb_tbl);
-
-// To perform the test, first need to compute the value
-// of the temporal gb attrs.
- if(gdt->is_buffer_type()){
- // NOTE : if the SE defining the gb is anything
- // other than a ref to a variable, this will generate
- // illegal code. To be resolved with Spatch.
- sprintf(tmpstr,"\tgb_attr_tmp%d = %s;\n",
- g, generate_se_code(gb_tbl->get_def(g),schema).c_str() );
- temporal_flush += tmpstr;
- sprintf(tmpstr,"\t%s(f, &gb_attr_%d, &gb_attr_tmp%d);\n",
- gdt->get_buffer_assign_copy().c_str(), g, g);
- }else{
- sprintf(tmpstr,"\tgb_attr_%d = %s;\n",g,generate_se_code(gb_tbl->get_def(g),schema).c_str());
- }
- temporal_flush += tmpstr;
-// END computing the value of the temporal GB attr.
-
-
- sprintf(tmpstr,"t->last_gb_%d",g); string lhs_op = tmpstr;
- sprintf(tmpstr,"gb_attr_%d",g); string rhs_op = tmpstr;
- if(first_one){first_one = false;} else {change_test.append(") && (");}
- change_test += generate_equality_test(lhs_op, rhs_op, gdt);
- }
- }
- if(!first_one){ // will be false iff. there is a temporal GB attribute
- temporal_flush += "\n/*\t\tFlush the aggregates if the temporal gb attrs have changed.\t*/\n";
- temporal_flush += "\tif( !( (";
- temporal_flush += change_test;
- temporal_flush += ") ) ){\n";
-
-// temporal_flush+="\t\tif(t->flush_pos<t->max_aggrs) fta_aggr_flush_old_"+node_name+"(f,t->max_aggrs);\n";
- temporal_flush+="\t\tif(t->flush_pos<t->max_aggrs){ \n";
- temporal_flush+="\t\t\tfta_aggr_flush_old_"+node_name+"(f,t->max_aggrs);\n";
- temporal_flush+="\t\t}\n";
- temporal_flush+="\t\t/* \t\tmark all groups as old */\n";
- temporal_flush+="\t\tt->generation++;\n";
- temporal_flush+="\t\tt->flush_pos = 0;\n";
-
-
-// Now set the saved temporal value of the gb to the
-// current value of the gb. Only for simple types,
-// not for buffer types -- but the strings are not
-// temporal in any case.
-
- for(g=0;g<gb_tbl->size();g++){
- data_type *gdt = gb_tbl->get_data_type(g);
- if(gdt->is_temporal()){
- if(gdt->is_buffer_type()){
-
- fprintf(stderr,"ERROR : can't handle temporal buffer types, ignoring in buffer flush control.\n");
- }else{
- sprintf(tmpstr,"\t\tt->flush_start_gb_%d = gb_attr_%d;\n",g,g);
- temporal_flush += tmpstr;
- sprintf(tmpstr,"\t\tt->last_gb_%d = gb_attr_%d;\n",g,g);
- temporal_flush += tmpstr;
- }
- }
- }
- temporal_flush += "\t}\n\n";
- }
-
-// Unpack all the temporal attributes referenced in select clause
-// and update the last value of the attribute
- col_id_set temp_cids; // col ids of temp attributes in select clause
- col_id_set::iterator csi;
-
- for(s=0;s<sl_list.size();s++){
- data_type *sdt = sl_list[s]->get_data_type();
- if (sdt->is_temporal()) {
- gather_se_col_ids(sl_list[s],temp_cids, gb_tbl);
- }
- }
-
- for(csi=temp_cids.begin(); csi != temp_cids.end();++csi){
- if(unpacked_cids.count((*csi)) == 0){
- int tblref = (*csi).tblvar_ref;
- int schref = (*csi).schema_ref;
- string field = (*csi).field;
- ret += generate_unpack_code(tblref,schref,field,schema,node_name);
-/*
- data_type dt(schema->get_type_name(schref,field), schema->get_modifier_list(schref,field));
- sprintf(tmpstr,"\tretval = %s(p, &unpack_var_%s_%d);\n",
- schema->get_fcn(schref,field).c_str(), field.c_str(), tblref);
- ret += tmpstr;
- ret += "\tif(retval) return 1;\n";
-*/
- sprintf(tmpstr,"\tt->last_%s_%d = unpack_var_%s_%d;\n", field.c_str(), tblref, field.c_str(), tblref);
- ret += tmpstr;
-
- unpacked_cids.insert( (*csi) );
- }
- }
-
-
-// Do the flush here if this is a real_time query
- string rt_level = fs->get_val_of_def("real_time");
- if(rt_level != "" && temporal_flush != ""){
- for(csi=flush_cids.begin(); csi != flush_cids.end();++csi){
- if(unpacked_cids.count((*csi)) == 0){
- int tblref = (*csi).tblvar_ref;
- int schref = (*csi).schema_ref;
- string field = (*csi).field;
- ret += generate_unpack_code(tblref,schref,field,schema,node_name);
-/*
- sprintf(tmpstr,"\tretval = %s(p, &unpack_var_%s_%d);\n",
- schema->get_fcn(schref,field).c_str(), field.c_str(), tblref);
- ret += tmpstr;
- ret += "\tif(retval) return 1;\n";
-*/
- unpacked_cids.insert( (*csi) );
- }
- }
- ret += temporal_flush;
- }
-
- return ret;
- }
-
-string generate_sel_accept_body(qp_node *fs, string node_name, table_list *schema){
-
-int p,s;
-string ret;
-
-/////////////// Processing for filter-only query
-
-// test passed : create the tuple, then assign to it.
- ret += "/*\t\tCreate and post the tuple\t*/\n";
-
-// Unpack partial fcns ref'd by the select clause.
-// Its a kind of a WHERE clause ...
- for(p=sl_fcns_start;p<sl_fcns_end;p++){
- if(fcn_ref_cnt[p] > 1){
- ret += "\tif(fcn_ref_cnt_"+int_to_string(p)+"==0){\n";
- }
- if(is_partial_fcn[p]){
- ret += unpack_partial_fcn(partial_fcns[p], p, schema);
- ret += "\tif(retval) goto end;\n";
- }
- if(fcn_ref_cnt[p] > 1){
- if(!is_partial_fcn[p]){
- ret += "\t\tpartial_fcn_result_"+int_to_string(p)+"="+generate_cached_fcn(partial_fcns[p],schema)+";\n";
- }
- ret += "\t\tfcn_ref_cnt_"+int_to_string(p)+"=1;\n";
- ret += "\t}\n";
- }
- }
-
- // increment the counter of accepted tuples
- ret += "\n\t#ifdef LFTA_STATS\n";
- ret += "\n\tt->accepted_tuple_cnt++;\n\n";
- ret += "\t#endif\n\n";
-
-// First, compute the size of the tuple.
-
-// Unpack any BUFFER type selections into temporaries
-// so that I can compute their size and not have
-// to recompute their value during tuple packing.
-// I can use regular assignment here because
-// these temporaries are non-persistent.
-
- for(s=0;s<sl_list.size();s++){
- data_type *sdt = sl_list[s]->get_data_type();
- if(sdt->is_buffer_type()){
- sprintf(tmpstr,"\tselvar_%d = ",s);
- ret += tmpstr;
- ret += generate_se_code(sl_list[s],schema);
- ret += ";\n";
- }
- }
-
-
-// The size of the tuple is the size of the tuple struct plus the
-// size of the buffers to be copied in.
-
- ret+="\ttuple_size = sizeof( struct "+generate_tuple_name(node_name)+")";
- for(s=0;s<sl_list.size();s++){
- data_type *sdt = sl_list[s]->get_data_type();
- if(sdt->is_buffer_type()){
- sprintf(tmpstr," + %s(&selvar_%d)", sdt->get_buffer_size().c_str(),s);
- ret += tmpstr;
- }
- }
- ret += ";\n";
-
-
- ret += "\ttuple = allocate_tuple(f, tuple_size );\n";
- ret += "\tif( tuple == NULL)\n\t\tgoto end;\n";
-
-// Test passed, make assignments to the tuple.
-
- ret += "\ttuple_pos = sizeof( struct "+generate_tuple_name(node_name)+");\n";
-
-// Mark tuple as REGULAR_TUPLE
- ret += "\ttuple->tuple_type = REGULAR_TUPLE;\n";
-
-
- for(s=0;s<sl_list.size();s++){
- data_type *sdt = sl_list[s]->get_data_type();
- if(sdt->is_buffer_type()){
- sprintf(tmpstr,"\t%s(&(tuple->tuple_var%d), &selvar_%d, (char *)tuple, ((char *)tuple)+tuple_pos);\n", sdt->get_buffer_tuple_copy().c_str(),s, s);
- ret += tmpstr;
- sprintf(tmpstr,"\ttuple_pos += %s(&selvar_%d);\n", sdt->get_buffer_size().c_str(), s);
- ret += tmpstr;
- }else{
- sprintf(tmpstr,"\ttuple->tuple_var%d = ",s);
- ret += tmpstr;
-// if(sdt->needs_hn_translation())
-// ret += sdt->hton_translation() +"( ";
- ret += generate_se_code(sl_list[s],schema);
-// if(sdt->needs_hn_translation())
-// ret += ") ";
- ret += ";\n";
- }
- }
-
-// Generate output.
-
- ret += "\tpost_tuple(tuple);\n";
-
-// Increment the counter of posted tuples
- ret += "\n\t#ifdef LFTA_STATS\n";
- ret += "\tt->out_tuple_cnt++;\n";
- ret+="\tt->out_tuple_sz+=tuple_size;\n";
- ret += "\t#endif\n\n";
-
-
-
- return ret;
-}
-
-string generate_fj_accept_body(filter_join_qpn *fs, string node_name,col_id_set &unpacked_cids,ext_fcn_list *Ext_fcns, table_list *schema){
-
-int p,s,w;
-string ret;
-
-// Get parameters
- unsigned int window_len = fs->temporal_range;
- unsigned int n_bloom = 11;
- string n_bloom_str = fs->get_val_of_def("num_bloom");
- int tmp_n_bloom = atoi(n_bloom_str.c_str());
- if(tmp_n_bloom>0)
- n_bloom = tmp_n_bloom+1;
- float bloom_width = (window_len+1.0)/(1.0*n_bloom-1);
- sprintf(tmpstr,"%f",bloom_width);
- string bloom_width_str = tmpstr;
-
- if(window_len < n_bloom){
- n_bloom = window_len+1;
- bloom_width_str = "1";
- }
-
-
-// Grab the current window time
- scalarexp_t winvar(fs->temporal_var);
- ret += "\tcurr_fj_ts = "+generate_se_code(&winvar,schema)+";\n";
-
- int bf_exp_size = 12; // base-2 log of number of bits
- string bloom_len_str = fs->get_val_of_def("bloom_size");
- int tmp_bf_exp_size = atoi(bloom_len_str.c_str());
- if(tmp_bf_exp_size > 3 && tmp_bf_exp_size < 32){
- bf_exp_size = tmp_bf_exp_size;
- }
- int bf_bit_size = 1 << bf_exp_size;
- int bf_byte_size = bf_bit_size / (8*sizeof(char));
-
- unsigned int ht_size = 4096;
- string ht_size_s = fs->get_val_of_def("aggregate_slots");
- int tmp_ht_size = atoi(ht_size_s.c_str());
- if(tmp_ht_size > 1024){
- unsigned int hs = 1; // make it power of 2
- while(tmp_ht_size){
- hs =hs << 1;
- tmp_ht_size = tmp_ht_size >> 1;
- }
- ht_size = hs;
- }
-
- int i, bf_mask = 0;
- if(fs->use_bloom){
- for(i=0;i<bf_exp_size;i++)
- bf_mask = (bf_mask << 1) | 1;
- }else{
- for(i=ht_size;i>1;i=i>>1)
- bf_mask = (bf_mask << 1) | 1;
- }
-
-/*
-printf("n_bloom=%d, window_len=%d, bloom_width=%s, bf_exp_size=%d, bf_bit_size=%d, bf_byte_size=%d, ht_size=%d, ht_size_s=%s, bf_mask=%d\n",
- n_bloom,
- window_len,
- bloom_width_str.c_str(),
- bf_exp_size,
- bf_bit_size,
- bf_byte_size,
- ht_size,
- ht_size_s.c_str(),
- bf_mask);
-*/
-
-
-
-
-// If this is a bloom-filter fj, first test if the
-// bloom filter needs to be advanced.
-// SET_BF_EMPTY(table,number of bloom filters,bloom filter index,bit index)
-// t->bf_size : number of bits in bloom filter
- if(fs->use_bloom){
- ret +=
-"// Clean out old bloom filters if needed.\n"
-" if(t->first_exec){\n"
-" t->first_exec = 0;\n"
-" t->last_bin = (long long int)(curr_fj_ts/"+bloom_width_str+");\n"
-" t->last_bloom_pos = t->last_bin % "+int_to_string(n_bloom)+";\n"
-" }else{\n"
-" curr_bin = (long long int)(curr_fj_ts/"+bloom_width_str+");\n"
-" if(curr_bin != t->last_bin){\n"
-" for(the_bin=t->last_bin+1;the_bin<=curr_bin;the_bin++){\n"
-" t->last_bloom_pos++;\n"
-" if(t->last_bloom_pos >= "+int_to_string(n_bloom)+")\n"
-" t->last_bloom_pos = 0;\n"
-" tmp_i = t->last_bloom_pos;\n"
-" for(j=0;j<"+int_to_string(bf_bit_size)+";j++){\n"
-" SET_BF_EMPTY(t->bf_table, "+int_to_string(n_bloom)+", tmp_i,j);\n"
-" }\n"
-" }\n"
-" }\n"
-" t->last_bin = curr_bin;\n"
-" }\n"
-;
- }
-
-
-//-----------------------------------------------------------------
-// First, determine whether to do S (filter stream) processing.
-
- ret +=
-"// S (filtering stream) predicate, should it be processed?\n"
-"\n"
-;
-// Sort S preds based on cost.
- vector<cnf_elem *> s_filt = fs->pred_t1;
- col_id_set::iterator csi;
- if(s_filt.size() > 0){
-
-// Unpack fields ref'd in the S pred
- for(w=0;w<s_filt.size();++w){
- col_id_set this_pred_cids;
- gather_pr_col_ids(s_filt[w]->pr, this_pred_cids, gb_tbl);
- for(csi=this_pred_cids.begin();csi!=this_pred_cids.end();++csi){
- if(unpacked_cids.count( (*csi) ) == 0){
- int tblref = (*csi).tblvar_ref;
- int schref = (*csi).schema_ref;
- string field = (*csi).field;
- ret += generate_unpack_code(tblref,schref,field,schema,node_name,"end_s");
- unpacked_cids.insert( (*csi) );
- }
- }
- }
-
-
-// Sort by evaluation cost.
-// First, estimate evaluation costs
-// Eliminate predicates covered by the prefilter (those in s_pids).
-// I need to do it before the sort becuase the indices refer
-// to the position in the unsorted list.
- vector<cnf_elem *> tmp_wh;
- for(w=0;w<s_filt.size();++w){
- compute_cnf_cost(s_filt[w],Ext_fcns);
- tmp_wh.push_back(s_filt[w]);
- }
- s_filt = tmp_wh;
-
- sort(s_filt.begin(), s_filt.end(), compare_cnf_cost());
-
-// Now generate the predicates.
- for(w=0;w<s_filt.size();++w){
- sprintf(tmpstr,"//\t\tPredicate clause %d.(cost %d)\n",w,s_filt[w]->cost);
- ret += tmpstr;
-
-// Find partial fcns ref'd in this cnf element
- set<int> pfcn_refs;
- collect_partial_fcns_pr(s_filt[w]->pr, pfcn_refs);
-// Since set<..> is a "Sorted Associative Container",
-// we can walk through it in sorted order by walking from
-// begin() to end(). (and the partial fcns must be
-// evaluated in this order).
- set<int>::iterator si;
- string pf_preds;
- for(si=pfcn_refs.begin();si!=pfcn_refs.end();++si){
- if(fcn_ref_cnt[(*si)] > 1){
- ret += "\tif(fcn_ref_cnt_"+int_to_string((*si))+"==0){\n";
- }
- if(is_partial_fcn[(*si)]){
- ret += "\t"+unpack_partial_fcn(partial_fcns[(*si)], (*si), schema);
- ret += "\t\tif(retval) goto end_s;\n";
- }
- if(fcn_ref_cnt[(*si)] > 1){
- if(!is_partial_fcn[(*si)]){
- ret += "\t\tpartial_fcn_result_"+int_to_string((*si))+"="+generate_cached_fcn(partial_fcns[(*si)],schema)+";\n";
-// Testing for S is a side branch.
-// I don't want a cacheable partial function to be
-// marked as evaluated. Therefore I mark the function
-// as evalauted ONLY IF it is not partial.
- ret += "\t\tfcn_ref_cnt_"+int_to_string((*si))+"=1;\n";
- }
- ret += "\t}\n";
- }
- }
-
- ret += "\tif( !("+generate_predicate_code(s_filt[w]->pr,schema)+
- ") ) goto end_s;\n";
- }
- }else{
- ret += "\n\n/*\t\t (no predicate to test)\t*/\n\n";
- }
-
- for(p=0;p<fs->hash_eq.size();++p)
- ret += "\t\ts_equijoin_"+int_to_string(p)+" = "+generate_se_code(fs->hash_eq[p]->pr->get_right_se(),schema)+";\n";
-
- if(fs->use_bloom){
-// First, generate the S scalar expressions in the hash_eq
-
-// Iterate over the bloom filters
- for(i=0;i<3;i++){
- ret += "\t\tbucket=0;\n";
- for(p=0;p<fs->hash_eq.size();++p){
- ret +=
-" bucket ^= (("+hash_nums[(i*fs->hash_eq.size()+p)%NRANDS]+" * lfta_"+
- fs->hash_eq[p]->pr->get_right_se()->get_data_type()->get_type_str()+
- +"_to_hash(s_equijoin_"+int_to_string(p)+"))>>32);\n";
- }
-// SET_BF_BIT(table,number of bloom filters,bloom filter index,bit index)
- ret +=
-" bucket &= "+int_to_string(bf_mask)+";\n"
-" SET_BF_BIT(t->bf_table,"+int_to_string(n_bloom)+",t->last_bloom_pos,bucket);\n"
-"\n"
-;
- }
- }else{
- ret += "\t\tbucket=0;\n";
- for(p=0;p<fs->hash_eq.size();++p){
- ret +=
-" bucket ^= (("+hash_nums[(i*fs->hash_eq.size()+p)%NRANDS]+" * lfta_"+
- fs->hash_eq[p]->pr->get_right_se()->get_data_type()->get_type_str()+
- +"_to_hash(s_equijoin_"+int_to_string(p)+"))>>32);\n";
- }
- ret +=
-" bucket &= "+int_to_string(bf_mask)+";\n"
-" bucket1 = (bucket + 1) & "+int_to_string(bf_mask)+";\n"
-;
-// Try the first bucket
- ret += "\t\tif(";
- for(p=0;p<fs->hash_eq.size();++p){
- if(p>0) ret += " && ";
-// ret += "t->join_table[bucket].key_var"+int_to_string(p)+
-// " == s_equijoin_"+int_to_string(p);
- data_type *hdt = fs->hash_eq[p]->pr->get_right_se()->get_data_type();
- string lhs_op = "t->join_table[bucket].key_var"+int_to_string(p);
- string rhs_op = "s_equijoin_"+int_to_string(p);
- ret += generate_equality_test(lhs_op,rhs_op,hdt);
- }
- ret += "){\n\t\t\tthe_bucket = bucket;\n";
- ret += "\t\t}else {if(";
- for(p=0;p<fs->hash_eq.size();++p){
- if(p>0) ret += " && ";
-// ret += "t->join_table[bucket1].key_var"+int_to_string(p)+
-// " == s_equijoin_"+int_to_string(p);
- data_type *hdt = fs->hash_eq[p]->pr->get_right_se()->get_data_type();
- string lhs_op = "t->join_table[bucket].key_var"+int_to_string(p);
- string rhs_op = "s_equijoin_"+int_to_string(p);
- ret += generate_equality_test(lhs_op,rhs_op,hdt);
- }
- ret += "){\n\t\t\tthe_bucket = bucket1;\n";
- ret += "\t\t}else{ if(t->join_table[bucket].ts <= t->join_table[bucket1].ts)\n";
- ret+="\t\t\tthe_bucket = bucket;\n\t\t\telse the_bucket=bucket1;\n";
- ret += "\t\t}}\n";
- for(p=0;p<fs->hash_eq.size();++p){
- data_type *hdt = fs->hash_eq[p]->pr->get_right_se()->get_data_type();
- if(hdt->is_buffer_type()){
- sprintf(tmpstr,"\t\t%s(f, &(t->join_table[the_bucket].key_var%d), &s_equijoin_%d);\n", hdt->get_buffer_assign_copy().c_str(), p, p);
- ret += tmpstr;
- }else{
- ret += "\t\tt->join_table[the_bucket].key_var"+int_to_string(p)+
- " = s_equijoin_"+int_to_string(p)+";\n";
- }
- }
- ret+="\t\tt->join_table[the_bucket].ts = curr_fj_ts;\n";
- }
- ret += "\tend_s:\n";
-
-// ------------------------------------------------------------
-// Next, determine if the R record should be processed.
-
-
- ret +=
-"// R (main stream) cheap predicate\n"
-"\n"
-;
-
-// Unpack r_filt fields
- vector<cnf_elem *> r_filt = fs->pred_t0;
- for(w=0;w<r_filt.size();++w){
- col_id_set this_pred_cids;
- gather_pr_col_ids(r_filt[w]->pr, this_pred_cids, gb_tbl);
- for(csi=this_pred_cids.begin();csi!=this_pred_cids.end();++csi){
- if(unpacked_cids.count( (*csi) ) == 0){
- int tblref = (*csi).tblvar_ref;
- int schref = (*csi).schema_ref;
- string field = (*csi).field;
- ret += generate_unpack_code(tblref,schref,field,schema,node_name);
- unpacked_cids.insert( (*csi) );
- }
- }
- }
-
-// Sort S preds based on cost.
-
- vector<cnf_elem *> tmp_wh;
- for(w=0;w<r_filt.size();++w){
- compute_cnf_cost(r_filt[w],Ext_fcns);
- tmp_wh.push_back(r_filt[w]);
- }
- r_filt = tmp_wh;
-
- sort(r_filt.begin(), r_filt.end(), compare_cnf_cost());
-
-// WARNING! the constant 20 below is a wild-ass guess.
- int cheap_rpos;
- for(cheap_rpos=0;cheap_rpos<r_filt.size() && r_filt[cheap_rpos]->cost <= 20;cheap_rpos++)
-
-// Test the cheap filters on R.
- if(cheap_rpos >0){
-
-// Now generate the predicates.
- for(w=0;w<cheap_rpos;++w){
- sprintf(tmpstr,"//\t\tPredicate clause %d.(cost %d)\n",w,r_filt[w]->cost);
- ret += tmpstr;
-
-// Find partial fcns ref'd in this cnf element
- set<int> pfcn_refs;
- collect_partial_fcns_pr(r_filt[w]->pr, pfcn_refs);
-// Since set<..> is a "Sorted Associative Container",
-// we can walk through it in sorted order by walking from
-// begin() to end(). (and the partial fcns must be
-// evaluated in this order).
- set<int>::iterator si;
- for(si=pfcn_refs.begin();si!=pfcn_refs.end();++si){
- if(fcn_ref_cnt[(*si)] > 1){
- ret += "\tif(fcn_ref_cnt_"+int_to_string((*si))+"==0){\n";
- }
- if(is_partial_fcn[(*si)]){
- ret += "\t"+unpack_partial_fcn(partial_fcns[(*si)], (*si), schema);
- ret += "\t\tif(retval) goto end;\n";
- }
- if(fcn_ref_cnt[(*si)] > 1){
- if(!is_partial_fcn[(*si)]){
- ret += "\t\tpartial_fcn_result_"+int_to_string((*si))+"="+generate_cached_fcn(partial_fcns[(*si)],schema)+";\n";
- }
- ret += "\t\tfcn_ref_cnt_"+int_to_string((*si))+"=1;\n";
- ret += "\t}\n";
- }
- }
-
- ret += "\tif( !("+generate_predicate_code(r_filt[w]->pr,schema)+
- ") ) goto end;\n";
- }
- }else{
- ret += "\n\n/*\t\t (no predicate to test)\t*/\n\n";
- }
-
- ret += "\n// Do the join\n\n";
- for(p=0;p<fs->hash_eq.size();++p)
- ret += "\t\tr_equijoin_"+int_to_string(p)+" = "+generate_se_code(fs->hash_eq[p]->pr->get_left_se(),schema)+";\n";
-
-
-// Passed the cheap pred, now test the join with S.
- if(fs->use_bloom){
- for(i=0;i<3;i++){
- ret += "\t\tbucket"+int_to_string(i)+"=0;\n";
- for(p=0;p<fs->hash_eq.size();++p){
- ret +=
-" bucket"+int_to_string(i)+
- " ^= (("+hash_nums[(i*fs->hash_eq.size()+p)%NRANDS]+" * lfta_"+
- fs->hash_eq[p]->pr->get_right_se()->get_data_type()->get_type_str()+
- +"_to_hash(r_equijoin_"+int_to_string(p)+"))>>32);\n";
- }
- ret +=
-" bucket"+int_to_string(i)+" &= "+int_to_string(bf_mask)+";\n";
- }
- ret += "\tfound = 0;\n";
- ret += "\tfor(b=0;b<"+int_to_string(n_bloom)+" && !found; b++){\n";
- ret +=
-"\t\tif(IS_BF_SET(t->bf_table,"+int_to_string(n_bloom)+",t->last_bloom_pos,bucket0) && "
-"IS_BF_SET(t->bf_table,"+int_to_string(n_bloom)+",t->last_bloom_pos,bucket1) && "
-"IS_BF_SET(t->bf_table,"+int_to_string(n_bloom)+",t->last_bloom_pos,bucket2))\n "
-"\t\t\tfound=1;\n"
-"\t}\n"
-;
- ret +=
-" if(!found)\n"
-" goto end;\n"
-;
- }else{
- ret += "\tfound = 0;\n";
- ret += "\t\tbucket=0;\n";
- for(p=0;p<fs->hash_eq.size();++p){
- ret +=
-" bucket ^= (("+hash_nums[(i*fs->hash_eq.size()+p)%NRANDS]+" * lfta_"+
- fs->hash_eq[p]->pr->get_right_se()->get_data_type()->get_type_str()+
- +"_to_hash(r_equijoin_"+int_to_string(p)+"))>>32);\n";
- }
- ret +=
-" bucket &= "+int_to_string(bf_mask)+";\n"
-" bucket1 = (bucket + 1) & "+int_to_string(bf_mask)+";\n"
-;
-// Try the first bucket
- ret += "\t\tif(";
- for(p=0;p<fs->hash_eq.size();++p){
- if(p>0) ret += " && ";
-// ret += "t->join_table[bucket].key_var"+int_to_string(p)+
-// " == r_equijoin_"+int_to_string(p);
- data_type *hdt = fs->hash_eq[p]->pr->get_right_se()->get_data_type();
- string lhs_op = "t->join_table[bucket].key_var"+int_to_string(p);
- string rhs_op = "s_equijoin_"+int_to_string(p);
- ret += generate_equality_test(lhs_op,rhs_op,hdt);
- }
- if(p>0) ret += " && ";
- ret += "t->join_table[bucket].ts+"+int_to_string(fs->temporal_range)+" <= curr_fj_ts";
- ret += "){\n\t\t\tfound = 1;\n";
- ret += "\t\t}else {if(";
- for(p=0;p<fs->hash_eq.size();++p){
- if(p>0) ret += " && ";
-// ret += "t->join_table[bucket1].key_var"+int_to_string(p)+
-// " == r_equijoin_"+int_to_string(p);
- data_type *hdt = fs->hash_eq[p]->pr->get_right_se()->get_data_type();
- string lhs_op = "t->join_table[bucket].key_var"+int_to_string(p);
- string rhs_op = "s_equijoin_"+int_to_string(p);
- ret += generate_equality_test(lhs_op,rhs_op,hdt);
- }
- if(p>0) ret += " && ";
- ret += "t->join_table[bucket1].ts+"+int_to_string(fs->temporal_range)+" <= curr_fj_ts";
- ret += ")\n\t\t\tfound=1;\n";
- ret+="\t\t}\n";
- ret +=
-" if(!found)\n"
-" goto end;\n"
-;
- }
-
-
-// Test the expensive filters on R.
- if(cheap_rpos < r_filt.size()){
-
-// Now generate the predicates.
- for(w=cheap_rpos;w<r_filt.size();++w){
- sprintf(tmpstr,"//\t\tPredicate clause %d.(cost %d)\n",w,r_filt[w]->cost);
- ret += tmpstr;
-
-// Find partial fcns ref'd in this cnf element
- set<int> pfcn_refs;
- collect_partial_fcns_pr(r_filt[w]->pr, pfcn_refs);
-// Since set<..> is a "Sorted Associative Container",
-// we can walk through it in sorted order by walking from
-// begin() to end(). (and the partial fcns must be
-// evaluated in this order).
- set<int>::iterator si;
- for(si=pfcn_refs.begin();si!=pfcn_refs.end();++si){
- if(fcn_ref_cnt[(*si)] > 1){
- ret += "\tif(fcn_ref_cnt_"+int_to_string((*si))+"==0){\n";
- }
- if(is_partial_fcn[(*si)]){
- ret += "\t"+unpack_partial_fcn(partial_fcns[(*si)], (*si), schema);
- ret += "\t\tif(retval) goto end;\n";
- }
- if(fcn_ref_cnt[(*si)] > 1){
- if(!is_partial_fcn[(*si)]){
- ret += "\t\tpartial_fcn_result_"+int_to_string((*si))+"="+generate_cached_fcn(partial_fcns[(*si)],schema)+";\n";
- }
- ret += "\t\tfcn_ref_cnt_"+int_to_string((*si))+"=1;\n";
- ret += "\t}\n";
- }
- }
-
- ret += "\tif( !("+generate_predicate_code(r_filt[w]->pr,schema)+
- ") ) goto end;\n";
- }
- }else{
- ret += "\n\n/*\t\t (no predicate to test)\t*/\n\n";
- }
-
-
-
-/////////////// post the tuple
-
-// test passed : create the tuple, then assign to it.
- ret += "/*\t\tCreate and post the tuple\t*/\n";
-
-// Unpack r_filt fields
- for(s=0;s<sl_list.size();++s){
- col_id_set this_se_cids;
- gather_se_col_ids(sl_list[s], this_se_cids, gb_tbl);
- for(csi=this_se_cids.begin();csi!=this_se_cids.end();++csi){
- if(unpacked_cids.count( (*csi) ) == 0){
- int tblref = (*csi).tblvar_ref;
- int schref = (*csi).schema_ref;
- string field = (*csi).field;
- ret += generate_unpack_code(tblref,schref,field,schema,node_name);
- unpacked_cids.insert( (*csi) );
- }
- }
- }
-
-
-// Unpack partial fcns ref'd by the select clause.
-// Its a kind of a WHERE clause ...
- for(p=sl_fcns_start;p<sl_fcns_end;p++){
- if(fcn_ref_cnt[p] > 1){
- ret += "\tif(fcn_ref_cnt_"+int_to_string(p)+"==0){\n";
- }
- if(is_partial_fcn[p]){
- ret += unpack_partial_fcn(partial_fcns[p], p, schema);
- ret += "\tif(retval) goto end;\n";
- }
- if(fcn_ref_cnt[p] > 1){
- if(!is_partial_fcn[p]){
- ret += "\t\tpartial_fcn_result_"+int_to_string(p)+"="+generate_cached_fcn(partial_fcns[p],schema)+";\n";
- }
- ret += "\t\tfcn_ref_cnt_"+int_to_string(p)+"=1;\n";
- ret += "\t}\n";
- }
- }
-
- // increment the counter of accepted tuples
- ret += "\n\t#ifdef LFTA_STATS\n";
- ret += "\n\tt->accepted_tuple_cnt++;\n\n";
- ret += "\t#endif\n\n";
-
-// First, compute the size of the tuple.
-
-// Unpack any BUFFER type selections into temporaries
-// so that I can compute their size and not have
-// to recompute their value during tuple packing.
-// I can use regular assignment here because
-// these temporaries are non-persistent.
-
- for(s=0;s<sl_list.size();s++){
- data_type *sdt = sl_list[s]->get_data_type();
- if(sdt->is_buffer_type()){
- sprintf(tmpstr,"\tselvar_%d = ",s);
- ret += tmpstr;
- ret += generate_se_code(sl_list[s],schema);
- ret += ";\n";
- }
- }
-
-
-// The size of the tuple is the size of the tuple struct plus the
-// size of the buffers to be copied in.
-
- ret+="\ttuple_size = sizeof( struct "+generate_tuple_name(node_name)+")";
- for(s=0;s<sl_list.size();s++){
- data_type *sdt = sl_list[s]->get_data_type();
- if(sdt->is_buffer_type()){
- sprintf(tmpstr," + %s(&selvar_%d)", sdt->get_buffer_size().c_str(),s);
- ret += tmpstr;
- }
- }
- ret += ";\n";
-
-
- ret += "\ttuple = allocate_tuple(f, tuple_size );\n";
- ret += "\tif( tuple == NULL)\n\t\tgoto end;\n";
-
-// Test passed, make assignments to the tuple.
-
- ret += "\ttuple_pos = sizeof( struct "+generate_tuple_name(node_name)+");\n";
-
-// Mark tuple as REGULAR_TUPLE
- ret += "\ttuple->tuple_type = REGULAR_TUPLE;\n";
-
-
- for(s=0;s<sl_list.size();s++){
- data_type *sdt = sl_list[s]->get_data_type();
- if(sdt->is_buffer_type()){
- sprintf(tmpstr,"\t%s(&(tuple->tuple_var%d), &selvar_%d, (char *)tuple, ((char *)tuple)+tuple_pos);\n", sdt->get_buffer_tuple_copy().c_str(),s, s);
- ret += tmpstr;
- sprintf(tmpstr,"\ttuple_pos += %s(&selvar_%d);\n", sdt->get_buffer_size().c_str(), s);
- ret += tmpstr;
- }else{
- sprintf(tmpstr,"\ttuple->tuple_var%d = ",s);
- ret += tmpstr;
-// if(sdt->needs_hn_translation())
-// ret += sdt->hton_translation() +"( ";
- ret += generate_se_code(sl_list[s],schema);
-// if(sdt->needs_hn_translation())
-// ret += ") ";
- ret += ";\n";
- }
- }
-
-// Generate output.
-
- ret += "\tpost_tuple(tuple);\n";
-
-// Increment the counter of posted tuples
- ret += "\n\t#ifdef LFTA_STATS\n";
- ret += "\n\tt->out_tuple_cnt++;\n\n";
- ret+="\t\t\t\tt->out_tuple_sz+=tuple_size;\n";
- ret += "\t#endif\n\n";
-
-
- return ret;
-}
-
-string generate_aggr_accept_body(qp_node *fs,string node_name,table_list *schema, string &temporal_flush){
- string ret;
- int a,p,g;
-
-////////////// Processing for aggregtion query
-
-// First, search for a match. Start by unpacking the group-by attributes.
-
-// One complication : if a real-time aggregate flush occurs,
-// the GB attr has already been calculated. So don't compute
-// it again if 1) its temporal and 2) it will be computed in the
-// agggregate flush code.
-
-// Unpack the partial fcns ref'd by the gb's and the aggr defs.
- for(p=gb_fcns_start;p<gb_fcns_end;p++){
- if(is_partial_fcn[p]){
- ret += unpack_partial_fcn(partial_fcns[p], p, schema);
- ret += "\tif(retval) goto end;\n";
- }
- }
- for(p=ag_fcns_start;p<ag_fcns_end;p++){
- if(is_partial_fcn[p]){
- ret += unpack_partial_fcn(partial_fcns[p], p, schema);
- ret += "\tif(retval) goto end;\n";
- }
- }
-
- // increment the counter of accepted tuples
- ret += "\n\t#ifdef LFTA_STATS\n";
- ret += "\n\tt->accepted_tuple_cnt++;\n\n";
- ret += "\t#endif\n\n";
-
- ret += "/*\t\tTest if the group is in the hash table \t*/\n";
-// Compute the values of the group-by variables.
- for(g=0;g<gb_tbl->size();g++){
- data_type *gdt = gb_tbl->get_data_type(g);
- if((! gdt->is_temporal()) || temporal_flush == ""){
-
- if(gdt->is_buffer_type()){
- // NOTE : if the SE defining the gb is anything
- // other than a ref to a variable, this will generate
- // illegal code. To be resolved with Spatch.
- sprintf(tmpstr,"\tgb_attr_tmp%d = %s;\n",
- g, generate_se_code(gb_tbl->get_def(g),schema).c_str() );
- ret += tmpstr;
- sprintf(tmpstr,"\t%s(f, &gb_attr_%d, &gb_attr_tmp%d);\n",
- gdt->get_buffer_assign_copy().c_str(), g, g);
- }else{
- sprintf(tmpstr,"\tgb_attr_%d = %s;\n",g,generate_se_code(gb_tbl->get_def(g),schema).c_str());
- }
- ret += tmpstr;
- }
- }
- ret += "\n";
-
-// A quick aside : if any of the GB attrs are temporal,
-// test for change and flush if any change occurred.
-// We've already computed the flush code,
-// Put it here if this is not a real time query.
-// We've already unpacked all column refs, so no need to
-// do it again here.
-
- string rt_level = fs->get_val_of_def("real_time");
- if(rt_level == "" && temporal_flush != ""){
- ret += temporal_flush;
- }
-
-// Compute the hash bucket
- if(gb_tbl->size() > 0){
- ret += "\thashval = ";\
- for(g=0;g<gb_tbl->size();g++){
- if(g>0) ret += " ^ ";
- data_type *gdt = gb_tbl->get_data_type(g);
- if(gdt->is_buffer_type()){
- sprintf(tmpstr,"((%s * lfta_%s_to_hash(gb_attr_%d)))",hash_nums[g%NRANDS].c_str(),
- gdt->get_type_str().c_str(), g);
- }else{
- sprintf(tmpstr,"((%s * lfta_%s_to_hash(gb_attr_%d)))",hash_nums[g%NRANDS].c_str(),
- gdt->get_type_str().c_str(), g);
- }
- ret += tmpstr;
- }
- ret += ";\n";
- ret += "\thash2 = ((hashval * "+hash_nums[g%NRANDS]+") >> 32) & SLOT_HASH_BITS;\n";
- ret+="\tprobe = (hashval >> 32) & (t->max_aggrs-1);\n";
- }else{
- ret+="\tprobe = 0;\n";
- ret+="\thash2 = 0;\n\n";
- }
-
-// Does the lfta reference a udaf?
- bool has_udaf = false;
- for(a=0;a<aggr_tbl->size();a++){
- if(! aggr_tbl->is_builtin(a)) has_udaf = true;
- }
-
-// Scan for a match, or alternatively the best slot.
-// Currently, hardcode 5 tests.
- ret +=
-" gen_val = t->generation & SLOT_GEN_BITS;\n"
-" match_found = 0;\n"
-" best_slot = probe;\n"
-" for(i=0;i<5 && match_found == 0;i++){\n"
-" if((t->aggr_table_hashmap[probe] & SLOT_FILLED) && (t->aggr_table_hashmap[probe] & SLOT_GEN_BITS) == gen_val && (t->aggr_table_hashmap[probe] & SLOT_HASH_BITS) == hash2 ){\n"
-;
- if(gb_tbl->size()>0){
- ret+="\n\t/* \t\tcheck if the grouping variables are equal */\n";
- ret+="\t\tif(";
- string rhs_op, lhs_op;
- for(g=0;g<gb_tbl->size();g++){
- if(g>0) ret += " && ";
- ret += "(";
- sprintf(tmpstr,"gb_attr_%d",g); lhs_op = tmpstr;
- sprintf(tmpstr,"t->aggr_table[probe].gb_var%d",g); rhs_op = tmpstr;
- ret += generate_equality_test(lhs_op,rhs_op,gb_tbl->get_data_type(g));
- ret += ")";
- }
- }
- ret += "){\n"
-" match_found = 1;\n"
-" best_slot = probe;\n"
-" }\n"
-" }\n"
-"// Rate slots in case no match found: prefer empty, then full but old slots\n"
-" if(t->aggr_table_hashmap[best_slot] & SLOT_FILLED){\n"
-" if((t->aggr_table_hashmap[probe] & SLOT_FILLED)==0)\n"
-" best_slot = probe;\n"
-" }else{\n"
-" if((t->aggr_table_hashmap[best_slot] & SLOT_GEN_BITS) == gen_val && (t->aggr_table_hashmap[probe] & SLOT_GEN_BITS) != gen_val){\n"
-" best_slot = probe;\n"
-" }\n"
-" }\n"
-" probe++;\n"
-" if(probe >= t->max_aggrs)\n"
-" probe=0;\n"
-" }\n"
-" if(match_found){\n"
-;
- ret += generate_gb_update(node_name, schema, "best_slot",has_udaf);
- ret +=
-" }else{\n"
-" if(t->aggr_table_hashmap[best_slot] & SLOT_FILLED){\n"
-;
-printf("sgah_qpn name is %s, disorder is %d\n",fs->node_name.c_str(),((sgah_qpn *)fs)->lfta_disorder);
- if(((sgah_qpn *)fs)->lfta_disorder <= 1){
- ret +=
-" if((t->aggr_table_hashmap[best_slot] & SLOT_GEN_BITS)==gen_val){\n"
-" if((";
- bool first_g = true;
- for(int g=0;g<gb_tbl->size();g++){
- data_type *gdt = gb_tbl->get_data_type(g);
- if(gdt->is_temporal()){
- if(first_g) first_g = false; else ret+=" + ";
- ret += "(gb_attr_"+int_to_string(g)+" - t->aggr_table[best_slot].gb_var"+int_to_string(g)+")";
- }
- }
- ret += ") == 0 ){\n";
-
- ret +=
-" fta_aggr_flush_old_"+ node_name+"(f,t->max_aggrs);\n"
-" }\n"
-" }\n"
-;
- }
-
- ret += generate_tuple_from_aggr(node_name,schema,"best_slot");
- ret +=
-"\t\t\t#ifdef LFTA_STATS\n"
-"\t\t\tif((t->aggr_table_hashmap[best_slot] & SLOT_GEN_BITS) == gen_val)\n"
-"\t\t\t\tt->collision_cnt++;\n\n"
-"\t\t\t#endif\n\n"
-"\t\t}\n"
-;
- ret += generate_init_group(schema,"best_slot");
-
-
- ret += "\t}\n";
-
- return ret;
-}
-
-
-
-string generate_fta_accept(qp_node *fs, string node_name, table_list *schema, ext_fcn_list *Ext_fcns, bool is_aggr_query, bool is_fj, set<unsigned int> &s_pids){
-
- string ret="static gs_retval_t accept_packet_"+node_name+
- "(struct FTA *f, FTAID * ftaid, void *pkt, gs_int32_t sz){\n";
- ret += "\tstruct packet *p = (struct packet *)pkt;\n";
-
- int a;
-
-// Define all of the variables needed by this
-// procedure.
-
-
-// Gather all column references, need to define unpacking variables.
- int w,s;
- col_id_set cid_set;
- col_id_set::iterator csi;
-
-// If its a filter join, rebind all colrefs
-// to the first range var, to avoid double unpacking.
-
- if(is_fj){
- for(w=0;w<where.size();++w)
- reset_pr_col_ids_tblvars(where[w]->pr, gb_tbl);
- for(s=0;s<sl_list.size();s++)
- reset_se_col_ids_tblvars(sl_list[s], gb_tbl);
- }
-
- for(w=0;w<where.size();++w){
- if(is_fj || s_pids.count(w) == 0)
- gather_pr_col_ids(where[w]->pr,cid_set, gb_tbl);
- }
- for(s=0;s<sl_list.size();s++){
- gather_se_col_ids(sl_list[s],cid_set, gb_tbl);
- }
-
- int g;
- if(gb_tbl != NULL){
- for(g=0;g<gb_tbl->size();g++)
- gather_se_col_ids(gb_tbl->get_def(g),cid_set, gb_tbl);
- }
-
- // Variables for unpacking attributes.
- ret += "/*\t\tVariables for unpacking attributes\t*/\n";
- for(csi=cid_set.begin(); csi!=cid_set.end();++csi){
- int schref = (*csi).schema_ref;
- int tblref = (*csi).tblvar_ref;
- string field = (*csi).field;
- data_type dt(schema->get_type_name(schref,field));
- sprintf(tmpstr,"\t%s unpack_var_%s_%d;\n",dt.get_cvar_type().c_str(),
- field.c_str(), tblref);
- ret += tmpstr;
- }
-
- ret += "\n\n";
-
-// Variables that are always needed
- ret += "/*\t\tVariables which are always needed\t*/\n";
- ret += "\tgs_retval_t retval;\n";
- ret += "\tgs_int32_t tuple_size, tuple_pos, lfta_bailout;\n";
- ret += "\tstruct "+generate_tuple_name(node_name)+" *tuple;\n";
-
- ret+="\tstruct "+generate_fta_name(node_name)+" *t = (struct "+generate_fta_name(node_name)+"*) f;\n\n";
-
-
-// Variables needed for aggregation queries.
- if(is_aggr_query){
- ret += "\n/*\t\tVariables for aggregation\t*/\n";
- ret+="\tunsigned int i, probe;\n";
- ret+="\tunsigned int gen_val, match_found, best_slot;\n";
- ret+="\tgs_uint64_t hashval, hash2;\n";
-// Variables for storing group-by attribute values.
- if(gb_tbl->size() > 0)
- ret += "/*\t\tGroup-by attributes\t*/\n";
- for(g=0;g<gb_tbl->size();g++){
- sprintf(tmpstr,"\t%s gb_attr_%d;\n",gb_tbl->get_data_type(g)->get_cvar_type().c_str(),g);
- ret += tmpstr;
- data_type *gdt = gb_tbl->get_data_type(g);
- if(gdt->is_buffer_type()){
- sprintf(tmpstr,"\t%s gb_attr_tmp%d;\n",gb_tbl->get_data_type(g)->get_cvar_type().c_str(),g);
- ret += tmpstr;
- }
- }
- ret += "\n";
-// Temporaries for min/max
- string aggr_tmp_str = "";
- for(a=0;a<aggr_tbl->size();a++){
- string aggr_op = aggr_tbl->get_op(a);
- if(aggr_op == "MIN" || aggr_op == "MAX"){
- sprintf(tmpstr,"\t%s aggr_tmp_%d;\n",aggr_tbl->get_data_type(a)->get_cvar_type().c_str(),a);
- aggr_tmp_str.append(tmpstr);
- }
- }
- if(aggr_tmp_str != ""){
- ret += "/*\t\tTemp vars for BUFFER aggregates\t*/\n";
- ret += aggr_tmp_str;
- ret += "\n";
- }
-// Variables for udaf output temporaries
- bool no_udaf = true;
- for(a=0;a<aggr_tbl->size();a++){
- if(! aggr_tbl->is_builtin(a)){
- if(no_udaf){
- ret+="/*\t\tUDAF output vars.\t*/\n";
- no_udaf = false;
- }
- int afcn_id = aggr_tbl->get_fcn_id(a);
- data_type *adt = Ext_fcns->get_fcn_dt(afcn_id);
- sprintf(tmpstr,"udaf_ret%d", a);
- ret+="\t"+adt->make_cvar(tmpstr)+";\n";
- }
- }
- }
-
-// Variables needed for a filter join query
- if(fs->node_type() == "filter_join"){
- filter_join_qpn *fjq = (filter_join_qpn *)fs;
- bool uses_bloom = fjq->use_bloom;
- ret += "/*\t\tJoin fields\t*/\n";
- for(g=0;g<fjq->hash_eq.size();g++){
- sprintf(tmpstr,"\t%s s_equijoin_%d, r_equijoin_%d;\n",fjq->hash_eq[g]->pr->get_left_se()->get_data_type()->get_cvar_type().c_str(),g,g);
- ret += tmpstr;
- }
- if(uses_bloom){
- ret +=
-" /* Variables for fj bloom filter */ \n"
-"\tunsigned int i=0,j=0,k=0, b, bf_clean = 0, tmp_i, found; \n"
-"\tunsigned int bucket, bucket0, bucket1, bucket2;\n"
-"\tlong long int curr_fj_ts;\n"
-"\tunsigned int curr_bin, the_bin;\n"
-"\n"
-;
- }else{
- ret +=
-" /* Variables for fj join table */ \n"
-"\tunsigned int i, bucket, found; \n"
-"\tunsigned int bucket1, the_bucket;\n"
-" long long int curr_fj_ts;\n"
-"\n"
-;
- }
- }
-
-
-// Variables needed to store selected attributes of BUFFER type
-// temporarily, in order to compute their size for storage
-// in an output tuple.
-
- string select_var_defs = "";
- for(s=0;s<sl_list.size();s++){
- data_type *sdt = sl_list[s]->get_data_type();
- if(sdt->is_buffer_type()){
- sprintf(tmpstr,"\t%s selvar_%d;\n",sdt->get_cvar_type().c_str(),s);
- select_var_defs.append(tmpstr);
- }
- }
- if(select_var_defs != ""){
- ret += "/*\t\tTemporaries for computing buffer sizes.\t*/\n";
- ret += select_var_defs;
- }
-
-// Variables to store results of partial functions.
- int p;
- if(partial_fcns.size()>0){
- ret += "/*\t\tVariables for storing results of partial functions. \t*/\n";
- for(p=0;p<partial_fcns.size();++p){
- if(is_partial_fcn[p] || (!is_aggr_query && fcn_ref_cnt[p] >1)){
- sprintf(tmpstr,"\t%s partial_fcn_result_%d;\n",
- partial_fcns[p]->get_data_type()->get_cvar_type().c_str(), p);
- ret += tmpstr;
- if(!is_aggr_query && fcn_ref_cnt[p] >1){
- ret += "\tint fcn_ref_cnt_"+int_to_string(p)+" = 0;\n";
- }
- }
- }
-
- if(is_aggr_query) ret += "\tint unpack_failed = 0;\n";
- ret += "\n";
- }
-
-// variable to hold packet struct //
- if(packed_return){
- ret += "\t struct "+node_name+"_input_struct *"+node_name+"_input_struct_var;\n";
- }
-
-
- ret += "\t#ifdef LFTA_STATS\n";
-// variable to store counter of cpu cycles spend in accept_tuple
- ret += "\tgs_uint64_t start_cycle = rdtsc();\n";
-// increment counter of received tuples
- ret += "\tt->in_tuple_cnt++;\n";
- ret += "\t#endif\n";
-
-
-// -------------------------------------------------
-// If the packet is "packet", test if its for this lfta,
-// and if so load it into its struct
-
- if(packed_return){
- ret+="\n/* packed tuple : test and load. \t*/\n";
- ret+="\t"+node_name+"_input_struct_var = (struct "+node_name+"_input_struct *) pkt;\n";
- ret+="\tif("+node_name+"_input_struct_var->__lfta_id_fm_nic__ != "+int_to_string(global_id) + ")\n";
- ret+="\t\tgoto end;\n\n";
- }
-
-
-
- col_id_set unpacked_cids; // Keep track of the cols that have been unpacked.
-
- string temporal_flush;
- if(is_aggr_query)
- ret += generate_aggr_accept_prelim(fs, node_name, schema, unpacked_cids, temporal_flush);
- else { // non-aggregation operators
-
-// Unpack all the temporal attributes referenced in select clause
-// and update the last value of the attribute
- col_id_set temp_cids; // col ids of temp attributes in select clause
-
- for(s=0;s<sl_list.size();s++){
- data_type *sdt = sl_list[s]->get_data_type();
- if (sdt->is_temporal()) {
- gather_se_col_ids(sl_list[s],temp_cids, gb_tbl);
- }
- }
-// If this is a filter join,
-// ensure that the temporal range field is unpacked.
- if(is_fj){
- col_id window_var_cid(((filter_join_qpn *)fs)->temporal_var);
- if(temp_cids.count(window_var_cid)==0)
- temp_cids.insert(window_var_cid);
- }
-
- for(csi=temp_cids.begin(); csi != temp_cids.end();++csi){
- if(unpacked_cids.count((*csi)) == 0){
- int tblref = (*csi).tblvar_ref;
- int schref = (*csi).schema_ref;
- string field = (*csi).field;
- ret += generate_unpack_code(tblref,schref,field,schema,node_name);
- sprintf(tmpstr,"\tt->last_%s_%d = unpack_var_%s_%d;\n", field.c_str(), tblref, field.c_str(), tblref);
- ret += tmpstr;
-
- unpacked_cids.insert( (*csi) );
- }
- }
-
- }
-
- vector<cnf_elem *> filter = fs->get_filter_clause();
-// Test the filter predicate (some query types have additional preds).
- if(filter.size() > 0){
-
-// Sort by evaluation cost.
-// First, estimate evaluation costs
-// Eliminate predicates covered by the prefilter (those in s_pids).
-// I need to do it before the sort becuase the indices refer
-// to the position in the unsorted list./
- vector<cnf_elem *> tmp_wh;
- for(w=0;w<filter.size();++w){
- if(s_pids.count(w) == 0){
- compute_cnf_cost(filter[w],Ext_fcns);
- tmp_wh.push_back(filter[w]);
- }
- }
- filter = tmp_wh;
-
- sort(filter.begin(), filter.end(), compare_cnf_cost());
-
-// Now generate the predicates.
- for(w=0;w<filter.size();++w){
- sprintf(tmpstr,"//\t\tPredicate clause %d.(cost %d)\n",w,filter[w]->cost);
- ret += tmpstr;
-// Find the set of variables accessed in this CNF elem,
-// but in no previous element.
- col_id_set this_pred_cids;
- gather_pr_col_ids(filter[w]->pr, this_pred_cids, gb_tbl);
- for(csi=this_pred_cids.begin();csi!=this_pred_cids.end();++csi){
- if(unpacked_cids.count( (*csi) ) == 0){
- int tblref = (*csi).tblvar_ref;
- int schref = (*csi).schema_ref;
- string field = (*csi).field;
- ret += generate_unpack_code(tblref,schref,field,schema,node_name);
- unpacked_cids.insert( (*csi) );
- }
- }
-// Find partial fcns ref'd in this cnf element
- set<int> pfcn_refs;
- collect_partial_fcns_pr(filter[w]->pr, pfcn_refs);
-// Since set<..> is a "Sorted Associative Container",
-// we can walk through it in sorted order by walking from
-// begin() to end(). (and the partial fcns must be
-// evaluated in this order).
- set<int>::iterator si;
- for(si=pfcn_refs.begin();si!=pfcn_refs.end();++si){
- if(fcn_ref_cnt[(*si)] > 1){
- ret += "\tif(fcn_ref_cnt_"+int_to_string((*si))+"==0){\n";
- }
- if(is_partial_fcn[(*si)]){
- ret += "\t"+unpack_partial_fcn(partial_fcns[(*si)], (*si), schema);
- ret += "\t\tif(retval) goto end;\n";
- }
- if(fcn_ref_cnt[(*si)] > 1){
- if(!is_partial_fcn[(*si)]){
- ret += "\t\tpartial_fcn_result_"+int_to_string((*si))+"="+generate_cached_fcn(partial_fcns[(*si)],schema)+";\n";
- }
- ret += "\t\tfcn_ref_cnt_"+int_to_string((*si))+"=1;\n";
- ret += "\t}\n";
- }
- }
-
- ret += "\tif( !("+generate_predicate_code(filter[w]->pr,schema)+
- ") ) goto end;\n";
- }
- }else{
- ret += "\n\n/*\t\t (no predicate to test)\t*/\n\n";
- }
-
-
-// We've passed the WHERE clause,
-// unpack the remainder of the accessed fields.
- if(is_fj){
- ret += "\n/*\tPassed the WHERE clause, unpack the hash fields. */\n";
- vector<cnf_elem *> h_eq = ((filter_join_qpn *)fs)-> hash_eq;
- for(w=0;w<h_eq.size();++w){
- col_id_set this_pred_cids;
- gather_pr_col_ids(h_eq[w]->pr, this_pred_cids, gb_tbl);
- for(csi=this_pred_cids.begin();csi!=this_pred_cids.end();++csi){
- if(unpacked_cids.count( (*csi) ) == 0){
- int tblref = (*csi).tblvar_ref;
- int schref = (*csi).schema_ref;
- string field = (*csi).field;
- ret += generate_unpack_code(tblref,schref,field,schema,node_name);
- unpacked_cids.insert( (*csi) );
- }
- }
- }
- }else{
- ret += "\n/*\tPassed the WHERE clause, unpack the rest of the accessed fields. */\n";
-
- for(csi=cid_set.begin();csi!=cid_set.end();++csi){
- if(unpacked_cids.count( (*csi) ) == 0){
- int schref = (*csi).schema_ref;
- int tblref = (*csi).tblvar_ref;
- string field = (*csi).field;
- ret += generate_unpack_code(tblref,schref,field,schema,node_name);
- unpacked_cids.insert( (*csi) );
- }
- }
- }
-
-
-//////////////////
-////////////////// After this, the query types
-////////////////// are processed differently.
-
- if(!is_aggr_query && !is_fj)
- ret += generate_sel_accept_body(fs, node_name, schema);
- else if(is_aggr_query)
- ret += generate_aggr_accept_body(fs, node_name, schema, temporal_flush);
- else
- ret += generate_fj_accept_body((filter_join_qpn *)fs, node_name, unpacked_cids, Ext_fcns, schema);
-
-
-// Finish up.
-
- ret += "\n\tend:\n";
- ret += "\t#ifdef LFTA_STATS\n";
- ret+= "\tt->cycle_cnt += rdtsc() - start_cycle;\n";
- ret += "\t#endif\n";
- ret += "\n\treturn 1;\n}\n\n";
-
- return(ret);
-}
-
-
-string generate_fta_alloc(qp_node *fs, string node_name, table_list *schema, bool is_aggr_query, bool is_fj, bool uses_bloom){
- int g, cl;
-
- string ret = "struct FTA * "+generate_alloc_name(node_name) +
- "(struct FTAID ftaid, gs_uint32_t reusable, gs_int32_t command, gs_int32_t sz, void *value){\n";
-
- ret+="\tstruct "+generate_fta_name(node_name)+"* f;\n";
- ret+="\tint i;\n";
- ret += "\n";
- ret+="\tif((f=fta_alloc(0,sizeof(struct "+generate_fta_name(node_name)+")))==0){\n\t\treturn(0);\n\t}\n";
-
-// assign a streamid to fta instance
- ret+="\t/* assign a streamid */\n";
- ret+="\tf->f.ftaid = ftaid;\n";
- ret+="\tf->f.ftaid.streamid = (gs_p_t)f;\n";
- ret+="\tgslog(LOG_INFO,\"Lfta "+node_name+" has FTAID {ip=%u,port=%u,index=%u,streamid=%u}\\n\",f->f.ftaid.ip,f->f.ftaid.port,f->f.ftaid.index,f->f.ftaid.streamid);\n";
-
- if(is_aggr_query){
- ret += "\tf->n_aggrs = 0;\n";
-
- ret += "\tf->max_aggrs = ";
-
-// Computing the number of aggregate blocks is a little
-// tricky. If there are no GB attrs, or if all GB attrs
-// are temporal, then use a single aggregate block, else
-// use a default value (10). A user specification overrides
-// this logic.
- bool single_group = true;
- for(g=0;g<gb_tbl->size();g++){
- data_type *gdt = gb_tbl->get_data_type(g);
- if(! gdt->is_temporal() ){
- single_group = false;
- }
- }
- string max_aggr_str = fs->get_val_of_def("aggregate_slots");
- int max_aggr_i = atoi(max_aggr_str.c_str());
- if(max_aggr_i <= 0){
- if(single_group)
- ret += "2";
- else
- ret += int_to_string(DEFAULT_LFTA_HASH_TABLE_SIZE);
- }else{
- unsigned int naggrs = 1; // make it power of 2
- unsigned int nones = 0;
- while(max_aggr_i){
- if(max_aggr_i&1)
- nones++;
- naggrs = naggrs << 1;
- max_aggr_i = max_aggr_i >> 1;
- }
- if(nones==1) // in case it was already a power of 2.
- naggrs/=2;
- ret += int_to_string(naggrs);
- }
- ret += ";\n";
-
- ret+="\tif ((f->aggr_table = sp_fta_alloc((struct FTA *)f,sizeof(struct "+generate_aggr_struct_name(node_name)+") * f->max_aggrs))==0) {\n";
- ret+="\t\treturn(0);\n";
- ret+="\t}\n\n";
-// ret+="/* compute how many integers we need to store the hashmap */\n";
-// ret+="\tf->bitmap_size = (f->max_aggrs % (sizeof(gs_uint32_t) * 4)) ? (f->max_aggrs / (sizeof(gs_uint32_t) * 4) + 1) : (f->max_aggrs / (sizeof(gs_uint32_t) * 4));\n\n";
- ret+="\tif ((f->aggr_table_hashmap = sp_fta_alloc((struct FTA *)f,sizeof(gs_uint32_t) * f->max_aggrs))==0) {\n";
- ret+="\t\treturn(0);\n";
- ret+="\t}\n";
- ret+="/*\t\tfill bitmap with zero \t*/\n";
- ret+="\tfor (i = 0; i < f->max_aggrs; ++i)\n";
- ret+="\t\tf->aggr_table_hashmap[i] = 0;\n";
- ret+="\tf->generation=0;\n";
- ret+="\tf->flush_pos = f->max_aggrs;\n";
-
- ret += "\tf->flush_ctr = 0;\n";
-
- }
-
- if(is_fj){
- if(uses_bloom){
- ret+="\tf->first_exec = 1;\n";
- unsigned int n_bloom = 11;
- string n_bloom_str = fs->get_val_of_def("num_bloom");
- int tmp_n_bloom = atoi(n_bloom_str.c_str());
- if(tmp_n_bloom>0)
- n_bloom = tmp_n_bloom+1;
-
- unsigned int window_len = ((filter_join_qpn *)fs)->temporal_range;
- if(window_len < n_bloom){
- n_bloom = window_len+1;
- }
-
- int bf_exp_size = 12; // base-2 log of number of bits
- string bloom_len_str = fs->get_val_of_def("bloom_size");
- int tmp_bf_exp_size = atoi(bloom_len_str.c_str());
- if(tmp_bf_exp_size > 3 && tmp_bf_exp_size < 32){
- bf_exp_size = tmp_bf_exp_size;
- }
- int bf_bit_size = 1 << 12;
- int bf_byte_size = bf_bit_size / (8*sizeof(char));
-
- int bf_tot = n_bloom*bf_byte_size;
- ret+="\tif ((f->bf_table = sp_fta_alloc((struct FTA *)f,"+int_to_string(bf_tot)+"))==0) {\n";
- ret+="\t\treturn(0);\n";
- ret+="\t}\n";
- ret +=
-" for(i=0;i<"+int_to_string(bf_tot)+";i++)\n"
-" f->bf_table[i] = 0;\n"
-;
- }else{
- unsigned int ht_size = 4096;
- string ht_size_s = fs->get_val_of_def("aggregate_slots");
- int tmp_ht_size = atoi(ht_size_s.c_str());
- if(tmp_ht_size > 1024){
- unsigned int hs = 1; // make it power of 2
- while(tmp_ht_size){
- hs =hs << 1;
- tmp_ht_size = tmp_ht_size >> 1;
- }
- ht_size = hs;
- }
- ret+="\tif ((f->join_table = sp_fta_alloc((struct FTA *)f,sizeof(struct "+generate_fj_struct_name(node_name)+") * "+int_to_string(ht_size)+"))==0) {\n";
- ret+="\t\treturn(0);\n";
- ret+="\t}\n\n";
- ret +=
-" for(i=0;i<"+int_to_string(ht_size)+";i++)\n"
-" f->join_table[i].ts = 0;\n"
-;
- }
- }
-
-// Initialize the complex literals (which might be handles).
-
- for(cl=0;cl<complex_literals->size();cl++){
- literal_t *l = complex_literals->get_literal(cl);
-// sprintf(tmpstr,"\tf->complex_literal_%d = ",cl);
-// ret += tmpstr + l->to_C_code() + ";\n";
- sprintf(tmpstr,"&(f->complex_literal_%d)",cl);
- ret += "\t" + l->to_C_code(tmpstr) + ";\n";
- }
-
- ret += "\n";
-
-// Initialize the last seen values of temporal attributes to min(max) value of
-// their respective type
-// Create places to hold the last values of temporal attributes referenced in select clause
-
-
- col_id_set temp_cids; // col ids of temp attributes in select clause
-
- int s;
- col_id_set::iterator csi;
-
- for(s=0;s<sl_list.size();s++){
- data_type *sdt = sl_list[s]->get_data_type();
- if (sdt->is_temporal()) {
- gather_se_col_ids(sl_list[s],temp_cids, gb_tbl);
- }
- }
-
- for(csi=temp_cids.begin(); csi != temp_cids.end();++csi){
- int tblref = (*csi).tblvar_ref;
- int schref = (*csi).schema_ref;
- string field = (*csi).field;
- data_type dt(schema->get_type_name(schref,field), schema->get_modifier_list(schref,field));
- if (dt.is_increasing()) {
- sprintf(tmpstr,"\tf->last_%s_%d = %s;\n", field.c_str(), tblref, dt.get_min_literal().c_str());
- ret += tmpstr;
- } else if (dt.is_decreasing()) {
- sprintf(tmpstr,"\tf->last_%s_%d = %s;\n", field.c_str(), tblref, dt.get_max_literal().c_str());
- ret += tmpstr;
- }
- }
-
-// initialize last seen values of temporal groubpy variables
- if(is_aggr_query){
- for(g=0;g<gb_tbl->size();g++){
- data_type *dt = gb_tbl->get_data_type(g);
- if(dt->is_temporal()){
-/*
- fprintf(stderr,"group by attribute %s is temporal, ",
- gb_tbl->get_name(g).c_str());
-*/
- if(dt->is_increasing()){
- sprintf(tmpstr,"\tf->last_gb_%d = f->last_flushed_gb_%d = %s;\n",g, g, dt->get_min_literal().c_str());
- }else{
- sprintf(tmpstr,"\tf->last_gb_%d = f->last_flushed_gb_%d = %s;\n",g, g, dt->get_max_literal().c_str());
- }
- ret += tmpstr;
- }
- }
- }
-
- ret += "\tf->f.alloc_fta="+generate_alloc_name(node_name)+";\n";
- ret+="\tf->f.free_fta=free_fta_"+node_name+";\n";
- ret+="\tf->f.control_fta=control_fta_"+node_name+";\n";
- ret+="\tf->f.accept_packet=accept_packet_"+node_name+";\n";
- ret+="\tf->f.clock_fta=clock_fta_"+node_name+";\n\n";
-
-// Initialize runtime stats
- ret+="\tf->in_tuple_cnt = 0;\n";
- ret+="\tf->out_tuple_cnt = 0;\n";
- ret+="\tf->out_tuple_sz = 0;\n";
- ret+="\tf->accepted_tuple_cnt = 0;\n";
- ret+="\tf->cycle_cnt = 0;\n";
- ret+="\tf->collision_cnt = 0;\n";
- ret+="\tf->eviction_cnt = 0;\n";
- ret+="\tf->sampling_rate = 1.0;\n";
-
- ret+="\tf->trace_id = 0;\n\n";
- if(param_tbl->size() > 0){
- ret+=
-"\tif(load_params_"+node_name+"(f, sz, value, 1)){\n"
-"#ifndef LFTA_IN_NIC\n"
-"\t\t\tfprintf(stderr,\"WARNING: parameter passed to lfta "+node_name+" is too small (%d). This query does not have valid parameters, bailing out.\\n\",sz);\n"
-"#else\n"
-"\t\t}\n"
-"#endif\n"
-"\t\t\treturn 0;\n"
-"\t\t}\n";
- }
-
-// Register the pass-by-handle parameters
- int ph;
- for(ph=0;ph<param_handle_table.size();++ph){
- data_type pdt(param_handle_table[ph]->type_name);
- sprintf(tmpstr,"\tf->handle_param_%d = %s((struct FTA *)f,",ph,param_handle_table[ph]->lfta_registration_fcn().c_str());
- switch(param_handle_table[ph]->val_type){
- case cplx_lit_e:
- ret += tmpstr;
- if(pdt.is_buffer_type()) ret += "&(";
- sprintf(tmpstr,"f->complex_literal_%d",param_handle_table[ph]->complex_literal_idx);
- ret += tmpstr ;
- if(pdt.is_buffer_type()) ret += ")";
- ret += ");\n";
- break;
- case litval_e:
-// not complex, no constructor
- ret += tmpstr;
- ret += param_handle_table[ph]->litval->to_C_code("") + ");\n";
- break;
- case param_e:
-// query parameter handles are regstered/deregistered in the
-// load_params function.
-// ret += "t->param_"+param_handle_table[ph]->param_name;
- break;
- default:
- fprintf(stderr, "INTERNAL ERROR unknown case found when processing pass-by-handle parameter table.\n");
- exit(1);
- }
- }
-
- ret += "\treturn (struct FTA *) f;\n";
- ret += "}\n\n";
-
- return(ret);
-}
-
-
-
-
-//////////////////////////////////////////////////////////////////
-
-string generate_lfta_block(qp_node *fs, table_list *schema, int gid,
-// map<string,string> &int_fcn_defs,
- ext_fcn_list *Ext_fcns, string &schema_embed_str, ifq_t *ifdb, nic_property *nicp, set<unsigned int> &s_pids){
- bool is_aggr_query;
- int s,p,g;
- string retval;
-
-/////////////////////////////////////////////////////////////
-/// Do operator-generic processing, such as
-/// gathering the set of referenced columns,
-/// generating structures, etc.
-
-// Initialize globals to empty.
- gb_tbl = NULL; aggr_tbl = NULL;
- global_id = -1; nicprop = NULL;
- param_tbl = fs->get_param_tbl();
- sl_list.clear(); where.clear();
- partial_fcns.clear();
- fcn_ref_cnt.clear(); is_partial_fcn.clear();
- pred_class.clear(); pred_pos.clear();
- sl_fcns_start=sl_fcns_end=wh_fcns_start=wh_fcns_end=0;
- gb_fcns_start=gb_fcns_end=ag_fcns_start=ag_fcns_end=0;
-
-
-// Does the lfta read packed results from the NIC?
- nicprop = nicp; // load into global
- global_id = gid;
- packed_return = false;
- if(nicp && nicp->option_exists("Return")){
- if(nicp->option_value("Return") == "Packed"){
- packed_return = true;
- }else{
- fprintf(stderr,"Warning, nic option value of Return=%s is not recognized, ignoring\n",nicp->option_value("Return").c_str());
- }
- }
-
-
-// Extract data which defines the query.
-// complex literals gathered now.
- complex_literals = fs->get_cplx_lit_tbl(Ext_fcns);
- param_handle_table = fs->get_handle_param_tbl(Ext_fcns);
- string node_name = fs->get_node_name();
- bool is_fj = false, uses_bloom = false;
-
-
- if(fs->node_type() == "spx_qpn"){
- is_aggr_query = false;
- spx_qpn *spx_node = (spx_qpn *)fs;
- sl_list = spx_node->get_select_se_list();
- where = spx_node->get_where_clause();
- gb_tbl = NULL;
- aggr_tbl = NULL;
- } else
- if(fs->node_type() == "sgah_qpn"){
- is_aggr_query = true;
- sgah_qpn *sgah_node = (sgah_qpn *)fs;
- sl_list = sgah_node->get_select_se_list();
- where = sgah_node->get_where_clause();
- gb_tbl = sgah_node->get_gb_tbl();
- aggr_tbl = sgah_node->get_aggr_tbl();
-
- if((sgah_node->get_having_clause()).size() > 0){
- fprintf(stderr,"Warning in LFTA %s: HAVING clause will be ignored.\n", fs->get_node_name().c_str());
- }
- } else
- if(fs->node_type() == "filter_join"){
- is_aggr_query = false;
- is_fj = true;
- filter_join_qpn *fj_node = (filter_join_qpn *)fs;
- sl_list = fj_node->get_select_se_list();
- where = fj_node->get_where_clause();
- uses_bloom = fj_node->use_bloom;
- gb_tbl = NULL;
- aggr_tbl = NULL;
- } else {
- fprintf(stderr,"INTERNAL ERROR, unrecognized node type %s in generate_lfta_block\n", fs->node_type().c_str());
- exit(1);
- }
-
-// Build list of "partial functions", by clause.
-// NOTE : partial fcns are not handles well.
-// The act of searching for them associates the fcn call
-// in the SE with an index to an array. Refs to the
-// fcn value are replaced with refs to the variable they are
-// unpacked into. A more general tagging mechanism would be better.
-
- int i;
- vector<bool> *pfunc_ptr = NULL;
- vector<int> *ref_cnt_ptr = NULL;
- if(!is_aggr_query){ // don't collect cacheable fcns on aggr query.
- ref_cnt_ptr = &fcn_ref_cnt;
- pfunc_ptr = &is_partial_fcn;
- }
-
- sl_fcns_start = 0;
- for(i=0;i<sl_list.size();i++){
- find_partial_fcns(sl_list[i], &partial_fcns, ref_cnt_ptr, pfunc_ptr, Ext_fcns);
- }
- wh_fcns_start = sl_fcns_end = partial_fcns.size();
- for(i=0;i<where.size();i++){
- find_partial_fcns_pr(where[i]->pr, &partial_fcns, ref_cnt_ptr, pfunc_ptr, Ext_fcns);
- }
- gb_fcns_start = wh_fcns_end = partial_fcns.size();
- if(gb_tbl != NULL){
- for(i=0;i<gb_tbl->size();i++){
- find_partial_fcns(gb_tbl->get_def(i), &partial_fcns, NULL, NULL, Ext_fcns);
- }
- }
- ag_fcns_start = gb_fcns_end = partial_fcns.size();
- if(aggr_tbl != NULL){
- for(i=0;i<aggr_tbl->size();i++){
- find_partial_fcns(aggr_tbl->get_aggr_se(i), NULL, NULL, &is_partial_fcn, Ext_fcns);
- }
- }
- ag_fcns_end = partial_fcns.size();
-
-// Fill up the is_partial_fcn and fcn_ref_cnt arrays.
- if(is_aggr_query){
- for(i=0; i<partial_fcns.size();i++){
- fcn_ref_cnt.push_back(1);
- is_partial_fcn.push_back(true);
- }
- }
-
-// Unmark non-partial expensive functions referenced only once.
- for(i=0; i<partial_fcns.size();i++){
- if(!is_partial_fcn[i] && fcn_ref_cnt[i] <= 1){
- partial_fcns[i]->set_partial_ref(-1);
- }
- }
-
- node_name = normalize_name(node_name);
-
- retval += generate_preamble(schema, /*int_fcn_defs,*/ node_name, schema_embed_str);
-
- if(packed_return){ // generate unpack struct
- vector<tablevar_t *> input_tbls = fs->get_input_tbls();
- int schref = input_tbls[0]->get_schema_ref();
- vector<string> refd_cols;
- for(s=0;s<sl_list.size();++s){
- gather_nicsafe_cols(sl_list[s],refd_cols, nicp, gb_tbl);
- }
- for(p=0;p<where.size();++p){
-// I'm not disabling these preds ...
- gather_nicsafe_cols(where[p]->pr,refd_cols, nicp, gb_tbl);
- }
- if(gb_tbl){
- for(g=0;g<gb_tbl->size();++g){
- gather_nicsafe_cols(gb_tbl->get_def(g),refd_cols, nicp, gb_tbl);
- }
- }
- sort(refd_cols.begin(), refd_cols.end());
- retval += "struct "+node_name+"_input_struct{\n";
- retval += "\tint __lfta_id_fm_nic__;\n";
- int vsi;
- for(vsi=0;vsi<refd_cols.size();++vsi){
- data_type dt(schema->get_type_name(schref,refd_cols[vsi]));
- retval+="\t"+dt.get_cvar_type()+" unpack_var_"+refd_cols[vsi]+";\n";
- }
- retval+="};\n\n";
- }
-
-
-/////////////////////////////////////////////////////
-// Common stuff unpacked, do some generation
-
- if(is_aggr_query)
- retval += generate_aggr_struct(node_name, gb_tbl, aggr_tbl);
- if(is_fj)
- retval += generate_fj_struct((filter_join_qpn *)fs, node_name);
-
- retval += generate_fta_struct(node_name, gb_tbl, aggr_tbl, param_tbl, complex_literals, param_handle_table, is_aggr_query, is_fj, uses_bloom, schema);
- retval += generate_tuple_struct(node_name, sl_list) ;
-
- if(is_aggr_query)
- retval += generate_fta_flush(node_name, schema, Ext_fcns) ;
- if(param_tbl->size() > 0)
- retval += generate_fta_load_params(node_name) ;
- retval += generate_fta_free(node_name, is_aggr_query) ;
- retval += generate_fta_control(node_name, schema, is_aggr_query) ;
- retval += generate_fta_accept(fs, node_name, schema, Ext_fcns, is_aggr_query, is_fj, s_pids) ;
-
-
- /* extract the value of Time_Correlation from interface definition */
- int e,v;
- string es;
- unsigned time_corr;
- vector<tablevar_t *> tvec = fs->get_input_tbls();
- vector<string> time_corr_vec = ifdb->get_iface_vals(tvec[0]->get_machine(), tvec[0]->get_interface(),"Time_Correlation",e,es);
- if (time_corr_vec.empty())
- time_corr = DEFAULT_TIME_CORR;
- else
- time_corr = atoi(time_corr_vec[0].c_str());
-
- retval.append( generate_fta_clock(node_name, schema, time_corr, is_aggr_query) );
- retval.append( generate_fta_alloc(fs, node_name, schema, is_aggr_query, is_fj, uses_bloom) );
-
- return(retval);
-}
-
-
-
-int compute_snap_len(qp_node *fs, table_list *schema){
-
-// Initialize global vars
- gb_tbl = NULL;
- sl_list.clear(); where.clear();
-
- if(fs->node_type() == "spx_qpn"){
- spx_qpn *spx_node = (spx_qpn *)fs;
- sl_list = spx_node->get_select_se_list();
- where = spx_node->get_where_clause();
- }
- else if(fs->node_type() == "sgah_qpn"){
- sgah_qpn *sgah_node = (sgah_qpn *)fs;
- sl_list = sgah_node->get_select_se_list();
- where = sgah_node->get_where_clause();
- gb_tbl = sgah_node->get_gb_tbl();
- }
- else if(fs->node_type() == "filter_join"){
- filter_join_qpn *fj_node = (filter_join_qpn *)fs;
- sl_list = fj_node->get_select_se_list();
- where = fj_node->get_where_clause();
- } else{
- fprintf(stderr,"INTERNAL ERROR, node type %s not recognized in compute_snap_len\n",fs->node_type().c_str());
- exit(1);
- }
-
-// Gather all column references, need to define unpacking variables.
- int w,s;
- col_id_set cid_set;
- col_id_set::iterator csi;
-
- for(w=0;w<where.size();++w)
- gather_pr_col_ids(where[w]->pr,cid_set, gb_tbl);
- for(s=0;s<sl_list.size();s++){
- gather_se_col_ids(sl_list[s],cid_set, gb_tbl);
- }
-
- int g;
- if(gb_tbl != NULL){
- for(g=0;g<gb_tbl->size();g++)
- gather_se_col_ids(gb_tbl->get_def(g),cid_set, gb_tbl);
- }
-
- // compute snap length
- int snap_len = -1;
- int n_snap=0;
- for(csi=cid_set.begin(); csi!=cid_set.end();++csi){
- int schref = (*csi).schema_ref;
- int tblref = (*csi).tblvar_ref;
- string field = (*csi).field;
-
- param_list *field_params = schema->get_modifier_list(schref, field);
- if(field_params->contains_key("snap_len")){
- string fld_snap_str = field_params->val_of("snap_len");
- int fld_snap;
- if(sscanf(fld_snap_str.c_str(),"%d",&fld_snap)>0){
- if(fld_snap > snap_len) snap_len = fld_snap;
- n_snap++;
- }else{
- fprintf(stderr,"CONFIGURATION ERROR: field %s has a non-numeric snap length (%s), ignoring\n",field.c_str(), fld_snap_str.c_str() );
- }
- }
- }
-
- if(n_snap == cid_set.size()){
- return (snap_len);
- }else{
- return -1;
- }
-
-
-}
-
-// Function which computes an optimal
-// set of unpacking functions.
-
-void find_optimal_unpack_fcns(col_id_set &upref_cids, table_list *Schema, map<col_id, string,lt_col_id> &ucol_fcn_map){
- map<string, int> pfcn_count;
- map<string, int>::iterator msii;
- col_id_set::iterator cisi;
- set<string>::iterator ssi;
- string best_fcn;
-
- while(ucol_fcn_map.size() < upref_cids.size()){
-
-// Gather unpack functions referenced by unaccounted-for
-// columns, and increment their reference count.
- pfcn_count.clear();
- for(cisi=upref_cids.begin();cisi!=upref_cids.end();++cisi){
- if(ucol_fcn_map.count((*cisi)) == 0){
- set<string> ufcns = Schema->get_field((*cisi).schema_ref, (*cisi).field)->get_unpack_fcns();
- for(ssi=ufcns.begin();ssi!=ufcns.end();++ssi)
- pfcn_count[(*ssi)]++;
- }
- }
-
-// Get the lowest cost per field function.
- float min_cost = 0.0;
- string best_fcn = "";
- for(msii=pfcn_count.begin();msii!=pfcn_count.end();++msii){
- int fcost = Schema->get_ufcn_cost((*msii).first);
- if(fcost < 0){
- fprintf(stderr,"CONFIGURATION ERROR, unpack function %s either has negative cost or is not defined.\n",(*msii).first.c_str());
- exit(1);
- }
- float this_cost = (1.0*fcost)/(*msii).second;
- if(msii == pfcn_count.begin() || this_cost < min_cost){
- min_cost = this_cost;
- best_fcn = (*msii).first;
- }
- }
- if(best_fcn == ""){
- fprintf(stderr,"ERROR, could not find a best field unpqacking function.\n");
- exit(1);
- }
-
-// Assign this function to the unassigned fcns which use it.
- for(cisi=upref_cids.begin();cisi!=upref_cids.end();++cisi){
- if(ucol_fcn_map.count((*cisi)) == 0){
- set<string> ufcns = Schema->get_field((*cisi).schema_ref, (*cisi).field)->get_unpack_fcns();
- if(ufcns.count(best_fcn)>0)
- ucol_fcn_map[(*cisi)] = best_fcn;
- }
- }
- }
-}
-
-
-
-// Generate an initial test test for the lfta
-// Assume that the predicate references no external functions,
-// and especially no partial functions,
-// aggregates, internal functions.
-string generate_lfta_prefilter(vector<cnf_set *> &pred_list,
- col_id_set &temp_cids, table_list *Schema, ext_fcn_list *Ext_fcns,
- vector<col_id_set> &lfta_cols, vector<long long int> &lfta_sigs,
- vector<int> &lfta_snap_lens, string iface){
- col_id_set tmp_cid_set, cid_set,upref_cids,upall_cids;
- col_id_set::iterator csi;
- int o,p,q;
- string ret;
-
-// Gather complex literals in the prefilter.
- cplx_lit_table *complex_literals = new cplx_lit_table();
- for(p=0;p<pred_list.size();++p){
- find_complex_literal_pr(pred_list[p]->pr,Ext_fcns, complex_literals);
- }
-
-
-// Find the combinable predicates
- vector<predicate_t *> pr_list;
- for(p=0;p<pred_list.size();++p){
- find_combinable_preds(pred_list[p]->pr,&pr_list, Schema, Ext_fcns);
- }
-
-// Analyze the combinable predicates to find the predicate classes.
- pred_class.clear(); // idx to equiv pred in equiv_list
- pred_pos.clear(); // idx to returned bitmask.
- vector<predicate_t *> equiv_list;
- vector<int> num_equiv;
-
-
- for(p=0;p<pr_list.size();++p){
- for(q=0;q<equiv_list.size();++q){
- if(is_equivalent_class_pred_base(equiv_list[q],pr_list[p],Schema,Ext_fcns))
- break;
- }
- if(q == equiv_list.size()){ // no equiv : create new
- pred_class.push_back(equiv_list.size());
- equiv_list.push_back(pr_list[p]);
- pred_pos.push_back(0);
- num_equiv.push_back(1);
-
- }else{ // pr_list[p] is equivalent to pred q
- pred_class.push_back(q);
- pred_pos.push_back(num_equiv[q]);
- num_equiv[q]++;
- }
- }
-
-// Generate the variables which hold the common pred handles
- ret += "/*\t\tprefilter global vars.\t*/\n";
- for(q=0;q<equiv_list.size();++q){
- for(p=0;p<=(num_equiv[q]/32);++p){
- ret += "void *pref_common_pred_hdl_"+int_to_string(q)+"_"+int_to_string(p)+"_"+iface+";\n";
- }
- }
-
-// Struct to hold prefilter complex literals
- ret += "struct prefilter_complex_lit_struct_"+iface+" {\n";
- if(complex_literals->size() == 0)
- ret += "\tint no_variable;\n";
- int cl;
- for(cl=0;cl<complex_literals->size();cl++){
- literal_t *l = complex_literals->get_literal(cl);
- data_type *dtl = new data_type( l->get_type() );
- sprintf(tmpstr,"\t%s complex_literal_%d;\n",dtl->get_cvar_type().c_str(),cl);
- ret += tmpstr;
- }
- ret += "} prefilter_complex_lits_"+iface+";\n\n";
-
-
-// Generate the prefilter initialziation code
- ret += "void init_lfta_prefilter_"+iface+"(){\n";
-
-// First initialize complex literals, if any.
- ret += "\tstruct prefilter_complex_lit_struct_"+iface+" *t = &prefilter_complex_lits_"+iface+";\n";
- for(cl=0;cl<complex_literals->size();cl++){
- literal_t *l = complex_literals->get_literal(cl);
- sprintf(tmpstr,"&(t->complex_literal_%d)",cl);
- ret += "\t" + l->to_C_code(tmpstr) + ";\n";
- }
-
-
- set<int> epred_seen;
- for(p=0;p<pr_list.size();++p){
- int q = pred_class[p];
-//printf("\tq=%d\n",q);
- if(epred_seen.count(q)>0){
- ret += "\tregister_commonpred_handles_"+equiv_list[q]->get_op()+"(";
- vector<bool> cl_op = Ext_fcns->get_class_indicators(equiv_list[q]->get_fcn_id());
- vector<scalarexp_t *> op_list = pr_list[p]->get_op_list();
- for(o=0;o<op_list.size();++o){
- if(! cl_op[o]){
- ret += generate_se_code(op_list[o],Schema)+", ";
- }
- }
- ret += "pref_common_pred_hdl_"+int_to_string(q)+"_"+int_to_string(pred_pos[p]/32)+"_"+iface+","+int_to_string(pred_pos[p]%32)+");\n";
- epred_seen.insert(q);
- }else{
- ret += "\tpref_common_pred_hdl_"+int_to_string(q)+"_"+int_to_string(pred_pos[p]/32)+"_"+iface+" = (void *)register_commonpred_handles_"+equiv_list[q]->get_op()+"(";
- vector<bool> cl_op = Ext_fcns->get_class_indicators(equiv_list[q]->get_fcn_id());
- vector<scalarexp_t *> op_list = pr_list[p]->get_op_list();
- for(o=0;o<op_list.size();++o){
- if(! cl_op[o]){
- ret += generate_se_code(op_list[o],Schema)+", ";
- }
- }
- ret += "NULL,"+int_to_string(pred_pos[p]%32)+");\n";
- epred_seen.insert(q);
- }
- }
- ret += "}\n\n";
-
-
-
-// Start on main body code generation
- ret+="gs_uint64_t lfta_prefilter_"+iface+"(void *pkt){\n";
-
-
-///--------------------------------------------------------------
-/// Generate and store the prefilter body,
-/// reuse it for the snap length calculator
-///-------------------------------------------------------------
- string body;
-
- body += "\tstruct packet *p = (struct packet *)pkt;\n";
-
-
-
-// Gather the colids to store unpacked variables.
- for(p=0;p<pred_list.size();++p){
- gather_pr_col_ids(pred_list[p]->pr,tmp_cid_set, gb_tbl);
- }
-
-// make the col_ids refer to the base tables, and
-// grab the col_ids with at least one unpacking function.
- for(csi=tmp_cid_set.begin();csi!=tmp_cid_set.end();++csi){
- string c_tbl = Schema->get_basetbl_name((*csi).schema_ref,(*csi).field);
- col_id tmp_col_id;
- tmp_col_id.field = (*csi).field;
- tmp_col_id.tblvar_ref = (*csi).tblvar_ref;
- tmp_col_id.schema_ref = Schema->get_table_ref(c_tbl);
- cid_set.insert(tmp_col_id);
- field_entry *fe = Schema->get_field(tmp_col_id.schema_ref, tmp_col_id.field);
- if(fe->get_unpack_fcns().size()>0)
- upref_cids.insert(tmp_col_id);
-
-
- }
-
-// Find the set of unpacking programs needed for the
-// prefilter fields.
- map<col_id, string,lt_col_id> ucol_fcn_map;
- find_optimal_unpack_fcns(upref_cids, Schema, ucol_fcn_map);
- set<string> pref_ufcns;
- map<col_id, string,lt_col_id>::iterator mcis;
- for(mcis=ucol_fcn_map.begin(); mcis!=ucol_fcn_map.end(); mcis++){
- pref_ufcns.insert((*mcis).second);
- }
-
-
-
-// Variables for unpacking attributes.
- body += "/*\t\tVariables for unpacking attributes\t*/\n";
- for(csi=cid_set.begin(); csi!=cid_set.end();++csi){
- int schref = (*csi).schema_ref;
- int tblref = (*csi).tblvar_ref;
- string field = (*csi).field;
- data_type dt(Schema->get_type_name(schref,field));
- sprintf(tmpstr,"\t%s unpack_var_%s_%d;\n",dt.get_cvar_type().c_str(),
- field.c_str(), tblref);
- body += tmpstr;
- sprintf(tmpstr,"\tgs_retval_t ret_%s_%d;\n", field.c_str(),tblref);
- body += tmpstr;
- }
-// Variables for unpacking temporal attributes.
- body += "/*\t\tVariables for unpacking temporal attributes\t*/\n";
- for(csi=temp_cids.begin(); csi!=temp_cids.end();++csi){
- if (cid_set.count(*csi) == 0) {
- int schref = (*csi).schema_ref;
- int tblref = (*csi).tblvar_ref;
- string field = (*csi).field;
- data_type dt(Schema->get_type_name(schref,field));
- sprintf(tmpstr,"\t%s unpack_var_%s_%d;\n",dt.get_cvar_type().c_str(),
- field.c_str(), tblref);
- body += tmpstr;
-
- }
- }
- body += "\n\n";
-
-// Variables for combinable predicate evaluation
- body += "/*\t\tVariables for common prdicate evaluation\t*/\n";
- for(q=0;q<equiv_list.size();++q){
- for(p=0;p<=(num_equiv[q]/32);++p){
- body += "unsigned long int pref_common_pred_val_"+int_to_string(q)+"_"+int_to_string(p)+" = 0;\n";
- }
- }
-
-
-// Variables that are always needed
- body += "/*\t\tVariables which are always needed\t*/\n";
- body += "\tgs_uint64_t retval=0, bitpos=1;\n";
- body += "\tstruct prefilter_complex_lit_struct_"+iface+" *t = &prefilter_complex_lits_"+iface+";\n";
-
-// Call the unpacking functions for the prefilter fields
- if(pref_ufcns.size() > 0)
- body += "\n/*\t\tcall field unpacking functions\t*/\n";
- set<string>::iterator ssi;
- for(ssi=pref_ufcns.begin(); ssi!=pref_ufcns.end(); ++ssi){
- body += "\t"+Schema->get_ufcn_fcn((*ssi))+"(p);\n";
- }
-
-
-// Unpack the accessed attributes
- body += "\n/*\t\tUnpack the accessed attributes.\t*/\n";
- for(csi=cid_set.begin();csi!=cid_set.end();++csi){
- int tblref = (*csi).tblvar_ref;
- int schref = (*csi).schema_ref;
- string field = (*csi).field;
- sprintf(tmpstr,"\tret_%s_%d = (%s(p, &unpack_var_%s_%d) == 0);\n",
- field.c_str(),tblref,Schema->get_fcn(schref,field).c_str(), field.c_str(), tblref);
- body += tmpstr;
- }
-
-// next unpack the temporal attributes and ignore the errors
-// We are assuming here that failed unpack of temporal attributes
-// is not going to overwrite the last stored value
-// Failed upacks are ignored
- for(csi=temp_cids.begin();csi!=temp_cids.end();++csi){
- int tblref = (*csi).tblvar_ref;
- int schref = (*csi).schema_ref;
- string field = (*csi).field;
- sprintf(tmpstr,"\t%s(p, &prefilter_temp_vars.unpack_var_%s_%d);\n",
- Schema->get_fcn(schref,field).c_str(), field.c_str(), tblref);
- body += tmpstr;
- }
-
-// Evaluate the combinable predicates
- if(equiv_list.size()>0)
- body += "/*\t\tEvaluate the combinable predicates.\t*/\n";
- for(q=0;q<equiv_list.size();++q){
- for(p=0;p<=(num_equiv[q]/32);++p){
-
-// Only call the common eval fcn if all ref'd fields present.
- col_id_set pred_cids;
- col_id_set::iterator cpi;
- gather_pr_col_ids(equiv_list[q], pred_cids, gb_tbl);
- if(pred_cids.size()>0){
- body += "\tif(";
- for(cpi=pred_cids.begin();cpi!=pred_cids.end();++cpi){
- if(cpi != pred_cids.begin())
- body += " && ";
- string field = (*cpi).field;
- int tblref = (*cpi).tblvar_ref;
- body += "ret_"+field+"_"+int_to_string(tblref);
- }
- body+=")\n";
- }
-
- body += "\t\tpref_common_pred_val_"+int_to_string(q)+"_"+int_to_string(p)+" = eval_commonpred_"+equiv_list[q]->get_op()+"(pref_common_pred_hdl_"+int_to_string(q)+"_"+int_to_string(p)+"_"+iface;
- vector<scalarexp_t *> op_list = equiv_list[q]->get_op_list();
- vector<bool> cl_op = Ext_fcns->get_class_indicators(equiv_list[q]->get_fcn_id());
- for(o=0;o<op_list.size();++o){
- if(cl_op[o]){
- body += ","+generate_se_code(op_list[o],Schema);
- }
- }
- body += ");\n";
- }
- }
-
-
- for(p=0;p<pred_list.size();++p){
- col_id_set pred_cids;
- col_id_set::iterator cpi;
- gather_pr_col_ids(pred_list[p]->pr,pred_cids, gb_tbl);
- if(pred_cids.size()>0){
- body += "\tif(";
- for(cpi=pred_cids.begin();cpi!=pred_cids.end();++cpi){
- if(cpi != pred_cids.begin())
- body += " && ";
- string field = (*cpi).field;
- int tblref = (*cpi).tblvar_ref;
- body += "ret_"+field+"_"+int_to_string(tblref);
- }
- body+=")\n";
- }
- body += "\t\tif("+generate_predicate_code(pred_list[p]->pr,Schema)+")\n\t\t\tretval |= bitpos;\n";
- body+="\tbitpos = bitpos << 1;\n";
- }
-
-// ---------------------------------------------------------------
-// Finished with the body of the prefilter
-// --------------------------------------------------------------
-
- ret += body;
-
-// Collect fields referenced by an lfta but not
-// already unpacked for the prefilter.
-
-//printf("upref_cids is:\n");
-//for(csi=upref_cids.begin();csi!=upref_cids.end();csi++)
-//printf("\t%s %d\n",(*csi).field.c_str(), (*csi).schema_ref);
-//printf("pref_ufcns is:\n");
-//for(ssi=pref_ufcns.begin();ssi!=pref_ufcns.end();++ssi)
-//printf("\t%s\n",(*ssi).c_str());
-
- int l;
- for(l=0;l<lfta_cols.size();++l){
- for(csi=lfta_cols[l].begin();csi!=lfta_cols[l].end();++csi){
- string c_tbl = Schema->get_basetbl_name((*csi).schema_ref,(*csi).field);
- col_id tmp_col_id;
- tmp_col_id.field = (*csi).field;
- tmp_col_id.tblvar_ref = (*csi).tblvar_ref;
- tmp_col_id.schema_ref = Schema->get_table_ref(c_tbl);
- field_entry *fe = Schema->get_field(tmp_col_id.schema_ref, tmp_col_id.field);
- set<string> fld_ufcns = fe->get_unpack_fcns();
-//printf("tmpcol is (%s, %d), ufcns size is %d, upref_cids cnt is %d\n",tmp_col_id.field.c_str(),tmp_col_id.schema_ref,fld_ufcns.size(), upref_cids.count(tmp_col_id));
- if(fld_ufcns.size()>0 && upref_cids.count(tmp_col_id) == 0){
-// Ensure that this field not already unpacked.
- bool found = false;
- for(ssi=fld_ufcns.begin();ssi!=fld_ufcns.end();++ssi){
-//printf("\tField has unpacking fcn %s\n",(*ssi).c_str());
- if(pref_ufcns.count((*ssi))){
-//printf("Field already unpacked.\n");
- found = true;;
- }
- }
- if(! found){
-//printf("\tadding to unpack list\n");
- upall_cids.insert(tmp_col_id);
- }
- }
- }
- }
-
-//printf("upall_cids is:\n");
-//for(csi=upall_cids.begin();csi!=upall_cids.end();csi++)
-//printf("\t%s %d\n",(*csi).field.c_str(), (*csi).schema_ref);
-
-// Get the set of unpacking programs for these.
- map<col_id, string,lt_col_id> uall_fcn_map;
- find_optimal_unpack_fcns(upall_cids, Schema, uall_fcn_map);
- set<string> pall_ufcns;
- for(mcis=uall_fcn_map.begin(); mcis!=uall_fcn_map.end(); mcis++){
-//printf("uall_fcn_map[%s %d] = %s\n",(*mcis).first.field.c_str(),(*mcis).first.schema_ref,(*mcis).second.c_str());
- pall_ufcns.insert((*mcis).second);
- }
-
-// Iterate through the remaining set of unpacking function
- if(pall_ufcns.size() > 0)
- ret += "//\t\tcall all remaining field unpacking functions.\n";
- for(ssi=pall_ufcns.begin(); ssi!=pall_ufcns.end(); ++ssi){
-// gather the set of columns unpacked by this ufcn
- col_id_set fcol_set;
- for(csi=upall_cids.begin();csi!=upall_cids.end();++csi){
- if(uall_fcn_map[(*csi)] == (*ssi))
- fcol_set.insert((*csi));
- }
-
-// gather the set of lftas which access a field unpacked by the fcn
- set<long long int> clfta;
- for(l=0;l<lfta_cols.size();l++){
- for(csi=fcol_set.begin();csi!=fcol_set.end();++csi){
- if(lfta_cols[l].count((*csi)) > 0)
- break;
- }
- if(csi != fcol_set.end())
- clfta.insert(lfta_sigs[l]);
- }
-
-// generate the unpacking code
- ret += "\tif(";
- set<long long int>::iterator sii;
- for(sii=clfta.begin();sii!=clfta.end();++sii){
- if(sii!=clfta.begin())
- ret += " || ";
- sprintf(tmpstr,"((retval & %lluull) == %lluull)",(*sii),(*sii));
- ret += tmpstr;
- }
- ret += ")\n\t\t"+Schema->get_ufcn_fcn((*ssi))+"(p);\n";
- }
-
-
- ret += "\treturn(retval);\n\n";
- ret += "}\n\n";
-
-
-// --------------------------------------------------------
-// reuse prefilter body for snaplen calculator
-//
-// This is dummy code, so I'm commenting it out.
-
-/*
- ret+="gs_uint32_t lfta_pkt_snaplen(void *pkt){\n";
-
- ret += body;
-
- int i;
- vector<int> s_snaps = lfta_snap_lens;
- sort(s_snaps.begin(), s_snaps.end());
-
- if(s_snaps[0] == -1){
- set<unsigned long long int> sigset;
- for(i=0;i<lfta_snap_lens.size();++i){
- if(lfta_snap_lens[i] == -1){
- sigset.insert(lfta_sigs[i]);
- }
- }
- ret += "\tif( ";
- set<unsigned long long int>::iterator sulli;
- for(sulli=sigset.begin();sulli!=sigset.end();++sulli){
- if(sulli!=sigset.begin())
- ret += " || ";
- sprintf(tmpstr,"((retval & %lluull) == %lluull)",(*sulli),(*sulli));
- ret += tmpstr;
- }
- ret += ") return -1;\n";
- }
-
- int nextpos = lfta_snap_lens.size()-1;
- int nextval = lfta_snap_lens[nextpos];
- while(nextval >= 0){
- set<unsigned long long int> sigset;
- for(i=0;i<lfta_snap_lens.size();++i){
- if(lfta_snap_lens[i] == nextval){
- sigset.insert(lfta_sigs[i]);
- }
- }
- ret += "\tif( ";
- set<unsigned long long int>::iterator sulli;
- for(sulli=sigset.begin();sulli!=sigset.end();++sulli){
- if(sulli!=sigset.begin())
- ret += " || ";
- sprintf(tmpstr,"((retval & %lluull) == %lluull)",(*sulli),(*sulli));
- ret += tmpstr;
- }
- ret += ") return "+int_to_string(nextval)+";\n";
-
- for(nextpos--;nextpos>0 && lfta_snap_lens[nextpos] == nextval;nextpos--);
- if(nextpos>0)
- nextval = lfta_snap_lens[nextpos];
- else
- nextval = -1;
- }
- ret += "\treturn 0;\n";
- ret += "}\n\n";
-*/
-
-
- return(ret);
-}
-
-
-
-
-// Generate the struct which will store the the values of
-// temporal attributesunpacked by prefilter
-string generate_lfta_prefilter_struct(col_id_set &cid_set, table_list *Schema) {
-
- col_id_set::iterator csi;
-
-// printf("generate_lfta_prefilter_struct : %d vars\n",cid_set.size());
-
- string ret="struct prefilter_unpacked_temp_vars {\n";
- ret += "\t/*\tVariables for unpacking temporal attributes\t*/\n";
-
- string init_code;
-
- for(csi=cid_set.begin(); csi!=cid_set.end();++csi){
- int schref = (*csi).schema_ref;
- int tblref = (*csi).tblvar_ref;
- string field = (*csi).field;
- data_type dt(Schema->get_type_name(schref,field), Schema->get_modifier_list(schref,field));
- sprintf(tmpstr,"\t%s unpack_var_%s_%d;\n",dt.get_cvar_type().c_str(),
- field.c_str(), tblref);
- ret += tmpstr;
-
- if (init_code != "")
- init_code += ", ";
- if (dt.is_increasing())
- init_code += dt.get_min_literal();
- else
- init_code += dt.get_max_literal();
-
- }
- ret += "};\n\n";
-
- ret += "struct prefilter_unpacked_temp_vars prefilter_temp_vars = {" + init_code + "};\n\n";
-
- return(ret);
-}
+/* ------------------------------------------------\r
+Copyright 2014 AT&T Intellectual Property\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+ ------------------------------------------- */\r
+\r
+#include <string>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+//#include <algo.h>\r
+#include<algorithm>\r
+\r
+#include "parse_fta.h"\r
+#include "parse_schema.h"\r
+#include "analyze_fta.h"\r
+#include "generate_utils.h"\r
+#include "query_plan.h"\r
+#include "generate_lfta_code.h"\r
+#include "generate_nic_code.h"\r
+\r
+using namespace std;\r
+\r
+extern int DEFAULT_LFTA_HASH_TABLE_SIZE;\r
+\r
+// default value for correlation between the interface card and\r
+// the system clock\r
+#define DEFAULT_TIME_CORR 16\r
+\r
+\r
+// For fast hashing\r
+//#define NRANDS 100\r
+extern string hash_nums[NRANDS];\r
+/*\r
+= {\r
+"12916008961267169387ull", "13447227858232756685ull",\r
+"15651770379918602919ull", "1154671861688431608ull",\r
+"6777078091984849858ull", "14217205709582564356ull",\r
+"4955408621820609982ull", "15813680319165523695ull",\r
+"9897969721407807129ull", "5799700135519793083ull",\r
+"3446529189623437397ull", "2766403683465910630ull",\r
+"3759321430908793328ull", "6569396511892890354ull",\r
+"11124853911180290924ull", "17425412145238035549ull",\r
+"6879931585355039943ull", "16598635011539670441ull",\r
+"9615975578494811651ull", "4378135509538422740ull",\r
+"741282195344332574ull", "17368612862906255584ull",\r
+"17294299200556814618ull", "518343398779663051ull",\r
+"3861893449302272757ull", "8951107288843549591ull",\r
+"15785139392894559409ull", "5917810836789601602ull",\r
+"16169988133001117004ull", "9792861259254509262ull",\r
+"5089058010244872136ull", "2130075224835397689ull",\r
+"844136788226150435ull", "1303298091153875333ull",\r
+"3579898206894361183ull", "7529542662845336496ull",\r
+"13151949992653382522ull", "2145333536541545660ull",\r
+"11258221828939586934ull", "3741808146124570279ull",\r
+"16272841626371307089ull", "12174572036188391283ull",\r
+"9749343496254107661ull", "9141275584134508830ull",\r
+"10134192232065698216ull", "12944268412561423018ull",\r
+"17499725811865666340ull", "5281482378159088661ull",\r
+"13254803486023572607ull", "4526762838498717025ull",\r
+"15990846379668494011ull", "10680949816169027468ull",\r
+"7116154096012931030ull", "5296740689865236632ull",\r
+"5222427027515795922ull", "6893215299448261251ull",\r
+"10164707755932877485ull", "15325979189512082255ull",\r
+"3713267224148573289ull", "12292682741753167354ull",\r
+"4098115959960163588ull", "16095675565885113990ull",\r
+"11391590846210510720ull", "8432889531466002673ull",\r
+"7146668520368482523ull", "7678169991822407997ull",\r
+"9882712513525031447ull", "13904414563513869160ull",\r
+"1080076724395768626ull", "8448147843172150388ull",\r
+"17633093729608185134ull", "10044622457050142303ull",\r
+"4128911859292425737ull", "30642269109444395ull",\r
+"16124215396922640581ull", "15444089895060081110ull",\r
+"16437006538696302944ull", "800338649777443426ull",\r
+"5355794945275091932ull", "11656354278827687117ull",\r
+"1110873718944691255ull", "10829576045617693977ull",\r
+"3846916616884579955ull", "17055821716837625668ull",\r
+"13418968402643535758ull", "11671612594828802128ull",\r
+"11597298928184328586ull", "13196028510862205499ull",\r
+"16539578557089782373ull", "3182048322921507591ull",\r
+"10016080431267550241ull", "148751875162592690ull",\r
+"10400930266590768572ull", "4023803397139127870ull",\r
+"17766462746879108920ull", "14807761432134600873ull",\r
+"13521540421053792403ull", "13980983198941385205ull",\r
+"16257584414193564367ull", "1760484796451765024ull"\r
+};\r
+*/\r
+\r
+\r
+// ----------------------------------------------\r
+// Data extracted from the query plan node\r
+// for use by code generation.\r
+\r
+static cplx_lit_table *complex_literals; //Table of literals with constructors.\r
+static vector<handle_param_tbl_entry *> param_handle_table;\r
+static param_table *param_tbl; // Table of all referenced parameters.\r
+\r
+static vector<scalarexp_t *> sl_list;\r
+static vector<cnf_elem *> where;\r
+\r
+static gb_table *gb_tbl; // Table of all group-by attributes.\r
+static aggregate_table *aggr_tbl; // Table of all referenced aggregates.\r
+\r
+static bool packed_return; // unpack using structyure, not fcns\r
+static nic_property *nicprop; // nic properties for this interface.\r
+static int global_id;\r
+\r
+\r
+// The partial_fcns vector can now refer to\r
+// partial functions, or expensive functions\r
+// which can be cached (if there are multiple refs). A couple\r
+// of int vectors distinguish the cases.\r
+static vector<scalarexp_t *> partial_fcns;\r
+static vector<int> fcn_ref_cnt;\r
+static vector<bool> is_partial_fcn;\r
+int sl_fcns_start = 0, sl_fcns_end = 0;\r
+int wh_fcns_start = 0, wh_fcns_end = 0;\r
+int gb_fcns_start = 0, gb_fcns_end = 0;\r
+int ag_fcns_start = 0, ag_fcns_end = 0;\r
+\r
+\r
+// These vectors are for combinable predicates.\r
+static vector<int> pred_class; // identifies the group\r
+static vector<int> pred_pos; // position in the group.\r
+\r
+\r
+\r
+static char tmpstr[1000];\r
+\r
+//////////////////////////////////////////////////////////////////////\r
+/// Various utilities\r
+\r
+string generate_fta_name(string node_name){\r
+ string ret = normalize_name(node_name);\r
+ if(ret == ""){\r
+ ret = "default";\r
+ }\r
+ ret += "_fta";\r
+\r
+ return(ret);\r
+}\r
+\r
+\r
+string generate_aggr_struct_name(string node_name){\r
+ string ret = normalize_name(node_name);\r
+ if(ret == ""){\r
+ ret = "default";\r
+ }\r
+ ret += "_aggr_struct";\r
+\r
+ return(ret);\r
+}\r
+\r
+string generate_fj_struct_name(string node_name){\r
+ string ret = normalize_name(node_name);\r
+ if(ret == ""){\r
+ ret = "default";\r
+ }\r
+ ret += "_fj_struct";\r
+\r
+ return(ret);\r
+}\r
+\r
+string generate_unpack_code(int tblref, int schref, string field, table_list *schema, string node_name, string end_goto = string("end")){\r
+ string ret;\r
+ if(! packed_return){\r
+ sprintf(tmpstr,"\tretval = %s(p, &unpack_var_%s_%d);\n",\r
+ schema->get_fcn(schref,field).c_str(), field.c_str(), tblref);\r
+ ret += tmpstr;\r
+ if(!schema->get_modifier_list(schref,field)->contains_key("required"))\r
+ ret += "\tif(retval) goto "+end_goto+";\n";\r
+\r
+ }else{\r
+// TODO: ntoh xforms (aug 2010 : removing ntoh, hton)\r
+ data_type dt(schema->get_type_name(schref,field), schema->get_modifier_list(schref,field));\r
+ if(dt.is_buffer_type()){\r
+ if(dt.get_type() != v_str_t){\r
+ ret += "\tif(sizeof(struct "+node_name+"_input_struct)+"+node_name+"_input_struct_var->unpack_var_"+field+".length+int("+node_name+"_input_struct_var->unpack_var_"+field+".data) > sz)\n";\r
+ ret += "\t\tgoto "+end_goto+";\n";\r
+ ret+= "\t\t"+node_name+"_input_struct_var->unpack_var_"+field+".data += "+node_name+"_input_struct_var->unpack_var_"+field+".length;\n";\r
+ ret += "\tunpack_var_"+field+"_"+int_to_string(tblref)+\r
+ " = "+node_name+"_input_struct_var->unpack_var_"+field+";+\n";\r
+ }else{\r
+ fprintf(stderr,"INTERNAL ERROR buffer type not string type in generate_lfta_code.cc:generate_unpack_code\n");\r
+ exit(1);\r
+ }\r
+ }else{\r
+ ret += "\tunpack_var_"+field+"_"+int_to_string(tblref)+\r
+ " = "+node_name+"_input_struct_var->unpack_var_"+field+";\n";\r
+ }\r
+ }\r
+ return ret;\r
+}\r
+\r
+string generate_aggr_struct(string node_name, gb_table *gb_tbl, aggregate_table *aggr_tbl){\r
+ string ret = "struct " + generate_aggr_struct_name(node_name) + "{\n";\r
+\r
+ int g;\r
+ for(g=0;g<gb_tbl->size();g++){\r
+ sprintf(tmpstr,"gb_var%d",g);\r
+ ret += "\t"+gb_tbl->get_data_type(g)->make_cvar(tmpstr)+";\n";\r
+ }\r
+\r
+ int a;\r
+ for(a=0;a<aggr_tbl->size();a++){\r
+ ret += "\t";\r
+ sprintf(tmpstr,"aggr_var%d",a);\r
+ if(aggr_tbl->is_builtin(a))\r
+ ret+="\t"+aggr_tbl->get_data_type(a)->make_cvar(tmpstr)+";\n";\r
+ else\r
+ ret+="\t"+aggr_tbl->get_storage_type(a)->make_cvar(tmpstr)+";\n";\r
+ }\r
+\r
+/*\r
+ ret += "\tstruct "+generate_aggr_struct_name(node_name)+" *next;\n";\r
+*/\r
+\r
+ ret += "};\n\n";\r
+\r
+ return(ret);\r
+}\r
+\r
+\r
+string generate_fj_struct(filter_join_qpn *fs, string node_name ){\r
+ string ret;\r
+\r
+ if(fs->use_bloom == false){ // uses hash table instead\r
+ ret = "struct " + generate_fj_struct_name(node_name) + "{\n";\r
+ int k;\r
+ for(k=0;k<fs->hash_eq.size();++k){\r
+ sprintf(tmpstr,"key_var%d",k);\r
+ ret += "\t"+fs->hash_eq[k]->pr->get_left_se()->get_data_type()->make_cvar(tmpstr)+";\n";\r
+ }\r
+ ret += "\tlong long int ts;\n";\r
+ ret += "};\n\n";\r
+ }\r
+\r
+ return(ret);\r
+}\r
+\r
+\r
+\r
+\r
+string generate_fta_struct(string node_name, gb_table *gb_tbl,\r
+ aggregate_table *aggr_tbl, param_table *param_tbl,\r
+ cplx_lit_table *complex_literals,\r
+ vector<handle_param_tbl_entry *> ¶m_handle_table,\r
+ bool is_aggr_query, bool is_fj, bool uses_bloom,\r
+ table_list *schema){\r
+\r
+ string ret = "struct " + generate_fta_name(node_name) + "{\n";\r
+ ret += "\tstruct FTA f;\n";\r
+\r
+//-------------------------------------------------------------\r
+// Aggregate-specific fields\r
+\r
+ if(is_aggr_query){\r
+/*\r
+ ret += "\tstruct "+generate_aggr_struct_name(node_name)+" *aggr_head, *flush_head;\n";\r
+*/\r
+ ret+="\tstruct "+generate_aggr_struct_name(node_name)+" *aggr_table; // the groups\n";\r
+ ret+="\tgs_uint32_t *aggr_table_hashmap; // hash val, plus control info.\n";\r
+// ret+="\tint bitmap_size;\n";\r
+ ret += "\tint n_aggrs; // # of non-empty slots in aggr_table\n";\r
+ ret += "\tint max_aggrs; // size of aggr_table and its hashmap.\n";\r
+ ret += "\tint max_windows; // max number of open windows.\n";\r
+ ret += "\tunsigned int generation; // initially zero, increment on\n";\r
+ ret += "\t // every hash table flush - whether regular or induced.\n";\r
+ ret += "\t // Old groups are identified by a generation mismatch.\n";\r
+ ret += "\tunsigned int flush_pos; // next aggr_table entry to examine\n";\r
+ ret += "\tunsigned int flush_ctr; // control slow flushing\n";\r
+\r
+\r
+\r
+ int g;\r
+ bool uses_temporal_flush = false;\r
+ for(g=0;g<gb_tbl->size();g++){\r
+ data_type *dt = gb_tbl->get_data_type(g);\r
+ if(dt->is_temporal()){\r
+/*\r
+ fprintf(stderr,"group by attribute %s is temporal, ",\r
+ gb_tbl->get_name(g).c_str());\r
+ if(dt->is_increasing()){\r
+ fprintf(stderr,"increasing.\n");\r
+ }else{\r
+ fprintf(stderr,"decreasing.\n");\r
+ }\r
+*/\r
+ data_type *gdt = gb_tbl->get_data_type(g);\r
+ if(gdt->is_buffer_type()){\r
+ fprintf(stderr, "\t but temporal BUFFER types are not supported, skipping.\n");\r
+ }else{\r
+ sprintf(tmpstr,"\t%s last_gb_%d;\n",gdt->get_cvar_type().c_str(),g);\r
+ ret += tmpstr;\r
+ sprintf(tmpstr,"\t%s flush_start_gb_%d;\n",gdt->get_cvar_type().c_str(),g);\r
+ ret += tmpstr;\r
+ sprintf(tmpstr,"\t%s last_flushed_gb_%d;\n",gdt->get_cvar_type().c_str(),g);\r
+ ret += tmpstr;\r
+ uses_temporal_flush = true;\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+ if(! uses_temporal_flush){\r
+ fprintf(stderr,"Warning: no temporal flush.\n");\r
+ }\r
+ }\r
+\r
+// ---------------------------------------------------------\r
+// Filter-join specific fields\r
+\r
+ if(is_fj){\r
+ if(uses_bloom){\r
+ ret +=\r
+"\tunsigned char * bf_table; //array of bloom filters with layout \n"\r
+"\t\t// bit 0 bf 0| bit 0 bf 1| bit 0 bf 2| bit 1 bf 0| bit 1 bf 1|.....\n"\r
+"\tint first_exec;\n"\r
+"\tlong long int last_bin;\n"\r
+"\tint last_bloom_pos;\n"\r
+"\n"\r
+;\r
+ }else{ // limited hash table\r
+ ret +=\r
+" struct "+generate_fj_struct_name(node_name)+" *join_table;\n"\r
+"\n"\r
+;\r
+ }\r
+\r
+ }\r
+\r
+//--------------------------------------------------------\r
+// Common fields\r
+\r
+// Create places to hold the parameters.\r
+ int p;\r
+ vector<string> param_vec = param_tbl->get_param_names();\r
+ for(p=0;p<param_vec.size();p++){\r
+ data_type *dt = param_tbl->get_data_type(param_vec[p]);\r
+ sprintf(tmpstr,"\t%s param_%s;\n",dt->get_cvar_type().c_str(),\r
+ param_vec[p].c_str());\r
+ ret += tmpstr;\r
+ if(param_tbl->handle_access(param_vec[p])){\r
+ ret += "\tstruct search_handle *param_handle_"+param_vec[p]+";\n";\r
+ }\r
+ }\r
+\r
+// Create places to hold complex literals.\r
+ int cl;\r
+ for(cl=0;cl<complex_literals->size();cl++){\r
+ literal_t *l = complex_literals->get_literal(cl);\r
+ data_type *dtl = new data_type( l->get_type() );\r
+ sprintf(tmpstr,"\t%s complex_literal_%d;\n",dtl->get_cvar_type().c_str(),cl);\r
+ ret += tmpstr;\r
+ }\r
+\r
+// Create places to hold the pass-by-handle parameters.\r
+ for(p=0;p<param_handle_table.size();++p){\r
+ sprintf(tmpstr,"\tgs_param_handle_t handle_param_%d;\n",p);\r
+ ret += tmpstr;\r
+ }\r
+\r
+// Create places to hold the last values of temporal\r
+// attributes referenced in select clause\r
+// we also need to store values of the temoral attributed\r
+// of last flushed tuple in aggr queries\r
+// to make sure we generate the cirrect temporal tuple\r
+// in the presense of slow flushes\r
+\r
+\r
+ col_id_set temp_cids; // col ids of temp attributes in select clause\r
+\r
+ int s;\r
+ col_id_set::iterator csi;\r
+\r
+ for(s=0;s<sl_list.size();s++){\r
+ data_type *sdt = sl_list[s]->get_data_type();\r
+ if (sdt->is_temporal()) {\r
+ gather_se_col_ids(sl_list[s],temp_cids, gb_tbl);\r
+ }\r
+ }\r
+\r
+ for(csi=temp_cids.begin(); csi != temp_cids.end();++csi){\r
+ int tblref = (*csi).tblvar_ref;\r
+ int schref = (*csi).schema_ref;\r
+ string field = (*csi).field;\r
+ data_type dt(schema->get_type_name(schref,field), schema->get_modifier_list(schref,field));\r
+ sprintf(tmpstr,"\t%s last_%s_%d;\n", dt.get_cvar_type().c_str(), field.c_str(), tblref);\r
+ ret += tmpstr;\r
+ }\r
+\r
+ ret += "\tgs_uint64_t trace_id;\n\n";\r
+\r
+// Fields to store the runtime stats\r
+\r
+ ret += "\tgs_uint32_t in_tuple_cnt;\n";\r
+ ret += "\tgs_uint32_t out_tuple_cnt;\n";\r
+ ret += "\tgs_uint32_t out_tuple_sz;\n";\r
+ ret += "\tgs_uint32_t accepted_tuple_cnt;\n";\r
+ ret += "\tgs_uint64_t cycle_cnt;\n";\r
+ ret += "\tgs_uint32_t collision_cnt;\n";\r
+ ret += "\tgs_uint32_t eviction_cnt;\n";\r
+ ret += "\tgs_float_t sampling_rate;\n";\r
+\r
+\r
+\r
+ ret += "};\n\n";\r
+\r
+ return(ret);\r
+}\r
+\r
+//------------------------------------------------------------\r
+// Set colref tblvars to 0..\r
+// (special processing for join-like operators in an lfta).\r
+\r
+void reset_se_col_ids_tblvars(scalarexp_t *se, gb_table *gtbl){\r
+ vector<scalarexp_t *> operands;\r
+ int o;\r
+\r
+ if(! se)\r
+ return;\r
+\r
+ switch(se->get_operator_type()){\r
+ case SE_LITERAL:\r
+ case SE_PARAM:\r
+ case SE_IFACE_PARAM:\r
+ return;\r
+ case SE_UNARY_OP:\r
+ reset_se_col_ids_tblvars(se->get_left_se(),gtbl);\r
+ return;\r
+ case SE_BINARY_OP:\r
+ reset_se_col_ids_tblvars(se->get_left_se(),gtbl);\r
+ reset_se_col_ids_tblvars(se->get_right_se(),gtbl);\r
+ return;\r
+ case SE_COLREF:\r
+ if(! se->is_gb() ){\r
+ se->get_colref()->set_tablevar_ref(0);\r
+ }else{\r
+ if(gtbl==NULL){\r
+ fprintf(stderr,"INTERNAL ERROR: gbvar ref in gather_se_col_ids, but gtbl is NULL.\n");\r
+ exit(1);\r
+ }\r
+ reset_se_col_ids_tblvars(gtbl->get_def(se->get_gb_ref()),gtbl);\r
+ }\r
+ return;\r
+ case SE_AGGR_STAR:\r
+ return;\r
+ case SE_AGGR_SE:\r
+ reset_se_col_ids_tblvars(se->get_left_se(),gtbl);\r
+ return;\r
+ case SE_FUNC:\r
+ operands = se->get_operands();\r
+ for(o=0;o<operands.size();o++){\r
+ reset_se_col_ids_tblvars(operands[o], gtbl);\r
+ }\r
+ return;\r
+ default:\r
+ fprintf(stderr,"INTERNAL ERROR in reset_se_col_ids_tblvars, line %d, character %d: unknown operator type %d\n",\r
+ se->get_lineno(), se->get_charno(),se->get_operator_type());\r
+ exit(1);\r
+ }\r
+}\r
+\r
+\r
+// reset column tblvars accessed in this pr.\r
+\r
+void reset_pr_col_ids_tblvars(predicate_t *pr, gb_table *gtbl){\r
+ vector<scalarexp_t *> op_list;\r
+ int o;\r
+\r
+ switch(pr->get_operator_type()){\r
+ case PRED_IN:\r
+ reset_se_col_ids_tblvars(pr->get_left_se(), gtbl);\r
+ return;\r
+ case PRED_COMPARE:\r
+ reset_se_col_ids_tblvars(pr->get_left_se(),gtbl) ;\r
+ reset_se_col_ids_tblvars(pr->get_right_se(),gtbl) ;\r
+ return;\r
+ case PRED_UNARY_OP:\r
+ reset_pr_col_ids_tblvars(pr->get_left_pr(),gtbl) ;\r
+ return;\r
+ case PRED_BINARY_OP:\r
+ reset_pr_col_ids_tblvars(pr->get_left_pr(),gtbl) ;\r
+ reset_pr_col_ids_tblvars(pr->get_right_pr(),gtbl) ;\r
+ return;\r
+ case PRED_FUNC:\r
+ op_list = pr->get_op_list();\r
+ for(o=0;o<op_list.size();++o){\r
+ reset_se_col_ids_tblvars(op_list[o],gtbl) ;\r
+ }\r
+ return;\r
+ default:\r
+ fprintf(stderr,"INTERNAL ERROR in reset_pr_col_ids_tblvars, line %d, character %d, unknown predicate operator type %d\n",\r
+ pr->get_lineno(), pr->get_charno(), pr->get_operator_type() );\r
+ }\r
+}\r
+\r
+\r
+\r
+\r
+// Generate code that makes reference\r
+// to the tuple, and not to any aggregates.\r
+static string generate_se_code(scalarexp_t *se,table_list *schema){\r
+ string ret;\r
+ data_type *ldt, *rdt;\r
+ int o;\r
+ vector<scalarexp_t *> operands;\r
+\r
+\r
+ switch(se->get_operator_type()){\r
+ case SE_LITERAL:\r
+ if(se->is_handle_ref()){\r
+ sprintf(tmpstr,"t->handle_param_%d",se->get_handle_ref() );\r
+ ret = tmpstr;\r
+ return(ret);\r
+ }\r
+ if(se->get_literal()->is_cpx_lit()){\r
+ sprintf(tmpstr,"t->complex_literal_%d",se->get_literal()->get_cpx_lit_ref() );\r
+ ret = tmpstr;\r
+ return(ret);\r
+ }\r
+ return(se->get_literal()->to_C_code("")); // not complex, no constructor\r
+ case SE_PARAM:\r
+ if(se->is_handle_ref()){\r
+ sprintf(tmpstr,"t->handle_param_%d",se->get_handle_ref() );\r
+ ret = tmpstr;\r
+ return(ret);\r
+ }\r
+ ret += "t->param_";\r
+ ret += se->get_param_name();\r
+ return(ret);\r
+ case SE_UNARY_OP:\r
+ ldt = se->get_left_se()->get_data_type();\r
+ if(ldt->complex_operator(se->get_op()) ){\r
+ ret += ldt->get_complex_operator(se->get_op());\r
+ ret += "(";\r
+ ret += generate_se_code(se->get_left_se(),schema);\r
+ ret += ")";\r
+ }else{\r
+ ret += "(";\r
+ ret += se->get_op();\r
+ ret += generate_se_code(se->get_left_se(),schema);\r
+ ret += ")";\r
+ }\r
+ return(ret);\r
+ case SE_BINARY_OP:\r
+ ldt = se->get_left_se()->get_data_type();\r
+ rdt = se->get_right_se()->get_data_type();\r
+\r
+ if(ldt->complex_operator(rdt, se->get_op()) ){\r
+ ret += ldt->get_complex_operator(rdt, se->get_op());\r
+ ret += "(";\r
+ ret += generate_se_code(se->get_left_se(),schema);\r
+ ret += ", ";\r
+ ret += generate_se_code(se->get_right_se(),schema);\r
+ ret += ")";\r
+ }else{\r
+ ret += "(";\r
+ ret += generate_se_code(se->get_left_se(),schema);\r
+ ret += se->get_op();\r
+ ret += generate_se_code(se->get_right_se(),schema);\r
+ ret += ")";\r
+ }\r
+ return(ret);\r
+ case SE_COLREF:\r
+ if(se->is_gb()){ // OK to ref gb attrs, but they're not yet unpacked ...\r
+ // so return the defining code.\r
+ ret = generate_se_code(gb_tbl->get_def(se->get_gb_ref()), schema );\r
+\r
+ }else{\r
+ sprintf(tmpstr,"unpack_var_%s_%d",\r
+ se->get_colref()->get_field().c_str(), se->get_colref()->get_tablevar_ref() );\r
+ ret = tmpstr;\r
+ }\r
+ return(ret);\r
+ case SE_FUNC:\r
+// Should not be ref'ing any aggr here.\r
+ if(se->get_aggr_ref() >= 0){\r
+ fprintf(stderr,"INTERNAL ERROR, UDAF reference in generate_se_code.\n");\r
+ return("ERROR in generate_se_code");\r
+ }\r
+\r
+ if(se->is_partial()){\r
+ sprintf(tmpstr,"partial_fcn_result_%d",se->get_partial_ref());\r
+ ret = tmpstr;\r
+ }else{\r
+ ret += se->op + "(";\r
+ operands = se->get_operands();\r
+ for(o=0;o<operands.size();o++){\r
+ if(o>0) ret += ", ";\r
+ if(operands[o]->get_data_type()->is_buffer_type() && (! (operands[o]->is_handle_ref()) ) )\r
+ ret += "&";\r
+ ret += generate_se_code(operands[o], schema);\r
+ }\r
+ ret += ")";\r
+ }\r
+ return(ret);\r
+ default:\r
+ fprintf(stderr,"INTERNAL ERROR in generate_se_code (lfta), line %d, character %d: unknown operator type %d\n",\r
+ se->get_lineno(), se->get_charno(),se->get_operator_type());\r
+ return("ERROR in generate_se_code");\r
+ }\r
+}\r
+\r
+// generate code that refers only to aggregate data and constants.\r
+static string generate_se_code_fm_aggr(scalarexp_t *se, string var, table_list *schema){\r
+\r
+ string ret;\r
+ data_type *ldt, *rdt;\r
+ int o;\r
+ vector<scalarexp_t *> operands;\r
+\r
+\r
+ switch(se->get_operator_type()){\r
+ case SE_LITERAL:\r
+ if(se->is_handle_ref()){\r
+ sprintf(tmpstr,"t->handle_param_%d",se->get_handle_ref() );\r
+ ret = tmpstr;\r
+ return(ret);\r
+ }\r
+ if(se->get_literal()->is_cpx_lit()){\r
+ sprintf(tmpstr,"t->complex_literal_%d",se->get_literal()->get_cpx_lit_ref() );\r
+ ret = tmpstr;\r
+ return(ret);\r
+ }\r
+ return(se->get_literal()->to_C_code("")); // not complex no constructor\r
+ case SE_PARAM:\r
+ if(se->is_handle_ref()){\r
+ sprintf(tmpstr,"t->handle_param_%d",se->get_handle_ref() );\r
+ ret = tmpstr;\r
+ return(ret);\r
+ }\r
+ ret += "t->param_";\r
+ ret += se->get_param_name();\r
+ return(ret);\r
+ case SE_UNARY_OP:\r
+ ldt = se->get_left_se()->get_data_type();\r
+ if(ldt->complex_operator(se->get_op()) ){\r
+ ret += ldt->get_complex_operator(se->get_op());\r
+ ret += "(";\r
+ ret += generate_se_code_fm_aggr(se->get_left_se(),var,schema);\r
+ ret += ")";\r
+ }else{\r
+ ret += "(";\r
+ ret += se->get_op();\r
+ ret += generate_se_code_fm_aggr(se->get_left_se(),var,schema);\r
+ ret += ")";\r
+ }\r
+ return(ret);\r
+ case SE_BINARY_OP:\r
+ ldt = se->get_left_se()->get_data_type();\r
+ rdt = se->get_right_se()->get_data_type();\r
+\r
+ if(ldt->complex_operator(rdt, se->get_op()) ){\r
+ ret += ldt->get_complex_operator(rdt, se->get_op());\r
+ ret += "(";\r
+ ret += generate_se_code_fm_aggr(se->get_left_se(),var,schema);\r
+ ret += ", ";\r
+ ret += generate_se_code_fm_aggr(se->get_right_se(),var,schema);\r
+ ret += ")";\r
+ }else{\r
+ ret += "(";\r
+ ret += generate_se_code_fm_aggr(se->get_left_se(),var,schema);\r
+ ret += se->get_op();\r
+ ret += generate_se_code_fm_aggr(se->get_right_se(),var,schema);\r
+ ret += ")";\r
+ }\r
+ return(ret);\r
+ case SE_COLREF:\r
+ if(se->is_gb()){ // OK to ref gb attrs, but they're not yet\r
+ // unpacked ... so return the defining code.\r
+ sprintf(tmpstr,"%sgb_var%d",var.c_str(),se->get_gb_ref());\r
+ ret = tmpstr;\r
+\r
+ }else{\r
+ fprintf(stderr,"ERROR reference to non-GB column ref not permitted here,"\r
+ "error in generate_se_code_fm_aggr, line %d, character %d.\n",\r
+ se->get_lineno(), se->get_charno());\r
+ ret = tmpstr;\r
+ }\r
+ return(ret);\r
+ case SE_AGGR_STAR:\r
+ case SE_AGGR_SE:\r
+ sprintf(tmpstr,"%saggr_var%d",var.c_str(),se->get_aggr_ref());\r
+ ret = tmpstr;\r
+ return(ret);\r
+ case SE_FUNC:\r
+// Is it a UDAF?\r
+ if(se->get_aggr_ref() >= 0){\r
+ sprintf(tmpstr,"udaf_ret%d",se->get_aggr_ref());\r
+ ret = tmpstr;\r
+ return(ret);\r
+ }\r
+\r
+ if(se->is_partial()){\r
+ sprintf(tmpstr,"partial_fcn_result_%d",se->get_partial_ref());\r
+ ret = tmpstr;\r
+ }else{\r
+ ret += se->op + "(";\r
+ operands = se->get_operands();\r
+ for(o=0;o<operands.size();o++){\r
+ if(o>0) ret += ", ";\r
+ if(operands[o]->get_data_type()->is_buffer_type() && (! (operands[o]->is_handle_ref()) ) )\r
+ ret += "&";\r
+ ret += generate_se_code_fm_aggr(operands[o], var, schema);\r
+ }\r
+ ret += ")";\r
+ }\r
+ return(ret);\r
+ default:\r
+ fprintf(stderr,"INTERNAL ERROR in generate_lfta_code.cc::generate_se_code_fm_aggr, line %d, character %d: unknown operator type %d\n",\r
+ se->get_lineno(), se->get_charno(),se->get_operator_type());\r
+ return("ERROR in generate_se_code");\r
+ }\r
+\r
+}\r
+\r
+\r
+static string unpack_partial_fcn_fm_aggr(scalarexp_t *se, int pfn_id, string var, table_list *schema){\r
+ string ret;\r
+ int o;\r
+ vector<scalarexp_t *> operands;\r
+\r
+\r
+ if(se->get_operator_type() != SE_FUNC || se->get_aggr_ref() >= 0){\r
+ fprintf(stderr,"INTERNAL ERROR, non-function SE passed to unpack_partial_fcn_fm_aggr. line %d, character %d\n",\r
+ se->get_lineno(), se->get_charno());\r
+ return("ERROR in generate_se_code");\r
+ }\r
+\r
+ ret = "\tretval = " + se->get_op() + "( ";\r
+ sprintf(tmpstr, "&partial_fcn_result_%d",pfn_id);\r
+ ret += tmpstr;\r
+\r
+ operands = se->get_operands();\r
+ for(o=0;o<operands.size();o++){\r
+ ret += ", ";\r
+ if(operands[o]->get_data_type()->is_buffer_type() && (! (operands[o]->is_handle_ref()) ) )\r
+ ret += "&";\r
+ ret += generate_se_code_fm_aggr(operands[o], var, schema);\r
+ }\r
+ ret += ");\n";\r
+\r
+ return(ret);\r
+}\r
+\r
+static string generate_cached_fcn(scalarexp_t *se, table_list *schema){\r
+ string ret;\r
+ int o;\r
+ vector<scalarexp_t *> operands;\r
+\r
+ if(se->get_operator_type() != SE_FUNC || se->get_aggr_ref() >= 0){\r
+ fprintf(stderr,"INTERNAL ERROR, non-function SE passed to generate_cached_fcn. line %d, character %d\n",\r
+ se->get_lineno(), se->get_charno());\r
+ return("ERROR in generate_se_code");\r
+ }\r
+\r
+ ret = se->get_op() + "( ";\r
+\r
+ operands = se->get_operands();\r
+ for(o=0;o<operands.size();o++){\r
+ if(o) ret += ", ";\r
+ if(operands[o]->get_data_type()->is_buffer_type() && (! (operands[o]->is_handle_ref()) ) )\r
+ ret += "&";\r
+ ret += generate_se_code(operands[o], schema);\r
+ }\r
+ ret += ");\n";\r
+\r
+ return(ret);\r
+}\r
+\r
+\r
+\r
+static string unpack_partial_fcn(scalarexp_t *se, int pfn_id, table_list *schema){\r
+ string ret;\r
+ int o;\r
+ vector<scalarexp_t *> operands;\r
+\r
+\r
+ if(se->get_operator_type() != SE_FUNC || se->get_aggr_ref() >= 0){\r
+ fprintf(stderr,"INTERNAL ERROR, non-function SE passed to unpack_partial_fcn. line %d, character %d\n",\r
+ se->get_lineno(), se->get_charno());\r
+ return("ERROR in generate_se_code");\r
+ }\r
+\r
+ ret = "\tretval = " + se->get_op() + "( ",\r
+ sprintf(tmpstr, "&partial_fcn_result_%d",pfn_id);\r
+ ret += tmpstr;\r
+\r
+ operands = se->get_operands();\r
+ for(o=0;o<operands.size();o++){\r
+ ret += ", ";\r
+ if(operands[o]->get_data_type()->is_buffer_type() && (! (operands[o]->is_handle_ref()) ) )\r
+ ret += "&";\r
+ ret += generate_se_code(operands[o], schema);\r
+ }\r
+ ret += ");\n";\r
+\r
+ return(ret);\r
+}\r
+\r
+\r
+\r
+\r
+\r
+static string generate_C_comparison_op(string op){\r
+ if(op == "=") return("==");\r
+ if(op == "<>") return("!=");\r
+ return(op);\r
+}\r
+\r
+static string generate_C_boolean_op(string op){\r
+ if( (op == "AND") || (op == "And") || (op == "and") ){\r
+ return("&&");\r
+ }\r
+ if( (op == "OR") || (op == "Or") || (op == "or") ){\r
+ return("||");\r
+ }\r
+ if( (op == "NOT") || (op == "Not") || (op == "not") ){\r
+ return("!");\r
+ }\r
+\r
+ fprintf(stderr,"INTERNAL ERROR: unknown boolean operator %s\n",op.c_str());\r
+ return("ERROR UNKNOWN BOOLEAN OPERATOR :"+op);\r
+}\r
+\r
+\r
+static string generate_predicate_code(predicate_t *pr,table_list *schema){\r
+ string ret;\r
+ vector<literal_t *> litv;\r
+ int i;\r
+ data_type *ldt, *rdt;\r
+ vector<scalarexp_t *> op_list;\r
+ int o,cref,ppos;\r
+ unsigned int bitmask;\r
+\r
+ switch(pr->get_operator_type()){\r
+ case PRED_IN:\r
+ ldt = pr->get_left_se()->get_data_type();\r
+\r
+ ret += "( ";\r
+ litv = pr->get_lit_vec();\r
+ for(i=0;i<litv.size();i++){\r
+ if(i>0) ret += " || ";\r
+ ret += "( ";\r
+\r
+ if(ldt->complex_comparison(ldt) ){\r
+ ret += ldt->get_comparison_fcn(ldt) ;\r
+ ret += "( ";\r
+ if(ldt->is_buffer_type() ) ret += "&";\r
+ ret += generate_se_code(pr->get_left_se(), schema);\r
+ ret += ", ";\r
+ if(ldt->is_buffer_type() ) ret += "&";\r
+ if(litv[i]->is_cpx_lit()){\r
+ sprintf(tmpstr,"t->complex_literal_%d",litv[i]->get_cpx_lit_ref() );\r
+ ret += tmpstr;\r
+ }else{\r
+ ret += litv[i]->to_C_code("");\r
+ }\r
+ ret += ") == 0";\r
+ }else{\r
+ ret += generate_se_code(pr->get_left_se(), schema);\r
+ ret += " == ";\r
+ ret += litv[i]->to_C_code("");\r
+ }\r
+\r
+ ret += " )";\r
+ }\r
+ ret += " )";\r
+ return(ret);\r
+\r
+ case PRED_COMPARE:\r
+ ldt = pr->get_left_se()->get_data_type();\r
+ rdt = pr->get_right_se()->get_data_type();\r
+\r
+ ret += "( ";\r
+ if(ldt->complex_comparison(rdt) ){\r
+ ret += ldt->get_comparison_fcn(rdt);\r
+ ret += "(";\r
+ if(ldt->is_buffer_type() ) ret += "&";\r
+ ret += generate_se_code(pr->get_left_se(),schema);\r
+ ret += ", ";\r
+ if(rdt->is_buffer_type() ) ret += "&";\r
+ ret += generate_se_code(pr->get_right_se(),schema);\r
+ ret += ") ";\r
+ ret += generate_C_comparison_op(pr->get_op());\r
+ ret += "0";\r
+ }else{\r
+ ret += generate_se_code(pr->get_left_se(),schema);\r
+ ret += generate_C_comparison_op(pr->get_op());\r
+ ret += generate_se_code(pr->get_right_se(),schema);\r
+ }\r
+ ret += " )";\r
+ return(ret);\r
+ case PRED_UNARY_OP:\r
+ ret += "( ";\r
+ ret += generate_C_boolean_op(pr->get_op());\r
+ ret += generate_predicate_code(pr->get_left_pr(),schema);\r
+ ret += " )";\r
+ return(ret);\r
+ case PRED_BINARY_OP:\r
+ ret += "( ";\r
+ ret += generate_predicate_code(pr->get_left_pr(),schema);\r
+ ret += generate_C_boolean_op(pr->get_op());\r
+ ret += generate_predicate_code(pr->get_right_pr(),schema);\r
+ ret += " )";\r
+ return(ret);\r
+ case PRED_FUNC:\r
+ op_list = pr->get_op_list();\r
+ cref = pr->get_combinable_ref();\r
+ if(cref >= 0){ // predicate is a combinable pred reference\r
+ // Trust, but verify\r
+ if(pred_class.size() >= cref && pred_class[cref] >= 0){\r
+ ppos = pred_pos[cref];\r
+ bitmask = 1 << ppos % 32;\r
+ sprintf(tmpstr,"(pref_common_pred_val_%d_%d & %u)",pred_class[cref],ppos/32,bitmask);\r
+ ret = tmpstr;\r
+ return ret;\r
+ }\r
+ }\r
+\r
+ ret = pr->get_op() + "(";\r
+ if (pr->is_sampling_fcn) {\r
+ ret += "t->sampling_rate";\r
+ if (!op_list.empty())\r
+ ret += ", ";\r
+ }\r
+ for(o=0;o<op_list.size();++o){\r
+ if(o>0) ret += ", ";\r
+ if(op_list[o]->get_data_type()->is_buffer_type() && (! (op_list[o]->is_handle_ref()) ) )\r
+ ret += "&";\r
+ ret += generate_se_code(op_list[o],schema);\r
+ }\r
+ ret += " )";\r
+ return(ret);\r
+ default:\r
+ fprintf(stderr,"INTERNAL ERROR in generate_predicate_code, line %d, character %d, unknown predicate operator type %d\n",\r
+ pr->get_lineno(), pr->get_charno(), pr->get_operator_type() );\r
+ return("ERROR in generate_predicate_code");\r
+ }\r
+}\r
+\r
+\r
+static string generate_equality_test(string &lhs_op, string &rhs_op, data_type *dt){\r
+ string ret;\r
+\r
+ if(dt->complex_comparison(dt) ){\r
+ ret += dt->get_comparison_fcn(dt);\r
+ ret += "(";\r
+ if(dt->is_buffer_type() ) ret += "&";\r
+ ret += lhs_op;\r
+ ret += ", ";\r
+ if(dt->is_buffer_type() ) ret += "&";\r
+ ret += rhs_op;\r
+ ret += ") == 0";\r
+ }else{\r
+ ret += lhs_op;\r
+ ret += " == ";\r
+ ret += rhs_op;\r
+ }\r
+\r
+ return(ret);\r
+}\r
+\r
+static string generate_comparison(string &lhs_op, string &rhs_op, data_type *dt){\r
+ string ret;\r
+\r
+ if(dt->complex_comparison(dt) ){\r
+ ret += dt->get_comparison_fcn(dt);\r
+ ret += "(";\r
+ if(dt->is_buffer_type() ) ret += "&";\r
+ ret += lhs_op;\r
+ ret += ", ";\r
+ if(dt->is_buffer_type() ) ret += "&";\r
+ ret += rhs_op;\r
+ ret += ") == 0";\r
+ }else{\r
+ ret += lhs_op;\r
+ ret += " == ";\r
+ ret += rhs_op;\r
+ }\r
+\r
+ return(ret);\r
+}\r
+\r
+// Here I assume that only MIN and MAX aggregates can be computed\r
+// over BUFFER data types.\r
+\r
+static string generate_aggr_update(string var, aggregate_table *atbl,int aidx, table_list *schema){\r
+ string retval = "\t\t";\r
+ string op = atbl->get_op(aidx);\r
+\r
+// Is it a UDAF\r
+ if(! atbl->is_builtin(aidx)) {\r
+ int o;\r
+ retval += op+"_LFTA_AGGR_UPDATE_(";\r
+ if(atbl->get_storage_type(aidx)->get_type() != fstring_t) retval+="&";\r
+ retval+="("+var+")";\r
+ vector<scalarexp_t *> opl = atbl->get_operand_list(aidx);\r
+ for(o=0;o<opl.size();++o){\r
+ retval += ",";\r
+ if(opl[o]->get_data_type()->is_buffer_type() && (! (opl[o]->is_handle_ref()) ) )\r
+ retval.append("&");\r
+ retval += generate_se_code(opl[o], schema);\r
+ }\r
+ retval += ");\n";\r
+\r
+ return retval;\r
+ }\r
+\r
+// Built-in aggregate processing.\r
+\r
+ data_type *dt = atbl->get_data_type(aidx);\r
+\r
+ if(op == "COUNT"){\r
+ retval.append(var);\r
+ retval.append("++;\n");\r
+ return(retval);\r
+ }\r
+ if(op == "SUM"){\r
+ retval.append(var);\r
+ retval.append(" += ");\r
+ retval.append(generate_se_code(atbl->get_aggr_se(aidx), schema) );\r
+ retval.append(";\n");\r
+ return(retval);\r
+ }\r
+ if(op == "MIN"){\r
+ sprintf(tmpstr,"aggr_tmp_%d = %s;\n",aidx,generate_se_code(atbl->get_aggr_se(aidx), schema ).c_str() );\r
+ retval.append(tmpstr);\r
+ if(dt->complex_comparison(dt)){\r
+ if(dt->is_buffer_type())\r
+ sprintf(tmpstr,"\t\tif(%s(&aggr_tmp_%d,&(%s)) < 0)\n",dt->get_comparison_fcn(dt).c_str(), aidx, var.c_str());\r
+ else\r
+ sprintf(tmpstr,"\t\tif(%s(aggr_tmp_%d,%s) < 0)\n",dt->get_comparison_fcn(dt).c_str(), aidx, var.c_str());\r
+ }else{\r
+ sprintf(tmpstr,"\t\tif(aggr_tmp_%d < %s)\n",aidx,var.c_str());\r
+ }\r
+ retval.append(tmpstr);\r
+ if(dt->is_buffer_type()){\r
+ sprintf(tmpstr,"\t\t\t%s(f,&(%s),&aggr_tmp_%d);\n",dt->get_buffer_replace().c_str(),var.c_str(),aidx);\r
+ }else{\r
+ sprintf(tmpstr,"\t\t\t%s = aggr_tmp_%d;\n",var.c_str(),aidx);\r
+ }\r
+ retval.append(tmpstr);\r
+\r
+ return(retval);\r
+ }\r
+ if(op == "MAX"){\r
+ sprintf(tmpstr,"aggr_tmp_%d = %s;\n",aidx,generate_se_code(atbl->get_aggr_se(aidx), schema ).c_str() );\r
+ retval.append(tmpstr);\r
+ if(dt->complex_comparison(dt)){\r
+ if(dt->is_buffer_type())\r
+ sprintf(tmpstr,"\t\tif(%s(&aggr_tmp_%d,&(%s)) > 0)\n",dt->get_comparison_fcn(dt).c_str(), aidx, var.c_str());\r
+ else\r
+ sprintf(tmpstr,"\t\tif(%s(aggr_tmp_%d,%s) > 0)\n",dt->get_comparison_fcn(dt).c_str(), aidx, var.c_str());\r
+ }else{\r
+ sprintf(tmpstr,"\t\tif(aggr_tmp_%d > %s)\n",aidx,var.c_str());\r
+ }\r
+ retval.append(tmpstr);\r
+ if(dt->is_buffer_type()){\r
+ sprintf(tmpstr,"\t\t\t%s(f,&(%s),&aggr_tmp_%d);\n",dt->get_buffer_replace().c_str(),var.c_str(),aidx);\r
+ }else{\r
+ sprintf(tmpstr,"\t\t\t%s = aggr_tmp_%d;\n",var.c_str(),aidx);\r
+ }\r
+ retval.append(tmpstr);\r
+\r
+ return(retval);\r
+\r
+ }\r
+ if(op == "AND_AGGR"){\r
+ retval.append(var);\r
+ retval.append(" &= ");\r
+ retval.append(generate_se_code(atbl->get_aggr_se(aidx), schema) );\r
+ retval.append(";\n");\r
+ return(retval);\r
+ }\r
+ if(op == "OR_AGGR"){\r
+ retval.append(var);\r
+ retval.append(" |= ");\r
+ retval.append(generate_se_code(atbl->get_aggr_se(aidx), schema) );\r
+ retval.append(";\n");\r
+ return(retval);\r
+ }\r
+ if(op == "XOR_AGGR"){\r
+ retval.append(var);\r
+ retval.append(" ^= ");\r
+ retval.append(generate_se_code(atbl->get_aggr_se(aidx), schema) );\r
+ retval.append(";\n");\r
+ return(retval);\r
+ }\r
+ fprintf(stderr,"INTERNAL ERROR : aggregate %s not recognized in generate_aggr_update.\n",op.c_str());\r
+ return("ERROR: aggregate not recognized: "+op);\r
+\r
+}\r
+\r
+\r
+\r
+static string generate_aggr_init(string var, aggregate_table *atbl,int aidx, table_list *schema){\r
+ string retval;\r
+ string op = atbl->get_op(aidx);\r
+\r
+// Is it a UDAF\r
+ if(! atbl->is_builtin(aidx)) {\r
+ int o;\r
+ retval += "\t\t"+op+"_LFTA_AGGR_INIT_(";\r
+ if(atbl->get_storage_type(aidx)->get_type() != fstring_t) retval+="&";\r
+ retval+="("+var+"));\n";\r
+// Add 1st tupl\r
+ retval += "\t"+atbl->get_op(aidx)+"_LFTA_AGGR_UPDATE_(";\r
+ if(atbl->get_storage_type(aidx)->get_type() != fstring_t) retval+="&";\r
+ retval+="("+var+")";\r
+ vector<scalarexp_t *> opl = atbl->get_operand_list(aidx);\r
+ for(o=0;o<opl.size();++o){\r
+ retval += ",";\r
+ if(opl[o]->get_data_type()->is_buffer_type() && (! (opl[o]->is_handle_ref()) ) )\r
+ retval.append("&");\r
+ retval += generate_se_code(opl[o],schema);\r
+ }\r
+ retval += ");\n";\r
+ return(retval);\r
+ }\r
+\r
+// Built-in aggregate processing.\r
+\r
+\r
+ data_type *dt = atbl->get_data_type(aidx);\r
+\r
+ if(op == "COUNT"){\r
+ retval = "\t\t"+var;\r
+ retval.append(" = 1;\n");\r
+ return(retval);\r
+ }\r
+\r
+ if(op == "SUM" || op == "MIN" || op == "MAX" || op == "AND_AGGR" ||\r
+ op == "OR_AGGR" || op == "XOR_AGGR"){\r
+ if(dt->is_buffer_type()){\r
+ sprintf(tmpstr,"\t\taggr_tmp_%d = %s;\n",aidx,generate_se_code(atbl->get_aggr_se(aidx), schema ).c_str() );\r
+ retval.append(tmpstr);\r
+ sprintf(tmpstr,"\t\t%s(f,&(%s),&aggr_tmp_%d);\n",dt->get_buffer_assign_copy().c_str(),var.c_str(),aidx);\r
+ retval.append(tmpstr);\r
+ }else{\r
+ retval = "\t\t"+var;\r
+ retval += " = ";\r
+ retval.append(generate_se_code(atbl->get_aggr_se(aidx), schema));\r
+ retval.append(";\n");\r
+ }\r
+ return(retval);\r
+ }\r
+\r
+ fprintf(stderr,"INTERNAL ERROR : aggregate %s not recognized in generate_aggr_init.\n",op.c_str());\r
+ return("ERROR: aggregate not recognized: "+op);\r
+}\r
+\r
+\r
+////////////////////////////////////////////////////////////\r
+\r
+\r
+string generate_preamble(table_list *schema, //map<string,string> &int_fcn_defs,\r
+ std::string &node_name, std::string &schema_embed_str){\r
+// Include these only once, not once per lfta\r
+// string ret = "#include \"rts.h\"\n";\r
+// ret += "#include \"fta.h\"\n\n");\r
+\r
+ string ret = "#ifndef LFTA_IN_NIC\n";\r
+ ret += "char *"+generate_schema_string_name(node_name)+" = " +schema_embed_str+";\n";\r
+ ret += "#include<stdio.h>\n";\r
+ ret += "#include <limits.h>\n";\r
+ ret += "#include <float.h>\n";\r
+ ret += "#include \"rdtsc.h\"\n";\r
+ ret += "#endif\n";\r
+\r
+\r
+\r
+ return(ret);\r
+}\r
+\r
+\r
+string generate_tuple_from_aggr(string node_name, table_list *schema, string idx){\r
+ int a,p,s;\r
+// need to create and output the tuple.\r
+ string ret = "/*\t\tCreate an output tuple for the aggregate being kicked out \t*/\n";\r
+// Check for any UDAFs with LFTA_BAILOUT\r
+ ret += "\tlfta_bailout = 0;\n";\r
+ for(a=0;a<aggr_tbl->size();a++){\r
+ if(aggr_tbl->has_bailout(a)){\r
+ ret += "\tlfta_bailout+="+aggr_tbl->get_op(a)+"_LFTA_AGGR_BAILOUT_(";\r
+ if(aggr_tbl->get_storage_type(a)->get_type() != fstring_t) ret+="&";\r
+ ret+="(t->aggr_table["+idx+"].aggr_var"+int_to_string(a)+"));\n";\r
+ }\r
+ }\r
+ ret += "\tif(! lfta_bailout){\n";\r
+\r
+// First, compute the size of the tuple.\r
+\r
+// Unpack UDAF return values\r
+ for(a=0;a<aggr_tbl->size();a++){\r
+ if(! aggr_tbl->is_builtin(a)){\r
+ ret += "\t"+aggr_tbl->get_op(a)+"_LFTA_AGGR_OUTPUT_(&(udaf_ret"+int_to_string(a)+"),";\r
+ if(aggr_tbl->get_storage_type(a)->get_type() != fstring_t) ret+="&";\r
+ ret+="(t->aggr_table["+idx+"].aggr_var"+int_to_string(a)+"));\n";\r
+\r
+ }\r
+ }\r
+\r
+\r
+// Unpack partial fcns ref'd by the select clause.\r
+ if(sl_fcns_start != sl_fcns_end){\r
+ ret += "\t\tunpack_failed = 0;\n";\r
+ for(p=sl_fcns_start;p<sl_fcns_end;p++){\r
+ if(is_partial_fcn[p]){\r
+ ret += "\t" + unpack_partial_fcn_fm_aggr(partial_fcns[p], p,\r
+ "t->aggr_table["+idx+"].",schema);\r
+ ret += "\t\tif(retval) unpack_failed = 1;\n";\r
+ }\r
+ }\r
+ // BEGIN don't allocate tuple if\r
+ ret += "\t\tif( unpack_failed == 0 ){\n"; // unpack failed.\r
+ }\r
+\r
+// Unpack any BUFFER type selections into temporaries\r
+// so that I can compute their size and not have\r
+// to recompute their value during tuple packing.\r
+// I can use regular assignment here because\r
+// these temporaries are non-persistent.\r
+\r
+ for(s=0;s<sl_list.size();s++){\r
+ data_type *sdt = sl_list[s]->get_data_type();\r
+ if(sdt->is_buffer_type()){\r
+ sprintf(tmpstr,"\t\t\tselvar_%d = ",s);\r
+ ret += tmpstr;\r
+ ret += generate_se_code_fm_aggr(sl_list[s],"t->aggr_table["+idx+"].",schema);\r
+ ret += ";\n";\r
+ }\r
+ }\r
+\r
+\r
+// The size of the tuple is the size of the tuple struct plus the\r
+// size of the buffers to be copied in.\r
+\r
+ ret += "\t\t\ttuple_size = sizeof( struct ";\r
+ ret += generate_tuple_name(node_name);\r
+ ret += ")";\r
+ for(s=0;s<sl_list.size();s++){\r
+ data_type *sdt = sl_list[s]->get_data_type();\r
+ if(sdt->is_buffer_type()){\r
+ sprintf(tmpstr," + %s(&selvar_%d)", sdt->get_buffer_size().c_str(),s);\r
+ ret += tmpstr;\r
+ }\r
+ }\r
+ ret += ";\n";\r
+\r
+\r
+ ret += "\t\t\ttuple = allocate_tuple(f, tuple_size );\n";\r
+ ret += "\t\t\tif( tuple != NULL){\n";\r
+\r
+\r
+// Test passed, make assignments to the tuple.\r
+\r
+ ret += "\t\t\t\ttuple_pos = sizeof( struct ";\r
+ ret += generate_tuple_name(node_name) ;\r
+ ret += ");\n";\r
+\r
+// Mark tuple as REGULAR_TUPLE\r
+ ret += "\n\t\t\t\ttuple->tuple_type = REGULAR_TUPLE;\n";\r
+\r
+ for(s=0;s<sl_list.size();s++){\r
+ data_type *sdt = sl_list[s]->get_data_type();\r
+ if(sdt->is_buffer_type()){\r
+ sprintf(tmpstr,"\t\t\t\t%s(&(tuple->tuple_var%d), &selvar_%d, (char *)tuple, ((char *)tuple)+tuple_pos);\n", sdt->get_buffer_tuple_copy().c_str(),s, s);\r
+ ret += tmpstr;\r
+ sprintf(tmpstr,"\t\t\t\ttuple_pos += %s(&selvar_%d);\n", sdt->get_buffer_size().c_str(), s);\r
+ ret += tmpstr;\r
+ }else{\r
+ sprintf(tmpstr,"\t\t\t\ttuple->tuple_var%d = ",s);\r
+ ret += tmpstr;\r
+// if(sdt->needs_hn_translation())\r
+// ret += sdt->hton_translation() +"( ";\r
+ ret += generate_se_code_fm_aggr(sl_list[s],"t->aggr_table["+idx+"].",schema);\r
+// if(sdt->needs_hn_translation())\r
+// ret += ") ";\r
+ ret += ";\n";\r
+ }\r
+ }\r
+\r
+// Generate output.\r
+ ret += "\t\t\t\tpost_tuple(tuple);\n";\r
+ ret += "\t\t\t\t#ifdef LFTA_STATS\n";\r
+ ret+="\t\t\t\tt->out_tuple_cnt++;\n";\r
+ ret+="\t\t\t\tt->out_tuple_sz+=tuple_size;\n";\r
+ ret += "\t\t\t\t#endif\n\n";\r
+ ret += "\t\t\t}\n";\r
+\r
+ if(sl_fcns_start != sl_fcns_end) // END don't allocate tuple if\r
+ ret += "\t\t}\n"; // unpack failed.\r
+ ret += "\t}\n";\r
+\r
+// Need to release memory held by BUFFER types.\r
+ int g;\r
+\r
+ for(g=0;g<gb_tbl->size();g++){\r
+ data_type *gdt = gb_tbl->get_data_type(g);\r
+ if(gdt->is_buffer_type()){\r
+ sprintf(tmpstr,"\t\t\t%s(&(t->aggr_table[%s].gb_var%d));\n",gdt->get_buffer_destroy().c_str(),idx.c_str(),g);\r
+ ret += tmpstr;\r
+ }\r
+ }\r
+ for(a=0;a<aggr_tbl->size();a++){\r
+ if(aggr_tbl->is_builtin(a)){\r
+ data_type *adt = aggr_tbl->get_data_type(a);\r
+ if(adt->is_buffer_type()){\r
+ sprintf(tmpstr,"\t\t\t%s(&(t->aggr_table[%s].aggr_var%d));\n",adt->get_buffer_destroy().c_str(),idx.c_str(),a);\r
+ ret += tmpstr;\r
+ }\r
+ }else{\r
+ ret += "\t\t"+aggr_tbl->get_op(a)+"_LFTA_AGGR_DESTROY_(";\r
+ if(aggr_tbl->get_storage_type(a)->get_type() != fstring_t) ret+="&";\r
+ ret+="(t->aggr_table["+idx+"].aggr_var"+int_to_string(a)+"));\n";\r
+ }\r
+ }\r
+\r
+ ret += "\t\tt->n_aggrs--;\n";\r
+\r
+ return(ret);\r
+\r
+}\r
+\r
+string generate_gb_match_test(string idx){\r
+ int g;\r
+ string ret="\tif (IS_FILLED(t->aggr_table_bitmap, "+idx+") && IS_NEW(t->aggr_table_bitmap,"+idx+")";\r
+ if(gb_tbl->size()>0){\r
+ ret+="\n\t/* \t\tcheck if the grouping variables are equal */\n";\r
+ ret+="\t\t";\r
+\r
+// Next, scan list for a match on the group-by attributes.\r
+ string rhs_op, lhs_op;\r
+ for(g=0;g<gb_tbl->size();g++){\r
+ ret += " && ";\r
+ ret += "(";\r
+ sprintf(tmpstr,"gb_attr_%d",g); lhs_op = tmpstr;\r
+ sprintf(tmpstr,"t->aggr_table[%s].gb_var%d",idx.c_str(),g); rhs_op = tmpstr;\r
+ ret += generate_equality_test(lhs_op, rhs_op, gb_tbl->get_data_type(g) );\r
+ ret += ")";\r
+ }\r
+ }\r
+\r
+ ret += "){\n";\r
+\r
+ return ret;\r
+}\r
+\r
+string generate_gb_update(string node_name, table_list *schema, string idx, bool has_udaf){\r
+ int g;\r
+ string ret;\r
+\r
+ ret += "/*\t\tMatch found : update in place.\t*/\n";\r
+ int a;\r
+ has_udaf = false;\r
+ for(a=0;a<aggr_tbl->size();a++){\r
+ sprintf(tmpstr,"t->aggr_table[%s].aggr_var%d",idx.c_str(),a);\r
+ ret += generate_aggr_update(tmpstr,aggr_tbl,a, schema);\r
+ if(! aggr_tbl->is_builtin(a)) has_udaf = true;\r
+ }\r
+\r
+// garbage collect copied buffer type gb attrs.\r
+ for(g=0;g<gb_tbl->size();g++){\r
+ data_type *gdt = gb_tbl->get_data_type(g);\r
+ if(gdt->is_buffer_type()){\r
+ sprintf(tmpstr,"\t\t\t%s(&(gb_attr_%d));\n",gdt->get_buffer_destroy().c_str(),g);\r
+ ret+=tmpstr;\r
+ }\r
+ }\r
+\r
+\r
+\r
+ bool first_udaf = true;\r
+ if(has_udaf){\r
+ ret += "\t\tif(";\r
+ for(a=0;a<aggr_tbl->size();a++){\r
+ if(! aggr_tbl->is_builtin(a)){\r
+ if(! first_udaf)ret += " || ";\r
+ else first_udaf = false;\r
+ ret += aggr_tbl->get_op(a)+"_LFTA_AGGR_FLUSHME_(";\r
+ if(aggr_tbl->get_storage_type(a)->get_type() != fstring_t) ret+="&";\r
+ ret+="(t->aggr_table["+idx+"].aggr_var"+int_to_string(a)+"))";\r
+ }\r
+ }\r
+ ret+="){\n";\r
+ ret+=" fta_aggr_flush_old_"+node_name+"(f,t->max_aggrs);\n";\r
+ ret += generate_tuple_from_aggr(node_name,schema,idx);\r
+ ret += "\t\tt->aggr_table_hashmap["+idx+"] &= ~SLOT_FILLED;\n";\r
+ ret+="\t\t}\n";\r
+ }\r
+ return ret;\r
+}\r
+\r
+\r
+string generate_init_group( table_list *schema, string idx){\r
+ int g,a;\r
+ string ret="\t\t\tt->aggr_table_hashmap["+idx+"] = hash2 | SLOT_FILLED | gen_val;\n";\r
+// Fill up the aggregate block.\r
+ for(g=0;g<gb_tbl->size();g++){\r
+ sprintf(tmpstr,"\t\t\tt->aggr_table[%s].gb_var%d = gb_attr_%d;\n",idx.c_str(),g,g);\r
+ ret += tmpstr;\r
+ }\r
+ for(a=0;a<aggr_tbl->size();a++){\r
+ sprintf(tmpstr,"t->aggr_table[%s].aggr_var%d",idx.c_str(),a);\r
+ ret += generate_aggr_init(tmpstr, aggr_tbl,a, schema);\r
+ }\r
+ ret+="\t\tt->n_aggrs++;\n";\r
+ return ret;\r
+}\r
+\r
+\r
+string generate_fta_flush(string node_name, table_list *schema,\r
+ ext_fcn_list *Ext_fcns){\r
+\r
+ string ret;\r
+ string select_var_defs ;\r
+ int s, p;\r
+\r
+// Flush from previous epoch\r
+\r
+ ret+="static void fta_aggr_flush_old_"+node_name+"(struct FTA *f, unsigned int nflush){\n";\r
+\r
+ ret += "\tgs_int32_t tuple_size, tuple_pos;\n";\r
+ ret += "\tstruct "+generate_tuple_name(node_name)+" *tuple;\n";\r
+ ret += "\tint i, lfta_bailout;\n";\r
+ ret += "\tunsigned int gen_val;\n";\r
+\r
+ ret += "\tstruct "+generate_fta_name(node_name)+" * t = (struct ";\r
+ ret += generate_fta_name(node_name)+" *) f;\n";\r
+\r
+ ret += "\n";\r
+\r
+\r
+// Variables needed to store selected attributes of BUFFER type\r
+// temporarily, in order to compute their size for storage\r
+// in an output tuple.\r
+\r
+ select_var_defs = "";\r
+ for(s=0;s<sl_list.size();s++){\r
+ data_type *sdt = sl_list[s]->get_data_type();\r
+ if(sdt->is_buffer_type()){\r
+ sprintf(tmpstr,"\t%s selvar_%d;\n",sdt->get_cvar_type().c_str(),s);\r
+ select_var_defs.append(tmpstr);\r
+ }\r
+ }\r
+ if(select_var_defs != ""){\r
+ ret += "/*\t\tTemporaries for computing buffer sizes.\t*/\n";\r
+ ret += select_var_defs;\r
+ }\r
+\r
+\r
+// Variables to store results of partial functions.\r
+ if(sl_fcns_start != sl_fcns_end){\r
+ ret += "/*\t\tVariables to store the results of partial functions.\t*/\n";\r
+ for(p=sl_fcns_start;p<sl_fcns_end;p++){\r
+ sprintf(tmpstr,"\t%s partial_fcn_result_%d;\n",\r
+ partial_fcns[p]->get_data_type()->get_cvar_type().c_str(), p);\r
+ ret += tmpstr;\r
+ }\r
+ ret += "\tgs_retval_t retval = 0;\n\tint unpack_failed = 0;\n;";\r
+ }\r
+\r
+// Variables for udaf output temporaries\r
+ bool no_udaf = true;\r
+ int a;\r
+ for(a=0;a<aggr_tbl->size();a++){\r
+ if(! aggr_tbl->is_builtin(a)){\r
+ if(no_udaf){\r
+ ret+="/*\t\tUDAF output vars.\t*/\n";\r
+ no_udaf = false;\r
+ }\r
+ int afcn_id = aggr_tbl->get_fcn_id(a);\r
+ data_type *adt = Ext_fcns->get_fcn_dt(afcn_id);\r
+ sprintf(tmpstr,"udaf_ret%d", a);\r
+ ret+="\t"+adt->make_cvar(tmpstr)+";\n";\r
+ }\r
+ }\r
+\r
+\r
+// ret+="\tt->flush_finished=1; /* flush will be completed */\n";\r
+ ret+="\n";\r
+ ret+="\tgen_val = t->generation & SLOT_GEN_BITS;\n";\r
+ ret+="\tfor (i=t->flush_pos; (i < t->max_aggrs) && t->n_aggrs && nflush>0; ++i){\n";\r
+ ret+="\t\tif ( (t->aggr_table_hashmap[i] & SLOT_FILLED) && (((t->aggr_table_hashmap[i] & SLOT_GEN_BITS) != gen_val ) || (";\r
+ bool first_g=true;\r
+ int g;\r
+ for(g=0;g<gb_tbl->size();g++){\r
+ data_type *gdt = gb_tbl->get_data_type(g);\r
+ if(gdt->is_temporal()){\r
+ if(first_g) first_g=false; else ret+=" || ";\r
+ ret += "t->last_gb_"+int_to_string(g)+" > t->aggr_table[i].gb_var"+int_to_string(g)+" ";\r
+ }\r
+ }\r
+ ret += "))) {\n";\r
+ ret+="\t\t\tt->aggr_table_hashmap[i] = 0;\n";\r
+ ret+=\r
+"#ifdef LFTA_STATS\n"\r
+"\t\t\tt->eviction_cnt++;\n"\r
+"#endif\n"\r
+;\r
+\r
+\r
+ ret+=generate_tuple_from_aggr(node_name,schema,"i");\r
+\r
+// ret+="\t\t\tt->n_aggrs--;\n"; // done in generate_tuple_from_aggr\r
+ ret+="\t\t\tnflush--;\n";\r
+ ret+="\t\t}\n";\r
+ ret+="\t}\n";\r
+ ret+="\tt->flush_pos=i;\n";\r
+ ret+="\tif(t->n_aggrs == 0) {\n";\r
+ ret+="\t\tt->flush_pos = t->max_aggrs;\n";\r
+ ret += "\t}\n\n";\r
+\r
+ ret+="\tif(t->flush_pos == t->max_aggrs) {\n";\r
+\r
+ for(int g=0;g<gb_tbl->size();g++){\r
+ data_type *dt = gb_tbl->get_data_type(g);\r
+ if(dt->is_temporal()){\r
+ data_type *gdt = gb_tbl->get_data_type(g);\r
+ if(!gdt->is_buffer_type()){\r
+ sprintf(tmpstr,"\t\tt->last_flushed_gb_%d = t->flush_start_gb_%d;\n",g,g);\r
+ ret += tmpstr;\r
+ }\r
+ }\r
+ }\r
+ ret += "\t}\n}\n\n";\r
+\r
+ return(ret);\r
+}\r
+\r
+// TODO Remove sprintf to perform string catenation\r
+string generate_fta_load_params(string node_name){\r
+ int p;\r
+ vector<string> param_names = param_tbl->get_param_names();\r
+\r
+ string ret = "static int load_params_"+node_name+"(struct "+generate_fta_name(node_name);\r
+ ret += " *t, int sz, void *value, int initial_call){\n";\r
+ ret += "\tint pos=0;\n";\r
+ ret += "\tint data_pos;\n";\r
+\r
+ for(p=0;p<param_names.size();p++){\r
+ data_type *dt = param_tbl->get_data_type(param_names[p]);\r
+ if(dt->is_buffer_type()){\r
+ sprintf(tmpstr,"\t%s tmp_var_%s;\n",dt->get_cvar_type().c_str(), param_names[p].c_str() );\r
+ ret += tmpstr;\r
+ sprintf(tmpstr,"\t%s access_var_%s;\n",dt->get_tuple_cvar_type().c_str(), param_names[p].c_str() );\r
+ ret += tmpstr;\r
+ }\r
+ }\r
+\r
+\r
+\r
+ ret += "\n\tdata_pos = ";\r
+ for(p=0;p<param_names.size();p++){\r
+ if(p>0) ret += " + ";\r
+ data_type *dt = param_tbl->get_data_type(param_names[p]);\r
+ ret += "sizeof( ";\r
+ ret += dt->get_tuple_cvar_type();\r
+ ret += " )";\r
+ }\r
+ ret += ";\n";\r
+ ret += "\tif(data_pos > sz) return 1;\n\n";\r
+\r
+\r
+ for(p=0;p<param_names.size();p++){\r
+ data_type *dt = param_tbl->get_data_type(param_names[p]);\r
+ if(dt->is_buffer_type()){\r
+ sprintf(tmpstr,"\taccess_var_%s = *( (%s *)((char *)value+pos) );\n",param_names[p].c_str(), dt->get_tuple_cvar_type().c_str() );\r
+ ret += tmpstr;\r
+ switch( dt->get_type() ){\r
+ case v_str_t:\r
+// ret += "\ttmp_var_"+param_names[p]+".data = ntohl( tmp_var_"+param_names[p]+".data );\n"; // ntoh conversion\r
+// ret += "\ttmp_var_"+param_names[p]+".length = ntohl( tmp_var_"+param_names[p]+".length );\n"; // ntoh conversion\r
+ sprintf(tmpstr,"\tif( (access_var_%s.offset) + access_var_%s.length > sz) return 1;\n",param_names[p].c_str(), param_names[p].c_str() );\r
+ ret += tmpstr;\r
+ sprintf(tmpstr,"\ttmp_var_%s.data = (gs_sp_t)(value) + access_var_%s.offset ;\n",param_names[p].c_str(), param_names[p].c_str() );\r
+ ret += tmpstr;\r
+ sprintf(tmpstr,"\ttmp_var_%s.length = access_var_%s.length ;\n",param_names[p].c_str(), param_names[p].c_str() );\r
+ ret += tmpstr;\r
+ break;\r
+ default:\r
+ fprintf(stderr,"ERROR: parameter %s is of type %s, a buffered type, but I don't know how to unpack it as a parameter.\n",param_names[p].c_str(), dt->get_type_str().c_str() );\r
+ exit(1);\r
+ break;\r
+ }\r
+// First, destroy the old\r
+ ret += "\tif(! initial_call)\n";\r
+ sprintf(tmpstr,"\t\t%s(&(t->param_%s));\n",dt->get_buffer_destroy().c_str(),param_names[p].c_str());\r
+ ret += tmpstr;\r
+// Next, create the new.\r
+ sprintf(tmpstr,"\t%s((struct FTA *)t, &(t->param_%s), &tmp_var_%s);\n", dt->get_buffer_assign_copy().c_str(), param_names[p].c_str(), param_names[p].c_str() );\r
+ ret += tmpstr;\r
+ }else{\r
+// if(dt->needs_hn_translation()){\r
+// sprintf(tmpstr,"\tt->param_%s = %s( *( (%s *)( (char *)value+pos) ) );\n",\r
+// param_names[p].c_str(), dt->ntoh_translation().c_str(), dt->get_cvar_type().c_str() );\r
+// }else{\r
+ sprintf(tmpstr,"\tt->param_%s = *( (%s *)( (char *)value+pos) );\n",\r
+ param_names[p].c_str(), dt->get_cvar_type().c_str() );\r
+// }\r
+ ret += tmpstr;\r
+ }\r
+ sprintf(tmpstr,"\tpos += sizeof( %s );\n",dt->get_cvar_type().c_str() );\r
+ ret += tmpstr;\r
+ }\r
+\r
+// Register the pass-by-handle parameters\r
+\r
+ ret += "/* register and de-register the pass-by-handle parameters */\n";\r
+\r
+ int ph;\r
+ for(ph=0;ph<param_handle_table.size();++ph){\r
+ data_type pdt(param_handle_table[ph]->type_name);\r
+ switch(param_handle_table[ph]->val_type){\r
+ case cplx_lit_e:\r
+ break;\r
+ case litval_e:\r
+ break;\r
+ case param_e:\r
+ ret += "\tif(! initial_call)\n";\r
+ sprintf(tmpstr, "\t\t%s(t->handle_param_%d);\n",\r
+ param_handle_table[ph]->lfta_deregistration_fcn().c_str(),ph);\r
+ ret += tmpstr;\r
+ sprintf(tmpstr,"\tt->handle_param_%d = %s((struct FTA *)t,",ph,param_handle_table[ph]->lfta_registration_fcn().c_str());\r
+ ret += tmpstr;\r
+\r
+ if(pdt.is_buffer_type()) ret += "&(";\r
+ ret += "t->param_"+param_handle_table[ph]->param_name;\r
+ if(pdt.is_buffer_type()) ret += ")";\r
+ ret += ");\n";\r
+ break;\r
+ default:\r
+ sprintf(tmpstr, "INTERNAL ERROR unknown case (%d) found when processing pass-by-handle parameter table.",param_handle_table[ph]->val_type);\r
+ fprintf(stderr,"%s\n",tmpstr);\r
+ ret+=tmpstr;\r
+ }\r
+ }\r
+\r
+ ret+="\treturn 0;\n";\r
+ ret += "}\n\n";\r
+\r
+ return(ret);\r
+}\r
+\r
+\r
+\r
+\r
+string generate_fta_free(string node_name, bool is_aggr_query){\r
+\r
+ string ret="static gs_retval_t free_fta_"+node_name+"(struct FTA *f, gs_uint32_t recursive){\n";\r
+ ret+= "\tstruct "+generate_fta_name(node_name)+\r
+ " * t = (struct "+generate_fta_name(node_name)+" *) f;\n";\r
+ ret += "\tint i;\n";\r
+\r
+ if(is_aggr_query){\r
+ ret+="\tfta_aggr_flush_old_" + node_name+"(f,t->max_aggrs);\n";\r
+ ret+="\t/* \t\tmark all groups as old */\n";\r
+ ret+="\tt->generation++;\n";\r
+ ret+="\tt->flush_pos = 0;\n";\r
+ ret+="\tfta_aggr_flush_old_" + node_name+"(f,t->max_aggrs);\n";\r
+ }\r
+\r
+// Deregister the pass-by-handle parameters\r
+ ret += "/* de-register the pass-by-handle parameters */\n";\r
+ int ph;\r
+ for(ph=0;ph<param_handle_table.size();++ph){\r
+ sprintf(tmpstr, "\t%s(t->handle_param_%d);\n",\r
+ param_handle_table[ph]->lfta_deregistration_fcn().c_str(),ph);\r
+ ret += tmpstr;\r
+ }\r
+\r
+\r
+ ret += "\treturn 0;\n}\n\n";\r
+ return(ret);\r
+}\r
+\r
+\r
+string generate_fta_control(string node_name, table_list *schema, bool is_aggr_query){\r
+ string ret="static gs_retval_t control_fta_"+node_name+"(struct FTA *f, gs_int32_t command, gs_int32_t sz, void *value){\n";\r
+ ret += "\tstruct "+generate_fta_name(node_name)+" * t = (struct ";\r
+ ret += generate_fta_name(node_name)+" *) f;\n\n";\r
+ ret+="\tint i;\n";\r
+\r
+\r
+ ret += "\t/* temp status tuple */\n";\r
+ ret += "\tstruct "+generate_tuple_name(node_name)+" *tuple;\n";\r
+ ret += "\tgs_int32_t tuple_size;\n";\r
+\r
+\r
+ if(is_aggr_query){\r
+ ret+="\tif(command == FTA_COMMAND_FLUSH){\n";\r
+\r
+ ret+="\t\tif (!t->n_aggrs) {\n";\r
+ ret+="\t\t\ttuple = allocate_tuple(f, 0);\n";\r
+ ret+="\t\t\tif( tuple != NULL)\n";\r
+ ret+="\t\t\t\tpost_tuple(tuple);\n";\r
+\r
+ ret+="\t\t}else{\n";\r
+\r
+ ret+="\t\t\tfta_aggr_flush_old_" + node_name+"(f,t->max_aggrs);\n";\r
+ ret+="\t\t\t/* \t\tmark all groups as old */\n";\r
+ ret +="\t\tt->generation++;\n";\r
+ ret += "//\tmarking groups old should happen implicitly by advancing the generation.\n";\r
+ ret+="//\t\t\tfor (i = 0; i < t->bitmap_size; ++i)\n";\r
+ ret+="//\t\t\t\tt->aggr_table_bitmap[i] &= 0xAAAAAAAA;\n";\r
+ ret+="\t\t\tt->flush_pos = 0;\n";\r
+ ret+="\t\t\tfta_aggr_flush_old_" + node_name+"(f,t->max_aggrs);\n";\r
+ ret+="\t\t}\n";\r
+\r
+ ret+="\t}\n";\r
+ }\r
+ if(param_tbl->size() > 0){\r
+ ret+=\r
+"\tif(command == FTA_COMMAND_LOAD_PARAMS){\n"\r
+"\t\tif(load_params_"+node_name+"(t, sz, value, 0))\n"\r
+"#ifndef LFTA_IN_NIC\n"\r
+"\t\t\tfprintf(stderr,\"WARNING: parameter passed to lfta "+node_name+" is too small, ignored.\\n\");\n"\r
+"#else\n"\r
+"\t\t{}\n"\r
+"#endif\n"\r
+"\t}\n";\r
+ }\r
+ ret+=\r
+"\tif(command == FTA_COMMAND_SET_SAMPLING_RATE){\n"\r
+"\t\tmemcpy(&t->sampling_rate, value, sizeof(gs_float_t));\n"\r
+"\t}\n\n";\r
+\r
+\r
+ ret += "\tif(command == FTA_COMMAND_FILE_DONE ){\n";\r
+\r
+ if(is_aggr_query){\r
+ ret+="\t\tif (t->n_aggrs) {\n";\r
+ ret+="\t\t\tfta_aggr_flush_old_" + node_name+"(f,t->max_aggrs);\n";\r
+ ret+="\t\t\t/* \t\tmark all groups as old */\n";\r
+ ret +="\t\tt->generation++;\n";\r
+ ret += "//\tmarking groups old should happen implicitly by advancing the generation.\n";\r
+ ret+="//\t\t\tfor (i = 0; i < t->bitmap_size; ++i)\n";\r
+ ret+="//\t\t\t\tt->aggr_table_bitmap[i] &= 0xAAAAAAAA;\n";\r
+ ret+="\t\t\tt->flush_pos = 0;\n";\r
+ ret+="\t\t\tfta_aggr_flush_old_" + node_name+"(f,t->max_aggrs);\n";\r
+ ret+="\t\t}\n";\r
+ }\r
+\r
+ ret += "\t\ttuple_size = sizeof( struct "+generate_tuple_name(node_name)+");\n";\r
+ ret += "\t\ttuple = allocate_tuple(f, tuple_size );\n";\r
+ ret += "\t\tif( tuple == NULL)\n\t\treturn 1;\n";\r
+\r
+ /* mark tuple as EOF_TUPLE */\r
+ ret += "\n\t\t/* Mark tuple as eof_tuple */\n";\r
+ ret += "\t\ttuple->tuple_type = EOF_TUPLE;\n";\r
+ ret += "\t\tpost_tuple(tuple);\n";\r
+ ret += "\t}\n";\r
+\r
+ ret += "\treturn 0;\n}\n\n";\r
+\r
+ return(ret);\r
+}\r
+\r
+string generate_fta_clock(string node_name, table_list *schema, unsigned time_corr, bool is_aggr_query){\r
+ string ret="static gs_retval_t clock_fta_"+node_name+"(struct FTA *f){\n";\r
+ ret += "\tstruct "+generate_fta_name(node_name)+" * t = (struct ";\r
+ ret += generate_fta_name(node_name)+" *) f;\n\n";\r
+\r
+ ret += "\t/* Create a temp status tuple */\n";\r
+ ret += "\tstruct "+generate_tuple_name(node_name)+" *tuple;\n";\r
+ ret += "\tgs_int32_t tuple_size;\n";\r
+ ret += "\tunsigned int i;\n";\r
+ ret += "\ttime_t cur_time;\n";\r
+ ret += "\tint time_advanced;\n";\r
+ ret += "\tstruct fta_stat stats;\n";\r
+\r
+\r
+\r
+ /* copy the last seen values of temporal attributes */\r
+ col_id_set temp_cids; // col ids of temp attributes in select clause\r
+\r
+\r
+ /* HACK: in order to reuse the SE generation code, we need to copy\r
+ * the last values of the temp attributes into new variables\r
+ * which have names unpack_var_XXX_XXX\r
+ */\r
+\r
+ int s, g;\r
+ col_id_set::iterator csi;\r
+\r
+ for(s=0;s<sl_list.size();s++){\r
+ data_type *sdt = sl_list[s]->get_data_type();\r
+ if (sdt->is_temporal()) {\r
+ gather_se_col_ids(sl_list[s],temp_cids, gb_tbl);\r
+ }\r
+ }\r
+\r
+ for(csi=temp_cids.begin(); csi != temp_cids.end();++csi){\r
+ int tblref = (*csi).tblvar_ref;\r
+ int schref = (*csi).schema_ref;\r
+ string field = (*csi).field;\r
+ data_type dt(schema->get_type_name(schref,field), schema->get_modifier_list(schref,field));\r
+ sprintf(tmpstr,"\t%s unpack_var_%s_%d;\n", dt.get_cvar_type().c_str(), field.c_str(), tblref);\r
+ ret += tmpstr;\r
+ }\r
+\r
+ if (is_aggr_query) {\r
+ for(g=0;g<gb_tbl->size();g++){\r
+ data_type *gdt = gb_tbl->get_data_type(g);\r
+ if(gdt->is_temporal()){\r
+ sprintf(tmpstr,"\t%s gb_attr_%d;\n",gb_tbl->get_data_type(g)->get_cvar_type().c_str(),g);\r
+ ret += tmpstr;\r
+ data_type *gdt = gb_tbl->get_data_type(g);\r
+ if(gdt->is_buffer_type()){\r
+ sprintf(tmpstr,"\t%s gb_attr_tmp%d;\n",gb_tbl->get_data_type(g)->get_cvar_type().c_str(),g);\r
+ ret += tmpstr;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ ret += "\n";\r
+\r
+ ret += "\ttime_advanced = 0;\n";\r
+\r
+ for(csi=temp_cids.begin(); csi != temp_cids.end();++csi){\r
+ int tblref = (*csi).tblvar_ref;\r
+ int schref = (*csi).schema_ref;\r
+ string field = (*csi).field;\r
+ data_type dt(schema->get_type_name(schref,field), schema->get_modifier_list(schref,field));\r
+\r
+ // update last seen value with the value seen\r
+ ret += "\t#ifdef PREFILTER_DEFINED\n";\r
+ sprintf(tmpstr,"\tif (prefilter_temp_vars.unpack_var_%s_%d > t->last_%s_%d) {\n\t\tt->last_%s_%d = prefilter_temp_vars.unpack_var_%s_%d;\n",\r
+ field.c_str(), tblref, field.c_str(), tblref, field.c_str(), tblref, field.c_str(), tblref);\r
+ ret += tmpstr;\r
+ ret += "\t\ttime_advanced = 1;\n\t}\n";\r
+ ret += "\t#endif\n";\r
+\r
+ // we need to pay special attention to time fields\r
+ if (field == "time" || field == "timestamp"){\r
+ ret += "\tcur_time = time(&cur_time);\n";\r
+\r
+ if (field == "time") {\r
+ sprintf(tmpstr,"\tif (!gscp_blocking_mode() && (t->last_time_%d < (cur_time - %d))) {\n",\r
+ tblref, time_corr);\r
+ ret += tmpstr;\r
+ sprintf(tmpstr,"\t\tunpack_var_%s_%d = t->last_%s_%d = cur_time - %d;\n",\r
+ field.c_str(), tblref, field.c_str(), tblref, time_corr);\r
+ } else {\r
+ sprintf(tmpstr,"\tif (!gscp_blocking_mode() && ((gs_uint32_t)(t->last_%s_%d>>32) < (cur_time - %d))) {\n",\r
+ field.c_str(), tblref, time_corr);\r
+ ret += tmpstr;\r
+ sprintf(tmpstr,"\t\tunpack_var_%s_%d = t->last_%s_%d = ((gs_uint64_t)(cur_time - %d))<<32;\n",\r
+ field.c_str(), tblref, field.c_str(), tblref, time_corr);\r
+ }\r
+ ret += tmpstr;\r
+\r
+ ret += "\t\ttime_advanced = 1;\n";\r
+ ret += "\t}\n";\r
+\r
+ sprintf(tmpstr,"\telse\n\t\tunpack_var_%s_%d = t->last_%s_%d;\n",\r
+ field.c_str(), tblref, field.c_str(), tblref);\r
+ ret += tmpstr;\r
+ } else {\r
+ sprintf(tmpstr,"\tunpack_var_%s_%d = t->last_%s_%d;\n",\r
+ field.c_str(), tblref, field.c_str(), tblref);\r
+ ret += tmpstr;\r
+ }\r
+ }\r
+\r
+ // for aggregation lftas we need to check if the time was advanced beyond the current epoch\r
+ if (is_aggr_query) {\r
+\r
+ string change_test;\r
+ bool first_one = true;\r
+ for(g=0;g<gb_tbl->size();g++){\r
+ data_type *gdt = gb_tbl->get_data_type(g);\r
+ if(gdt->is_temporal()){\r
+// To perform the test, first need to compute the value\r
+// of the temporal gb attrs.\r
+ if(gdt->is_buffer_type()){\r
+ // NOTE : if the SE defining the gb is anything\r
+ // other than a ref to a variable, this will generate\r
+ // illegal code. To be resolved with Spatch.\r
+ sprintf(tmpstr,"\tgb_attr_tmp%d = %s;\n",\r
+ g, generate_se_code(gb_tbl->get_def(g),schema).c_str() );\r
+ ret+=tmpstr;\r
+ sprintf(tmpstr,"\t%s(f, &gb_attr_%d, &gb_attr_tmp%d);\n",\r
+ gdt->get_buffer_assign_copy().c_str(), g, g);\r
+ }else{\r
+ sprintf(tmpstr,"\tgb_attr_%d = %s;\n",g,generate_se_code(gb_tbl->get_def(g),schema).c_str());\r
+ }\r
+ ret += tmpstr;\r
+\r
+ sprintf(tmpstr,"t->last_gb_%d",g); string lhs_op = tmpstr;\r
+ sprintf(tmpstr,"gb_attr_%d",g); string rhs_op = tmpstr;\r
+ if(first_one){first_one = false;} else {change_test.append(") && (");}\r
+ change_test.append(generate_equality_test(lhs_op, rhs_op, gdt));\r
+ }\r
+ }\r
+\r
+ ret += "\n\tif( time_advanced && !( (";\r
+ ret += change_test;\r
+ ret += ") ) ){\n";\r
+\r
+ ret += "\n/*\t\tFlush the aggregates if the temporal gb attrs have changed.\t*/\n";\r
+ ret += "\t\tif(t->flush_pos<t->max_aggrs) \n";\r
+ ret += "\t\t\tfta_aggr_flush_old_"+node_name+"(f,t->max_aggrs);\n";\r
+\r
+ ret += "\t\t/* \t\tmark all groups as old */\n";\r
+ ret +="\t\tt->generation++;\n";\r
+ ret += "//\tmarking groups old should happen implicitly by advancing the generation.\n";\r
+ ret += "//\t\tfor (i = 0; i < t->bitmap_size; ++i)\n";\r
+ ret += "//\t\t\tt->aggr_table_bitmap[i] &= 0xAAAAAAAA;\n";\r
+ ret += "\t\tt->flush_pos = 0;\n";\r
+\r
+ for(g=0;g<gb_tbl->size();g++){\r
+ data_type *gdt = gb_tbl->get_data_type(g);\r
+ if(gdt->is_temporal()){\r
+ sprintf(tmpstr,"\t\tt->flush_start_gb_%d = gb_attr_%d;\n",g,g); ret += tmpstr;\r
+ sprintf(tmpstr,"\t\tt->last_gb_%d = gb_attr_%d;\n",g,g); ret += tmpstr;\r
+ }\r
+ }\r
+ ret += "\t}\n\n";\r
+\r
+ }\r
+\r
+ ret += "\ttuple_size = sizeof( struct "+generate_tuple_name(node_name)+") + sizeof(gs_uint64_t) + sizeof(struct fta_stat);\n";\r
+ ret += "\ttuple = allocate_tuple(f, tuple_size );\n";\r
+ ret += "\tif( tuple == NULL)\n\t\treturn 1;\n";\r
+\r
+\r
+ for(s=0;s<sl_list.size();s++){\r
+ data_type *sdt = sl_list[s]->get_data_type();\r
+ if(sdt->is_temporal()){\r
+\r
+ if (sl_list[s]->is_gb()) {\r
+ sprintf(tmpstr,"\tt->last_flushed_gb_%d = (t->n_aggrs) ? t->last_flushed_gb_%d : %s;\n",sl_list[s]->get_gb_ref(), sl_list[s]->get_gb_ref(), generate_se_code(sl_list[s],schema).c_str());\r
+ ret += tmpstr;\r
+ }\r
+\r
+ sprintf(tmpstr,"\ttuple->tuple_var%d = ",s);\r
+ ret += tmpstr;\r
+// if(sdt->needs_hn_translation())\r
+// ret += sdt->hton_translation() +"( ";\r
+ if (sl_list[s]->is_gb()) {\r
+ sprintf(tmpstr, "t->last_flushed_gb_%d",sl_list[s]->get_gb_ref());\r
+ ret += tmpstr;\r
+ } else{\r
+ ret += generate_se_code(sl_list[s],schema);\r
+ }\r
+// if(sdt->needs_hn_translation())\r
+// ret += " )";\r
+ ret += ";\n";\r
+ }\r
+ }\r
+\r
+ /* mark tuple as temporal */\r
+ ret += "\n\t/* Mark tuple as temporal */\n";\r
+ ret += "\ttuple->tuple_type = TEMPORAL_TUPLE;\n";\r
+\r
+ ret += "\n\t/* Copy trace id */\n";\r
+ ret += "\tmemcpy((gs_sp_t)tuple+sizeof( struct "+generate_tuple_name(node_name)+"), &t->trace_id, sizeof(gs_uint64_t));\n\n";\r
+\r
+ ret += "\n\t/* Populate runtime stats */\n";\r
+ ret += "\tstats.ftaid = f->ftaid;\n";\r
+ ret += "\tstats.in_tuple_cnt = t->in_tuple_cnt;\n";\r
+ ret += "\tstats.out_tuple_cnt = t->out_tuple_cnt;\n";\r
+ ret += "\tstats.out_tuple_sz = t->out_tuple_sz;\n";\r
+ ret += "\tstats.accepted_tuple_cnt = t->accepted_tuple_cnt;\n";\r
+ ret += "\tstats.cycle_cnt = t->cycle_cnt;\n";\r
+ ret += "\tstats.collision_cnt = t->collision_cnt;\n";\r
+ ret += "\tstats.eviction_cnt = t->eviction_cnt;\n";\r
+ ret += "\tstats.sampling_rate = t->sampling_rate;\n";\r
+\r
+ ret += "\n#ifdef LFTA_PROFILE\n";\r
+ ret += "\n\t/* Print stats */\n";\r
+ ret += "\tfprintf(stderr, \"STATS " + node_name + " \");\n";\r
+ ret += "\tfprintf(stderr, \"in_tuple_cnt= %u \", t->in_tuple_cnt);\n";\r
+ ret += "\tfprintf(stderr, \"out_tuple_cnt= %u \", t->out_tuple_cnt);\n";\r
+ ret += "\tfprintf(stderr, \"out_tuple_sz= %u \", t->out_tuple_sz);\n";\r
+ ret += "\tfprintf(stderr, \"accepted_tuple_cnt= %u \", t->accepted_tuple_cnt);\n";\r
+ ret += "\tfprintf(stderr, \"cycle_cnt= %llu \", t->cycle_cnt);\n";\r
+ ret += "\tfprintf(stderr, \"cycle_per_in_tuple= %lf \", ((double)t->cycle_cnt)/((double)t->in_tuple_cnt));\n";\r
+ ret += "\tfprintf(stderr, \"collision_cnt= %d\\n\", t->collision_cnt);\n\n";\r
+ ret += "\tfprintf(stderr, \"eviction_cnt= %d\\n\", t->eviction_cnt);\n\n";\r
+ ret += "\n#endif\n";\r
+\r
+\r
+ ret += "\n\t/* Copy stats */\n";\r
+ ret += "\tmemcpy((gs_sp_t)tuple+sizeof( struct "+generate_tuple_name(node_name)+") + sizeof(gs_uint64_t), &stats, sizeof(fta_stat));\n\n";\r
+ ret+="\tpost_tuple(tuple);\n";\r
+\r
+ ret += "\n\t/* Send a heartbeat message to clearinghouse */\n";\r
+ ret += "\tfta_heartbeat(f->ftaid, t->trace_id++, 1, &stats);\n";\r
+\r
+ ret += "\n\t/* Reset runtime stats */\n";\r
+ ret += "\tt->in_tuple_cnt = 0;\n";\r
+ ret += "\tt->out_tuple_cnt = 0;\n";\r
+ ret += "\tt->out_tuple_sz = 0;\n";\r
+ ret += "\tt->accepted_tuple_cnt = 0;\n";\r
+ ret += "\tt->cycle_cnt = 0;\n";\r
+ ret += "\tt->collision_cnt = 0;\n";\r
+ ret += "\tt->eviction_cnt = 0;\n";\r
+\r
+ ret += "\treturn 0;\n}\n\n";\r
+\r
+ return(ret);\r
+}\r
+\r
+\r
+// accept processing before the where clause,\r
+// do flush processwing.\r
+string generate_aggr_accept_prelim(qp_node *fs, string node_name, table_list *schema, col_id_set &unpacked_cids, string &temporal_flush){\r
+ int s;\r
+\r
+// Slow flush\r
+ string ret="\n/*\tslow flush\t*/\n";\r
+ string slow_flush_str = fs->get_val_of_def("slow_flush");\r
+ int n_slow_flush = atoi(slow_flush_str.c_str());\r
+ if(n_slow_flush <= 0) n_slow_flush = 2;\r
+ if(n_slow_flush > 1){\r
+ ret += "\tt->flush_ctr++;\n";\r
+ ret += "\tif(t->flush_ctr >= "+int_to_string(n_slow_flush)+"){\n";\r
+ ret += "\t\tt->flush_ctr = 0;\n";\r
+ ret+="\t\tif(t->flush_pos<t->max_aggrs) fta_aggr_flush_old_"+node_name+"(f,1);\n";\r
+ ret += "\t}\n\n";\r
+ }else{\r
+ ret+="\tif(t->flush_pos<t->max_aggrs) fta_aggr_flush_old_"+node_name+"(f,1);\n\n";\r
+ }\r
+\r
+\r
+ string change_test;\r
+ bool first_one = true;\r
+ int g;\r
+ col_id_set flush_cids; // col ids accessed when computing flush variables.\r
+ // unpack them at temporal flush test time.\r
+ temporal_flush = "";\r
+\r
+\r
+ for(g=0;g<gb_tbl->size();g++){\r
+ data_type *gdt = gb_tbl->get_data_type(g);\r
+ if(gdt->is_temporal()){\r
+ gather_se_col_ids(gb_tbl->get_def(g), flush_cids, gb_tbl);\r
+\r
+// To perform the test, first need to compute the value\r
+// of the temporal gb attrs.\r
+ if(gdt->is_buffer_type()){\r
+ // NOTE : if the SE defining the gb is anything\r
+ // other than a ref to a variable, this will generate\r
+ // illegal code. To be resolved with Spatch.\r
+ sprintf(tmpstr,"\tgb_attr_tmp%d = %s;\n",\r
+ g, generate_se_code(gb_tbl->get_def(g),schema).c_str() );\r
+ temporal_flush += tmpstr;\r
+ sprintf(tmpstr,"\t%s(f, &gb_attr_%d, &gb_attr_tmp%d);\n",\r
+ gdt->get_buffer_assign_copy().c_str(), g, g);\r
+ }else{\r
+ sprintf(tmpstr,"\tgb_attr_%d = %s;\n",g,generate_se_code(gb_tbl->get_def(g),schema).c_str());\r
+ }\r
+ temporal_flush += tmpstr;\r
+// END computing the value of the temporal GB attr.\r
+\r
+\r
+ sprintf(tmpstr,"t->last_gb_%d",g); string lhs_op = tmpstr;\r
+ sprintf(tmpstr,"gb_attr_%d",g); string rhs_op = tmpstr;\r
+ if(first_one){first_one = false;} else {change_test.append(") && (");}\r
+ change_test += generate_equality_test(lhs_op, rhs_op, gdt);\r
+ }\r
+ }\r
+ if(!first_one){ // will be false iff. there is a temporal GB attribute\r
+ temporal_flush += "\n/*\t\tFlush the aggregates if the temporal gb attrs have changed.\t*/\n";\r
+ temporal_flush += "\tif( !( (";\r
+ temporal_flush += change_test;\r
+ temporal_flush += ") ) ){\n";\r
+\r
+// temporal_flush+="\t\tif(t->flush_pos<t->max_aggrs) fta_aggr_flush_old_"+node_name+"(f,t->max_aggrs);\n";\r
+ temporal_flush+="\t\tif(t->flush_pos<t->max_aggrs){ \n";\r
+ temporal_flush+="\t\t\tfta_aggr_flush_old_"+node_name+"(f,t->max_aggrs);\n";\r
+ temporal_flush+="\t\t}\n";\r
+ temporal_flush+="\t\t/* \t\tmark all groups as old */\n";\r
+ temporal_flush+="\t\tt->generation++;\n";\r
+ temporal_flush+="\t\tt->flush_pos = 0;\n";\r
+\r
+\r
+// Now set the saved temporal value of the gb to the\r
+// current value of the gb. Only for simple types,\r
+// not for buffer types -- but the strings are not\r
+// temporal in any case.\r
+\r
+ for(g=0;g<gb_tbl->size();g++){\r
+ data_type *gdt = gb_tbl->get_data_type(g);\r
+ if(gdt->is_temporal()){\r
+ if(gdt->is_buffer_type()){\r
+\r
+ fprintf(stderr,"ERROR : can't handle temporal buffer types, ignoring in buffer flush control.\n");\r
+ }else{\r
+ sprintf(tmpstr,"\t\tt->flush_start_gb_%d = gb_attr_%d;\n",g,g);\r
+ temporal_flush += tmpstr;\r
+ sprintf(tmpstr,"\t\tt->last_gb_%d = gb_attr_%d;\n",g,g);\r
+ temporal_flush += tmpstr;\r
+ }\r
+ }\r
+ }\r
+ temporal_flush += "\t}\n\n";\r
+ }\r
+\r
+// Unpack all the temporal attributes referenced in select clause\r
+// and update the last value of the attribute\r
+ col_id_set temp_cids; // col ids of temp attributes in select clause\r
+ col_id_set::iterator csi;\r
+\r
+ for(s=0;s<sl_list.size();s++){\r
+ data_type *sdt = sl_list[s]->get_data_type();\r
+ if (sdt->is_temporal()) {\r
+ gather_se_col_ids(sl_list[s],temp_cids, gb_tbl);\r
+ }\r
+ }\r
+\r
+ for(csi=temp_cids.begin(); csi != temp_cids.end();++csi){\r
+ if(unpacked_cids.count((*csi)) == 0){\r
+ int tblref = (*csi).tblvar_ref;\r
+ int schref = (*csi).schema_ref;\r
+ string field = (*csi).field;\r
+ ret += generate_unpack_code(tblref,schref,field,schema,node_name);\r
+/*\r
+ data_type dt(schema->get_type_name(schref,field), schema->get_modifier_list(schref,field));\r
+ sprintf(tmpstr,"\tretval = %s(p, &unpack_var_%s_%d);\n",\r
+ schema->get_fcn(schref,field).c_str(), field.c_str(), tblref);\r
+ ret += tmpstr;\r
+ ret += "\tif(retval) return 1;\n";\r
+*/\r
+ sprintf(tmpstr,"\tt->last_%s_%d = unpack_var_%s_%d;\n", field.c_str(), tblref, field.c_str(), tblref);\r
+ ret += tmpstr;\r
+\r
+ unpacked_cids.insert( (*csi) );\r
+ }\r
+ }\r
+\r
+\r
+// Do the flush here if this is a real_time query\r
+ string rt_level = fs->get_val_of_def("real_time");\r
+ if(rt_level != "" && temporal_flush != ""){\r
+ for(csi=flush_cids.begin(); csi != flush_cids.end();++csi){\r
+ if(unpacked_cids.count((*csi)) == 0){\r
+ int tblref = (*csi).tblvar_ref;\r
+ int schref = (*csi).schema_ref;\r
+ string field = (*csi).field;\r
+ ret += generate_unpack_code(tblref,schref,field,schema,node_name);\r
+/*\r
+ sprintf(tmpstr,"\tretval = %s(p, &unpack_var_%s_%d);\n",\r
+ schema->get_fcn(schref,field).c_str(), field.c_str(), tblref);\r
+ ret += tmpstr;\r
+ ret += "\tif(retval) return 1;\n";\r
+*/\r
+ unpacked_cids.insert( (*csi) );\r
+ }\r
+ }\r
+ ret += temporal_flush;\r
+ }\r
+\r
+ return ret;\r
+ }\r
+\r
+string generate_sel_accept_body(qp_node *fs, string node_name, table_list *schema){\r
+\r
+int p,s;\r
+string ret;\r
+\r
+/////////////// Processing for filter-only query\r
+\r
+// test passed : create the tuple, then assign to it.\r
+ ret += "/*\t\tCreate and post the tuple\t*/\n";\r
+\r
+// Unpack partial fcns ref'd by the select clause.\r
+// Its a kind of a WHERE clause ...\r
+ for(p=sl_fcns_start;p<sl_fcns_end;p++){\r
+ if(fcn_ref_cnt[p] > 1){\r
+ ret += "\tif(fcn_ref_cnt_"+int_to_string(p)+"==0){\n";\r
+ }\r
+ if(is_partial_fcn[p]){\r
+ ret += unpack_partial_fcn(partial_fcns[p], p, schema);\r
+ ret += "\tif(retval) goto end;\n";\r
+ }\r
+ if(fcn_ref_cnt[p] > 1){\r
+ if(!is_partial_fcn[p]){\r
+ ret += "\t\tpartial_fcn_result_"+int_to_string(p)+"="+generate_cached_fcn(partial_fcns[p],schema)+";\n";\r
+ }\r
+ ret += "\t\tfcn_ref_cnt_"+int_to_string(p)+"=1;\n";\r
+ ret += "\t}\n";\r
+ }\r
+ }\r
+\r
+ // increment the counter of accepted tuples\r
+ ret += "\n\t#ifdef LFTA_STATS\n";\r
+ ret += "\n\tt->accepted_tuple_cnt++;\n\n";\r
+ ret += "\t#endif\n\n";\r
+\r
+// First, compute the size of the tuple.\r
+\r
+// Unpack any BUFFER type selections into temporaries\r
+// so that I can compute their size and not have\r
+// to recompute their value during tuple packing.\r
+// I can use regular assignment here because\r
+// these temporaries are non-persistent.\r
+\r
+ for(s=0;s<sl_list.size();s++){\r
+ data_type *sdt = sl_list[s]->get_data_type();\r
+ if(sdt->is_buffer_type()){\r
+ sprintf(tmpstr,"\tselvar_%d = ",s);\r
+ ret += tmpstr;\r
+ ret += generate_se_code(sl_list[s],schema);\r
+ ret += ";\n";\r
+ }\r
+ }\r
+\r
+\r
+// The size of the tuple is the size of the tuple struct plus the\r
+// size of the buffers to be copied in.\r
+\r
+ ret+="\ttuple_size = sizeof( struct "+generate_tuple_name(node_name)+")";\r
+ for(s=0;s<sl_list.size();s++){\r
+ data_type *sdt = sl_list[s]->get_data_type();\r
+ if(sdt->is_buffer_type()){\r
+ sprintf(tmpstr," + %s(&selvar_%d)", sdt->get_buffer_size().c_str(),s);\r
+ ret += tmpstr;\r
+ }\r
+ }\r
+ ret += ";\n";\r
+\r
+\r
+ ret += "\ttuple = allocate_tuple(f, tuple_size );\n";\r
+ ret += "\tif( tuple == NULL)\n\t\tgoto end;\n";\r
+\r
+// Test passed, make assignments to the tuple.\r
+\r
+ ret += "\ttuple_pos = sizeof( struct "+generate_tuple_name(node_name)+");\n";\r
+\r
+// Mark tuple as REGULAR_TUPLE\r
+ ret += "\ttuple->tuple_type = REGULAR_TUPLE;\n";\r
+\r
+\r
+ for(s=0;s<sl_list.size();s++){\r
+ data_type *sdt = sl_list[s]->get_data_type();\r
+ if(sdt->is_buffer_type()){\r
+ sprintf(tmpstr,"\t%s(&(tuple->tuple_var%d), &selvar_%d, (char *)tuple, ((char *)tuple)+tuple_pos);\n", sdt->get_buffer_tuple_copy().c_str(),s, s);\r
+ ret += tmpstr;\r
+ sprintf(tmpstr,"\ttuple_pos += %s(&selvar_%d);\n", sdt->get_buffer_size().c_str(), s);\r
+ ret += tmpstr;\r
+ }else{\r
+ sprintf(tmpstr,"\ttuple->tuple_var%d = ",s);\r
+ ret += tmpstr;\r
+// if(sdt->needs_hn_translation())\r
+// ret += sdt->hton_translation() +"( ";\r
+ ret += generate_se_code(sl_list[s],schema);\r
+// if(sdt->needs_hn_translation())\r
+// ret += ") ";\r
+ ret += ";\n";\r
+ }\r
+ }\r
+\r
+// Generate output.\r
+\r
+ ret += "\tpost_tuple(tuple);\n";\r
+\r
+// Increment the counter of posted tuples\r
+ ret += "\n\t#ifdef LFTA_STATS\n";\r
+ ret += "\tt->out_tuple_cnt++;\n";\r
+ ret+="\tt->out_tuple_sz+=tuple_size;\n";\r
+ ret += "\t#endif\n\n";\r
+\r
+\r
+\r
+ return ret;\r
+}\r
+\r
+string generate_fj_accept_body(filter_join_qpn *fs, string node_name,col_id_set &unpacked_cids,ext_fcn_list *Ext_fcns, table_list *schema){\r
+\r
+int p,s,w;\r
+string ret;\r
+\r
+// Get parameters\r
+ unsigned int window_len = fs->temporal_range;\r
+ unsigned int n_bloom = 11;\r
+ string n_bloom_str = fs->get_val_of_def("num_bloom");\r
+ int tmp_n_bloom = atoi(n_bloom_str.c_str());\r
+ if(tmp_n_bloom>0)\r
+ n_bloom = tmp_n_bloom+1;\r
+ float bloom_width = (window_len+1.0)/(1.0*n_bloom-1);\r
+ sprintf(tmpstr,"%f",bloom_width);\r
+ string bloom_width_str = tmpstr;\r
+\r
+ if(window_len < n_bloom){\r
+ n_bloom = window_len+1;\r
+ bloom_width_str = "1";\r
+ }\r
+\r
+\r
+// Grab the current window time\r
+ scalarexp_t winvar(fs->temporal_var);\r
+ ret += "\tcurr_fj_ts = "+generate_se_code(&winvar,schema)+";\n";\r
+\r
+ int bf_exp_size = 12; // base-2 log of number of bits\r
+ string bloom_len_str = fs->get_val_of_def("bloom_size");\r
+ int tmp_bf_exp_size = atoi(bloom_len_str.c_str());\r
+ if(tmp_bf_exp_size > 3 && tmp_bf_exp_size < 32){\r
+ bf_exp_size = tmp_bf_exp_size;\r
+ }\r
+ int bf_bit_size = 1 << bf_exp_size;\r
+ int bf_byte_size = bf_bit_size / (8*sizeof(char));\r
+\r
+ unsigned int ht_size = 4096;\r
+ string ht_size_s = fs->get_val_of_def("aggregate_slots");\r
+ int tmp_ht_size = atoi(ht_size_s.c_str());\r
+ if(tmp_ht_size > 1024){\r
+ unsigned int hs = 1; // make it power of 2\r
+ while(tmp_ht_size){\r
+ hs =hs << 1;\r
+ tmp_ht_size = tmp_ht_size >> 1;\r
+ }\r
+ ht_size = hs;\r
+ }\r
+\r
+ int i, bf_mask = 0;\r
+ if(fs->use_bloom){\r
+ for(i=0;i<bf_exp_size;i++)\r
+ bf_mask = (bf_mask << 1) | 1;\r
+ }else{\r
+ for(i=ht_size;i>1;i=i>>1)\r
+ bf_mask = (bf_mask << 1) | 1;\r
+ }\r
+\r
+/*\r
+printf("n_bloom=%d, window_len=%d, bloom_width=%s, bf_exp_size=%d, bf_bit_size=%d, bf_byte_size=%d, ht_size=%d, ht_size_s=%s, bf_mask=%d\n",\r
+ n_bloom,\r
+ window_len,\r
+ bloom_width_str.c_str(),\r
+ bf_exp_size,\r
+ bf_bit_size,\r
+ bf_byte_size,\r
+ ht_size,\r
+ ht_size_s.c_str(),\r
+ bf_mask);\r
+*/\r
+\r
+\r
+\r
+\r
+// If this is a bloom-filter fj, first test if the\r
+// bloom filter needs to be advanced.\r
+// SET_BF_EMPTY(table,number of bloom filters,bloom filter index,bit index)\r
+// t->bf_size : number of bits in bloom filter\r
+ if(fs->use_bloom){\r
+ ret +=\r
+"// Clean out old bloom filters if needed.\n"\r
+" if(t->first_exec){\n"\r
+" t->first_exec = 0;\n"\r
+" t->last_bin = (long long int)(curr_fj_ts/"+bloom_width_str+");\n"\r
+" t->last_bloom_pos = t->last_bin % "+int_to_string(n_bloom)+";\n"\r
+" }else{\n"\r
+" curr_bin = (long long int)(curr_fj_ts/"+bloom_width_str+");\n"\r
+" if(curr_bin != t->last_bin){\n"\r
+" for(the_bin=t->last_bin+1;the_bin<=curr_bin;the_bin++){\n"\r
+" t->last_bloom_pos++;\n"\r
+" if(t->last_bloom_pos >= "+int_to_string(n_bloom)+")\n"\r
+" t->last_bloom_pos = 0;\n"\r
+" tmp_i = t->last_bloom_pos;\n"\r
+" for(j=0;j<"+int_to_string(bf_bit_size)+";j++){\n"\r
+" SET_BF_EMPTY(t->bf_table, "+int_to_string(n_bloom)+", tmp_i,j);\n"\r
+" }\n"\r
+" }\n"\r
+" }\n"\r
+" t->last_bin = curr_bin;\n"\r
+" }\n"\r
+;\r
+ }\r
+\r
+\r
+//-----------------------------------------------------------------\r
+// First, determine whether to do S (filter stream) processing.\r
+\r
+ ret +=\r
+"// S (filtering stream) predicate, should it be processed?\n"\r
+"\n"\r
+;\r
+// Sort S preds based on cost.\r
+ vector<cnf_elem *> s_filt = fs->pred_t1;\r
+ col_id_set::iterator csi;\r
+ if(s_filt.size() > 0){\r
+\r
+// Unpack fields ref'd in the S pred\r
+ for(w=0;w<s_filt.size();++w){\r
+ col_id_set this_pred_cids;\r
+ gather_pr_col_ids(s_filt[w]->pr, this_pred_cids, gb_tbl);\r
+ for(csi=this_pred_cids.begin();csi!=this_pred_cids.end();++csi){\r
+ if(unpacked_cids.count( (*csi) ) == 0){\r
+ int tblref = (*csi).tblvar_ref;\r
+ int schref = (*csi).schema_ref;\r
+ string field = (*csi).field;\r
+ ret += generate_unpack_code(tblref,schref,field,schema,node_name,"end_s");\r
+ unpacked_cids.insert( (*csi) );\r
+ }\r
+ }\r
+ }\r
+\r
+\r
+// Sort by evaluation cost.\r
+// First, estimate evaluation costs\r
+// Eliminate predicates covered by the prefilter (those in s_pids).\r
+// I need to do it before the sort becuase the indices refer\r
+// to the position in the unsorted list.\r
+ vector<cnf_elem *> tmp_wh;\r
+ for(w=0;w<s_filt.size();++w){\r
+ compute_cnf_cost(s_filt[w],Ext_fcns);\r
+ tmp_wh.push_back(s_filt[w]);\r
+ }\r
+ s_filt = tmp_wh;\r
+\r
+ sort(s_filt.begin(), s_filt.end(), compare_cnf_cost());\r
+\r
+// Now generate the predicates.\r
+ for(w=0;w<s_filt.size();++w){\r
+ sprintf(tmpstr,"//\t\tPredicate clause %d.(cost %d)\n",w,s_filt[w]->cost);\r
+ ret += tmpstr;\r
+\r
+// Find partial fcns ref'd in this cnf element\r
+ set<int> pfcn_refs;\r
+ collect_partial_fcns_pr(s_filt[w]->pr, pfcn_refs);\r
+// Since set<..> is a "Sorted Associative Container",\r
+// we can walk through it in sorted order by walking from\r
+// begin() to end(). (and the partial fcns must be\r
+// evaluated in this order).\r
+ set<int>::iterator si;\r
+ string pf_preds;\r
+ for(si=pfcn_refs.begin();si!=pfcn_refs.end();++si){\r
+ if(fcn_ref_cnt[(*si)] > 1){\r
+ ret += "\tif(fcn_ref_cnt_"+int_to_string((*si))+"==0){\n";\r
+ }\r
+ if(is_partial_fcn[(*si)]){\r
+ ret += "\t"+unpack_partial_fcn(partial_fcns[(*si)], (*si), schema);\r
+ ret += "\t\tif(retval) goto end_s;\n";\r
+ }\r
+ if(fcn_ref_cnt[(*si)] > 1){\r
+ if(!is_partial_fcn[(*si)]){\r
+ ret += "\t\tpartial_fcn_result_"+int_to_string((*si))+"="+generate_cached_fcn(partial_fcns[(*si)],schema)+";\n";\r
+// Testing for S is a side branch.\r
+// I don't want a cacheable partial function to be\r
+// marked as evaluated. Therefore I mark the function\r
+// as evalauted ONLY IF it is not partial.\r
+ ret += "\t\tfcn_ref_cnt_"+int_to_string((*si))+"=1;\n";\r
+ }\r
+ ret += "\t}\n";\r
+ }\r
+ }\r
+\r
+ ret += "\tif( !("+generate_predicate_code(s_filt[w]->pr,schema)+\r
+ ") ) goto end_s;\n";\r
+ }\r
+ }else{\r
+ ret += "\n\n/*\t\t (no predicate to test)\t*/\n\n";\r
+ }\r
+\r
+ for(p=0;p<fs->hash_eq.size();++p)\r
+ ret += "\t\ts_equijoin_"+int_to_string(p)+" = "+generate_se_code(fs->hash_eq[p]->pr->get_right_se(),schema)+";\n";\r
+\r
+ if(fs->use_bloom){\r
+// First, generate the S scalar expressions in the hash_eq\r
+\r
+// Iterate over the bloom filters\r
+ for(i=0;i<3;i++){\r
+ ret += "\t\tbucket=0;\n";\r
+ for(p=0;p<fs->hash_eq.size();++p){\r
+ ret +=\r
+" bucket ^= (("+hash_nums[(i*fs->hash_eq.size()+p)%NRANDS]+" * lfta_"+\r
+ fs->hash_eq[p]->pr->get_right_se()->get_data_type()->get_type_str()+\r
+ +"_to_hash(s_equijoin_"+int_to_string(p)+"))>>32);\n";\r
+ }\r
+// SET_BF_BIT(table,number of bloom filters,bloom filter index,bit index)\r
+ ret +=\r
+" bucket &= "+int_to_string(bf_mask)+";\n"\r
+" SET_BF_BIT(t->bf_table,"+int_to_string(n_bloom)+",t->last_bloom_pos,bucket);\n"\r
+"\n"\r
+;\r
+ }\r
+ }else{\r
+ ret += "\t\tbucket=0;\n";\r
+ for(p=0;p<fs->hash_eq.size();++p){\r
+ ret +=\r
+" bucket ^= (("+hash_nums[(i*fs->hash_eq.size()+p)%NRANDS]+" * lfta_"+\r
+ fs->hash_eq[p]->pr->get_right_se()->get_data_type()->get_type_str()+\r
+ +"_to_hash(s_equijoin_"+int_to_string(p)+"))>>32);\n";\r
+ }\r
+ ret +=\r
+" bucket &= "+int_to_string(bf_mask)+";\n"\r
+" bucket1 = (bucket + 1) & "+int_to_string(bf_mask)+";\n"\r
+;\r
+// Try the first bucket\r
+ ret += "\t\tif(";\r
+ for(p=0;p<fs->hash_eq.size();++p){\r
+ if(p>0) ret += " && ";\r
+// ret += "t->join_table[bucket].key_var"+int_to_string(p)+\r
+// " == s_equijoin_"+int_to_string(p);\r
+ data_type *hdt = fs->hash_eq[p]->pr->get_right_se()->get_data_type();\r
+ string lhs_op = "t->join_table[bucket].key_var"+int_to_string(p);\r
+ string rhs_op = "s_equijoin_"+int_to_string(p);\r
+ ret += generate_equality_test(lhs_op,rhs_op,hdt);\r
+ }\r
+ ret += "){\n\t\t\tthe_bucket = bucket;\n";\r
+ ret += "\t\t}else {if(";\r
+ for(p=0;p<fs->hash_eq.size();++p){\r
+ if(p>0) ret += " && ";\r
+// ret += "t->join_table[bucket1].key_var"+int_to_string(p)+\r
+// " == s_equijoin_"+int_to_string(p);\r
+ data_type *hdt = fs->hash_eq[p]->pr->get_right_se()->get_data_type();\r
+ string lhs_op = "t->join_table[bucket].key_var"+int_to_string(p);\r
+ string rhs_op = "s_equijoin_"+int_to_string(p);\r
+ ret += generate_equality_test(lhs_op,rhs_op,hdt);\r
+ }\r
+ ret += "){\n\t\t\tthe_bucket = bucket1;\n";\r
+ ret += "\t\t}else{ if(t->join_table[bucket].ts <= t->join_table[bucket1].ts)\n";\r
+ ret+="\t\t\tthe_bucket = bucket;\n\t\t\telse the_bucket=bucket1;\n";\r
+ ret += "\t\t}}\n";\r
+ for(p=0;p<fs->hash_eq.size();++p){\r
+ data_type *hdt = fs->hash_eq[p]->pr->get_right_se()->get_data_type();\r
+ if(hdt->is_buffer_type()){\r
+ sprintf(tmpstr,"\t\t%s(f, &(t->join_table[the_bucket].key_var%d), &s_equijoin_%d);\n", hdt->get_buffer_assign_copy().c_str(), p, p);\r
+ ret += tmpstr;\r
+ }else{\r
+ ret += "\t\tt->join_table[the_bucket].key_var"+int_to_string(p)+\r
+ " = s_equijoin_"+int_to_string(p)+";\n";\r
+ }\r
+ }\r
+ ret+="\t\tt->join_table[the_bucket].ts = curr_fj_ts;\n";\r
+ }\r
+ ret += "\tend_s:\n";\r
+\r
+// ------------------------------------------------------------\r
+// Next, determine if the R record should be processed.\r
+\r
+\r
+ ret +=\r
+"// R (main stream) cheap predicate\n"\r
+"\n"\r
+;\r
+\r
+// Unpack r_filt fields\r
+ vector<cnf_elem *> r_filt = fs->pred_t0;\r
+ for(w=0;w<r_filt.size();++w){\r
+ col_id_set this_pred_cids;\r
+ gather_pr_col_ids(r_filt[w]->pr, this_pred_cids, gb_tbl);\r
+ for(csi=this_pred_cids.begin();csi!=this_pred_cids.end();++csi){\r
+ if(unpacked_cids.count( (*csi) ) == 0){\r
+ int tblref = (*csi).tblvar_ref;\r
+ int schref = (*csi).schema_ref;\r
+ string field = (*csi).field;\r
+ ret += generate_unpack_code(tblref,schref,field,schema,node_name);\r
+ unpacked_cids.insert( (*csi) );\r
+ }\r
+ }\r
+ }\r
+\r
+// Sort S preds based on cost.\r
+\r
+ vector<cnf_elem *> tmp_wh;\r
+ for(w=0;w<r_filt.size();++w){\r
+ compute_cnf_cost(r_filt[w],Ext_fcns);\r
+ tmp_wh.push_back(r_filt[w]);\r
+ }\r
+ r_filt = tmp_wh;\r
+\r
+ sort(r_filt.begin(), r_filt.end(), compare_cnf_cost());\r
+\r
+// WARNING! the constant 20 below is a wild-ass guess.\r
+ int cheap_rpos;\r
+ for(cheap_rpos=0;cheap_rpos<r_filt.size() && r_filt[cheap_rpos]->cost <= 20;cheap_rpos++)\r
+\r
+// Test the cheap filters on R.\r
+ if(cheap_rpos >0){\r
+\r
+// Now generate the predicates.\r
+ for(w=0;w<cheap_rpos;++w){\r
+ sprintf(tmpstr,"//\t\tPredicate clause %d.(cost %d)\n",w,r_filt[w]->cost);\r
+ ret += tmpstr;\r
+\r
+// Find partial fcns ref'd in this cnf element\r
+ set<int> pfcn_refs;\r
+ collect_partial_fcns_pr(r_filt[w]->pr, pfcn_refs);\r
+// Since set<..> is a "Sorted Associative Container",\r
+// we can walk through it in sorted order by walking from\r
+// begin() to end(). (and the partial fcns must be\r
+// evaluated in this order).\r
+ set<int>::iterator si;\r
+ for(si=pfcn_refs.begin();si!=pfcn_refs.end();++si){\r
+ if(fcn_ref_cnt[(*si)] > 1){\r
+ ret += "\tif(fcn_ref_cnt_"+int_to_string((*si))+"==0){\n";\r
+ }\r
+ if(is_partial_fcn[(*si)]){\r
+ ret += "\t"+unpack_partial_fcn(partial_fcns[(*si)], (*si), schema);\r
+ ret += "\t\tif(retval) goto end;\n";\r
+ }\r
+ if(fcn_ref_cnt[(*si)] > 1){\r
+ if(!is_partial_fcn[(*si)]){\r
+ ret += "\t\tpartial_fcn_result_"+int_to_string((*si))+"="+generate_cached_fcn(partial_fcns[(*si)],schema)+";\n";\r
+ }\r
+ ret += "\t\tfcn_ref_cnt_"+int_to_string((*si))+"=1;\n";\r
+ ret += "\t}\n";\r
+ }\r
+ }\r
+\r
+ ret += "\tif( !("+generate_predicate_code(r_filt[w]->pr,schema)+\r
+ ") ) goto end;\n";\r
+ }\r
+ }else{\r
+ ret += "\n\n/*\t\t (no predicate to test)\t*/\n\n";\r
+ }\r
+\r
+ ret += "\n// Do the join\n\n";\r
+ for(p=0;p<fs->hash_eq.size();++p)\r
+ ret += "\t\tr_equijoin_"+int_to_string(p)+" = "+generate_se_code(fs->hash_eq[p]->pr->get_left_se(),schema)+";\n";\r
+\r
+\r
+// Passed the cheap pred, now test the join with S.\r
+ if(fs->use_bloom){\r
+ for(i=0;i<3;i++){\r
+ ret += "\t\tbucket"+int_to_string(i)+"=0;\n";\r
+ for(p=0;p<fs->hash_eq.size();++p){\r
+ ret +=\r
+" bucket"+int_to_string(i)+\r
+ " ^= (("+hash_nums[(i*fs->hash_eq.size()+p)%NRANDS]+" * lfta_"+\r
+ fs->hash_eq[p]->pr->get_right_se()->get_data_type()->get_type_str()+\r
+ +"_to_hash(r_equijoin_"+int_to_string(p)+"))>>32);\n";\r
+ }\r
+ ret +=\r
+" bucket"+int_to_string(i)+" &= "+int_to_string(bf_mask)+";\n";\r
+ }\r
+ ret += "\tfound = 0;\n";\r
+ ret += "\tfor(b=0;b<"+int_to_string(n_bloom)+" && !found; b++){\n";\r
+ ret +=\r
+"\t\tif(IS_BF_SET(t->bf_table,"+int_to_string(n_bloom)+",t->last_bloom_pos,bucket0) && "\r
+"IS_BF_SET(t->bf_table,"+int_to_string(n_bloom)+",t->last_bloom_pos,bucket1) && "\r
+"IS_BF_SET(t->bf_table,"+int_to_string(n_bloom)+",t->last_bloom_pos,bucket2))\n "\r
+"\t\t\tfound=1;\n"\r
+"\t}\n"\r
+;\r
+ ret +=\r
+" if(!found)\n"\r
+" goto end;\n"\r
+;\r
+ }else{\r
+ ret += "\tfound = 0;\n";\r
+ ret += "\t\tbucket=0;\n";\r
+ for(p=0;p<fs->hash_eq.size();++p){\r
+ ret +=\r
+" bucket ^= (("+hash_nums[(i*fs->hash_eq.size()+p)%NRANDS]+" * lfta_"+\r
+ fs->hash_eq[p]->pr->get_right_se()->get_data_type()->get_type_str()+\r
+ +"_to_hash(r_equijoin_"+int_to_string(p)+"))>>32);\n";\r
+ }\r
+ ret +=\r
+" bucket &= "+int_to_string(bf_mask)+";\n"\r
+" bucket1 = (bucket + 1) & "+int_to_string(bf_mask)+";\n"\r
+;\r
+// Try the first bucket\r
+ ret += "\t\tif(";\r
+ for(p=0;p<fs->hash_eq.size();++p){\r
+ if(p>0) ret += " && ";\r
+// ret += "t->join_table[bucket].key_var"+int_to_string(p)+\r
+// " == r_equijoin_"+int_to_string(p);\r
+ data_type *hdt = fs->hash_eq[p]->pr->get_right_se()->get_data_type();\r
+ string lhs_op = "t->join_table[bucket].key_var"+int_to_string(p);\r
+ string rhs_op = "s_equijoin_"+int_to_string(p);\r
+ ret += generate_equality_test(lhs_op,rhs_op,hdt);\r
+ }\r
+ if(p>0) ret += " && ";\r
+ ret += "t->join_table[bucket].ts+"+int_to_string(fs->temporal_range)+" <= curr_fj_ts";\r
+ ret += "){\n\t\t\tfound = 1;\n";\r
+ ret += "\t\t}else {if(";\r
+ for(p=0;p<fs->hash_eq.size();++p){\r
+ if(p>0) ret += " && ";\r
+// ret += "t->join_table[bucket1].key_var"+int_to_string(p)+\r
+// " == r_equijoin_"+int_to_string(p);\r
+ data_type *hdt = fs->hash_eq[p]->pr->get_right_se()->get_data_type();\r
+ string lhs_op = "t->join_table[bucket].key_var"+int_to_string(p);\r
+ string rhs_op = "s_equijoin_"+int_to_string(p);\r
+ ret += generate_equality_test(lhs_op,rhs_op,hdt);\r
+ }\r
+ if(p>0) ret += " && ";\r
+ ret += "t->join_table[bucket1].ts+"+int_to_string(fs->temporal_range)+" <= curr_fj_ts";\r
+ ret += ")\n\t\t\tfound=1;\n";\r
+ ret+="\t\t}\n";\r
+ ret +=\r
+" if(!found)\n"\r
+" goto end;\n"\r
+;\r
+ }\r
+\r
+\r
+// Test the expensive filters on R.\r
+ if(cheap_rpos < r_filt.size()){\r
+\r
+// Now generate the predicates.\r
+ for(w=cheap_rpos;w<r_filt.size();++w){\r
+ sprintf(tmpstr,"//\t\tPredicate clause %d.(cost %d)\n",w,r_filt[w]->cost);\r
+ ret += tmpstr;\r
+\r
+// Find partial fcns ref'd in this cnf element\r
+ set<int> pfcn_refs;\r
+ collect_partial_fcns_pr(r_filt[w]->pr, pfcn_refs);\r
+// Since set<..> is a "Sorted Associative Container",\r
+// we can walk through it in sorted order by walking from\r
+// begin() to end(). (and the partial fcns must be\r
+// evaluated in this order).\r
+ set<int>::iterator si;\r
+ for(si=pfcn_refs.begin();si!=pfcn_refs.end();++si){\r
+ if(fcn_ref_cnt[(*si)] > 1){\r
+ ret += "\tif(fcn_ref_cnt_"+int_to_string((*si))+"==0){\n";\r
+ }\r
+ if(is_partial_fcn[(*si)]){\r
+ ret += "\t"+unpack_partial_fcn(partial_fcns[(*si)], (*si), schema);\r
+ ret += "\t\tif(retval) goto end;\n";\r
+ }\r
+ if(fcn_ref_cnt[(*si)] > 1){\r
+ if(!is_partial_fcn[(*si)]){\r
+ ret += "\t\tpartial_fcn_result_"+int_to_string((*si))+"="+generate_cached_fcn(partial_fcns[(*si)],schema)+";\n";\r
+ }\r
+ ret += "\t\tfcn_ref_cnt_"+int_to_string((*si))+"=1;\n";\r
+ ret += "\t}\n";\r
+ }\r
+ }\r
+\r
+ ret += "\tif( !("+generate_predicate_code(r_filt[w]->pr,schema)+\r
+ ") ) goto end;\n";\r
+ }\r
+ }else{\r
+ ret += "\n\n/*\t\t (no predicate to test)\t*/\n\n";\r
+ }\r
+\r
+\r
+\r
+/////////////// post the tuple\r
+\r
+// test passed : create the tuple, then assign to it.\r
+ ret += "/*\t\tCreate and post the tuple\t*/\n";\r
+\r
+// Unpack r_filt fields\r
+ for(s=0;s<sl_list.size();++s){\r
+ col_id_set this_se_cids;\r
+ gather_se_col_ids(sl_list[s], this_se_cids, gb_tbl);\r
+ for(csi=this_se_cids.begin();csi!=this_se_cids.end();++csi){\r
+ if(unpacked_cids.count( (*csi) ) == 0){\r
+ int tblref = (*csi).tblvar_ref;\r
+ int schref = (*csi).schema_ref;\r
+ string field = (*csi).field;\r
+ ret += generate_unpack_code(tblref,schref,field,schema,node_name);\r
+ unpacked_cids.insert( (*csi) );\r
+ }\r
+ }\r
+ }\r
+\r
+\r
+// Unpack partial fcns ref'd by the select clause.\r
+// Its a kind of a WHERE clause ...\r
+ for(p=sl_fcns_start;p<sl_fcns_end;p++){\r
+ if(fcn_ref_cnt[p] > 1){\r
+ ret += "\tif(fcn_ref_cnt_"+int_to_string(p)+"==0){\n";\r
+ }\r
+ if(is_partial_fcn[p]){\r
+ ret += unpack_partial_fcn(partial_fcns[p], p, schema);\r
+ ret += "\tif(retval) goto end;\n";\r
+ }\r
+ if(fcn_ref_cnt[p] > 1){\r
+ if(!is_partial_fcn[p]){\r
+ ret += "\t\tpartial_fcn_result_"+int_to_string(p)+"="+generate_cached_fcn(partial_fcns[p],schema)+";\n";\r
+ }\r
+ ret += "\t\tfcn_ref_cnt_"+int_to_string(p)+"=1;\n";\r
+ ret += "\t}\n";\r
+ }\r
+ }\r
+\r
+ // increment the counter of accepted tuples\r
+ ret += "\n\t#ifdef LFTA_STATS\n";\r
+ ret += "\n\tt->accepted_tuple_cnt++;\n\n";\r
+ ret += "\t#endif\n\n";\r
+\r
+// First, compute the size of the tuple.\r
+\r
+// Unpack any BUFFER type selections into temporaries\r
+// so that I can compute their size and not have\r
+// to recompute their value during tuple packing.\r
+// I can use regular assignment here because\r
+// these temporaries are non-persistent.\r
+\r
+ for(s=0;s<sl_list.size();s++){\r
+ data_type *sdt = sl_list[s]->get_data_type();\r
+ if(sdt->is_buffer_type()){\r
+ sprintf(tmpstr,"\tselvar_%d = ",s);\r
+ ret += tmpstr;\r
+ ret += generate_se_code(sl_list[s],schema);\r
+ ret += ";\n";\r
+ }\r
+ }\r
+\r
+\r
+// The size of the tuple is the size of the tuple struct plus the\r
+// size of the buffers to be copied in.\r
+\r
+ ret+="\ttuple_size = sizeof( struct "+generate_tuple_name(node_name)+")";\r
+ for(s=0;s<sl_list.size();s++){\r
+ data_type *sdt = sl_list[s]->get_data_type();\r
+ if(sdt->is_buffer_type()){\r
+ sprintf(tmpstr," + %s(&selvar_%d)", sdt->get_buffer_size().c_str(),s);\r
+ ret += tmpstr;\r
+ }\r
+ }\r
+ ret += ";\n";\r
+\r
+\r
+ ret += "\ttuple = allocate_tuple(f, tuple_size );\n";\r
+ ret += "\tif( tuple == NULL)\n\t\tgoto end;\n";\r
+\r
+// Test passed, make assignments to the tuple.\r
+\r
+ ret += "\ttuple_pos = sizeof( struct "+generate_tuple_name(node_name)+");\n";\r
+\r
+// Mark tuple as REGULAR_TUPLE\r
+ ret += "\ttuple->tuple_type = REGULAR_TUPLE;\n";\r
+\r
+\r
+ for(s=0;s<sl_list.size();s++){\r
+ data_type *sdt = sl_list[s]->get_data_type();\r
+ if(sdt->is_buffer_type()){\r
+ sprintf(tmpstr,"\t%s(&(tuple->tuple_var%d), &selvar_%d, (char *)tuple, ((char *)tuple)+tuple_pos);\n", sdt->get_buffer_tuple_copy().c_str(),s, s);\r
+ ret += tmpstr;\r
+ sprintf(tmpstr,"\ttuple_pos += %s(&selvar_%d);\n", sdt->get_buffer_size().c_str(), s);\r
+ ret += tmpstr;\r
+ }else{\r
+ sprintf(tmpstr,"\ttuple->tuple_var%d = ",s);\r
+ ret += tmpstr;\r
+// if(sdt->needs_hn_translation())\r
+// ret += sdt->hton_translation() +"( ";\r
+ ret += generate_se_code(sl_list[s],schema);\r
+// if(sdt->needs_hn_translation())\r
+// ret += ") ";\r
+ ret += ";\n";\r
+ }\r
+ }\r
+\r
+// Generate output.\r
+\r
+ ret += "\tpost_tuple(tuple);\n";\r
+\r
+// Increment the counter of posted tuples\r
+ ret += "\n\t#ifdef LFTA_STATS\n";\r
+ ret += "\n\tt->out_tuple_cnt++;\n\n";\r
+ ret+="\t\t\t\tt->out_tuple_sz+=tuple_size;\n";\r
+ ret += "\t#endif\n\n";\r
+\r
+\r
+ return ret;\r
+}\r
+\r
+string generate_aggr_accept_body(qp_node *fs,string node_name,table_list *schema, string &temporal_flush){\r
+ string ret;\r
+ int a,p,g;\r
+\r
+////////////// Processing for aggregtion query\r
+\r
+// First, search for a match. Start by unpacking the group-by attributes.\r
+\r
+// One complication : if a real-time aggregate flush occurs,\r
+// the GB attr has already been calculated. So don't compute\r
+// it again if 1) its temporal and 2) it will be computed in the\r
+// agggregate flush code.\r
+\r
+// Unpack the partial fcns ref'd by the gb's and the aggr defs.\r
+ for(p=gb_fcns_start;p<gb_fcns_end;p++){\r
+ if(is_partial_fcn[p]){\r
+ ret += unpack_partial_fcn(partial_fcns[p], p, schema);\r
+ ret += "\tif(retval) goto end;\n";\r
+ }\r
+ }\r
+ for(p=ag_fcns_start;p<ag_fcns_end;p++){\r
+ if(is_partial_fcn[p]){\r
+ ret += unpack_partial_fcn(partial_fcns[p], p, schema);\r
+ ret += "\tif(retval) goto end;\n";\r
+ }\r
+ }\r
+\r
+ // increment the counter of accepted tuples\r
+ ret += "\n\t#ifdef LFTA_STATS\n";\r
+ ret += "\n\tt->accepted_tuple_cnt++;\n\n";\r
+ ret += "\t#endif\n\n";\r
+\r
+ ret += "/*\t\tTest if the group is in the hash table \t*/\n";\r
+// Compute the values of the group-by variables.\r
+ for(g=0;g<gb_tbl->size();g++){\r
+ data_type *gdt = gb_tbl->get_data_type(g);\r
+ if((! gdt->is_temporal()) || temporal_flush == ""){\r
+\r
+ if(gdt->is_buffer_type()){\r
+ // NOTE : if the SE defining the gb is anything\r
+ // other than a ref to a variable, this will generate\r
+ // illegal code. To be resolved with Spatch.\r
+ sprintf(tmpstr,"\tgb_attr_tmp%d = %s;\n",\r
+ g, generate_se_code(gb_tbl->get_def(g),schema).c_str() );\r
+ ret += tmpstr;\r
+ sprintf(tmpstr,"\t%s(f, &gb_attr_%d, &gb_attr_tmp%d);\n",\r
+ gdt->get_buffer_assign_copy().c_str(), g, g);\r
+ }else{\r
+ sprintf(tmpstr,"\tgb_attr_%d = %s;\n",g,generate_se_code(gb_tbl->get_def(g),schema).c_str());\r
+ }\r
+ ret += tmpstr;\r
+ }\r
+ }\r
+ ret += "\n";\r
+\r
+// A quick aside : if any of the GB attrs are temporal,\r
+// test for change and flush if any change occurred.\r
+// We've already computed the flush code,\r
+// Put it here if this is not a real time query.\r
+// We've already unpacked all column refs, so no need to\r
+// do it again here.\r
+\r
+ string rt_level = fs->get_val_of_def("real_time");\r
+ if(rt_level == "" && temporal_flush != ""){\r
+ ret += temporal_flush;\r
+ }\r
+\r
+// Compute the hash bucket\r
+ if(gb_tbl->size() > 0){\r
+ ret += "\thashval = ";\\r
+ for(g=0;g<gb_tbl->size();g++){\r
+ if(g>0) ret += " ^ ";\r
+ data_type *gdt = gb_tbl->get_data_type(g);\r
+ if(gdt->is_buffer_type()){\r
+ sprintf(tmpstr,"((%s * lfta_%s_to_hash(gb_attr_%d)))",hash_nums[g%NRANDS].c_str(),\r
+ gdt->get_type_str().c_str(), g);\r
+ }else{\r
+ sprintf(tmpstr,"((%s * lfta_%s_to_hash(gb_attr_%d)))",hash_nums[g%NRANDS].c_str(),\r
+ gdt->get_type_str().c_str(), g);\r
+ }\r
+ ret += tmpstr;\r
+ }\r
+ ret += ";\n";\r
+ ret += "\thash2 = ((hashval * "+hash_nums[g%NRANDS]+") >> 32) & SLOT_HASH_BITS;\n";\r
+ ret+="\tprobe = (hashval >> 32) & (t->max_aggrs-1);\n";\r
+ }else{\r
+ ret+="\tprobe = 0;\n";\r
+ ret+="\thash2 = 0;\n\n";\r
+ }\r
+\r
+// Does the lfta reference a udaf?\r
+ bool has_udaf = false;\r
+ for(a=0;a<aggr_tbl->size();a++){\r
+ if(! aggr_tbl->is_builtin(a)) has_udaf = true;\r
+ }\r
+\r
+// Scan for a match, or alternatively the best slot.\r
+// Currently, hardcode 5 tests.\r
+ ret +=\r
+" gen_val = t->generation & SLOT_GEN_BITS;\n"\r
+" match_found = 0;\n"\r
+" best_slot = probe;\n"\r
+" for(i=0;i<5 && match_found == 0;i++){\n"\r
+" if((t->aggr_table_hashmap[probe] & SLOT_FILLED) && (t->aggr_table_hashmap[probe] & SLOT_GEN_BITS) == gen_val && (t->aggr_table_hashmap[probe] & SLOT_HASH_BITS) == hash2 ){\n"\r
+;\r
+ if(gb_tbl->size()>0){\r
+ ret+="\n\t/* \t\tcheck if the grouping variables are equal */\n";\r
+ ret+="\t\tif(";\r
+ string rhs_op, lhs_op;\r
+ for(g=0;g<gb_tbl->size();g++){\r
+ if(g>0) ret += " && ";\r
+ ret += "(";\r
+ sprintf(tmpstr,"gb_attr_%d",g); lhs_op = tmpstr;\r
+ sprintf(tmpstr,"t->aggr_table[probe].gb_var%d",g); rhs_op = tmpstr;\r
+ ret += generate_equality_test(lhs_op,rhs_op,gb_tbl->get_data_type(g));\r
+ ret += ")";\r
+ }\r
+ }\r
+ ret += "){\n"\r
+" match_found = 1;\n"\r
+" best_slot = probe;\n"\r
+" }\n"\r
+" }\n"\r
+"// Rate slots in case no match found: prefer empty, then full but old slots\n"\r
+" if(t->aggr_table_hashmap[best_slot] & SLOT_FILLED){\n"\r
+" if((t->aggr_table_hashmap[probe] & SLOT_FILLED)==0)\n"\r
+" best_slot = probe;\n"\r
+" }else{\n"\r
+" if((t->aggr_table_hashmap[best_slot] & SLOT_GEN_BITS) == gen_val && (t->aggr_table_hashmap[probe] & SLOT_GEN_BITS) != gen_val){\n"\r
+" best_slot = probe;\n"\r
+" }\n"\r
+" }\n"\r
+" probe++;\n"\r
+" if(probe >= t->max_aggrs)\n"\r
+" probe=0;\n"\r
+" }\n"\r
+" if(match_found){\n"\r
+;\r
+ ret += generate_gb_update(node_name, schema, "best_slot",has_udaf);\r
+ ret +=\r
+" }else{\n"\r
+" if(t->aggr_table_hashmap[best_slot] & SLOT_FILLED){\n"\r
+;\r
+printf("sgah_qpn name is %s, disorder is %d\n",fs->node_name.c_str(),((sgah_qpn *)fs)->lfta_disorder);\r
+ if(((sgah_qpn *)fs)->lfta_disorder <= 1){\r
+ ret +=\r
+" if((t->aggr_table_hashmap[best_slot] & SLOT_GEN_BITS)==gen_val){\n"\r
+" if((";\r
+ bool first_g = true;\r
+ for(int g=0;g<gb_tbl->size();g++){\r
+ data_type *gdt = gb_tbl->get_data_type(g);\r
+ if(gdt->is_temporal()){\r
+ if(first_g) first_g = false; else ret+=" + ";\r
+ ret += "(gb_attr_"+int_to_string(g)+" - t->aggr_table[best_slot].gb_var"+int_to_string(g)+")";\r
+ }\r
+ }\r
+ ret += ") == 0 ){\n";\r
+\r
+ ret +=\r
+" fta_aggr_flush_old_"+ node_name+"(f,t->max_aggrs);\n"\r
+" }\n"\r
+" }\n"\r
+;\r
+ }\r
+\r
+ ret += generate_tuple_from_aggr(node_name,schema,"best_slot");\r
+ ret +=\r
+"\t\t\t#ifdef LFTA_STATS\n"\r
+"\t\t\tif((t->aggr_table_hashmap[best_slot] & SLOT_GEN_BITS) == gen_val)\n"\r
+"\t\t\t\tt->collision_cnt++;\n\n"\r
+"\t\t\t#endif\n\n"\r
+"\t\t}\n"\r
+;\r
+ ret += generate_init_group(schema,"best_slot");\r
+\r
+\r
+ ret += "\t}\n";\r
+\r
+ return ret;\r
+}\r
+\r
+\r
+\r
+string generate_fta_accept(qp_node *fs, string node_name, table_list *schema, ext_fcn_list *Ext_fcns, bool is_aggr_query, bool is_fj, set<unsigned int> &s_pids){\r
+\r
+ string ret="static gs_retval_t accept_packet_"+node_name+\r
+ "(struct FTA *f, FTAID * ftaid, void *pkt, gs_int32_t sz){\n";\r
+ ret += "\tstruct packet *p = (struct packet *)pkt;\n";\r
+\r
+ int a;\r
+\r
+// Define all of the variables needed by this\r
+// procedure.\r
+\r
+\r
+// Gather all column references, need to define unpacking variables.\r
+ int w,s;\r
+ col_id_set cid_set;\r
+ col_id_set::iterator csi;\r
+\r
+// If its a filter join, rebind all colrefs\r
+// to the first range var, to avoid double unpacking.\r
+\r
+ if(is_fj){\r
+ for(w=0;w<where.size();++w)\r
+ reset_pr_col_ids_tblvars(where[w]->pr, gb_tbl);\r
+ for(s=0;s<sl_list.size();s++)\r
+ reset_se_col_ids_tblvars(sl_list[s], gb_tbl);\r
+ }\r
+\r
+ for(w=0;w<where.size();++w){\r
+ if(is_fj || s_pids.count(w) == 0)\r
+ gather_pr_col_ids(where[w]->pr,cid_set, gb_tbl);\r
+ }\r
+ for(s=0;s<sl_list.size();s++){\r
+ gather_se_col_ids(sl_list[s],cid_set, gb_tbl);\r
+ }\r
+\r
+ int g;\r
+ if(gb_tbl != NULL){\r
+ for(g=0;g<gb_tbl->size();g++)\r
+ gather_se_col_ids(gb_tbl->get_def(g),cid_set, gb_tbl);\r
+ }\r
+\r
+ // Variables for unpacking attributes.\r
+ ret += "/*\t\tVariables for unpacking attributes\t*/\n";\r
+ for(csi=cid_set.begin(); csi!=cid_set.end();++csi){\r
+ int schref = (*csi).schema_ref;\r
+ int tblref = (*csi).tblvar_ref;\r
+ string field = (*csi).field;\r
+ data_type dt(schema->get_type_name(schref,field));\r
+ sprintf(tmpstr,"\t%s unpack_var_%s_%d;\n",dt.get_cvar_type().c_str(),\r
+ field.c_str(), tblref);\r
+ ret += tmpstr;\r
+ }\r
+\r
+ ret += "\n\n";\r
+\r
+// Variables that are always needed\r
+ ret += "/*\t\tVariables which are always needed\t*/\n";\r
+ ret += "\tgs_retval_t retval;\n";\r
+ ret += "\tgs_int32_t tuple_size, tuple_pos, lfta_bailout;\n";\r
+ ret += "\tstruct "+generate_tuple_name(node_name)+" *tuple;\n";\r
+\r
+ ret+="\tstruct "+generate_fta_name(node_name)+" *t = (struct "+generate_fta_name(node_name)+"*) f;\n\n";\r
+\r
+\r
+// Variables needed for aggregation queries.\r
+ if(is_aggr_query){\r
+ ret += "\n/*\t\tVariables for aggregation\t*/\n";\r
+ ret+="\tunsigned int i, probe;\n";\r
+ ret+="\tunsigned int gen_val, match_found, best_slot;\n";\r
+ ret+="\tgs_uint64_t hashval, hash2;\n";\r
+// Variables for storing group-by attribute values.\r
+ if(gb_tbl->size() > 0)\r
+ ret += "/*\t\tGroup-by attributes\t*/\n";\r
+ for(g=0;g<gb_tbl->size();g++){\r
+ sprintf(tmpstr,"\t%s gb_attr_%d;\n",gb_tbl->get_data_type(g)->get_cvar_type().c_str(),g);\r
+ ret += tmpstr;\r
+ data_type *gdt = gb_tbl->get_data_type(g);\r
+ if(gdt->is_buffer_type()){\r
+ sprintf(tmpstr,"\t%s gb_attr_tmp%d;\n",gb_tbl->get_data_type(g)->get_cvar_type().c_str(),g);\r
+ ret += tmpstr;\r
+ }\r
+ }\r
+ ret += "\n";\r
+// Temporaries for min/max\r
+ string aggr_tmp_str = "";\r
+ for(a=0;a<aggr_tbl->size();a++){\r
+ string aggr_op = aggr_tbl->get_op(a);\r
+ if(aggr_op == "MIN" || aggr_op == "MAX"){\r
+ sprintf(tmpstr,"\t%s aggr_tmp_%d;\n",aggr_tbl->get_data_type(a)->get_cvar_type().c_str(),a);\r
+ aggr_tmp_str.append(tmpstr);\r
+ }\r
+ }\r
+ if(aggr_tmp_str != ""){\r
+ ret += "/*\t\tTemp vars for BUFFER aggregates\t*/\n";\r
+ ret += aggr_tmp_str;\r
+ ret += "\n";\r
+ }\r
+// Variables for udaf output temporaries\r
+ bool no_udaf = true;\r
+ for(a=0;a<aggr_tbl->size();a++){\r
+ if(! aggr_tbl->is_builtin(a)){\r
+ if(no_udaf){\r
+ ret+="/*\t\tUDAF output vars.\t*/\n";\r
+ no_udaf = false;\r
+ }\r
+ int afcn_id = aggr_tbl->get_fcn_id(a);\r
+ data_type *adt = Ext_fcns->get_fcn_dt(afcn_id);\r
+ sprintf(tmpstr,"udaf_ret%d", a);\r
+ ret+="\t"+adt->make_cvar(tmpstr)+";\n";\r
+ }\r
+ }\r
+ }\r
+\r
+// Variables needed for a filter join query\r
+ if(fs->node_type() == "filter_join"){\r
+ filter_join_qpn *fjq = (filter_join_qpn *)fs;\r
+ bool uses_bloom = fjq->use_bloom;\r
+ ret += "/*\t\tJoin fields\t*/\n";\r
+ for(g=0;g<fjq->hash_eq.size();g++){\r
+ sprintf(tmpstr,"\t%s s_equijoin_%d, r_equijoin_%d;\n",fjq->hash_eq[g]->pr->get_left_se()->get_data_type()->get_cvar_type().c_str(),g,g);\r
+ ret += tmpstr;\r
+ }\r
+ if(uses_bloom){\r
+ ret +=\r
+" /* Variables for fj bloom filter */ \n"\r
+"\tunsigned int i=0,j=0,k=0, b, bf_clean = 0, tmp_i, found; \n"\r
+"\tunsigned int bucket, bucket0, bucket1, bucket2;\n"\r
+"\tlong long int curr_fj_ts;\n"\r
+"\tunsigned int curr_bin, the_bin;\n"\r
+"\n"\r
+;\r
+ }else{\r
+ ret +=\r
+" /* Variables for fj join table */ \n"\r
+"\tunsigned int i, bucket, found; \n"\r
+"\tunsigned int bucket1, the_bucket;\n"\r
+" long long int curr_fj_ts;\n"\r
+"\n"\r
+;\r
+ }\r
+ }\r
+\r
+\r
+// Variables needed to store selected attributes of BUFFER type\r
+// temporarily, in order to compute their size for storage\r
+// in an output tuple.\r
+\r
+ string select_var_defs = "";\r
+ for(s=0;s<sl_list.size();s++){\r
+ data_type *sdt = sl_list[s]->get_data_type();\r
+ if(sdt->is_buffer_type()){\r
+ sprintf(tmpstr,"\t%s selvar_%d;\n",sdt->get_cvar_type().c_str(),s);\r
+ select_var_defs.append(tmpstr);\r
+ }\r
+ }\r
+ if(select_var_defs != ""){\r
+ ret += "/*\t\tTemporaries for computing buffer sizes.\t*/\n";\r
+ ret += select_var_defs;\r
+ }\r
+\r
+// Variables to store results of partial functions.\r
+ int p;\r
+ if(partial_fcns.size()>0){\r
+ ret += "/*\t\tVariables for storing results of partial functions. \t*/\n";\r
+ for(p=0;p<partial_fcns.size();++p){\r
+ if(is_partial_fcn[p] || (!is_aggr_query && fcn_ref_cnt[p] >1)){\r
+ sprintf(tmpstr,"\t%s partial_fcn_result_%d;\n",\r
+ partial_fcns[p]->get_data_type()->get_cvar_type().c_str(), p);\r
+ ret += tmpstr;\r
+ if(!is_aggr_query && fcn_ref_cnt[p] >1){\r
+ ret += "\tint fcn_ref_cnt_"+int_to_string(p)+" = 0;\n";\r
+ }\r
+ }\r
+ }\r
+\r
+ if(is_aggr_query) ret += "\tint unpack_failed = 0;\n";\r
+ ret += "\n";\r
+ }\r
+\r
+// variable to hold packet struct //\r
+ if(packed_return){\r
+ ret += "\t struct "+node_name+"_input_struct *"+node_name+"_input_struct_var;\n";\r
+ }\r
+\r
+\r
+ ret += "\t#ifdef LFTA_STATS\n";\r
+// variable to store counter of cpu cycles spend in accept_tuple\r
+ ret += "\tgs_uint64_t start_cycle = rdtsc();\n";\r
+// increment counter of received tuples\r
+ ret += "\tt->in_tuple_cnt++;\n";\r
+ ret += "\t#endif\n";\r
+\r
+\r
+// -------------------------------------------------\r
+// If the packet is "packet", test if its for this lfta,\r
+// and if so load it into its struct\r
+\r
+ if(packed_return){\r
+ ret+="\n/* packed tuple : test and load. \t*/\n";\r
+ ret+="\t"+node_name+"_input_struct_var = (struct "+node_name+"_input_struct *) pkt;\n";\r
+ ret+="\tif("+node_name+"_input_struct_var->__lfta_id_fm_nic__ != "+int_to_string(global_id) + ")\n";\r
+ ret+="\t\tgoto end;\n\n";\r
+ }\r
+\r
+\r
+\r
+ col_id_set unpacked_cids; // Keep track of the cols that have been unpacked.\r
+\r
+ string temporal_flush;\r
+ if(is_aggr_query)\r
+ ret += generate_aggr_accept_prelim(fs, node_name, schema, unpacked_cids, temporal_flush);\r
+ else { // non-aggregation operators\r
+\r
+// Unpack all the temporal attributes referenced in select clause\r
+// and update the last value of the attribute\r
+ col_id_set temp_cids; // col ids of temp attributes in select clause\r
+\r
+ for(s=0;s<sl_list.size();s++){\r
+ data_type *sdt = sl_list[s]->get_data_type();\r
+ if (sdt->is_temporal()) {\r
+ gather_se_col_ids(sl_list[s],temp_cids, gb_tbl);\r
+ }\r
+ }\r
+// If this is a filter join,\r
+// ensure that the temporal range field is unpacked.\r
+ if(is_fj){\r
+ col_id window_var_cid(((filter_join_qpn *)fs)->temporal_var);\r
+ if(temp_cids.count(window_var_cid)==0)\r
+ temp_cids.insert(window_var_cid);\r
+ }\r
+\r
+ for(csi=temp_cids.begin(); csi != temp_cids.end();++csi){\r
+ if(unpacked_cids.count((*csi)) == 0){\r
+ int tblref = (*csi).tblvar_ref;\r
+ int schref = (*csi).schema_ref;\r
+ string field = (*csi).field;\r
+ ret += generate_unpack_code(tblref,schref,field,schema,node_name);\r
+ sprintf(tmpstr,"\tt->last_%s_%d = unpack_var_%s_%d;\n", field.c_str(), tblref, field.c_str(), tblref);\r
+ ret += tmpstr;\r
+\r
+ unpacked_cids.insert( (*csi) );\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ vector<cnf_elem *> filter = fs->get_filter_clause();\r
+// Test the filter predicate (some query types have additional preds).\r
+ if(filter.size() > 0){\r
+\r
+// Sort by evaluation cost.\r
+// First, estimate evaluation costs\r
+// Eliminate predicates covered by the prefilter (those in s_pids).\r
+// I need to do it before the sort becuase the indices refer\r
+// to the position in the unsorted list./\r
+ vector<cnf_elem *> tmp_wh;\r
+ for(w=0;w<filter.size();++w){\r
+ if(s_pids.count(w) == 0){\r
+ compute_cnf_cost(filter[w],Ext_fcns);\r
+ tmp_wh.push_back(filter[w]);\r
+ }\r
+ }\r
+ filter = tmp_wh;\r
+\r
+ sort(filter.begin(), filter.end(), compare_cnf_cost());\r
+\r
+// Now generate the predicates.\r
+ for(w=0;w<filter.size();++w){\r
+ sprintf(tmpstr,"//\t\tPredicate clause %d.(cost %d)\n",w,filter[w]->cost);\r
+ ret += tmpstr;\r
+// Find the set of variables accessed in this CNF elem,\r
+// but in no previous element.\r
+ col_id_set this_pred_cids;\r
+ gather_pr_col_ids(filter[w]->pr, this_pred_cids, gb_tbl);\r
+ for(csi=this_pred_cids.begin();csi!=this_pred_cids.end();++csi){\r
+ if(unpacked_cids.count( (*csi) ) == 0){\r
+ int tblref = (*csi).tblvar_ref;\r
+ int schref = (*csi).schema_ref;\r
+ string field = (*csi).field;\r
+ ret += generate_unpack_code(tblref,schref,field,schema,node_name);\r
+ unpacked_cids.insert( (*csi) );\r
+ }\r
+ }\r
+// Find partial fcns ref'd in this cnf element\r
+ set<int> pfcn_refs;\r
+ collect_partial_fcns_pr(filter[w]->pr, pfcn_refs);\r
+// Since set<..> is a "Sorted Associative Container",\r
+// we can walk through it in sorted order by walking from\r
+// begin() to end(). (and the partial fcns must be\r
+// evaluated in this order).\r
+ set<int>::iterator si;\r
+ for(si=pfcn_refs.begin();si!=pfcn_refs.end();++si){\r
+ if(fcn_ref_cnt[(*si)] > 1){\r
+ ret += "\tif(fcn_ref_cnt_"+int_to_string((*si))+"==0){\n";\r
+ }\r
+ if(is_partial_fcn[(*si)]){\r
+ ret += "\t"+unpack_partial_fcn(partial_fcns[(*si)], (*si), schema);\r
+ ret += "\t\tif(retval) goto end;\n";\r
+ }\r
+ if(fcn_ref_cnt[(*si)] > 1){\r
+ if(!is_partial_fcn[(*si)]){\r
+ ret += "\t\tpartial_fcn_result_"+int_to_string((*si))+"="+generate_cached_fcn(partial_fcns[(*si)],schema)+";\n";\r
+ }\r
+ ret += "\t\tfcn_ref_cnt_"+int_to_string((*si))+"=1;\n";\r
+ ret += "\t}\n";\r
+ }\r
+ }\r
+\r
+ ret += "\tif( !("+generate_predicate_code(filter[w]->pr,schema)+\r
+ ") ) goto end;\n";\r
+ }\r
+ }else{\r
+ ret += "\n\n/*\t\t (no predicate to test)\t*/\n\n";\r
+ }\r
+\r
+\r
+// We've passed the WHERE clause,\r
+// unpack the remainder of the accessed fields.\r
+ if(is_fj){\r
+ ret += "\n/*\tPassed the WHERE clause, unpack the hash fields. */\n";\r
+ vector<cnf_elem *> h_eq = ((filter_join_qpn *)fs)-> hash_eq;\r
+ for(w=0;w<h_eq.size();++w){\r
+ col_id_set this_pred_cids;\r
+ gather_pr_col_ids(h_eq[w]->pr, this_pred_cids, gb_tbl);\r
+ for(csi=this_pred_cids.begin();csi!=this_pred_cids.end();++csi){\r
+ if(unpacked_cids.count( (*csi) ) == 0){\r
+ int tblref = (*csi).tblvar_ref;\r
+ int schref = (*csi).schema_ref;\r
+ string field = (*csi).field;\r
+ ret += generate_unpack_code(tblref,schref,field,schema,node_name);\r
+ unpacked_cids.insert( (*csi) );\r
+ }\r
+ }\r
+ }\r
+ }else{\r
+ ret += "\n/*\tPassed the WHERE clause, unpack the rest of the accessed fields. */\n";\r
+\r
+ for(csi=cid_set.begin();csi!=cid_set.end();++csi){\r
+ if(unpacked_cids.count( (*csi) ) == 0){\r
+ int schref = (*csi).schema_ref;\r
+ int tblref = (*csi).tblvar_ref;\r
+ string field = (*csi).field;\r
+ ret += generate_unpack_code(tblref,schref,field,schema,node_name);\r
+ unpacked_cids.insert( (*csi) );\r
+ }\r
+ }\r
+ }\r
+\r
+\r
+//////////////////\r
+////////////////// After this, the query types\r
+////////////////// are processed differently.\r
+\r
+ if(!is_aggr_query && !is_fj)\r
+ ret += generate_sel_accept_body(fs, node_name, schema);\r
+ else if(is_aggr_query)\r
+ ret += generate_aggr_accept_body(fs, node_name, schema, temporal_flush);\r
+ else\r
+ ret += generate_fj_accept_body((filter_join_qpn *)fs, node_name, unpacked_cids, Ext_fcns, schema);\r
+\r
+\r
+// Finish up.\r
+\r
+ ret += "\n\tend:\n";\r
+ ret += "\t#ifdef LFTA_STATS\n";\r
+ ret+= "\tt->cycle_cnt += rdtsc() - start_cycle;\n";\r
+ ret += "\t#endif\n";\r
+ ret += "\n\treturn 1;\n}\n\n";\r
+\r
+ return(ret);\r
+}\r
+\r
+\r
+string generate_fta_alloc(qp_node *fs, string node_name, table_list *schema, bool is_aggr_query, bool is_fj, bool uses_bloom){\r
+ int g, cl;\r
+\r
+ string ret = "struct FTA * "+generate_alloc_name(node_name) +\r
+ "(struct FTAID ftaid, gs_uint32_t reusable, gs_int32_t command, gs_int32_t sz, void *value){\n";\r
+\r
+ ret+="\tstruct "+generate_fta_name(node_name)+"* f;\n";\r
+ ret+="\tint i;\n";\r
+ ret += "\n";\r
+ ret+="\tif((f=fta_alloc(0,sizeof(struct "+generate_fta_name(node_name)+")))==0){\n\t\treturn(0);\n\t}\n";\r
+\r
+// assign a streamid to fta instance\r
+ ret+="\t/* assign a streamid */\n";\r
+ ret+="\tf->f.ftaid = ftaid;\n";\r
+ ret+="\tf->f.ftaid.streamid = (gs_p_t)f;\n";\r
+ ret+="\tgslog(LOG_INFO,\"Lfta "+node_name+" has FTAID {ip=%u,port=%u,index=%u,streamid=%u}\\n\",f->f.ftaid.ip,f->f.ftaid.port,f->f.ftaid.index,f->f.ftaid.streamid);\n";\r
+\r
+ if(is_aggr_query){\r
+ ret += "\tf->n_aggrs = 0;\n";\r
+\r
+ ret += "\tf->max_aggrs = ";\r
+\r
+// Computing the number of aggregate blocks is a little\r
+// tricky. If there are no GB attrs, or if all GB attrs\r
+// are temporal, then use a single aggregate block, else\r
+// use a default value (10). A user specification overrides\r
+// this logic.\r
+ bool single_group = true;\r
+ for(g=0;g<gb_tbl->size();g++){\r
+ data_type *gdt = gb_tbl->get_data_type(g);\r
+ if(! gdt->is_temporal() ){\r
+ single_group = false;\r
+ }\r
+ }\r
+ string max_aggr_str = fs->get_val_of_def("aggregate_slots");\r
+ int max_aggr_i = atoi(max_aggr_str.c_str());\r
+ if(max_aggr_i <= 0){\r
+ if(single_group)\r
+ ret += "2";\r
+ else\r
+ ret += int_to_string(DEFAULT_LFTA_HASH_TABLE_SIZE);\r
+ }else{\r
+ unsigned int naggrs = 1; // make it power of 2\r
+ unsigned int nones = 0;\r
+ while(max_aggr_i){\r
+ if(max_aggr_i&1)\r
+ nones++;\r
+ naggrs = naggrs << 1;\r
+ max_aggr_i = max_aggr_i >> 1;\r
+ }\r
+ if(nones==1) // in case it was already a power of 2.\r
+ naggrs/=2;\r
+ ret += int_to_string(naggrs);\r
+ }\r
+ ret += ";\n";\r
+\r
+ ret+="\tif ((f->aggr_table = sp_fta_alloc((struct FTA *)f,sizeof(struct "+generate_aggr_struct_name(node_name)+") * f->max_aggrs))==0) {\n";\r
+ ret+="\t\treturn(0);\n";\r
+ ret+="\t}\n\n";\r
+// ret+="/* compute how many integers we need to store the hashmap */\n";\r
+// ret+="\tf->bitmap_size = (f->max_aggrs % (sizeof(gs_uint32_t) * 4)) ? (f->max_aggrs / (sizeof(gs_uint32_t) * 4) + 1) : (f->max_aggrs / (sizeof(gs_uint32_t) * 4));\n\n";\r
+ ret+="\tif ((f->aggr_table_hashmap = sp_fta_alloc((struct FTA *)f,sizeof(gs_uint32_t) * f->max_aggrs))==0) {\n";\r
+ ret+="\t\treturn(0);\n";\r
+ ret+="\t}\n";\r
+ ret+="/*\t\tfill bitmap with zero \t*/\n";\r
+ ret+="\tfor (i = 0; i < f->max_aggrs; ++i)\n";\r
+ ret+="\t\tf->aggr_table_hashmap[i] = 0;\n";\r
+ ret+="\tf->generation=0;\n";\r
+ ret+="\tf->flush_pos = f->max_aggrs;\n";\r
+\r
+ ret += "\tf->flush_ctr = 0;\n";\r
+\r
+ }\r
+\r
+ if(is_fj){\r
+ if(uses_bloom){\r
+ ret+="\tf->first_exec = 1;\n";\r
+ unsigned int n_bloom = 11;\r
+ string n_bloom_str = fs->get_val_of_def("num_bloom");\r
+ int tmp_n_bloom = atoi(n_bloom_str.c_str());\r
+ if(tmp_n_bloom>0)\r
+ n_bloom = tmp_n_bloom+1;\r
+\r
+ unsigned int window_len = ((filter_join_qpn *)fs)->temporal_range;\r
+ if(window_len < n_bloom){\r
+ n_bloom = window_len+1;\r
+ }\r
+\r
+ int bf_exp_size = 12; // base-2 log of number of bits\r
+ string bloom_len_str = fs->get_val_of_def("bloom_size");\r
+ int tmp_bf_exp_size = atoi(bloom_len_str.c_str());\r
+ if(tmp_bf_exp_size > 3 && tmp_bf_exp_size < 32){\r
+ bf_exp_size = tmp_bf_exp_size;\r
+ }\r
+ int bf_bit_size = 1 << 12;\r
+ int bf_byte_size = bf_bit_size / (8*sizeof(char));\r
+\r
+ int bf_tot = n_bloom*bf_byte_size;\r
+ ret+="\tif ((f->bf_table = sp_fta_alloc((struct FTA *)f,"+int_to_string(bf_tot)+"))==0) {\n";\r
+ ret+="\t\treturn(0);\n";\r
+ ret+="\t}\n";\r
+ ret +=\r
+" for(i=0;i<"+int_to_string(bf_tot)+";i++)\n"\r
+" f->bf_table[i] = 0;\n"\r
+;\r
+ }else{\r
+ unsigned int ht_size = 4096;\r
+ string ht_size_s = fs->get_val_of_def("aggregate_slots");\r
+ int tmp_ht_size = atoi(ht_size_s.c_str());\r
+ if(tmp_ht_size > 1024){\r
+ unsigned int hs = 1; // make it power of 2\r
+ while(tmp_ht_size){\r
+ hs =hs << 1;\r
+ tmp_ht_size = tmp_ht_size >> 1;\r
+ }\r
+ ht_size = hs;\r
+ }\r
+ ret+="\tif ((f->join_table = sp_fta_alloc((struct FTA *)f,sizeof(struct "+generate_fj_struct_name(node_name)+") * "+int_to_string(ht_size)+"))==0) {\n";\r
+ ret+="\t\treturn(0);\n";\r
+ ret+="\t}\n\n";\r
+ ret +=\r
+" for(i=0;i<"+int_to_string(ht_size)+";i++)\n"\r
+" f->join_table[i].ts = 0;\n"\r
+;\r
+ }\r
+ }\r
+\r
+// Initialize the complex literals (which might be handles).\r
+\r
+ for(cl=0;cl<complex_literals->size();cl++){\r
+ literal_t *l = complex_literals->get_literal(cl);\r
+// sprintf(tmpstr,"\tf->complex_literal_%d = ",cl);\r
+// ret += tmpstr + l->to_C_code() + ";\n";\r
+ sprintf(tmpstr,"&(f->complex_literal_%d)",cl);\r
+ ret += "\t" + l->to_C_code(tmpstr) + ";\n";\r
+ }\r
+\r
+ ret += "\n";\r
+\r
+// Initialize the last seen values of temporal attributes to min(max) value of\r
+// their respective type\r
+// Create places to hold the last values of temporal attributes referenced in select clause\r
+\r
+\r
+ col_id_set temp_cids; // col ids of temp attributes in select clause\r
+\r
+ int s;\r
+ col_id_set::iterator csi;\r
+\r
+ for(s=0;s<sl_list.size();s++){\r
+ data_type *sdt = sl_list[s]->get_data_type();\r
+ if (sdt->is_temporal()) {\r
+ gather_se_col_ids(sl_list[s],temp_cids, gb_tbl);\r
+ }\r
+ }\r
+\r
+ for(csi=temp_cids.begin(); csi != temp_cids.end();++csi){\r
+ int tblref = (*csi).tblvar_ref;\r
+ int schref = (*csi).schema_ref;\r
+ string field = (*csi).field;\r
+ data_type dt(schema->get_type_name(schref,field), schema->get_modifier_list(schref,field));\r
+ if (dt.is_increasing()) {\r
+ sprintf(tmpstr,"\tf->last_%s_%d = %s;\n", field.c_str(), tblref, dt.get_min_literal().c_str());\r
+ ret += tmpstr;\r
+ } else if (dt.is_decreasing()) {\r
+ sprintf(tmpstr,"\tf->last_%s_%d = %s;\n", field.c_str(), tblref, dt.get_max_literal().c_str());\r
+ ret += tmpstr;\r
+ }\r
+ }\r
+\r
+// initialize last seen values of temporal groubpy variables\r
+ if(is_aggr_query){\r
+ for(g=0;g<gb_tbl->size();g++){\r
+ data_type *dt = gb_tbl->get_data_type(g);\r
+ if(dt->is_temporal()){\r
+/*\r
+ fprintf(stderr,"group by attribute %s is temporal, ",\r
+ gb_tbl->get_name(g).c_str());\r
+*/\r
+ if(dt->is_increasing()){\r
+ sprintf(tmpstr,"\tf->last_gb_%d = f->last_flushed_gb_%d = %s;\n",g, g, dt->get_min_literal().c_str());\r
+ }else{\r
+ sprintf(tmpstr,"\tf->last_gb_%d = f->last_flushed_gb_%d = %s;\n",g, g, dt->get_max_literal().c_str());\r
+ }\r
+ ret += tmpstr;\r
+ }\r
+ }\r
+ }\r
+\r
+ ret += "\tf->f.alloc_fta="+generate_alloc_name(node_name)+";\n";\r
+ ret+="\tf->f.free_fta=free_fta_"+node_name+";\n";\r
+ ret+="\tf->f.control_fta=control_fta_"+node_name+";\n";\r
+ ret+="\tf->f.accept_packet=accept_packet_"+node_name+";\n";\r
+ ret+="\tf->f.clock_fta=clock_fta_"+node_name+";\n\n";\r
+\r
+// Initialize runtime stats\r
+ ret+="\tf->in_tuple_cnt = 0;\n";\r
+ ret+="\tf->out_tuple_cnt = 0;\n";\r
+ ret+="\tf->out_tuple_sz = 0;\n";\r
+ ret+="\tf->accepted_tuple_cnt = 0;\n";\r
+ ret+="\tf->cycle_cnt = 0;\n";\r
+ ret+="\tf->collision_cnt = 0;\n";\r
+ ret+="\tf->eviction_cnt = 0;\n";\r
+ ret+="\tf->sampling_rate = 1.0;\n";\r
+\r
+ ret+="\tf->trace_id = 0;\n\n";\r
+ if(param_tbl->size() > 0){\r
+ ret+=\r
+"\tif(load_params_"+node_name+"(f, sz, value, 1)){\n"\r
+"#ifndef LFTA_IN_NIC\n"\r
+"\t\t\tfprintf(stderr,\"WARNING: parameter passed to lfta "+node_name+" is too small (%d). This query does not have valid parameters, bailing out.\\n\",sz);\n"\r
+"#else\n"\r
+"\t\t}\n"\r
+"#endif\n"\r
+"\t\t\treturn 0;\n"\r
+"\t\t}\n";\r
+ }\r
+\r
+// Register the pass-by-handle parameters\r
+ int ph;\r
+ for(ph=0;ph<param_handle_table.size();++ph){\r
+ data_type pdt(param_handle_table[ph]->type_name);\r
+ sprintf(tmpstr,"\tf->handle_param_%d = %s((struct FTA *)f,",ph,param_handle_table[ph]->lfta_registration_fcn().c_str());\r
+ switch(param_handle_table[ph]->val_type){\r
+ case cplx_lit_e:\r
+ ret += tmpstr;\r
+ if(pdt.is_buffer_type()) ret += "&(";\r
+ sprintf(tmpstr,"f->complex_literal_%d",param_handle_table[ph]->complex_literal_idx);\r
+ ret += tmpstr ;\r
+ if(pdt.is_buffer_type()) ret += ")";\r
+ ret += ");\n";\r
+ break;\r
+ case litval_e:\r
+// not complex, no constructor\r
+ ret += tmpstr;\r
+ ret += param_handle_table[ph]->litval->to_C_code("") + ");\n";\r
+ break;\r
+ case param_e:\r
+// query parameter handles are regstered/deregistered in the\r
+// load_params function.\r
+// ret += "t->param_"+param_handle_table[ph]->param_name;\r
+ break;\r
+ default:\r
+ fprintf(stderr, "INTERNAL ERROR unknown case found when processing pass-by-handle parameter table.\n");\r
+ exit(1);\r
+ }\r
+ }\r
+\r
+ ret += "\treturn (struct FTA *) f;\n";\r
+ ret += "}\n\n";\r
+\r
+ return(ret);\r
+}\r
+\r
+\r
+\r
+\r
+//////////////////////////////////////////////////////////////////\r
+\r
+string generate_lfta_block(qp_node *fs, table_list *schema, int gid,\r
+// map<string,string> &int_fcn_defs,\r
+ ext_fcn_list *Ext_fcns, string &schema_embed_str, ifq_t *ifdb, nic_property *nicp, set<unsigned int> &s_pids){\r
+ bool is_aggr_query;\r
+ int s,p,g;\r
+ string retval;\r
+\r
+/////////////////////////////////////////////////////////////\r
+/// Do operator-generic processing, such as\r
+/// gathering the set of referenced columns,\r
+/// generating structures, etc.\r
+\r
+// Initialize globals to empty.\r
+ gb_tbl = NULL; aggr_tbl = NULL;\r
+ global_id = -1; nicprop = NULL;\r
+ param_tbl = fs->get_param_tbl();\r
+ sl_list.clear(); where.clear();\r
+ partial_fcns.clear();\r
+ fcn_ref_cnt.clear(); is_partial_fcn.clear();\r
+ pred_class.clear(); pred_pos.clear();\r
+ sl_fcns_start=sl_fcns_end=wh_fcns_start=wh_fcns_end=0;\r
+ gb_fcns_start=gb_fcns_end=ag_fcns_start=ag_fcns_end=0;\r
+\r
+\r
+// Does the lfta read packed results from the NIC?\r
+ nicprop = nicp; // load into global\r
+ global_id = gid;\r
+ packed_return = false;\r
+ if(nicp && nicp->option_exists("Return")){\r
+ if(nicp->option_value("Return") == "Packed"){\r
+ packed_return = true;\r
+ }else{\r
+ fprintf(stderr,"Warning, nic option value of Return=%s is not recognized, ignoring\n",nicp->option_value("Return").c_str());\r
+ }\r
+ }\r
+\r
+\r
+// Extract data which defines the query.\r
+// complex literals gathered now.\r
+ complex_literals = fs->get_cplx_lit_tbl(Ext_fcns);\r
+ param_handle_table = fs->get_handle_param_tbl(Ext_fcns);\r
+ string node_name = fs->get_node_name();\r
+ bool is_fj = false, uses_bloom = false;\r
+\r
+\r
+ if(fs->node_type() == "spx_qpn"){\r
+ is_aggr_query = false;\r
+ spx_qpn *spx_node = (spx_qpn *)fs;\r
+ sl_list = spx_node->get_select_se_list();\r
+ where = spx_node->get_where_clause();\r
+ gb_tbl = NULL;\r
+ aggr_tbl = NULL;\r
+ } else\r
+ if(fs->node_type() == "sgah_qpn"){\r
+ is_aggr_query = true;\r
+ sgah_qpn *sgah_node = (sgah_qpn *)fs;\r
+ sl_list = sgah_node->get_select_se_list();\r
+ where = sgah_node->get_where_clause();\r
+ gb_tbl = sgah_node->get_gb_tbl();\r
+ aggr_tbl = sgah_node->get_aggr_tbl();\r
+\r
+ if((sgah_node->get_having_clause()).size() > 0){\r
+ fprintf(stderr,"Warning in LFTA %s: HAVING clause will be ignored.\n", fs->get_node_name().c_str());\r
+ }\r
+ } else\r
+ if(fs->node_type() == "filter_join"){\r
+ is_aggr_query = false;\r
+ is_fj = true;\r
+ filter_join_qpn *fj_node = (filter_join_qpn *)fs;\r
+ sl_list = fj_node->get_select_se_list();\r
+ where = fj_node->get_where_clause();\r
+ uses_bloom = fj_node->use_bloom;\r
+ gb_tbl = NULL;\r
+ aggr_tbl = NULL;\r
+ } else {\r
+ fprintf(stderr,"INTERNAL ERROR, unrecognized node type %s in generate_lfta_block\n", fs->node_type().c_str());\r
+ exit(1);\r
+ }\r
+\r
+// Build list of "partial functions", by clause.\r
+// NOTE : partial fcns are not handles well.\r
+// The act of searching for them associates the fcn call\r
+// in the SE with an index to an array. Refs to the\r
+// fcn value are replaced with refs to the variable they are\r
+// unpacked into. A more general tagging mechanism would be better.\r
+\r
+ int i;\r
+ vector<bool> *pfunc_ptr = NULL;\r
+ vector<int> *ref_cnt_ptr = NULL;\r
+ if(!is_aggr_query){ // don't collect cacheable fcns on aggr query.\r
+ ref_cnt_ptr = &fcn_ref_cnt;\r
+ pfunc_ptr = &is_partial_fcn;\r
+ }\r
+\r
+ sl_fcns_start = 0;\r
+ for(i=0;i<sl_list.size();i++){\r
+ find_partial_fcns(sl_list[i], &partial_fcns, ref_cnt_ptr, pfunc_ptr, Ext_fcns);\r
+ }\r
+ wh_fcns_start = sl_fcns_end = partial_fcns.size();\r
+ for(i=0;i<where.size();i++){\r
+ find_partial_fcns_pr(where[i]->pr, &partial_fcns, ref_cnt_ptr, pfunc_ptr, Ext_fcns);\r
+ }\r
+ gb_fcns_start = wh_fcns_end = partial_fcns.size();\r
+ if(gb_tbl != NULL){\r
+ for(i=0;i<gb_tbl->size();i++){\r
+ find_partial_fcns(gb_tbl->get_def(i), &partial_fcns, NULL, NULL, Ext_fcns);\r
+ }\r
+ }\r
+ ag_fcns_start = gb_fcns_end = partial_fcns.size();\r
+ if(aggr_tbl != NULL){\r
+ for(i=0;i<aggr_tbl->size();i++){\r
+ find_partial_fcns(aggr_tbl->get_aggr_se(i), NULL, NULL, &is_partial_fcn, Ext_fcns);\r
+ }\r
+ }\r
+ ag_fcns_end = partial_fcns.size();\r
+\r
+// Fill up the is_partial_fcn and fcn_ref_cnt arrays.\r
+ if(is_aggr_query){\r
+ for(i=0; i<partial_fcns.size();i++){\r
+ fcn_ref_cnt.push_back(1);\r
+ is_partial_fcn.push_back(true);\r
+ }\r
+ }\r
+\r
+// Unmark non-partial expensive functions referenced only once.\r
+ for(i=0; i<partial_fcns.size();i++){\r
+ if(!is_partial_fcn[i] && fcn_ref_cnt[i] <= 1){\r
+ partial_fcns[i]->set_partial_ref(-1);\r
+ }\r
+ }\r
+\r
+ node_name = normalize_name(node_name);\r
+\r
+ retval += generate_preamble(schema, /*int_fcn_defs,*/ node_name, schema_embed_str);\r
+\r
+ if(packed_return){ // generate unpack struct\r
+ vector<tablevar_t *> input_tbls = fs->get_input_tbls();\r
+ int schref = input_tbls[0]->get_schema_ref();\r
+ vector<string> refd_cols;\r
+ for(s=0;s<sl_list.size();++s){\r
+ gather_nicsafe_cols(sl_list[s],refd_cols, nicp, gb_tbl);\r
+ }\r
+ for(p=0;p<where.size();++p){\r
+// I'm not disabling these preds ...\r
+ gather_nicsafe_cols(where[p]->pr,refd_cols, nicp, gb_tbl);\r
+ }\r
+ if(gb_tbl){\r
+ for(g=0;g<gb_tbl->size();++g){\r
+ gather_nicsafe_cols(gb_tbl->get_def(g),refd_cols, nicp, gb_tbl);\r
+ }\r
+ }\r
+ sort(refd_cols.begin(), refd_cols.end());\r
+ retval += "struct "+node_name+"_input_struct{\n";\r
+ retval += "\tint __lfta_id_fm_nic__;\n";\r
+ int vsi;\r
+ for(vsi=0;vsi<refd_cols.size();++vsi){\r
+ data_type dt(schema->get_type_name(schref,refd_cols[vsi]));\r
+ retval+="\t"+dt.get_cvar_type()+" unpack_var_"+refd_cols[vsi]+";\n";\r
+ }\r
+ retval+="};\n\n";\r
+ }\r
+\r
+\r
+/////////////////////////////////////////////////////\r
+// Common stuff unpacked, do some generation\r
+\r
+ if(is_aggr_query)\r
+ retval += generate_aggr_struct(node_name, gb_tbl, aggr_tbl);\r
+ if(is_fj)\r
+ retval += generate_fj_struct((filter_join_qpn *)fs, node_name);\r
+\r
+ retval += generate_fta_struct(node_name, gb_tbl, aggr_tbl, param_tbl, complex_literals, param_handle_table, is_aggr_query, is_fj, uses_bloom, schema);\r
+ retval += generate_tuple_struct(node_name, sl_list) ;\r
+\r
+ if(is_aggr_query)\r
+ retval += generate_fta_flush(node_name, schema, Ext_fcns) ;\r
+ if(param_tbl->size() > 0)\r
+ retval += generate_fta_load_params(node_name) ;\r
+ retval += generate_fta_free(node_name, is_aggr_query) ;\r
+ retval += generate_fta_control(node_name, schema, is_aggr_query) ;\r
+ retval += generate_fta_accept(fs, node_name, schema, Ext_fcns, is_aggr_query, is_fj, s_pids) ;\r
+\r
+\r
+ /* extract the value of Time_Correlation from interface definition */\r
+ int e,v;\r
+ string es;\r
+ unsigned time_corr;\r
+ vector<tablevar_t *> tvec = fs->get_input_tbls();\r
+ vector<string> time_corr_vec = ifdb->get_iface_vals(tvec[0]->get_machine(), tvec[0]->get_interface(),"Time_Correlation",e,es);\r
+ if (time_corr_vec.empty())\r
+ time_corr = DEFAULT_TIME_CORR;\r
+ else\r
+ time_corr = atoi(time_corr_vec[0].c_str());\r
+\r
+ retval.append( generate_fta_clock(node_name, schema, time_corr, is_aggr_query) );\r
+ retval.append( generate_fta_alloc(fs, node_name, schema, is_aggr_query, is_fj, uses_bloom) );\r
+\r
+ return(retval);\r
+}\r
+\r
+\r
+\r
+int compute_snap_len(qp_node *fs, table_list *schema){\r
+\r
+// Initialize global vars\r
+ gb_tbl = NULL;\r
+ sl_list.clear(); where.clear();\r
+\r
+ if(fs->node_type() == "spx_qpn"){\r
+ spx_qpn *spx_node = (spx_qpn *)fs;\r
+ sl_list = spx_node->get_select_se_list();\r
+ where = spx_node->get_where_clause();\r
+ }\r
+ else if(fs->node_type() == "sgah_qpn"){\r
+ sgah_qpn *sgah_node = (sgah_qpn *)fs;\r
+ sl_list = sgah_node->get_select_se_list();\r
+ where = sgah_node->get_where_clause();\r
+ gb_tbl = sgah_node->get_gb_tbl();\r
+ }\r
+ else if(fs->node_type() == "filter_join"){\r
+ filter_join_qpn *fj_node = (filter_join_qpn *)fs;\r
+ sl_list = fj_node->get_select_se_list();\r
+ where = fj_node->get_where_clause();\r
+ } else{\r
+ fprintf(stderr,"INTERNAL ERROR, node type %s not recognized in compute_snap_len\n",fs->node_type().c_str());\r
+ exit(1);\r
+ }\r
+\r
+// Gather all column references, need to define unpacking variables.\r
+ int w,s;\r
+ col_id_set cid_set;\r
+ col_id_set::iterator csi;\r
+\r
+ for(w=0;w<where.size();++w)\r
+ gather_pr_col_ids(where[w]->pr,cid_set, gb_tbl);\r
+ for(s=0;s<sl_list.size();s++){\r
+ gather_se_col_ids(sl_list[s],cid_set, gb_tbl);\r
+ }\r
+\r
+ int g;\r
+ if(gb_tbl != NULL){\r
+ for(g=0;g<gb_tbl->size();g++)\r
+ gather_se_col_ids(gb_tbl->get_def(g),cid_set, gb_tbl);\r
+ }\r
+\r
+ // compute snap length\r
+ int snap_len = -1;\r
+ int n_snap=0;\r
+ for(csi=cid_set.begin(); csi!=cid_set.end();++csi){\r
+ int schref = (*csi).schema_ref;\r
+ int tblref = (*csi).tblvar_ref;\r
+ string field = (*csi).field;\r
+\r
+ param_list *field_params = schema->get_modifier_list(schref, field);\r
+ if(field_params->contains_key("snap_len")){\r
+ string fld_snap_str = field_params->val_of("snap_len");\r
+ int fld_snap;\r
+ if(sscanf(fld_snap_str.c_str(),"%d",&fld_snap)>0){\r
+ if(fld_snap > snap_len) snap_len = fld_snap;\r
+ n_snap++;\r
+ }else{\r
+ fprintf(stderr,"CONFIGURATION ERROR: field %s has a non-numeric snap length (%s), ignoring\n",field.c_str(), fld_snap_str.c_str() );\r
+ }\r
+ }\r
+ }\r
+\r
+ if(n_snap == cid_set.size()){\r
+ return (snap_len);\r
+ }else{\r
+ return -1;\r
+ }\r
+\r
+\r
+}\r
+\r
+// Function which computes an optimal\r
+// set of unpacking functions.\r
+\r
+void find_optimal_unpack_fcns(col_id_set &upref_cids, table_list *Schema, map<col_id, string,lt_col_id> &ucol_fcn_map){\r
+ map<string, int> pfcn_count;\r
+ map<string, int>::iterator msii;\r
+ col_id_set::iterator cisi;\r
+ set<string>::iterator ssi;\r
+ string best_fcn;\r
+\r
+ while(ucol_fcn_map.size() < upref_cids.size()){\r
+\r
+// Gather unpack functions referenced by unaccounted-for\r
+// columns, and increment their reference count.\r
+ pfcn_count.clear();\r
+ for(cisi=upref_cids.begin();cisi!=upref_cids.end();++cisi){\r
+ if(ucol_fcn_map.count((*cisi)) == 0){\r
+ set<string> ufcns = Schema->get_field((*cisi).schema_ref, (*cisi).field)->get_unpack_fcns();\r
+ for(ssi=ufcns.begin();ssi!=ufcns.end();++ssi)\r
+ pfcn_count[(*ssi)]++;\r
+ }\r
+ }\r
+\r
+// Get the lowest cost per field function.\r
+ float min_cost = 0.0;\r
+ string best_fcn = "";\r
+ for(msii=pfcn_count.begin();msii!=pfcn_count.end();++msii){\r
+ int fcost = Schema->get_ufcn_cost((*msii).first);\r
+ if(fcost < 0){\r
+ fprintf(stderr,"CONFIGURATION ERROR, unpack function %s either has negative cost or is not defined.\n",(*msii).first.c_str());\r
+ exit(1);\r
+ }\r
+ float this_cost = (1.0*fcost)/(*msii).second;\r
+ if(msii == pfcn_count.begin() || this_cost < min_cost){\r
+ min_cost = this_cost;\r
+ best_fcn = (*msii).first;\r
+ }\r
+ }\r
+ if(best_fcn == ""){\r
+ fprintf(stderr,"ERROR, could not find a best field unpqacking function.\n");\r
+ exit(1);\r
+ }\r
+\r
+// Assign this function to the unassigned fcns which use it.\r
+ for(cisi=upref_cids.begin();cisi!=upref_cids.end();++cisi){\r
+ if(ucol_fcn_map.count((*cisi)) == 0){\r
+ set<string> ufcns = Schema->get_field((*cisi).schema_ref, (*cisi).field)->get_unpack_fcns();\r
+ if(ufcns.count(best_fcn)>0)\r
+ ucol_fcn_map[(*cisi)] = best_fcn;\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+\r
+\r
+// Generate an initial test test for the lfta\r
+// Assume that the predicate references no external functions,\r
+// and especially no partial functions,\r
+// aggregates, internal functions.\r
+string generate_lfta_prefilter(vector<cnf_set *> &pred_list,\r
+ col_id_set &temp_cids, table_list *Schema, ext_fcn_list *Ext_fcns,\r
+ vector<col_id_set> &lfta_cols, vector<long long int> &lfta_sigs,\r
+ vector<int> &lfta_snap_lens, string iface){\r
+ col_id_set tmp_cid_set, cid_set,upref_cids,upall_cids;\r
+ col_id_set::iterator csi;\r
+ int o,p,q;\r
+ string ret;\r
+\r
+// Gather complex literals in the prefilter.\r
+ cplx_lit_table *complex_literals = new cplx_lit_table();\r
+ for(p=0;p<pred_list.size();++p){\r
+ find_complex_literal_pr(pred_list[p]->pr,Ext_fcns, complex_literals);\r
+ }\r
+\r
+\r
+// Find the combinable predicates\r
+ vector<predicate_t *> pr_list;\r
+ for(p=0;p<pred_list.size();++p){\r
+ find_combinable_preds(pred_list[p]->pr,&pr_list, Schema, Ext_fcns);\r
+ }\r
+\r
+// Analyze the combinable predicates to find the predicate classes.\r
+ pred_class.clear(); // idx to equiv pred in equiv_list\r
+ pred_pos.clear(); // idx to returned bitmask.\r
+ vector<predicate_t *> equiv_list;\r
+ vector<int> num_equiv;\r
+\r
+\r
+ for(p=0;p<pr_list.size();++p){\r
+ for(q=0;q<equiv_list.size();++q){\r
+ if(is_equivalent_class_pred_base(equiv_list[q],pr_list[p],Schema,Ext_fcns))\r
+ break;\r
+ }\r
+ if(q == equiv_list.size()){ // no equiv : create new\r
+ pred_class.push_back(equiv_list.size());\r
+ equiv_list.push_back(pr_list[p]);\r
+ pred_pos.push_back(0);\r
+ num_equiv.push_back(1);\r
+\r
+ }else{ // pr_list[p] is equivalent to pred q\r
+ pred_class.push_back(q);\r
+ pred_pos.push_back(num_equiv[q]);\r
+ num_equiv[q]++;\r
+ }\r
+ }\r
+\r
+// Generate the variables which hold the common pred handles\r
+ ret += "/*\t\tprefilter global vars.\t*/\n";\r
+ for(q=0;q<equiv_list.size();++q){\r
+ for(p=0;p<=(num_equiv[q]/32);++p){\r
+ ret += "void *pref_common_pred_hdl_"+int_to_string(q)+"_"+int_to_string(p)+"_"+iface+";\n";\r
+ }\r
+ }\r
+\r
+// Struct to hold prefilter complex literals\r
+ ret += "struct prefilter_complex_lit_struct_"+iface+" {\n";\r
+ if(complex_literals->size() == 0)\r
+ ret += "\tint no_variable;\n";\r
+ int cl;\r
+ for(cl=0;cl<complex_literals->size();cl++){\r
+ literal_t *l = complex_literals->get_literal(cl);\r
+ data_type *dtl = new data_type( l->get_type() );\r
+ sprintf(tmpstr,"\t%s complex_literal_%d;\n",dtl->get_cvar_type().c_str(),cl);\r
+ ret += tmpstr;\r
+ }\r
+ ret += "} prefilter_complex_lits_"+iface+";\n\n";\r
+\r
+\r
+// Generate the prefilter initialziation code\r
+ ret += "void init_lfta_prefilter_"+iface+"(){\n";\r
+\r
+// First initialize complex literals, if any.\r
+ ret += "\tstruct prefilter_complex_lit_struct_"+iface+" *t = &prefilter_complex_lits_"+iface+";\n";\r
+ for(cl=0;cl<complex_literals->size();cl++){\r
+ literal_t *l = complex_literals->get_literal(cl);\r
+ sprintf(tmpstr,"&(t->complex_literal_%d)",cl);\r
+ ret += "\t" + l->to_C_code(tmpstr) + ";\n";\r
+ }\r
+\r
+\r
+ set<int> epred_seen;\r
+ for(p=0;p<pr_list.size();++p){\r
+ int q = pred_class[p];\r
+//printf("\tq=%d\n",q);\r
+ if(epred_seen.count(q)>0){\r
+ ret += "\tregister_commonpred_handles_"+equiv_list[q]->get_op()+"(";\r
+ vector<bool> cl_op = Ext_fcns->get_class_indicators(equiv_list[q]->get_fcn_id());\r
+ vector<scalarexp_t *> op_list = pr_list[p]->get_op_list();\r
+ for(o=0;o<op_list.size();++o){\r
+ if(! cl_op[o]){\r
+ ret += generate_se_code(op_list[o],Schema)+", ";\r
+ }\r
+ }\r
+ ret += "pref_common_pred_hdl_"+int_to_string(q)+"_"+int_to_string(pred_pos[p]/32)+"_"+iface+","+int_to_string(pred_pos[p]%32)+");\n";\r
+ epred_seen.insert(q);\r
+ }else{\r
+ ret += "\tpref_common_pred_hdl_"+int_to_string(q)+"_"+int_to_string(pred_pos[p]/32)+"_"+iface+" = (void *)register_commonpred_handles_"+equiv_list[q]->get_op()+"(";\r
+ vector<bool> cl_op = Ext_fcns->get_class_indicators(equiv_list[q]->get_fcn_id());\r
+ vector<scalarexp_t *> op_list = pr_list[p]->get_op_list();\r
+ for(o=0;o<op_list.size();++o){\r
+ if(! cl_op[o]){\r
+ ret += generate_se_code(op_list[o],Schema)+", ";\r
+ }\r
+ }\r
+ ret += "NULL,"+int_to_string(pred_pos[p]%32)+");\n";\r
+ epred_seen.insert(q);\r
+ }\r
+ }\r
+ ret += "}\n\n";\r
+\r
+\r
+\r
+// Start on main body code generation\r
+ ret+="gs_uint64_t lfta_prefilter_"+iface+"(void *pkt){\n";\r
+\r
+\r
+///--------------------------------------------------------------\r
+/// Generate and store the prefilter body,\r
+/// reuse it for the snap length calculator\r
+///-------------------------------------------------------------\r
+ string body;\r
+\r
+ body += "\tstruct packet *p = (struct packet *)pkt;\n";\r
+\r
+\r
+\r
+// Gather the colids to store unpacked variables.\r
+ for(p=0;p<pred_list.size();++p){\r
+ gather_pr_col_ids(pred_list[p]->pr,tmp_cid_set, gb_tbl);\r
+ }\r
+\r
+// make the col_ids refer to the base tables, and\r
+// grab the col_ids with at least one unpacking function.\r
+ for(csi=tmp_cid_set.begin();csi!=tmp_cid_set.end();++csi){\r
+ string c_tbl = Schema->get_basetbl_name((*csi).schema_ref,(*csi).field);\r
+ col_id tmp_col_id;\r
+ tmp_col_id.field = (*csi).field;\r
+ tmp_col_id.tblvar_ref = (*csi).tblvar_ref;\r
+ tmp_col_id.schema_ref = Schema->get_table_ref(c_tbl);\r
+ cid_set.insert(tmp_col_id);\r
+ field_entry *fe = Schema->get_field(tmp_col_id.schema_ref, tmp_col_id.field);\r
+ if(fe->get_unpack_fcns().size()>0)\r
+ upref_cids.insert(tmp_col_id);\r
+\r
+\r
+ }\r
+\r
+// Find the set of unpacking programs needed for the\r
+// prefilter fields.\r
+ map<col_id, string,lt_col_id> ucol_fcn_map;\r
+ find_optimal_unpack_fcns(upref_cids, Schema, ucol_fcn_map);\r
+ set<string> pref_ufcns;\r
+ map<col_id, string,lt_col_id>::iterator mcis;\r
+ for(mcis=ucol_fcn_map.begin(); mcis!=ucol_fcn_map.end(); mcis++){\r
+ pref_ufcns.insert((*mcis).second);\r
+ }\r
+\r
+\r
+\r
+// Variables for unpacking attributes.\r
+ body += "/*\t\tVariables for unpacking attributes\t*/\n";\r
+ for(csi=cid_set.begin(); csi!=cid_set.end();++csi){\r
+ int schref = (*csi).schema_ref;\r
+ int tblref = (*csi).tblvar_ref;\r
+ string field = (*csi).field;\r
+ data_type dt(Schema->get_type_name(schref,field));\r
+ sprintf(tmpstr,"\t%s unpack_var_%s_%d;\n",dt.get_cvar_type().c_str(),\r
+ field.c_str(), tblref);\r
+ body += tmpstr;\r
+ sprintf(tmpstr,"\tgs_retval_t ret_%s_%d;\n", field.c_str(),tblref);\r
+ body += tmpstr;\r
+ }\r
+// Variables for unpacking temporal attributes.\r
+ body += "/*\t\tVariables for unpacking temporal attributes\t*/\n";\r
+ for(csi=temp_cids.begin(); csi!=temp_cids.end();++csi){\r
+ if (cid_set.count(*csi) == 0) {\r
+ int schref = (*csi).schema_ref;\r
+ int tblref = (*csi).tblvar_ref;\r
+ string field = (*csi).field;\r
+ data_type dt(Schema->get_type_name(schref,field));\r
+ sprintf(tmpstr,"\t%s unpack_var_%s_%d;\n",dt.get_cvar_type().c_str(),\r
+ field.c_str(), tblref);\r
+ body += tmpstr;\r
+\r
+ }\r
+ }\r
+ body += "\n\n";\r
+\r
+// Variables for combinable predicate evaluation\r
+ body += "/*\t\tVariables for common prdicate evaluation\t*/\n";\r
+ for(q=0;q<equiv_list.size();++q){\r
+ for(p=0;p<=(num_equiv[q]/32);++p){\r
+ body += "unsigned long int pref_common_pred_val_"+int_to_string(q)+"_"+int_to_string(p)+" = 0;\n";\r
+ }\r
+ }\r
+\r
+\r
+// Variables that are always needed\r
+ body += "/*\t\tVariables which are always needed\t*/\n";\r
+ body += "\tgs_uint64_t retval=0, bitpos=1;\n";\r
+ body += "\tstruct prefilter_complex_lit_struct_"+iface+" *t = &prefilter_complex_lits_"+iface+";\n";\r
+\r
+// Call the unpacking functions for the prefilter fields\r
+ if(pref_ufcns.size() > 0)\r
+ body += "\n/*\t\tcall field unpacking functions\t*/\n";\r
+ set<string>::iterator ssi;\r
+ for(ssi=pref_ufcns.begin(); ssi!=pref_ufcns.end(); ++ssi){\r
+ body += "\t"+Schema->get_ufcn_fcn((*ssi))+"(p);\n";\r
+ }\r
+\r
+\r
+// Unpack the accessed attributes\r
+ body += "\n/*\t\tUnpack the accessed attributes.\t*/\n";\r
+ for(csi=cid_set.begin();csi!=cid_set.end();++csi){\r
+ int tblref = (*csi).tblvar_ref;\r
+ int schref = (*csi).schema_ref;\r
+ string field = (*csi).field;\r
+ sprintf(tmpstr,"\tret_%s_%d = (%s(p, &unpack_var_%s_%d) == 0);\n",\r
+ field.c_str(),tblref,Schema->get_fcn(schref,field).c_str(), field.c_str(), tblref);\r
+ body += tmpstr;\r
+ }\r
+\r
+// next unpack the temporal attributes and ignore the errors\r
+// We are assuming here that failed unpack of temporal attributes\r
+// is not going to overwrite the last stored value\r
+// Failed upacks are ignored\r
+ for(csi=temp_cids.begin();csi!=temp_cids.end();++csi){\r
+ int tblref = (*csi).tblvar_ref;\r
+ int schref = (*csi).schema_ref;\r
+ string field = (*csi).field;\r
+ sprintf(tmpstr,"\t%s(p, &prefilter_temp_vars.unpack_var_%s_%d);\n",\r
+ Schema->get_fcn(schref,field).c_str(), field.c_str(), tblref);\r
+ body += tmpstr;\r
+ }\r
+\r
+// Evaluate the combinable predicates\r
+ if(equiv_list.size()>0)\r
+ body += "/*\t\tEvaluate the combinable predicates.\t*/\n";\r
+ for(q=0;q<equiv_list.size();++q){\r
+ for(p=0;p<=(num_equiv[q]/32);++p){\r
+\r
+// Only call the common eval fcn if all ref'd fields present.\r
+ col_id_set pred_cids;\r
+ col_id_set::iterator cpi;\r
+ gather_pr_col_ids(equiv_list[q], pred_cids, gb_tbl);\r
+ if(pred_cids.size()>0){\r
+ body += "\tif(";\r
+ for(cpi=pred_cids.begin();cpi!=pred_cids.end();++cpi){\r
+ if(cpi != pred_cids.begin())\r
+ body += " && ";\r
+ string field = (*cpi).field;\r
+ int tblref = (*cpi).tblvar_ref;\r
+ body += "ret_"+field+"_"+int_to_string(tblref);\r
+ }\r
+ body+=")\n";\r
+ }\r
+\r
+ body += "\t\tpref_common_pred_val_"+int_to_string(q)+"_"+int_to_string(p)+" = eval_commonpred_"+equiv_list[q]->get_op()+"(pref_common_pred_hdl_"+int_to_string(q)+"_"+int_to_string(p)+"_"+iface;\r
+ vector<scalarexp_t *> op_list = equiv_list[q]->get_op_list();\r
+ vector<bool> cl_op = Ext_fcns->get_class_indicators(equiv_list[q]->get_fcn_id());\r
+ for(o=0;o<op_list.size();++o){\r
+ if(cl_op[o]){\r
+ body += ","+generate_se_code(op_list[o],Schema);\r
+ }\r
+ }\r
+ body += ");\n";\r
+ }\r
+ }\r
+\r
+\r
+ for(p=0;p<pred_list.size();++p){\r
+ col_id_set pred_cids;\r
+ col_id_set::iterator cpi;\r
+ gather_pr_col_ids(pred_list[p]->pr,pred_cids, gb_tbl);\r
+ if(pred_cids.size()>0){\r
+ body += "\tif(";\r
+ for(cpi=pred_cids.begin();cpi!=pred_cids.end();++cpi){\r
+ if(cpi != pred_cids.begin())\r
+ body += " && ";\r
+ string field = (*cpi).field;\r
+ int tblref = (*cpi).tblvar_ref;\r
+ body += "ret_"+field+"_"+int_to_string(tblref);\r
+ }\r
+ body+=")\n";\r
+ }\r
+ body += "\t\tif("+generate_predicate_code(pred_list[p]->pr,Schema)+")\n\t\t\tretval |= bitpos;\n";\r
+ body+="\tbitpos = bitpos << 1;\n";\r
+ }\r
+\r
+// ---------------------------------------------------------------\r
+// Finished with the body of the prefilter\r
+// --------------------------------------------------------------\r
+\r
+ ret += body;\r
+\r
+// Collect fields referenced by an lfta but not\r
+// already unpacked for the prefilter.\r
+\r
+//printf("upref_cids is:\n");\r
+//for(csi=upref_cids.begin();csi!=upref_cids.end();csi++)\r
+//printf("\t%s %d\n",(*csi).field.c_str(), (*csi).schema_ref);\r
+//printf("pref_ufcns is:\n");\r
+//for(ssi=pref_ufcns.begin();ssi!=pref_ufcns.end();++ssi)\r
+//printf("\t%s\n",(*ssi).c_str());\r
+\r
+ int l;\r
+ for(l=0;l<lfta_cols.size();++l){\r
+ for(csi=lfta_cols[l].begin();csi!=lfta_cols[l].end();++csi){\r
+ string c_tbl = Schema->get_basetbl_name((*csi).schema_ref,(*csi).field);\r
+ col_id tmp_col_id;\r
+ tmp_col_id.field = (*csi).field;\r
+ tmp_col_id.tblvar_ref = (*csi).tblvar_ref;\r
+ tmp_col_id.schema_ref = Schema->get_table_ref(c_tbl);\r
+ field_entry *fe = Schema->get_field(tmp_col_id.schema_ref, tmp_col_id.field);\r
+ set<string> fld_ufcns = fe->get_unpack_fcns();\r
+//printf("tmpcol is (%s, %d), ufcns size is %d, upref_cids cnt is %d\n",tmp_col_id.field.c_str(),tmp_col_id.schema_ref,fld_ufcns.size(), upref_cids.count(tmp_col_id));\r
+ if(fld_ufcns.size()>0 && upref_cids.count(tmp_col_id) == 0){\r
+// Ensure that this field not already unpacked.\r
+ bool found = false;\r
+ for(ssi=fld_ufcns.begin();ssi!=fld_ufcns.end();++ssi){\r
+//printf("\tField has unpacking fcn %s\n",(*ssi).c_str());\r
+ if(pref_ufcns.count((*ssi))){\r
+//printf("Field already unpacked.\n");\r
+ found = true;;\r
+ }\r
+ }\r
+ if(! found){\r
+//printf("\tadding to unpack list\n");\r
+ upall_cids.insert(tmp_col_id);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+//printf("upall_cids is:\n");\r
+//for(csi=upall_cids.begin();csi!=upall_cids.end();csi++)\r
+//printf("\t%s %d\n",(*csi).field.c_str(), (*csi).schema_ref);\r
+\r
+// Get the set of unpacking programs for these.\r
+ map<col_id, string,lt_col_id> uall_fcn_map;\r
+ find_optimal_unpack_fcns(upall_cids, Schema, uall_fcn_map);\r
+ set<string> pall_ufcns;\r
+ for(mcis=uall_fcn_map.begin(); mcis!=uall_fcn_map.end(); mcis++){\r
+//printf("uall_fcn_map[%s %d] = %s\n",(*mcis).first.field.c_str(),(*mcis).first.schema_ref,(*mcis).second.c_str());\r
+ pall_ufcns.insert((*mcis).second);\r
+ }\r
+\r
+// Iterate through the remaining set of unpacking function\r
+ if(pall_ufcns.size() > 0)\r
+ ret += "//\t\tcall all remaining field unpacking functions.\n";\r
+ for(ssi=pall_ufcns.begin(); ssi!=pall_ufcns.end(); ++ssi){\r
+// gather the set of columns unpacked by this ufcn\r
+ col_id_set fcol_set;\r
+ for(csi=upall_cids.begin();csi!=upall_cids.end();++csi){\r
+ if(uall_fcn_map[(*csi)] == (*ssi))\r
+ fcol_set.insert((*csi));\r
+ }\r
+\r
+// gather the set of lftas which access a field unpacked by the fcn\r
+ set<long long int> clfta;\r
+ for(l=0;l<lfta_cols.size();l++){\r
+ for(csi=fcol_set.begin();csi!=fcol_set.end();++csi){\r
+ if(lfta_cols[l].count((*csi)) > 0)\r
+ break;\r
+ }\r
+ if(csi != fcol_set.end())\r
+ clfta.insert(lfta_sigs[l]);\r
+ }\r
+\r
+// generate the unpacking code\r
+ ret += "\tif(";\r
+ set<long long int>::iterator sii;\r
+ for(sii=clfta.begin();sii!=clfta.end();++sii){\r
+ if(sii!=clfta.begin())\r
+ ret += " || ";\r
+ sprintf(tmpstr,"((retval & %lluull) == %lluull)",(*sii),(*sii));\r
+ ret += tmpstr;\r
+ }\r
+ ret += ")\n\t\t"+Schema->get_ufcn_fcn((*ssi))+"(p);\n";\r
+ }\r
+\r
+\r
+ ret += "\treturn(retval);\n\n";\r
+ ret += "}\n\n";\r
+\r
+\r
+// --------------------------------------------------------\r
+// reuse prefilter body for snaplen calculator\r
+//\r
+// This is dummy code, so I'm commenting it out.\r
+\r
+/*\r
+ ret+="gs_uint32_t lfta_pkt_snaplen(void *pkt){\n";\r
+\r
+ ret += body;\r
+\r
+ int i;\r
+ vector<int> s_snaps = lfta_snap_lens;\r
+ sort(s_snaps.begin(), s_snaps.end());\r
+\r
+ if(s_snaps[0] == -1){\r
+ set<unsigned long long int> sigset;\r
+ for(i=0;i<lfta_snap_lens.size();++i){\r
+ if(lfta_snap_lens[i] == -1){\r
+ sigset.insert(lfta_sigs[i]);\r
+ }\r
+ }\r
+ ret += "\tif( ";\r
+ set<unsigned long long int>::iterator sulli;\r
+ for(sulli=sigset.begin();sulli!=sigset.end();++sulli){\r
+ if(sulli!=sigset.begin())\r
+ ret += " || ";\r
+ sprintf(tmpstr,"((retval & %lluull) == %lluull)",(*sulli),(*sulli));\r
+ ret += tmpstr;\r
+ }\r
+ ret += ") return -1;\n";\r
+ }\r
+\r
+ int nextpos = lfta_snap_lens.size()-1;\r
+ int nextval = lfta_snap_lens[nextpos];\r
+ while(nextval >= 0){\r
+ set<unsigned long long int> sigset;\r
+ for(i=0;i<lfta_snap_lens.size();++i){\r
+ if(lfta_snap_lens[i] == nextval){\r
+ sigset.insert(lfta_sigs[i]);\r
+ }\r
+ }\r
+ ret += "\tif( ";\r
+ set<unsigned long long int>::iterator sulli;\r
+ for(sulli=sigset.begin();sulli!=sigset.end();++sulli){\r
+ if(sulli!=sigset.begin())\r
+ ret += " || ";\r
+ sprintf(tmpstr,"((retval & %lluull) == %lluull)",(*sulli),(*sulli));\r
+ ret += tmpstr;\r
+ }\r
+ ret += ") return "+int_to_string(nextval)+";\n";\r
+\r
+ for(nextpos--;nextpos>0 && lfta_snap_lens[nextpos] == nextval;nextpos--);\r
+ if(nextpos>0)\r
+ nextval = lfta_snap_lens[nextpos];\r
+ else\r
+ nextval = -1;\r
+ }\r
+ ret += "\treturn 0;\n";\r
+ ret += "}\n\n";\r
+*/\r
+\r
+\r
+ return(ret);\r
+}\r
+\r
+\r
+\r
+\r
+// Generate the struct which will store the the values of\r
+// temporal attributesunpacked by prefilter\r
+string generate_lfta_prefilter_struct(col_id_set &cid_set, table_list *Schema) {\r
+\r
+ col_id_set::iterator csi;\r
+\r
+// printf("generate_lfta_prefilter_struct : %d vars\n",cid_set.size());\r
+\r
+ string ret="struct prefilter_unpacked_temp_vars {\n";\r
+ ret += "\t/*\tVariables for unpacking temporal attributes\t*/\n";\r
+\r
+ string init_code;\r
+\r
+ for(csi=cid_set.begin(); csi!=cid_set.end();++csi){\r
+ int schref = (*csi).schema_ref;\r
+ int tblref = (*csi).tblvar_ref;\r
+ string field = (*csi).field;\r
+ data_type dt(Schema->get_type_name(schref,field), Schema->get_modifier_list(schref,field));\r
+ sprintf(tmpstr,"\t%s unpack_var_%s_%d;\n",dt.get_cvar_type().c_str(),\r
+ field.c_str(), tblref);\r
+ ret += tmpstr;\r
+\r
+ if (init_code != "")\r
+ init_code += ", ";\r
+ if (dt.is_increasing())\r
+ init_code += dt.get_min_literal();\r
+ else\r
+ init_code += dt.get_max_literal();\r
+\r
+ }\r
+ ret += "};\n\n";\r
+\r
+ ret += "struct prefilter_unpacked_temp_vars prefilter_temp_vars = {" + init_code + "};\n\n";\r
+\r
+ return(ret);\r
+}\r