Added quantiling UDAFs
[com/gs-lite.git] / src / ftacmp / translate_fta.cc
index 4a1263f..f50da21 100644 (file)
-/* ------------------------------------------------
-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<unistd.h>             // for gethostname
-
-#include <string>
-#include "parse_fta.h"
-#include "parse_schema.h"
-#include "parse_ext_fcns.h"
-#include"analyze_fta.h"
-#include"query_plan.h"
-#include"generate_lfta_code.h"
-#include"stream_query.h"
-#include"generate_utils.h"
-#include"nic_def.h"
-#include"generate_nic_code.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include<ctype.h>
-#include<glob.h>
-#include<string.h>
-
-#include<list>
-
-//             for the scandir
-     #include <sys/types.h>
-     #include <dirent.h>
-
-
-#include<errno.h>
-
-//             to verify that some files exist.
-     #include <sys/types.h>
-     #include <sys/stat.h>
-
-#include "parse_partn.h"
-
-#include "print_plan.h"
-
-//             Interface to the xml parser
-
-#include"xml_t.h"
-#include"field_list.h"
-
-extern int xmlParserparse(void);
-extern FILE *xmlParserin;
-extern int xmlParserdebug;
-
-std::vector<std::string> xml_attr_vec;
-std::vector<std::string> xml_val_vec;
-std::string xml_a, xml_v;
-xml_t *xml_leaves = NULL;
-
-//     Interface to the field list verifier
-field_list *field_verifier = NULL;
-
-#define TMPSTRLEN 1000
-
-#ifndef PATH_DELIM
-  #define PATH_DELIM '/'
-#endif
-
-char tmp_schema_str[10000];
-
-// maximum delay between two hearbeats produced
-// by UDOP. Used when its not explicity
-// provided in udop definition
-#define DEFAULT_UDOP_LIVENESS_TIMEOUT 5
-
-//             Default lfta hash table size, must be power of 2.
-int DEFAULT_LFTA_HASH_TABLE_SIZE = 4096;
-
-//             Interface to FTA definition lexer and parser ...
-
-extern int FtaParserparse(void);
-extern FILE *FtaParserin;
-extern int FtaParserdebug;
-
-fta_parse_t *fta_parse_result;
-var_defs_t *fta_parse_defines;
-
-
-
-//             Interface to external function lexer and parser ...
-
-extern int Ext_fcnsParserparse(void);
-extern FILE *Ext_fcnsParserin;
-extern int Ext_fcnsParserdebug;
-
-ext_fcn_list *Ext_fcns;
-
-
-//             Interface to partition definition parser
-extern int PartnParserparse();
-partn_def_list_t *partn_parse_result = NULL;
-
-
-
-using namespace std;
-//extern int errno;
-
-
-//             forward delcaration of local utility function
-void generate_makefile(vector<string> &input_file_names, int nfiles,
-                                          vector<string> &hfta_names, opview_set &opviews,
-                                               vector<string> &machine_names,
-                                               string schema_file_name,
-                                               vector<string> &interface_names,
-                                               ifq_t *ifdb, string &config_dir_path,
-                                               bool use_pads,
-                                               string extra_libs,
-                                               map<string, vector<int> > &rts_hload
-                                       );
-
-//static int split_string(char *instr,char sep, char **words,int max_words);
-#define MAXFLDS 100
-
-  FILE *schema_summary_output = NULL;          // query names
-
-//                     Dump schema summary
-void dump_summary(stream_query *str){
-       fprintf(schema_summary_output,"%s\n",str->query_name.c_str());
-
-       table_def *sch = str->get_output_tabledef();
-
-       vector<field_entry *> flds = sch->get_fields();
-       int f;
-       for(f=0;f<flds.size();++f){
-               if(f>0) fprintf(schema_summary_output,"|");
-               fprintf(schema_summary_output,"%s",flds[f]->get_name().c_str());
-       }
-       fprintf(schema_summary_output,"\n");
-       for(f=0;f<flds.size();++f){
-               if(f>0) fprintf(schema_summary_output,"|");
-               fprintf(schema_summary_output,"%s",flds[f]->get_type().c_str());
-       }
-       fprintf(schema_summary_output,"\n");
-}
-
-//             Globals
-string hostname;               // name of current host.
-int hostname_len;
-bool generate_stats = false;
-string root_path = "../..";
-
-
-int main(int argc, char **argv){
-  char tmpstr[TMPSTRLEN];
-  string err_str;
-  int q,s,h,f;
-
-  set<int>::iterator si;
-
-  vector<string> query_names;                  // for lfta.c registration
-  map<string, vector<int> > mach_query_names;  // list queries of machine
-  vector<int> snap_lengths;                            // for lfta.c registration
-  vector<string> interface_names;                      // for lfta.c registration
-  vector<string> machine_names;                        // machine of interface
-  vector<bool> lfta_reuse_options;                     // for lfta.c registration
-  vector<int> lfta_liveness_timeouts;          // fot qtree.xml generation
-  vector<string> hfta_names;                   // hfta cource code names, for
-                                                                               // creating make file.
-  vector<string> qnames;                               // ensure unique names
-  map<string, int> lfta_names;                 // keep track of unique lftas.
-
-
-//                             set these to 1 to debug the parser
-  FtaParserdebug = 0;
-  Ext_fcnsParserdebug = 0;
-
-  FILE *lfta_out;                              // lfta.c output.
-  FILE *fta_in;                                        // input file
-  FILE *table_schemas_in;              // source tables definition file
-  FILE *query_name_output;             // query names
-  FILE *qtree_output;                  // interconnections of query nodes
-
-  // -------------------------------
-  // Handling of Input Arguments
-  // -------------------------------
-    char optstr[] = "BDpLC:l:HNQMf:PSh:n:cR:";
-       const char *usage_str = "Usage: %s [-B] [-D] [-p] [-L] [-N] [-H] [-Q] [-M] [-C <config directory>] [-l <library directory>] [-f] [-P] [-S] [-n n_virtual_interfaces] [-h hostname] [-R root_path] [schema_file] input_file [input file ...]\n"
-               "\t[-B] : debug only (don't create output files)\n"
-               "\t[-D] : distributed mode (will use cluster.ifq instead of local .ifq file)\n"
-               "\t[-p] : partitioned mode (will use partition information in partition.txt to drive query optimization)\n"
-               "\t[-L] : use live_hosts.txt file to restrict queries to a set of live hosts\n"
-               "\t[-C] : use <config directory> for definition files\n"
-               "\t[-l] : use <library directory> for library queries\n"
-               "\t[-N] : output query names in query_names.txt\n"
-               "\t[-H] : create HFTA only (no schema_file)\n"
-               "\t[-Q] : use query name for hfta suffix\n"
-               "\t[-M] : generate make file and runit, stopit scripts\n"
-               "\t[-S] : enable LFTA statistics (alters Makefile).\n"
-               "\t[-f] : Output schema summary to schema_summary.txt\n"
-               "\t[-P] : link with PADS\n"
-               "\t[-h] : override host name.\n"
-               "\t[-c] : clean out Makefile and hfta_*.cc first.\n"
-               "\t[-R] : path to root of GS-lite\n"
-;
-
-//             parameters gathered from command line processing
-       string external_fcns_path;
-//     string internal_fcn_path;
-       string config_dir_path;
-       string library_path = "./";
-       vector<string> input_file_names;
-       string schema_file_name;
-       bool debug_only = false;
-       bool hfta_only = false;
-       bool output_query_names = false;
-       bool output_schema_summary=false;
-       bool numeric_hfta_flname = true;
-       bool create_makefile = false;
-       bool distributed_mode = false;
-       bool partitioned_mode = false;
-       bool use_live_hosts_file = false;
-       bool use_pads = false;
-       bool clean_make = false;
-       int n_virtual_interfaces = 1;
-
-   char chopt;
-   while((chopt = getopt(argc,argv,optstr)) != -1){
-               switch(chopt){
-               case 'B':
-                       debug_only = true;
-                       break;
-               case 'D':
-                       distributed_mode = true;
-                       break;
-               case 'p':
-                       partitioned_mode = true;
-                       break;
-               case 'L':
-                       use_live_hosts_file = true;
-                       break;
-               case 'C':
-                               if(optarg != NULL)
-                                config_dir_path = string(optarg) + string("/");
-                       break;
-               case 'l':
-                               if(optarg != NULL)
-                                library_path = string(optarg) + string("/");
-                       break;
-               case 'N':
-                       output_query_names = true;
-                       break;
-               case 'Q':
-                       numeric_hfta_flname = false;
-                       break;
-               case 'H':
-                       if(schema_file_name == ""){
-                               hfta_only = true;
-                       }
-                       break;
-               case 'f':
-                       output_schema_summary=true;
-                       break;
-               case 'M':
-                       create_makefile=true;
-                       break;
-               case 'S':
-                       generate_stats=true;
-                       break;
-               case 'P':
-                       use_pads = true;
-                       break;
-               case 'c':
-                       clean_make = true;
-                       break;
-               case 'h':
-                       if(optarg != NULL)
-                               hostname = optarg;
-                       break;
-               case 'R':
-                       if(optarg != NULL)
-                               root_path = optarg;
-                       break;
-               case 'n':
-                       if(optarg != NULL){
-                               n_virtual_interfaces = atoi(optarg);
-                               if(n_virtual_interfaces < 1 || n_virtual_interfaces > 128){
-                                       fprintf(stderr,"Warning, %d virtual interfaces specified, valid values are between 1 and 128 inclusive\n",n_virtual_interfaces);
-                                       n_virtual_interfaces = 1;
-                               }
-                       }
-                       break;
-               case '?':
-                       fprintf(stderr,"Error, argument %c not recognized.\n",optopt);
-                       fprintf(stderr,"%s\n", usage_str);
-                       exit(1);
-               default:
-                       fprintf(stderr, "Argument was %c\n", optopt);
-                       fprintf(stderr,"Invalid arguments\n");
-                       fprintf(stderr,"%s\n", usage_str);
-                       exit(1);
-               }
-       }
-       argc -= optind;
-       argv += optind;
-       for (int i = 0; i < argc; ++i) {
-               if((schema_file_name == "") && !hfta_only){
-                       schema_file_name = argv[i];
-               }else{
-                       input_file_names.push_back(argv[i]);
-               }
-       }
-
-       if(input_file_names.size() == 0){
-               fprintf(stderr,"%s\n", usage_str);
-               exit(1);
-       }
-
-       if(clean_make){
-               string clean_cmd = "rm Makefile hfta_*.cc";
-               int clean_ret = system(clean_cmd.c_str());
-               if(clean_ret){
-                       fprintf(stderr,"Warning, return value %d when trying to clean out old source files.\n", clean_ret);
-               }
-       }
-
-
-       nic_prop_db *npdb = new nic_prop_db(config_dir_path);
-
-//                     Open globally used file names.
-
-       // prepend config directory to schema file
-       schema_file_name = config_dir_path + schema_file_name;
-       external_fcns_path = config_dir_path + string("external_fcns.def");
-    string ifx_fname = config_dir_path + string("ifres.xml");
-
-//             Find interface query file(s).
-       if(hostname == ""){
-               gethostname(tmpstr,TMPSTRLEN);
-               hostname = tmpstr;
-       }
-       hostname_len = strlen(tmpstr);
-    string ifq_fname = config_dir_path + (distributed_mode ? "cluster" : hostname) + string(".ifq");
-       vector<string> ifq_fls;
-
-               ifq_fls.push_back(ifq_fname);
-
-
-//                     Get the field list, if it exists
-       string flist_fl = config_dir_path + "field_list.xml";
-       FILE *flf_in = NULL;
-       if((flf_in = fopen(flist_fl.c_str(), "r")) != NULL) {
-               fprintf(stderr,"Found field list file %s\n",flist_fl.c_str());
-               xml_leaves = new xml_t();
-               xmlParser_setfileinput(flf_in);
-               if(xmlParserparse()){
-                       fprintf(stderr,"WARNING, could not parse field list file %s\n",flist_fl.c_str());
-               }else{
-                       field_verifier = new field_list(xml_leaves);
-               }
-       }
-
-       if(!hfta_only){
-         if((table_schemas_in = fopen(schema_file_name.c_str(), "r")) == NULL) {
-               fprintf(stderr,"Can't open schema file %s\n%s\n",schema_file_name.c_str(),strerror(errno));
-               exit(1);
-         }
-       }
-
-/*
-       if(!(debug_only || hfta_only)){
-         if((lfta_out = fopen("lfta.c","w")) == NULL){
-               fprintf(stderr,"Can't open output file %s\n%s\n","lfta.c",strerror(errno));
-               exit(1);
-         }
-       }
-*/
-
-//             Get the output specification file.
-//             format is
-//                     query, operator, operator_param, directory, bucketwidth, partitioning_se, n_partitions
-       string ospec_fl = "output_spec.cfg";
-       FILE *osp_in = NULL;
-       vector<ospec_str *> output_specs;
-       multimap<string, int> qname_to_ospec;
-       if((osp_in = fopen(ospec_fl.c_str(), "r")) != NULL) {
-               char *flds[MAXFLDS];
-               int o_lineno = 0;
-               while(fgets(tmpstr,TMPSTRLEN,osp_in)){
-                       o_lineno++;
-                       int nflds = split_string(tmpstr,',',flds,MAXFLDS);
-                       if(nflds == 7){
-//             make operator type lowercase
-                               char *tmpc;
-                               for(tmpc=flds[1];*tmpc!='\0';++tmpc)
-                                       *tmpc = tolower(*tmpc);
-
-                               ospec_str *tmp_ospec = new ospec_str();
-                               tmp_ospec->query = flds[0];
-                               tmp_ospec->operator_type = flds[1];
-                               tmp_ospec->operator_param = flds[2];
-                               tmp_ospec->output_directory = flds[3];
-                               tmp_ospec->bucketwidth = atoi(flds[4]);
-                               tmp_ospec->partitioning_flds = flds[5];
-                               tmp_ospec->n_partitions = atoi(flds[6]);
-                               qname_to_ospec.insert(pair<string,int>(tmp_ospec->query,output_specs.size()));
-                               output_specs.push_back(tmp_ospec);
-                       }else{
-                               fprintf(stderr,"Warning, line %d corrupted in output_spec.cfg, has %d fields.\n",o_lineno,nflds);
-                       }
-               }
-               fclose(osp_in);
-       }else{
-               fprintf(stderr,"output_spec.cfg not found.  The query set has no output.  exiting.\n");
-               exit(1);
-       }
-
-//             hfta parallelism
-       string pspec_fl = "hfta_parallelism.cfg";
-       FILE *psp_in = NULL;
-       map<string, int> hfta_parallelism;
-       if((psp_in = fopen(pspec_fl.c_str(), "r")) != NULL){
-               char *flds[MAXFLDS];
-               int o_lineno = 0;
-               while(fgets(tmpstr,TMPSTRLEN,psp_in)){
-                       bool good_entry = true;
-                       o_lineno++;
-                       int nflds = split_string(tmpstr,',',flds,MAXFLDS);
-                       if(nflds == 2){
-                               string hname = flds[0];
-                               int par = atoi(flds[1]);
-                               if(par <= 0 || par > n_virtual_interfaces){
-                                       fprintf(stderr,"Warning, line %d of %s is incorrectly formatted, parallelism is %d, must be between 1 and %d\n",o_lineno,pspec_fl.c_str(),par,n_virtual_interfaces);
-                                       good_entry = false;
-                               }
-                               if(good_entry && n_virtual_interfaces % par != 0){
-                                       fprintf(stderr,"Warning, line %d of %s is incorrectly formatted, parallelism is %d, must divide the number of virtual interfaces (%d), ignoring.\n",o_lineno,pspec_fl.c_str(),par,n_virtual_interfaces);
-                                       good_entry = false;
-                               }
-                               if(good_entry)
-                                       hfta_parallelism[hname] = par;
-                       }
-               }
-       }else{
-               fprintf(stderr,"WARNING, no file %s found, using single copies of hftas.\n",pspec_fl.c_str());
-       }
-
-
-//             LFTA hash table sizes
-       string htspec_fl = "lfta_htsize.cfg";
-       FILE *htsp_in = NULL;
-       map<string, int> lfta_htsize;
-       if((htsp_in = fopen(htspec_fl.c_str(), "r")) != NULL){
-               char *flds[MAXFLDS];
-               int o_lineno = 0;
-               while(fgets(tmpstr,TMPSTRLEN,htsp_in)){
-                       bool good_entry = true;
-                       o_lineno++;
-                       int nflds = split_string(tmpstr,',',flds,MAXFLDS);
-                       if(nflds == 2){
-                               string lfta_name = flds[0];
-                               int htsz = atoi(flds[1]);
-                               if(htsz>0){
-                                       lfta_htsize[lfta_name] = htsz;
-                               }else{
-                                       fprintf(stderr,"Warning, line %d of %s is incorrectly formatted, htsize is %d, must be larger than 0.\n",o_lineno,htspec_fl.c_str(),htsz);
-                               }
-                       }
-               }
-       }else{
-               fprintf(stderr,"WARNING, no file %s found, using default LFTA hash table sizes.\n",htspec_fl.c_str());
-       }
-
-//             LFTA vitual interface hash split
-       string rtlspec_fl = "rts_load.cfg";
-       FILE *rtl_in = NULL;
-       map<string, vector<int> > rts_hload;
-       if((rtl_in = fopen(rtlspec_fl.c_str(), "r")) != NULL){
-               char *flds[MAXFLDS];
-               int r_lineno = 0;
-               string iface_name;
-               vector<int> hload;
-               while(fgets(tmpstr,TMPSTRLEN,rtl_in)){
-                       bool good_entry = true;
-                       r_lineno++;
-                       iface_name = "";
-                       hload.clear();
-                       int nflds = split_string(tmpstr,',',flds,MAXFLDS);
-                       if(nflds >1){
-                               iface_name = flds[0];
-                               int cumm_h = 0;
-                               int j;
-                               for(j=1;j<nflds;++j){
-                                       int h = atoi(flds[j]);
-                                       if(h<=0)
-                                               good_entry = false;
-                                       cumm_h += h;
-                                       hload.push_back(cumm_h);
-                               }
-                       }else{
-                               good_entry = false;
-                       }
-                       if(good_entry){
-                               rts_hload[iface_name] = hload;
-                       }else{
-                               fprintf(stderr,"Warning, line %d of %s is malformed, skipping.\n",r_lineno, rtlspec_fl.c_str());
-                       }
-               }
-       }
-
-
-
-       if(output_query_names){
-         if((query_name_output = fopen("query_names.txt","w")) == NULL){
-               fprintf(stderr,"Can't open output file %s\n%s\n","query_names.txt",strerror(errno));
-               exit(1);
-         }
-       }
-
-       if(output_schema_summary){
-         if((schema_summary_output = fopen("schema_summary.txt","w")) == NULL){
-               fprintf(stderr,"Can't open output file %s\n%s\n","schema_summary.txt",strerror(errno));
-               exit(1);
-         }
-       }
-
-       if((qtree_output = fopen("qtree.xml","w")) == NULL){
-               fprintf(stderr,"Can't open output file %s\n%s\n","qtree.xml",strerror(errno));
-               exit(1);
-       }
-       fprintf(qtree_output,"<?xml version='1.0' encoding='ISO-8859-1'?>\n");
-       fprintf(qtree_output,"<?xml-stylesheet type='text/xsl' href='qtree.xsl'?>\n");
-       fprintf(qtree_output,"<QueryNodes>\n");
-
-
-//                     Get an initial Schema
-       table_list *Schema;
-       if(!hfta_only){
-//                     Parse the table schema definitions.
-         fta_parse_result = new fta_parse_t();
-         FtaParser_setfileinput(table_schemas_in);
-         if(FtaParserparse()){
-               fprintf(stderr,"Table schema parse failed.\n");
-               exit(1);
-         }
-         if(fta_parse_result->parse_type != TABLE_PARSE){
-               fprintf(stderr,"ERROR, file %s is not a table definition file.\n",schema_file_name.c_str());
-               exit(1);
-         }
-         Schema = fta_parse_result->tables;
-
-//                     Process schema field inheritance
-         int retval;
-         retval = Schema->unroll_tables(err_str);
-         if(retval){
-               fprintf(stderr,"Error processing schema filed inheritance:\n %s\n", err_str.c_str() );
-               exit(1);
-         }
-       }else{
-//                     hfta only => we will try to fetch schemas from the registry.
-//                     therefore, start off with an empty schema.
-         Schema = new table_list();
-       }
-
-
-//                     Open and parse the external functions file.
-       Ext_fcnsParserin = fopen(external_fcns_path.c_str(),"r");
-       if(Ext_fcnsParserin == NULL){
-               fprintf(stderr,"Warning, can't find external functions definition file (external_fcns.def).\n");
-               Ext_fcns = new ext_fcn_list();
-       }else{
-               if(Ext_fcnsParserparse()){
-                       fprintf(stderr,"Warning, error parsing external functions definition file (external_fcns.def).\n");
-                       Ext_fcns = new ext_fcn_list();
-               }
-       }
-       if(Ext_fcns->validate_fcns(err_str)){
-               fprintf(stderr,"Error processing external functions definition file (external_fcns.def):\n%s\n",err_str.c_str());
-               exit(1);
-       }
-
-//             Open and parse the interface resources file.
-//     ifq_t *ifaces_db = new ifq_t();
-//   string ierr;
-//     if(ifaces_db->load_ifaces(ifx_fname,use_live_hosts_file,distributed_mode,ierr)){
-//             fprintf(stderr,"ERROR, can't load interface resource file %s :\n%s",
-//                             ifx_fname.c_str(), ierr.c_str());
-//             exit(1);
-//     }
-//     if(ifaces_db->load_ifqs(ifq_fname, ierr)){
-//             fprintf(stderr,"ERROR, can't load interface query file %s :\n%s",
-//                             ifq_fname.c_str(), ierr.c_str());
-//             exit(1);
-//     }
-
-
-//                     The LFTA code string.
-//                     Put the standard preamble here.
-//                     NOTE: the hash macros, fcns should go into the run time
-  map<string, string> lfta_val;
-  map<string, string> lfta_prefilter_val;
-
-  string lfta_header =
-"#include <limits.h>\n\n"
-"#include \"rts.h\"\n"
-"#include \"fta.h\"\n"
-"#include \"lapp.h\"\n"
-"#include \"rts_udaf.h\"\n\n"
-;
-// Get any locally defined parsing headers
-    glob_t glob_result;
-    memset(&glob_result, 0, sizeof(glob_result));
-
-    // do the glob operation
-    int return_value = glob("../../include/lfta/local/*h", GLOB_TILDE, NULL, &glob_result);
-       if(return_value == 0){
-       for(size_t i = 0; i < glob_result.gl_pathc; ++i) {
-                       char *flds[1000];
-                       int nflds = split_string(glob_result.gl_pathv[i],'/',flds,1000);
-                       lfta_header += "#include \"local/"+string(flds[nflds-1])+"\"\n\n";
-       }
-       }else{
-               fprintf(stderr,"Warning, glob on ../../include/lfta/local/*h failed.\n");
-       }
-
-/*
-"#define IS_FILLED(bitmap,bucket) (bitmap[bucket >> 4] & (0x80000000 >> ((bucket & 15)<<1)))\n"
-"#define IS_NEW(bitmap,bucket) (bitmap[bucket >> 4] & (0x80000000 >> (((bucket & 15) << 1) + 1)))\n"
-"#define SET_EMPTY(bitmap,bucket) (bitmap[bucket >> 4] &= (~(0x80000000 >> ((bucket & 15)<<1))))\n"
-"#define SET_FILLED_AND_NEW(bitmap,bucket) (bitmap[bucket >> 4] |= (0xC0000000 >> ((bucket & 15)<<1)))\n"
-*/
-
-       lfta_header += 
-"\n"
-"gs_uint64_t (*lfta_prefilter)(void *pkt) = NULL; // set at fta_init\n"
-"\n"
-"#define SLOT_FILLED 0x04\n"
-"#define SLOT_GEN_BITS 0x03\n"
-"#define SLOT_HASH_BITS 0xfffffff8\n"
-"#define SET_BF_BIT(bf_table, bf_num, bf_index, bucket) (bf_table[(((bucket) * (bf_num)) + (bf_index)) >> 3] |= (0x80 >> ((((bucket) * (bf_num)) + (bf_index)) & 7)))\n"
-"#define IS_BF_SET(bf_table, bf_num, bf_index, bucket) (bf_table[(((bucket) * (bf_num))+(bf_index)) >> 3] & (0x80 >> ((((bucket) * (bf_num))+(bf_index)) & 7)))\n"
-"#define SET_BF_EMPTY(bf_table, bf_num, bf_index, bucket) (bf_table[((bucket * bf_num)+bf_index) >> 3] &= (~0x80 >> (((bucket * bf_num)+bf_index) & 7)))\n"
-"\n\n"
-
-"#define lfta_BOOL_to_hash(x) (x)\n"
-"#define lfta_USHORT_to_hash(x) (x)\n"
-"#define lfta_UINT_to_hash(x) (x)\n"
-"#define lfta_IP_to_hash(x) (x)\n"
-"#define lfta_IPV6_to_hash(x) ( (x.v[0]) ^ (x.v[1]) ^ (x.v[2]) ^ (x.v[3]))\n"
-"#define lfta_INT_to_hash(x) (gs_uint32_t)(x)\n"
-"#define lfta_ULLONG_to_hash(x) ( (( (x) >>32)&0xffffffff) ^ ((x)&0xffffffff) )\n"
-"#define lfta_LLONG_to_hash(x) ( (( (x) >>32)&0xffffffff) ^ ((x)&0xffffffff) )\n"
-"#define lfta_FLOAT_to_hash(x) ( (( ((gs_uint64_t)(x)) >>32)&0xffffffff) ^ (((gs_uint64_t)(x))&0xffffffff) )\n"
-"static gs_uint32_t lfta_V_STR_to_hash(struct gs_string x){\n"
-"      gs_uint32_t i,ret=0,tmp_sum = 0;\n"
-"      for(i=0;i<x.length;++i){\n"
-"              tmp_sum |= (x.data[i]) << (8*(i%4));\n"
-"              if((i%4) == 3){\n"
-"                      ret ^= tmp_sum;\n"
-"                      tmp_sum = 0;\n"
-"              }\n"
-"      }\n"
-"      if((i%4)!=0) ret ^=tmp_sum;\n"
-"      return(ret);\n"
-"}\n\n\n";
-
-
-
-//////////////////////////////////////////////////////////////////
-/////                  Get all of the query parse trees
-
-
-  int i,p;
-  int hfta_count = 0;          // for numeric suffixes to hfta .cc files
-
-//---------------------------
-//             Global info needed for post processing.
-
-//                     Set of operator views ref'd in the query set.
-       opview_set opviews;
-//                     lftas on a per-machine basis.
-       map<string, vector<stream_query *> > lfta_mach_lists;
-       int nfiles = input_file_names.size();
-       vector<stream_query *> hfta_list;               // list of hftas.
-       map<string, stream_query *> sq_map;             // map from query name to stream query.
-
-
-//////////////////////////////////////////
-
-//             Open and parse the interface resources file.
-       ifq_t *ifaces_db = new ifq_t();
-    string ierr;
-       if(ifaces_db->load_ifaces(ifx_fname,use_live_hosts_file,distributed_mode,ierr)){
-               fprintf(stderr,"ERROR, can't load interface resource file %s :\n%s",
-                               ifx_fname.c_str(), ierr.c_str());
-               exit(1);
-       }
-       if(ifaces_db->load_ifqs(ifq_fls[0], ierr)){
-               fprintf(stderr,"ERROR, can't load interface query file %s :\n%s",
-                               ifq_fls[0].c_str(), ierr.c_str());
-               exit(1);
-       }
-
-  map<string, string> qname_to_flname; // for detecting duplicate query names
-
-
-
-//                     Parse the files to create a vector of parse trees.
-//                     Load qnodes with information to perform a topo sort
-//                     based on query dependencies.
-  vector<query_node *> qnodes;                         // for topo sort.
-  map<string,int> name_node_map;                       // map query name to qnodes entry
-  for(i=0;i<input_file_names.size();i++){
-
-         if((fta_in = fopen(input_file_names[i].c_str(), "r")) == NULL) {
-                 fprintf(stderr,"Can't open input file %s\n%s",input_file_names[i].c_str(),strerror(errno));
-                 continue;
-         }
-fprintf(stderr,"Parsing file %s\n",input_file_names[i].c_str());
-
-//                     Parse the FTA query
-         fta_parse_result = new fta_parse_t();
-         FtaParser_setfileinput(fta_in);
-         if(FtaParserparse()){
-               fprintf(stderr,"FTA parse failed.\n");
-               exit(1);
-         }
-         if(fta_parse_result->parse_type != QUERY_PARSE){
-               fprintf(stderr,"ERROR, file %s is not a query file.\n",input_file_names[i].c_str());
-               exit(1);
-         }
-
-//                     returns a list of parse trees
-         vector<table_exp_t *> qlist = fta_parse_result->parse_tree_list->qlist;
-         for(p=0;p<qlist.size();++p){
-           table_exp_t *fta_parse_tree = qlist[p];
-//             query_parse_trees.push_back(fta_parse_tree);
-
-//                     compute the default name -- extract from query name
-               strcpy(tmpstr,input_file_names[i].c_str());
-               char *qname = strrchr(tmpstr,PATH_DELIM);
-               if(qname == NULL)
-                       qname = tmpstr;
-               else
-                       qname++;
-               char *qname_end = strchr(qname,'.');
-               if(qname_end != NULL) *qname_end = '\0';
-               string qname_str = qname;
-               string imputed_qname = impute_query_name(fta_parse_tree, qname_str);
-
-//                     Deternmine visibility.  Should I be attaching all of the output methods?
-               if(qname_to_ospec.count(imputed_qname)>0)
-                       fta_parse_tree->set_visible(true);
-               else
-                       fta_parse_tree->set_visible(false);
-
-
-//                             Create a manipulable repesentation of the parse tree.
-//                             the qnode inherits the visibility assigned to the parse tree.
-           int pos = qnodes.size();
-               qnodes.push_back( new query_node(pos, imputed_qname, input_file_names[i], fta_parse_tree ));
-               name_node_map[ qnodes[pos]->name ] = pos;
-//printf("name_node_map[ %s ] = %d\n",qnodes[pos]->name.c_str(),pos);
-//             qnames.push_back(impute_query_name(fta_parse_tree, qname_str));
-//             qfiles.push_back(i);
-
-//                     Check for duplicate query names
-//                                     NOTE : in hfta-only generation, I should
-//                                     also check with the names of the registered queries.
-               if(qname_to_flname.count(qnodes[pos]->name) > 0){
-                       fprintf(stderr,"ERROR duplicate query name %s in files %s and %s.\n",
-                               qnodes[pos]->name.c_str(), (qname_to_flname[qnodes[pos]->name]).c_str(), input_file_names[i].c_str());
-                       exit(1);
-               }
-               if(Schema->find_tbl(qnodes[pos]->name) >= 0){
-                       fprintf(stderr,"ERROR duplicate query name %s (file %s) was already defined as a PROTOCOL.\n",
-                               qnodes[pos]->name.c_str(), input_file_names[i].c_str());
-                       exit(1);
-               }
-               qname_to_flname[qnodes[pos]->name] = input_file_names[i].c_str();
-
-
-       }
-  }
-
-//             Add the library queries
-
-  int pos;
-  for(pos=0;pos<qnodes.size();++pos){
-       int fi;
-       for(fi = 0;fi<qnodes[pos]->refd_tbls.size();++fi){
-               string src_tbl = qnodes[pos]->refd_tbls[fi];
-               if(qname_to_flname.count(src_tbl) == 0){
-                       int last_sep = src_tbl.find_last_of('/');
-                       if(last_sep != string::npos){
-fprintf(stderr,"Finding library query %s for query %s\n",src_tbl.c_str(),qnodes[pos]->name.c_str());
-                               string target_qname = src_tbl.substr(last_sep+1);
-                               string qpathname = library_path + src_tbl + ".gsql";
-                               if((fta_in = fopen(qpathname.c_str(), "r")) == NULL) {
-                                       fprintf(stderr,"Can't open library file %s, referenced by query %s in file %s\n\t%s\n",qpathname.c_str(),qnodes[pos]->name.c_str(), qname_to_flname[qnodes[pos]->name].c_str(), strerror(errno));
-                                       exit(1);
-                                       fprintf(stderr,"After exit\n");
-                               }
-fprintf(stderr,"Parsing file %s\n",qpathname.c_str());
-//                     Parse the FTA query
-                               fta_parse_result = new fta_parse_t();
-                               FtaParser_setfileinput(fta_in);
-                               if(FtaParserparse()){
-                                       fprintf(stderr,"FTA parse failed.\n");
-                                       exit(1);
-                               }
-                               if(fta_parse_result->parse_type != QUERY_PARSE){
-                                       fprintf(stderr,"ERROR, file %s is not a query file.\n",input_file_names[i].c_str());
-                                       exit(1);
-                               }
-
-                               map<string, int> local_query_map;
-                               vector<string> local_query_names;
-                               vector<table_exp_t *> qlist = fta_parse_result->parse_tree_list->qlist;
-                               for(p=0;p<qlist.size();++p){
-                               table_exp_t *fta_parse_tree = qlist[p];
-                                       fta_parse_tree->set_visible(false);             // assumed to not produce output
-                                       string imputed_qname = impute_query_name(fta_parse_tree, target_qname);
-                                       if(imputed_qname == target_qname)
-                                               imputed_qname = src_tbl;
-                                       if(local_query_map.count(imputed_qname)>0){
-                                               fprintf(stderr,"ERROR, multiple queries named %s in library file %s\n",imputed_qname.c_str(), qpathname.c_str());
-                                               exit(1);
-                                       }
-                                       local_query_map[ imputed_qname ] = p;
-                                       local_query_names.push_back(imputed_qname);
-                               }
-
-                               if(local_query_map.count(src_tbl)==0){
-                                       fprintf(stderr,"ERROR, library query file %s has no query named %s\n",qpathname.c_str(),target_qname.c_str());
-                                       exit(1);
-                               }
-
-                               vector<int> worklist;
-                               set<int> added_queries;
-                               vector<query_node *> new_qnodes;
-                               worklist.push_back(local_query_map[target_qname]);
-                               added_queries.insert(local_query_map[target_qname]);
-                               int qq;
-                               int qpos = qnodes.size();
-                               for(qq=0;qq<worklist.size();++qq){
-                                       int q_id = worklist[qq];
-                                       query_node *new_qnode = new query_node(qpos+qq, local_query_names[q_id], qpathname, qlist[q_id] );
-                                       new_qnodes.push_back( new_qnode);
-                                       vector<string> refd_tbls =  new_qnode->refd_tbls;
-                                       int ff;
-                                       for(ff = 0;ff<refd_tbls.size();++ff){
-                                               if(local_query_map.count(refd_tbls[ff])>0 && added_queries.count(local_query_map[refd_tbls[ff]])==0){
-
-                                                       if(name_node_map.count(refd_tbls[ff])>0){
-                                                               fprintf(stderr,"ERROR, query %s occurs both in the regular query set, file %s,  and in library file %s\n",refd_tbls[ff].c_str(), qname_to_flname[refd_tbls[ff]].c_str(), qpathname.c_str() );
-                                                               exit(1);
-                                                       }else{
-                                                               worklist.push_back(local_query_map[refd_tbls[ff]]);
-                                                       }
-                                               }
-                                       }
-                               }
-
-                               for(qq=0;qq<new_qnodes.size();++qq){
-                                       int qpos = qnodes.size();
-                                       qnodes.push_back(new_qnodes[qq]);
-                                       name_node_map[qnodes[qpos]->name ] = qpos;
-                                       qname_to_flname[qnodes[qpos]->name ] = qpathname;
-                               }
-                       }
-               }
-       }
-  }
-
-
-
-
-
-
-
-
-//---------------------------------------
-
-
-//             Add the UDOPS.
-
-  string udop_missing_sources;
-  for(i=0;i<qnodes.size();++i){
-       int fi;
-       for(fi = 0;fi<qnodes[i]->refd_tbls.size();++fi){
-               int sid = Schema->find_tbl(qnodes[i]->refd_tbls[fi]);
-               if(sid >= 0){
-                       if(Schema->get_schema_type(sid) == OPERATOR_VIEW_SCHEMA){
-                               if(name_node_map.count(qnodes[i]->refd_tbls[fi]) == 0){
-                               int pos = qnodes.size();
-                                       qnodes.push_back( new query_node(pos, qnodes[i]->refd_tbls[fi], Schema));
-                                       name_node_map[ qnodes[pos]->name ] = pos;
-                                       qnodes[pos]->is_externally_visible = false;   // its visible
-       //                                      Need to mark the source queries as visible.
-                                       int si;
-                                       string missing_sources = "";
-                                       for(si=0;si<qnodes[pos]->refd_tbls.size();++si){
-                                               string src_tbl = qnodes[pos]->refd_tbls[si];
-                                               if(name_node_map.count(src_tbl)==0){
-                                                       missing_sources += src_tbl + " ";
-                                               }
-                                       }
-                                       if(missing_sources != ""){
-                                               udop_missing_sources += "\tUDOP "+qnodes[pos]->name+" references undefined tables "+missing_sources+"\n";
-                                       }
-                               }
-                       }
-               }
-       }
-  }
-  if(udop_missing_sources != ""){
-       fprintf(stderr,"ERROR, User Defined OPerators reference source tables that are not part of the query set:\n%s",udop_missing_sources.c_str());
-       exit(1);
-  }
-
-
-
-////////////////////////////////////////////////////////////////////
-///                            Check parse trees to verify that some
-///                            global properties are met :
-///                            if q1 reads from q2, then
-///                              q2 is processed before q1
-///                              q1 can supply q2's parameters
-///                            Verify there is no cycle in the reads-from graph.
-
-//                     Compute an order in which to process the
-//                     queries.
-
-//                     Start by building the reads-from lists.
-//
-
-  for(i=0;i<qnodes.size();++i){
-       int qi, fi;
-       vector<string> refd_tbls =  qnodes[i]->refd_tbls;
-       for(fi = 0;fi<refd_tbls.size();++fi){
-               if(name_node_map.count(refd_tbls[fi])>0){
-//printf("query %d (%s) reads from %s (%d)\n", i, qnodes[i]->name.c_str(),refd_tbls[fi].c_str(),name_node_map[refd_tbls[fi]]);
-                       (qnodes[i]->reads_from).insert(name_node_map[refd_tbls[fi]]);
-               }
-       }
-  }
-
-
-//             If one query reads the result of another,
-//             check for parameter compatibility.  Currently it must
-//             be an exact match.  I will move to requiring
-//             containment after re-ordering, but will require
-//             some analysis for code generation which is not
-//             yet in place.
-//printf("There are %d query nodes.\n",qnodes.size());
-
-
-  for(i=0;i<qnodes.size();++i){
-       vector<var_pair_t *> target_params  = qnodes[i]->params;
-       for(si=qnodes[i]->reads_from.begin();si!=qnodes[i]->reads_from.end();++si){
-               vector<var_pair_t *> source_params  = qnodes[(*si)]->params;
-               if(target_params.size() != source_params.size()){
-                       fprintf(stderr,"ERROR, query %s (in file %s) reads from %s (in file %s), but they do not have identical parameters.\n",qnodes[i]->name.c_str(), qnodes[i]->file.c_str(), qnodes[(*si)]->name.c_str(), qnodes[(*si)]->file.c_str());
-                       exit(1);
-               }
-               int p;
-               for(p=0;p<target_params.size();++p){
-                       if(! (target_params[p]->name == source_params[p]->name &&
-                             target_params[p]->val == source_params[p]->val ) ){
-                       fprintf(stderr,"ERROR, query %s (in file %s) reads from %s (in file %s), but they do not have identical parameters.\n",qnodes[i]->name.c_str(), qnodes[i]->file.c_str(), qnodes[(*si)]->name.c_str(), qnodes[(*si)]->file.c_str());
-                               exit(1);
-                       }
-               }
-       }
-  }
-
-
-//             Find the roots.
-//             Start by counting inedges.
-  for(i=0;i<qnodes.size();++i){
-       for(si=qnodes[i]->reads_from.begin();si!=qnodes[i]->reads_from.end();++si){
-               qnodes[(*si)]->n_consumers++;
-       }
-  }
-
-//             The roots are the nodes with indegree zero.
-  set<int> roots;
-  for(i=0;i<qnodes.size();++i){
-       if(qnodes[i]->n_consumers == 0){
-               if(qnodes[i]->is_externally_visible == false){
-                       fprintf(stderr,"WARNING: query %s (file %s) is a root query but it isn't visible.  Ignored.\n",qnodes[i]->name.c_str(), qnodes[i]->file.c_str());
-               }
-               roots.insert(i);
-       }
-  }
-
-//             Remove the parts of the subtree that produce no output.
-  set<int> valid_roots;
-  set<int> discarded_nodes;
-  set<int> candidates;
-  while(roots.size() >0){
-       for(si=roots.begin();si!=roots.end();++si){
-               if(qnodes[(*si)]->is_externally_visible){
-                       valid_roots.insert((*si));
-               }else{
-                       discarded_nodes.insert((*si));
-                       set<int>::iterator sir;
-                       for(sir=qnodes[(*si)]->reads_from.begin(); sir!=qnodes[(*si)]->reads_from.end();++sir){
-                               qnodes[(*sir)]->n_consumers--;
-                               if(qnodes[(*sir)]->n_consumers == 0)
-                                       candidates.insert( (*sir));
-                       }
-               }
-       }
-       roots = candidates;
-       candidates.clear();
-  }
-  roots = valid_roots;
-  if(discarded_nodes.size()>0){
-       fprintf(stderr,"Warning, the following queries were discarded because they produce no output:\n");
-       int di = 0;
-       for(si=discarded_nodes.begin();si!=discarded_nodes.end();++si){
-               if(di>0 && (di%8)==0) fprintf(stderr,"\n");
-               di++;
-               fprintf(stderr," %s",qnodes[(*si)]->name.c_str());
-       }
-       fprintf(stderr,"\n");
-  }
-
-//             Compute the sources_to set, ignoring discarded nodes.
-  for(i=0;i<qnodes.size();++i){
-       if(discarded_nodes.count(i)==0)
-               for(si=qnodes[i]->reads_from.begin();si!=qnodes[i]->reads_from.end();++si){
-                       qnodes[(*si)]->sources_to.insert(i);
-       }
-  }
-
-
-//             Find the nodes that are shared by multiple visible subtrees.
-//             THe roots become inferred visible nodes.
-
-//             Find the visible nodes.
-       vector<int> visible_nodes;
-       for(i=0;i<qnodes.size();i++){
-               if(qnodes[i]->is_externally_visible){
-                       visible_nodes.push_back(i);
-               }
-       }
-
-//             Find UDOPs referenced by visible nodes.
-  list<int> workq;
-  for(i=0;i<visible_nodes.size();++i){
-       workq.push_back(visible_nodes[i]);
-  }
-  while(!workq.empty()){
-       int node = workq.front();
-       workq.pop_front();
-       set<int>::iterator children;
-       if(qnodes[node]->is_udop && qnodes[node]->is_externally_visible == false){
-               qnodes[node]->is_externally_visible = true;
-               visible_nodes.push_back(node);
-               for(children=qnodes[node]->reads_from.begin();children!=qnodes[node]->reads_from.end();++children){
-                       if(qnodes[(*children)]->is_externally_visible == false){
-                               qnodes[(*children)]->is_externally_visible = true;
-                               visible_nodes.push_back((*children));
-                       }
-               }
-       }
-       for(children=qnodes[node]->reads_from.begin();children!=qnodes[node]->reads_from.end();++children){
-               workq.push_back((*children));
-       }
-  }
-
-       bool done = false;
-       while(!done){
-//     reset the nodes
-               for(i=0;i<qnodes.size();i++){
-                       qnodes[i]->subtree_roots.clear();
-               }
-
-//             Walk the tree defined by a visible node, not descending into
-//             subtrees rooted by a visible node.  Mark the node visited with
-//             the visible node ID.
-               for(i=0;i<visible_nodes.size();++i){
-                       set<int> vroots;
-                       vroots.insert(visible_nodes[i]);
-                       while(vroots.size()>0){
-                               for(si=vroots.begin();si!=vroots.end();++si){
-                                       qnodes[(*si)]->subtree_roots.insert(visible_nodes[i]);
-
-                                       set<int>::iterator sir;
-                                       for(sir=qnodes[(*si)]->reads_from.begin(); sir!=qnodes[(*si)]->reads_from.end();++sir){
-                                               if(! qnodes[(*sir)]->is_externally_visible){
-                                                       candidates.insert( (*sir));
-                                               }
-                                       }
-                               }
-                               vroots = candidates;
-                               candidates.clear();
-                       }
-               }
-//             Find the nodes in multiple visible node subtrees, but with no parent
-//             that has is in multile visible node subtrees.  Mark these as inferred visible nodes.
-               done = true;    // until proven otherwise
-               for(i=0;i<qnodes.size();i++){
-                       if(qnodes[i]->subtree_roots.size()>1){
-                               bool is_new_root = true;
-                               set<int>::iterator sir;
-                               for(sir=qnodes[i]->sources_to.begin(); sir!=qnodes[i]->sources_to.end();++sir){
-                                       if(qnodes[(*sir)]->subtree_roots.size()>1)
-                                               is_new_root = false;
-                               }
-                               if(is_new_root){
-                                       qnodes[i]->is_externally_visible = true;
-                                       qnodes[i]->inferred_visible_node = true;
-                                       visible_nodes.push_back(i);
-                                       done = false;
-                               }
-                       }
-               }
-       }
-
-
-
-
-
-//             get visible nodes in topo ordering.
-//  for(i=0;i<qnodes.size();i++){
-//             qnodes[i]->n_consumers = qnodes[i]->sources_to.size();
-//  }
-  vector<int> process_order;
-  while(roots.size() >0){
-       for(si=roots.begin();si!=roots.end();++si){
-               if(discarded_nodes.count((*si))==0){
-                       process_order.push_back( (*si) );
-               }
-               set<int>::iterator sir;
-               for(sir=qnodes[(*si)]->reads_from.begin(); sir!=qnodes[(*si)]->reads_from.end();++sir){
-                       qnodes[(*sir)]->n_consumers--;
-                       if(qnodes[(*sir)]->n_consumers == 0)
-                               candidates.insert( (*sir));
-               }
-       }
-       roots = candidates;
-       candidates.clear();
-  }
-
-
-//printf("process_order.size() =%d\n",process_order.size());
-
-//             Search for cyclic dependencies
-  string found_dep;
-  for(i=0;i<qnodes.size();++i){
-       if(discarded_nodes.count(i)==0 && qnodes[i]->n_consumers > 0){
-               if(found_dep.size() != 0) found_dep += ", ";
-               found_dep += "query "+qnodes[i]->name+" (file "+qnodes[i]->file+")";
-       }
-  }
-  if(found_dep.size()>0){
-       fprintf(stderr,"ERROR, the following queries contain a cyclic reads-from dependency:\n%s\n",found_dep.c_str());
-       exit(1);
-  }
-
-//             Get a list of query sets, in the order to be processed.
-//             Start at visible root and do bfs.
-//             The query set includes queries referenced indirectly,
-//             as sources for user-defined operators.  These are needed
-//             to ensure that they are added to the schema, but are not part
-//             of the query tree.
-
-//             stream_node_sets contains queries reachable only through the
-//             FROM clause, so I can tell which queries to add to the stream
-//             query. (DISABLED, UDOPS are integrated, does this cause problems?)
-
-//                     NOTE: this code works because in order for data to be
-//                     read by multiple hftas, the node must be externally visible.
-//                     But visible nodes define roots of process sets.
-//                     internally visible nodes can feed data only
-//                     to other nodes in the same query file.
-//                     Therefore, any access can be restricted to a file,
-//                     hfta output sharing is done only on roots
-//                     never on interior nodes.
-
-
-
-
-//             Conpute the base collection of hftas.
-  vector<hfta_node *> hfta_sets;
-  map<string, int> hfta_name_map;
-//  vector< vector<int> > process_sets;
-//  vector< set<int> > stream_node_sets;
-  reverse(process_order.begin(), process_order.end());  // get listing in reverse order.
-                                                                                                               // i.e. process leaves 1st.
-  for(i=0;i<process_order.size();++i){
-       if(qnodes[process_order[i]]->is_externally_visible == true){
-//printf("Visible.\n");
-               int root = process_order[i];
-               hfta_node *hnode = new hfta_node();
-               hnode->name = qnodes[root]-> name;
-               hnode->source_name = qnodes[root]-> name;
-               hnode->is_udop = qnodes[root]->is_udop;
-               hnode->inferred_visible_node = qnodes[root]->inferred_visible_node;
-
-               vector<int> proc_list;  proc_list.push_back(root);
-//                     Ensure that nodes are added only once.
-               set<int> proc_set;      proc_set.insert(root);
-               roots.clear();                  roots.insert(root);
-               candidates.clear();
-               while(roots.size()>0){
-                       for(si=roots.begin();si!=roots.end();++si){
-//printf("Processing root %d\n",(*si));
-                               set<int>::iterator sir;
-                               for(sir=qnodes[(*si)]->reads_from.begin(); sir!=qnodes[(*si)]->reads_from.end();++sir){
-//printf("reads fom %d\n",(*sir));
-                                       if(qnodes[(*sir)]->is_externally_visible==false){
-                                               candidates.insert( (*sir) );
-                                               if(proc_set.count( (*sir) )==0){
-                                                       proc_set.insert( (*sir) );
-                                                       proc_list.push_back( (*sir) );
-                                               }
-                                       }
-                               }
-                       }
-                       roots = candidates;
-                       candidates.clear();
-               }
-
-               reverse(proc_list.begin(), proc_list.end());
-               hnode->query_node_indices = proc_list;
-               hfta_name_map[hnode->name] = hfta_sets.size();
-               hfta_sets.push_back(hnode);
-       }
-  }
-
-//             Compute the reads_from / sources_to graphs for the hftas.
-
-  for(i=0;i<hfta_sets.size();++i){
-       hfta_node *hnode = hfta_sets[i];
-       for(q=0;q<hnode->query_node_indices.size();q++){
-               query_node *qnode = qnodes[hnode->query_node_indices[q]];
-               for(s=0;s<qnode->refd_tbls.size();++s){
-                       if(hfta_name_map.count(qnode->refd_tbls[s])){
-                               int other_hfta = hfta_name_map[qnode->refd_tbls[s]];
-                               hnode->reads_from.insert(other_hfta);
-                               hfta_sets[other_hfta]->sources_to.insert(i);
-                       }
-               }
-       }
-  }
-
-//             Compute a topological sort of the hfta_sets.
-
-  vector<int> hfta_topsort;
-  workq.clear();
-  int hnode_srcs[hfta_sets.size()];
-  for(i=0;i<hfta_sets.size();++i){
-       hnode_srcs[i] = 0;
-       if(hfta_sets[i]->sources_to.size() == 0)
-               workq.push_back(i);
-  }
-
-  while(! workq.empty()){
-       int     node = workq.front();
-       workq.pop_front();
-       hfta_topsort.push_back(node);
-       set<int>::iterator stsi;
-       for(stsi=hfta_sets[node]->reads_from.begin();stsi!=hfta_sets[node]->reads_from.end();++stsi){
-               int parent = (*stsi);
-               hnode_srcs[parent]++;
-               if(hnode_srcs[parent] == hfta_sets[parent]->sources_to.size()){
-                       workq.push_back(parent);
-               }
-       }
-  }
-
-//             Decorate hfta nodes with the level of parallelism given as input.
-
-  map<string, int>::iterator msii;
-  for(msii=hfta_parallelism.begin();msii!=hfta_parallelism.end();++msii){
-       string hfta_name = (*msii).first;
-       int par = (*msii).second;
-       if(hfta_name_map.count(hfta_name) > 0){
-               hfta_sets[ hfta_name_map[hfta_name] ]->n_parallel = par;
-       }else{
-               fprintf(stderr,"Warning, hfta_parallelism.cfg has an entry for %s, but its not a hfta.\n",hfta_name.c_str());
-       }
-  }
-
-//             Propagate levels of parallelism: children should have a level of parallelism
-//             as large as any of its parents.  Adjust children upwards to compensate.
-//             Start at parents and adjust children, auto-propagation will occur.
-
-  for(i=hfta_sets.size()-1;i>=0;i--){
-       set<int>::iterator stsi;
-       for(stsi=hfta_sets[i]->reads_from.begin();stsi!=hfta_sets[i]->reads_from.end();++stsi){
-               if(hfta_sets[i]->n_parallel > hfta_sets[ (*stsi) ]->n_parallel){
-                       hfta_sets[ (*stsi) ]->n_parallel = hfta_sets[i]->n_parallel;
-               }
-       }
-  }
-
-//             Before all the name mangling, check if therey are any output_spec.cfg
-//             or hfta_parallelism.cfg entries that do not have a matching query.
-
-       string dangling_ospecs = "";
-       for(msii=qname_to_ospec.begin();msii!=qname_to_ospec.end();++msii){
-               string oq = (*msii).first;
-               if(hfta_name_map.count(oq) == 0){
-                       dangling_ospecs += " "+(*msii).first;
-               }
-       }
-       if(dangling_ospecs!=""){
-               fprintf(stderr,"WARNING, the following entries in output_spec.cfg don't have a matching query: %s\n",dangling_ospecs.c_str());
-       }
-
-       string dangling_par = "";
-       for(msii=hfta_parallelism.begin();msii!=hfta_parallelism.end();++msii){
-               string oq = (*msii).first;
-               if(hfta_name_map.count(oq) == 0){
-                       dangling_par += " "+(*msii).first;
-               }
-       }
-       if(dangling_par!=""){
-               fprintf(stderr,"WARNING, the following entries in hfta_parallelism.cfg don't have a matching query: %s\n",dangling_par.c_str());
-       }
-
-
-
-//             Replicate parallelized hftas.  Do __copyX name mangling.  Adjust
-//             FROM clauses: retarget any name which is an internal node, and
-//             any which is in hfta_sets (and which is parallelized). Add Merge nodes
-//             when the source hfta has more parallelism than the target node.
-//             Add new nodes to qnodes and hfta_nodes wth the appropriate linkages.
-
-
-  int n_original_hfta_sets = hfta_sets.size();
-  for(i=0;i<n_original_hfta_sets;++i){
-       if(hfta_sets[i]->n_parallel > 1){
-               hfta_sets[i]->do_generation =false;     // set the deletion flag for this entry.
-               set<string> local_nodes;                // names of query nodes in the hfta.
-               for(h=0;h<hfta_sets[i]->query_node_indices.size();++h){
-                       local_nodes.insert(qnodes[ hfta_sets[i]->query_node_indices[h] ]->name);
-               }
-
-               for(p=0;p<hfta_sets[i]->n_parallel;++p){
-                       string mangler = "__copy"+int_to_string(p);
-                       hfta_node *par_hfta  = new hfta_node();
-                       par_hfta->name = hfta_sets[i]->name + mangler;
-                       par_hfta->source_name = hfta_sets[i]->name;
-                       par_hfta->is_udop = hfta_sets[i]->is_udop;
-                       par_hfta->inferred_visible_node = hfta_sets[i]->inferred_visible_node;
-                       par_hfta->n_parallel = hfta_sets[i]->n_parallel;
-                       par_hfta->parallel_idx = p;
-
-                       map<string, int> par_qnode_map; // qnode name-to-idx, aids dependency tracking.
-
-//     Is it a UDOP?
-                       if(hfta_sets[i]->is_udop){
-                               int root = hfta_sets[i]->query_node_indices[0];
-
-                               string unequal_par_sources;
-                               set<int>::iterator rfsii;
-                               for(rfsii=hfta_sets[i]->reads_from.begin();rfsii!=hfta_sets[i]->reads_from.end();++rfsii){
-                                       if(hfta_sets[(*rfsii)]->n_parallel != par_hfta->n_parallel){
-                                               unequal_par_sources = hfta_sets[(*rfsii)]->name+" ("+int_to_string(hfta_sets[(*rfsii)]->n_parallel)+") ";
-                                       }
-                               }
-                               if(unequal_par_sources != ""){
-                                       fprintf(stderr,"ERROR, UDOP %s has parallelism %d, but some of its sources have a different parallelism: %s\n",hfta_sets[i]->name.c_str(), hfta_sets[i]->n_parallel, unequal_par_sources.c_str());
-                                       exit(1);
-                               }
-
-                               int rti;
-                               vector<string> new_sources;
-                               for(rti=0;rti<qnodes[root]->refd_tbls.size();++rti){
-                                       new_sources.push_back(qnodes[root]->refd_tbls[rti]+mangler);
-                               }
-
-                               query_node *new_qn = new query_node(qnodes.size(), qnodes[root]->name, Schema);
-                               new_qn->name += mangler;
-                               new_qn->mangler = mangler;
-                               new_qn->refd_tbls = new_sources;
-                               par_hfta->query_node_indices.push_back(qnodes.size());
-                               par_qnode_map[new_qn->name] = qnodes.size();
-                               name_node_map[ new_qn->name ] = qnodes.size();
-                               qnodes.push_back(new_qn);
-                       }else{
-//             regular query node
-                         for(h=0;h<hfta_sets[i]->query_node_indices.size();++h){
-                               int hqn_idx = hfta_sets[i]->query_node_indices[h];
-                               table_exp_t *dup_pt = dup_table_exp(qnodes[hqn_idx]->parse_tree);
-//                                     rehome the from clause on mangled names.
-//                                     create merge nodes as needed for external sources.
-                               for(f=0;f<dup_pt->fm->tlist.size();++f){
-                                       if(local_nodes.count(dup_pt->fm->tlist[f]->schema_name)>0){
-                                               dup_pt->fm->tlist[f]->schema_name += mangler;
-                                       }else if(hfta_name_map.count(dup_pt->fm->tlist[f]->schema_name)>0){
-//                     Ref's an external HFTA.  No parallelism => leave as is.  Else, if level of parallelism of the two hftas is the same, rename by the mangler.  Else, there mnust be more sources, so create a merge node.
-                                               int other_hidx = hfta_name_map[dup_pt->fm->tlist[f]->schema_name];
-                                               if(par_hfta->n_parallel == hfta_sets[other_hidx]->n_parallel){
-                                                       dup_pt->fm->tlist[f]->schema_name += mangler;
-                                               }else{
-                                                       vector<string> src_tbls;
-                                                       int stride = hfta_sets[other_hidx]->n_parallel / par_hfta->n_parallel;
-                                                       if(stride == 0){
-                                                               fprintf(stderr,"INTERNAL ERROR, parent hfta %s has a larger parallelism than its child %s\n",par_hfta->name.c_str(), hfta_sets[other_hidx]->name.c_str());
-                                                               exit(1);
-                                                       }
-                                                       for(s=0;s<stride;++s){
-                                                               string ext_src_name = hfta_sets[other_hidx]->name+"__copy"+int_to_string(s+stride*p);
-                                                               src_tbls.push_back(ext_src_name);
-                                                       }
-                                                       table_exp_t *merge_pt = table_exp_t::make_deferred_merge(src_tbls);
-                                                       string merge_node_name = qnodes[hqn_idx]->name+"__copy"+int_to_string(p)+"__merge"+int_to_string(f);
-                                                       dup_pt->fm->tlist[f]->schema_name = merge_node_name;
-//                                     Make a qnode to represent the new merge node
-                                                       query_node *qn_pt = new query_node(qnodes.size(),merge_node_name, qnodes[hqn_idx]->file,merge_pt);
-                                                       qn_pt->refd_tbls = src_tbls;
-                                                       qn_pt->is_udop  = false;
-                                                       qn_pt->is_externally_visible = false;
-                                                       qn_pt->inferred_visible_node  = false;
-                                                       par_hfta->query_node_indices.push_back(qnodes.size());
-                                                       par_qnode_map[merge_node_name] = qnodes.size();
-                                                       name_node_map[ merge_node_name ] = qnodes.size();
-                                                       qnodes.push_back(qn_pt);
-                                               }
-                                       }
-                               }
-                               query_node *new_qn = new query_node(qnodes.size(),qnodes[hqn_idx]->name+"__copy"+int_to_string(p),qnodes[hqn_idx]->file,dup_pt);
-                               for(f=0;f<dup_pt->fm->tlist.size();++f){
-                                       new_qn->refd_tbls.push_back(dup_pt->fm->tlist[f]->schema_name);
-                               }
-                               new_qn->params = qnodes[hqn_idx]->params;
-                               new_qn->is_udop = false;
-                               new_qn->is_externally_visible = qnodes[hqn_idx]->is_externally_visible;
-                               new_qn->inferred_visible_node = qnodes[hqn_idx]->inferred_visible_node;
-                               par_hfta->query_node_indices.insert(par_hfta->query_node_indices.begin(),qnodes.size());
-                               par_qnode_map[new_qn->name] = qnodes.size();
-                               name_node_map[ new_qn->name ] = qnodes.size();
-                               qnodes.push_back(new_qn);
-                         }
-                       }
-                       hfta_name_map[par_hfta->name] = hfta_sets.size();
-                       hfta_sets.push_back(par_hfta);
-               }
-       }else{
-//             This hfta isn't being parallelized, but add merge nodes for any parallelized
-//             hfta sources.
-               if(!hfta_sets[i]->is_udop){
-                 for(h=0;h<hfta_sets[i]->query_node_indices.size();++h){
-                       int hqn_idx = hfta_sets[i]->query_node_indices[h];
-                       for(f=0;f<qnodes[hqn_idx]->parse_tree->fm->tlist.size();++f){
-                               if(hfta_name_map.count(qnodes[hqn_idx]->parse_tree->fm->tlist[f]->schema_name)>0){
-//                     Ref's an external HFTA.  No parallelism => leave as is.  Else, if level of parallelism of the two hftas is the same, rename by the mangler.  Else, there mnust be more sources, so create a merge node.
-                                       int other_hidx = hfta_name_map[qnodes[hqn_idx]->parse_tree->fm->tlist[f]->schema_name];
-                                       if(hfta_sets[i]->n_parallel != hfta_sets[other_hidx]->n_parallel){
-                                               vector<string> src_tbls;
-                                               for(s=0;s<hfta_sets[other_hidx]->n_parallel;++s){
-                                                       string ext_src_name = hfta_sets[other_hidx]->name+"__copy"+int_to_string(s);
-                                                       src_tbls.push_back(ext_src_name);
-                                               }
-                                               table_exp_t *merge_pt = table_exp_t::make_deferred_merge(src_tbls);
-                                               string merge_node_name = qnodes[hqn_idx]->name+"__merge"+int_to_string(f);
-                                               qnodes[hqn_idx]->parse_tree->fm->tlist[f]->schema_name = merge_node_name;
-//                                     Make a qnode to represent the new merge node
-                                               query_node *qn_pt = new query_node(qnodes.size(),merge_node_name, qnodes[hqn_idx]->file,merge_pt);
-                                               qn_pt->refd_tbls = src_tbls;
-                                               qn_pt->is_udop  = false;
-                                               qn_pt->is_externally_visible = false;
-                                               qn_pt->inferred_visible_node  = false;
-                                               hfta_sets[i]->query_node_indices.insert(hfta_sets[i]->query_node_indices.begin(),qnodes.size());
-                                               name_node_map[ merge_node_name ] = qnodes.size();
-                                               qnodes.push_back(qn_pt);
-                                       }
-                               }
-                       }
-               }
-         }
-       }
-  }
-
-//                     Rebuild the reads_from / sources_to lists in the qnodes
-  for(q=0;q<qnodes.size();++q){
-       qnodes[q]->reads_from.clear();
-       qnodes[q]->sources_to.clear();
-  }
-  for(q=0;q<qnodes.size();++q){
-       for(s=0;s<qnodes[q]->refd_tbls.size();++s){
-               if(name_node_map.count(qnodes[q]->refd_tbls[s])>0){
-                       int rf = name_node_map[qnodes[q]->refd_tbls[s]];
-                       qnodes[q]->reads_from.insert(rf);
-                       qnodes[rf]->sources_to.insert(q);
-               }
-       }
-  }
-
-//                     Rebuild the reads_from / sources_to lists in hfta_sets
-  for(q=0;q<hfta_sets.size();++q){
-       hfta_sets[q]->reads_from.clear();
-       hfta_sets[q]->sources_to.clear();
-  }
-  for(q=0;q<hfta_sets.size();++q){
-       for(s=0;s<hfta_sets[q]->query_node_indices.size();++s){
-               int node = hfta_sets[q]->query_node_indices[s];
-               set<int>::iterator rfsii;
-               for(rfsii=qnodes[node]->reads_from.begin();rfsii!=qnodes[node]->reads_from.end();++rfsii){
-                       if(hfta_name_map.count(qnodes[(*rfsii)]->name)>0){
-                               hfta_sets[q]->reads_from.insert(hfta_name_map[qnodes[(*rfsii)]->name]);
-                               hfta_sets[hfta_name_map[qnodes[(*rfsii)]->name]]->sources_to.insert(q);
-                       }
-               }
-       }
-  }
-
-/*
-for(q=0;q<qnodes.size();++q){
- printf("qnode %d reads-from %d:",q,qnodes[q]->reads_from.size());
- set<int>::iterator rsii;
- for(rsii=qnodes[q]->reads_from.begin();rsii!=qnodes[q]->reads_from.end();++rsii)
-  printf(" %d",(*rsii));
-  printf(", and sources-to %d:",qnodes[q]->sources_to.size());
- for(rsii=qnodes[q]->sources_to.begin();rsii!=qnodes[q]->sources_to.end();++rsii)
-  printf(" %d",(*rsii));
- printf("\n");
-}
-
-for(q=0;q<hfta_sets.size();++q){
- if(hfta_sets[q]->do_generation==false)
-       continue;
- printf("hfta %d (%s) reads-from %d:",q,hfta_sets[q]->name.c_str(),hfta_sets[q]->reads_from.size());
- set<int>::iterator rsii;
- for(rsii=hfta_sets[q]->reads_from.begin();rsii!=hfta_sets[q]->reads_from.end();++rsii)
-  printf(" %d",(*rsii));
-  printf(", and sources-to %d:",hfta_sets[q]->sources_to.size());
- for(rsii=hfta_sets[q]->sources_to.begin();rsii!=hfta_sets[q]->sources_to.end();++rsii)
-  printf(" %d",(*rsii));
- printf("\n");
-}
-*/
-
-
-
-//             Re-topo sort the hftas
-  hfta_topsort.clear();
-  workq.clear();
-  int hnode_srcs_2[hfta_sets.size()];
-  for(i=0;i<hfta_sets.size();++i){
-       hnode_srcs_2[i] = 0;
-       if(hfta_sets[i]->sources_to.size() == 0 && hfta_sets[i]->do_generation){
-               workq.push_back(i);
-       }
-  }
-
-  while(workq.empty() == false){
-       int     node = workq.front();
-       workq.pop_front();
-       hfta_topsort.push_back(node);
-       set<int>::iterator stsii;
-       for(stsii=hfta_sets[node]->reads_from.begin();stsii!=hfta_sets[node]->reads_from.end();++stsii){
-               int child = (*stsii);
-               hnode_srcs_2[child]++;
-               if(hnode_srcs_2[child] == hfta_sets[child]->sources_to.size()){
-                       workq.push_back(child);
-               }
-       }
-  }
-
-//             Ensure that all of the query_node_indices in hfta_sets are topologically
-//             sorted, don't rely on assumptions that all transforms maintain some kind of order.
-  for(i=0;i<hfta_sets.size();++i){
-       if(hfta_sets[i]->do_generation){
-               map<int,int> n_accounted;
-               vector<int> new_order;
-               workq.clear();
-               vector<int>::iterator vii;
-               for(vii=hfta_sets[i]->query_node_indices.begin();vii!=hfta_sets[i]->query_node_indices.end();++vii){
-                       n_accounted[(*vii)]= 0;
-               }
-               for(vii=hfta_sets[i]->query_node_indices.begin();vii!=hfta_sets[i]->query_node_indices.end();++vii){
-                       set<int>::iterator rfsii;
-                       for(rfsii=qnodes[(*vii)]->reads_from.begin();rfsii!=qnodes[(*vii)]->reads_from.end();++rfsii){
-                               if(n_accounted.count((*rfsii)) == 0){
-                                       n_accounted[(*vii)]++;
-                               }
-                       }
-                       if(n_accounted[(*vii)] == qnodes[(*vii)]->reads_from.size()){
-                               workq.push_back((*vii));
-                       }
-               }
-
-               while(workq.empty() == false){
-                       int node = workq.front();
-                       workq.pop_front();
-                       new_order.push_back(node);
-                       set<int>::iterator stsii;
-                       for(stsii=qnodes[node]->sources_to.begin();stsii!=qnodes[node]->sources_to.end();++stsii){
-                               if(n_accounted.count((*stsii))){
-                                       n_accounted[(*stsii)]++;
-                                       if(n_accounted[(*stsii)] == qnodes[(*stsii)]->reads_from.size()){
-                                               workq.push_back((*stsii));
-                                       }
-                               }
-                       }
-               }
-               hfta_sets[i]->query_node_indices = new_order;
-       }
-  }
-
-
-
-
-
-///                    Global checkng is done, start the analysis and translation
-///                    of the query parse tree in the order specified by process_order
-
-
-//                     Get a list of the LFTAs for global lfta optimization
-//                             TODO: separate building operators from spliting lftas,
-//                                     that will make optimizations such as predicate pushing easier.
-       vector<stream_query *> lfta_list;
-
-       stream_query *rootq;
-
-    int qi,qj;
-
-       for(qi=hfta_topsort.size()-1;qi>=0;--qi){
-
-       int hfta_id = hfta_topsort[qi];
-    vector<int> curr_list = hfta_sets[hfta_id]->query_node_indices;
-
-
-
-//             Two possibilities, either its a UDOP, or its a collection of queries.
-//     if(qnodes[curr_list.back()]->is_udop)
-       if(hfta_sets[hfta_id]->is_udop){
-               int node_id = curr_list.back();
-               int udop_schref = Schema->find_tbl(qnodes[node_id]->file);
-               opview_entry *opv = new opview_entry();
-
-//                     Many of the UDOP properties aren't currently used.
-               opv->parent_qname = "no_parent";
-               opv->root_name = qnodes[node_id]->name;
-               opv->view_name = qnodes[node_id]->file;
-               opv->pos = qi;
-               sprintf(tmpstr,"%s_UDOP%d_%s",qnodes[node_id]->name.c_str(),qi,opv->view_name.c_str());
-               opv->udop_alias = tmpstr;
-               opv->mangler = qnodes[node_id]->mangler;
-
-               if(opv->mangler != ""){
-                       int new_udop_schref = Schema->add_duplicate_table(opv->view_name,opv->root_name);
-                       Schema->mangle_subq_names(new_udop_schref,opv->mangler);
-               }
-
-//                     This piece of code makes each hfta which referes to the same udop
-//                     reference a distinct running udop.  Do this at query optimization time?
-//             fmtbl->set_udop_alias(opv->udop_alias);
-
-               opv->exec_fl = Schema->get_op_prop(udop_schref, string("file"));
-               opv->liveness_timeout = atoi(Schema->get_op_prop(udop_schref, string("liveness_timeout")).c_str());
-
-               vector<subquery_spec *> subq = Schema->get_subqueryspecs(udop_schref);
-               int s,f,q;
-               for(s=0;s<subq.size();++s){
-//                             Validate that the fields match.
-                       subquery_spec *sqs = subq[s];
-                       string subq_name = sqs->name + opv->mangler;
-                       vector<field_entry *> flds = Schema->get_fields(subq_name);
-                       if(flds.size() == 0){
-                               fprintf(stderr,"INTERNAL ERROR: the subquery %s of view %s not found in Schema.\n",subq_name.c_str(), opv->view_name.c_str());
-                               return(1);
-                       }
-                       if(flds.size() < sqs->types.size()){
-                               fprintf(stderr,"ERROR: subquery %s of view %s does not have enough fields (%lu found, %lu expected).\n",subq_name.c_str(), opv->view_name.c_str(),flds.size(), sqs->types.size());
-                               return(1);
-                       }
-                       bool failed = false;
-                       for(f=0;f<sqs->types.size();++f){
-                               data_type dte(sqs->types[f],sqs->modifiers[f]);
-                               data_type dtf(flds[f]->get_type(),flds[f]->get_modifier_list());
-                               if(! dte.subsumes_type(&dtf) ){
-                                       fprintf(stderr,"ERROR: subquery %s of view %s does not have the correct type for field %d (%s found, %s expected).\n",subq_name.c_str(), opv->view_name.c_str(),f,dtf.to_string().c_str(), dte.to_string().c_str());
-                                       failed = true;
-                               }
-/*
-                               if(dte.is_temporal() && (dte.get_temporal() != dtf.get_temporal()) ){
-                                       string pstr = dte.get_temporal_string();
-                                       fprintf(stderr,"ERROR: subquery %s of view %s does not have the expected temporal value %s of field %d.\n",sqs->name.c_str(), opv->view_name.c_str(),pstr.c_str(),f);
-                                       failed = true;
-                               }
-*/
-                       }
-                       if(failed)
-                               return(1);
-///                            Validation done, find the subquery, make a copy of the
-///                            parse tree, and add it to the return list.
-                       for(q=0;q<qnodes.size();++q)
-                               if(qnodes[q]->name == subq_name)
-                                       break;
-                       if(q==qnodes.size()){
-                               fprintf(stderr,"INTERNAL ERROR: subquery %s of view %s not found in list of query names.\n",subq_name.c_str(), opv->view_name.c_str());
-                               return(1);
-                       }
-
-               }
-
-//                     Cross-link to from entry(s) in all sourced-to tables.
-               set<int>::iterator sii;
-               for(sii=qnodes[curr_list.back()]->sources_to.begin() ;sii!=qnodes[curr_list.back()]->sources_to.end();++sii){
-//printf("\tUDOP %s sources_to %d (%s)\n",hfta_sets[hfta_id]->name.c_str(),(*sii),hfta_sets[(*sii)]->name.c_str());
-                       vector<tablevar_t *> tblvars = qnodes[(*sii)]->parse_tree->get_from()->get_table_list();
-                       int ii;
-                       for(ii=0;ii<tblvars.size();++ii){
-                               if(tblvars[ii]->schema_name == opv->root_name){
-                                       tblvars[ii]->set_opview_idx(opviews.size());
-                               }
-
-                       }
-               }
-
-               opviews.append(opv);
-       }else{
-
-//                     Analyze the parse trees in this query,
-//                     put them in rootq
-//      vector<int> curr_list = process_sets[qi];
-
-
-////////////////////////////////////////
-
-         rootq = NULL;
-//printf("Process set %d, has %d queries\n",qi,curr_list.size());
-         for(qj=0;qj<curr_list.size();++qj){
-               i = curr_list[qj];
-       fprintf(stderr,"Processing query %s (file %s) is_udop = %d\n",qnodes[i]->name.c_str(), qnodes[i]->file.c_str(),qnodes[i]->is_udop);
-
-//                     Select the current query parse tree
-               table_exp_t *fta_parse_tree = qnodes[i]->parse_tree;
-
-//                     if hfta only, try to fetch any missing schemas
-//                     from the registry (using the print_schema program).
-//                     Here I use a hack to avoid analyzing the query -- all referenced
-//                     tables must be in the from clause
-//                     If there is a problem loading any table, just issue a warning,
-//
-               tablevar_list_t *fm = fta_parse_tree->get_from();
-               vector<string> refd_tbls =  fm->get_src_tbls(Schema);
-//                     iterate over all referenced tables
-               int t;
-               for(t=0;t<refd_tbls.size();++t){
-                 int tbl_ref = Schema->get_table_ref(refd_tbls[t]);
-
-                 if(tbl_ref < 0){      // if this table is not in the Schema
-
-                       if(hfta_only){
-                               string cmd="print_schema "+refd_tbls[t];
-                               FILE *schema_in = popen(cmd.c_str(), "r");
-                               if(schema_in == NULL){
-                                 fprintf(stderr,"ERROR: cannot execute command %s\n",cmd.c_str());
-                               }else{
-                                 string schema_instr;
-                                 while(fgets(tmpstr,TMPSTRLEN,schema_in)){
-                                       schema_instr += tmpstr;
-                                 }
-                         fta_parse_result = new fta_parse_t();
-                                 strcpy(tmp_schema_str,schema_instr.c_str());
-                                 FtaParser_setstringinput(tmp_schema_str);
-                         if(FtaParserparse()){
-                                       fprintf(stderr,"FTA parse failed on result from command %s.\n",cmd.c_str());
-                         }else{
-                                       if( fta_parse_result->tables != NULL){
-                                               int tl;
-                                               for(tl=0;tl<fta_parse_result->tables->size();++tl){
-                                                       Schema->add_table(fta_parse_result->tables->get_table(tl));
-                                               }
-                                       }else{
-                                               fprintf(stderr,"ERROR command %s returned no tables.\n",cmd.c_str());
-                                       }
-                               }
-                       }
-                 }else{
-                               fprintf(stderr,"ERROR, query %s (file %s) references stream %s, which is neither a PROTOCOL nor an externally visible query stream.\n", qnodes[i]->name.c_str(), qnodes[i]->file.c_str(), refd_tbls[t].c_str());
-                               exit(1);
-                 }
-
-               }
-         }
-
-
-//                             Analyze the query.
-         query_summary_class *qs = analyze_fta(fta_parse_tree, Schema, Ext_fcns, qnodes[i]->name);
-         if(qs == NULL){
-               fprintf(stderr,"analyze_fta failed on query %s (file %s) \n",qnodes[i]->name.c_str(),qnodes[i]->file.c_str());
-               exit(1);
-         }
-
-         stream_query new_sq(qs, Schema);
-         if(new_sq.error_code){
-                       fprintf(stderr,"ERROR, can't create query node for query %s (file %s):\n%s\n",qnodes[i]->name.c_str(),qnodes[i]->file.c_str(),new_sq.err_str.c_str());
-                       exit(1);
-         }
-
-//                     Add it to the Schema
-         table_def *output_td = new_sq.get_output_tabledef();
-         Schema->add_table(output_td);
-
-//                     Create a query plan from the analyzed parse tree.
-//                     If its a query referneced via FROM, add it to the stream query.
-         if(rootq){
-               rootq->add_query(new_sq);
-         }else{
-               rootq = new stream_query(new_sq);
-//                     have the stream query object inherit properties form the analyzed
-//                     hfta_node object.
-               rootq->set_nparallel(hfta_sets[hfta_id]->n_parallel,hfta_sets[hfta_id]->parallel_idx);
-               rootq->n_successors = hfta_sets[hfta_id]->sources_to.size();
-         }
-
-
-    }
-
-//             This stream query has all its parts
-//             Build and optimize it.
-//printf("translate_fta: generating plan.\n");
-       if(rootq->generate_plan(Schema)){
-               fprintf(stderr,"INTERNAL ERROR: Can't generate query plan for query %s.\n",rootq->query_name.c_str());
-               continue;
-       }
-
-//     If we've found the query plan head, so now add the output operators
-       if(qname_to_ospec.count(hfta_sets[hfta_id]->source_name)){
-               pair< multimap<string, int>::iterator, multimap<string, int>::iterator > oset;
-               multimap<string, int>::iterator mmsi;
-               oset = qname_to_ospec.equal_range(hfta_sets[hfta_id]->source_name);
-               for(mmsi=oset.first; mmsi!=oset.second; ++mmsi){
-                       rootq->add_output_operator(output_specs[(*mmsi).second]);
-               }
-       }
-
-
-
-//                             Perform query splitting if necessary.
-       bool hfta_returned;
-    vector<stream_query *> split_queries = rootq->split_query(Ext_fcns, Schema, hfta_returned, ifaces_db, n_virtual_interfaces, hfta_sets[hfta_id]->n_parallel, hfta_sets[hfta_id]->parallel_idx);
-
-       int l;
-//for(l=0;l<split_queries.size();++l){
-//printf("split query %d is %s\n",l,split_queries[l]->q`uery_name.c_str());
-//}
-
-
-
-
-    if(split_queries.size() > 0){      // should be at least one component.
-
-//                             Compute the number of LFTAs.
-         int n_lfta = split_queries.size();
-         if(hfta_returned) n_lfta--;
-
-
-//                             Process the LFTA components.
-         for(l=0;l<n_lfta;++l){
-          if(lfta_names.count(split_queries[l]->query_name) == 0){
-//                             Grab the lfta for global optimization.
-               vector<tablevar_t *> tvec =  split_queries[l]->query_plan[0]->get_input_tbls();
-               string liface = tvec[0]->get_interface();
-               string lmach = tvec[0]->get_machine();
-               if (lmach == "")
-                       lmach = hostname;
-               interface_names.push_back(liface);
-               machine_names.push_back(lmach);
-//printf("Machine is %s\n",lmach.c_str());
-
-//                     Set the ht size from the recommendation, if there is one in the rec file
-               if(lfta_htsize.count(split_queries[l]->query_name)>0){
-                       split_queries[l]->query_plan[0]->set_definition("aggregate_slots",int_to_string(lfta_htsize[split_queries[l]->query_name]));
-               }
-
-
-               lfta_names[split_queries[l]->query_name] = lfta_list.size();
-               split_queries[l]->set_gid(lfta_list.size());  // set lfta global id
-               lfta_list.push_back(split_queries[l]);
-               lfta_mach_lists[lmach].push_back(split_queries[l]);
-
-//                     THe following is a hack,
-//                     as I should be generating LFTA code through
-//                     the stream_query object.
-               split_queries[l]->query_plan[0]->bind_to_schema(Schema);
-//             split_queries[l]->query_plan[0]->definitions = split_queries[l]->defines;
-
-/*
-//                             Create query description to embed in lfta.c
-               string lfta_schema_str = split_queries[l]->make_schema();
-               string lfta_schema_embed = make_C_embedded_string(lfta_schema_str);
-
-//                             get NIC capabilities.
-               int erri;
-               nic_property *nicprop = NULL;
-               vector<string> iface_codegen_type = ifaces_db->get_iface_vals(lmach,liface,"iface_codegen_type",erri,err_str);
-               if(iface_codegen_type.size()){
-                       nicprop = npdb->get_nic_property(iface_codegen_type[0],erri);
-                       if(!nicprop){
-                               fprintf(stderr,"ERROR cannot load nic properties %s for interface %s of machine %s for lfta codegen\n",iface_codegen_type[0].c_str(), liface.c_str(), lmach.c_str());
-                                       exit(1);
-                       }
-               }
-
-               lfta_val[lmach] += generate_lfta_block(split_queries[l]->query_plan[0], Schema, split_queries[l]->get_gid(), Ext_fcns, lfta_schema_embed, ifaces_db,nicprop);
-*/
-
-               snap_lengths.push_back(compute_snap_len(split_queries[l]->query_plan[0], Schema));
-               query_names.push_back(split_queries[l]->query_name);
-               mach_query_names[lmach].push_back(query_names.size()-1);
-//                     NOTE: I will assume a 1-1 correspondance between
-//                     mach_query_names[lmach] and lfta_mach_lists[lmach]
-//                     where mach_query_names[lmach][i] contains the index into
-//                     query_names, which names the lfta, and
-//                     mach_query_names[lmach][i] is the stream_query * of the
-//                     corresponding lfta.
-//                     Later, lfta_iface_qnames are the query names matching lfta_iface_lists
-
-
-
-               // check if lfta is reusable
-               // FTA is reusable if reusable option is set explicitly or it doesn't have any parameters
-
-               bool lfta_reusable = false;
-               if (split_queries[l]->query_plan[0]->get_val_of_def("reusable") == "yes" ||
-                       split_queries[l]->query_plan[0]->get_param_tbl()->size() == 0) {
-                       lfta_reusable = true;
-               }
-               lfta_reuse_options.push_back(lfta_reusable);
-
-               // LFTA will inherit the liveness timeout specification from the containing query
-               // it is too conservative as lfta are expected to spend less time per tuple
-               // then full query
-
-               // extract liveness timeout from query definition
-               int liveness_timeout = atoi(split_queries[l]->query_plan[0]->get_val_of_def("liveness_timeout").c_str());
-               if (!liveness_timeout) {
-//                 fprintf(stderr, "WARNING: No liveness timeout specified for lfta %s, using default value of %d\n",
-//                   split_queries[l]->query_name.c_str(), DEFAULT_UDOP_LIVENESS_TIMEOUT);
-                   liveness_timeout = DEFAULT_UDOP_LIVENESS_TIMEOUT;
-               }
-               lfta_liveness_timeouts.push_back(liveness_timeout);
-
-//                     Add it to the schema
-               table_def *td = split_queries[l]->get_output_tabledef();
-               Schema->append_table(td);
-//printf("added lfta %d (%s)\n",l,split_queries[l]->query_name.c_str());
-
-         }
-        }
-
-//                             If the output is lfta-only, dump out the query name.
-      if(split_queries.size() == 1 && !hfta_returned){
-        if(output_query_names ){
-           fprintf(query_name_output,"%s L\n",split_queries[0]->query_name.c_str());
-               }
-/*
-else{
-           fprintf(stderr,"query name is %s\n",split_queries[0]->query_name.c_str());
-               }
-*/
-
-/*
-//                             output schema summary
-               if(output_schema_summary){
-                       dump_summary(split_queries[0]);
-               }
-*/
-      }
-
-
-         if(hfta_returned){            // query also has an HFTA component
-               int hfta_nbr = split_queries.size()-1;
-
-                       hfta_list.push_back(split_queries[hfta_nbr]);
-
-//                                     report on generated query names
-        if(output_query_names){
-                       string hfta_name =split_queries[hfta_nbr]->query_name;
-               fprintf(query_name_output,"%s H\n",hfta_name.c_str());
-                       for(l=0;l<hfta_nbr;++l){
-                               string lfta_name =split_queries[l]->query_name;
-                       fprintf(query_name_output,"%s L\n",lfta_name.c_str());
-                       }
-               }
-//             else{
-//             fprintf(stderr,"query names are ");
-//                     for(l=0;l<hfta_nbr;++l){
-//                             if(l>0) fprintf(stderr,",");
-//                             string fta_name =split_queries[l]->query_name;
-//                     fprintf(stderr," %s",fta_name.c_str());
-//                     }
-//                     fprintf(stderr,"\n");
-//             }
-         }
-
-  }else{
-         fprintf(stderr,"ERROR, query in file %s has a bug.\n",qnodes[i]->file.c_str());
-         fprintf(stderr,"%s\n",rootq->get_error_str().c_str());
-         exit(1);
-  }
- }
-}
-
-
-//-----------------------------------------------------------------
-//             Compute and propagate the SE in PROTOCOL fields compute a field.
-//-----------------------------------------------------------------
-
-for(i=0;i<lfta_list.size();i++){
-       lfta_list[i]->generate_protocol_se(sq_map, Schema);
-       sq_map[lfta_list[i]->get_sq_name()] = lfta_list[i];
-}
-for(i=0;i<hfta_list.size();i++){
-       hfta_list[i]->generate_protocol_se(sq_map, Schema);
-       sq_map[hfta_list[i]->get_sq_name()] = hfta_list[i];
-}
-
-
-
-//------------------------------------------------------------------------
-//             Perform  individual FTA optimizations
-//-----------------------------------------------------------------------
-
-if (partitioned_mode) {
-
-       // open partition definition file
-       string part_fname = config_dir_path + "partition.txt";
-
-       FILE* partfd = fopen(part_fname.c_str(), "r");
-       if (!partfd) {
-               fprintf(stderr,"ERROR, unable to open partition definition file %s\n",part_fname.c_str());
-               exit(1);
-       }
-       PartnParser_setfileinput(partfd);
-       if (PartnParserparse()) {
-               fprintf(stderr,"ERROR, unable to parse partition definition file %s\n",part_fname.c_str());
-               exit(1);
-       }
-       fclose(partfd);
-}
-
-
-print_hftas("preopt_hfta_info.txt", hfta_list, lfta_names, query_names, interface_names);
-
-int num_hfta = hfta_list.size();
-for(i=0; i < hfta_list.size(); ++i){
-       hfta_list[i]->optimize(hfta_list, lfta_names, interface_names, machine_names, Ext_fcns, Schema, ifaces_db, partn_parse_result);
-}
-
-//                     Add all new hftas to schema
-for(i=num_hfta; i < hfta_list.size(); ++i){
-               table_def *td = hfta_list[i]->get_output_tabledef();
-               Schema->append_table(td);
-}
-
-print_hftas("postopt_hfta_info.txt", hfta_list, lfta_names, query_names, interface_names);
-
-
-
-//------------------------------------------------------------------------
-//             Do global (cross-fta) optimization
-//-----------------------------------------------------------------------
-
-
-
-
-
-
-set<string> extra_external_libs;
-
-for(i=0;i<hfta_list.size();++i){               // query also has an HFTA component
-
-               if(! debug_only){
-//                                     build hfta file name, create output
-           if(numeric_hfta_flname){
-            sprintf(tmpstr,"hfta_%d",hfta_count);
-                       hfta_names.push_back(tmpstr);
-            sprintf(tmpstr,"hfta_%d.cc",hfta_count);
-         }else{
-            sprintf(tmpstr,"hfta_%s",hfta_list[i]->query_name.c_str());
-                       hfta_names.push_back(tmpstr);
-            sprintf(tmpstr,"hfta_%s.cc",hfta_list[i]->query_name.c_str());
-          }
-                 FILE *hfta_fl = fopen(tmpstr,"w");
-                 if(hfta_fl == NULL){
-                       fprintf(stderr,"ERROR can't open fta output file %s\n",tmpstr);
-                       exit(1);
-                 }
-                 fprintf(hfta_fl,"%s\n\n",hfta_list[i]->generate_hfta(Schema, Ext_fcns, opviews, distributed_mode).c_str());
-
-//                     If there is a field verifier, warn about
-//                     lack of compatability
-//                             NOTE : this code assumes that visible non-lfta queries
-//                             are those at the root of a stream query.
-                 string hfta_comment;
-                 string hfta_title;
-                 string hfta_namespace;
-                 if(hfta_list[i]->defines.count("comment")>0)
-                       hfta_comment = hfta_list[i]->defines["comment"];
-                 if(hfta_list[i]->defines.count("Comment")>0)
-                       hfta_comment = hfta_list[i]->defines["Comment"];
-                 if(hfta_list[i]->defines.count("COMMENT")>0)
-                       hfta_comment = hfta_list[i]->defines["COMMENT"];
-                 if(hfta_list[i]->defines.count("title")>0)
-                       hfta_title = hfta_list[i]->defines["title"];
-                 if(hfta_list[i]->defines.count("Title")>0)
-                       hfta_title = hfta_list[i]->defines["Title"];
-                 if(hfta_list[i]->defines.count("TITLE")>0)
-                       hfta_title = hfta_list[i]->defines["TITLE"];
-                 if(hfta_list[i]->defines.count("namespace")>0)
-                       hfta_namespace = hfta_list[i]->defines["namespace"];
-                 if(hfta_list[i]->defines.count("Namespace")>0)
-                       hfta_namespace = hfta_list[i]->defines["Namespace"];
-                 if(hfta_list[i]->defines.count("Namespace")>0)
-                       hfta_namespace = hfta_list[i]->defines["Namespace"];
-
-                 if(field_verifier != NULL){
-                       string warning_str;
-                       if(hfta_comment == "")
-                               warning_str += "\tcomment not found.\n";
-                       if(hfta_title == "")
-                               warning_str += "\ttitle not found.\n";
-                       if(hfta_namespace == "")
-                               warning_str += "\tnamespace not found.\n";
-
-                       vector<field_entry *> flds = hfta_list[i]->get_output_tabledef()->get_fields();
-                       int fi;
-                       for(fi=0;fi<flds.size();fi++){
-                               field_verifier->verify_field(flds[fi]->get_name(),flds[fi]->get_type(),warning_str);
-                       }
-                       if(warning_str != "")
-                               fprintf(stderr,"Warning, in HFTA stream %s:\n%s",
-                                       hfta_list[i]->get_output_tabledef()->get_tbl_name().c_str(),warning_str.c_str());
-                 }
-
-                 fprintf(qtree_output,"\t<HFTA name='%s'>\n",hfta_list[i]->get_output_tabledef()->get_tbl_name().c_str());
-                 if(hfta_comment != "")
-                       fprintf(qtree_output,"\t\t<Description value='%s' />\n",hfta_comment.c_str());
-                 if(hfta_title != "")
-                       fprintf(qtree_output,"\t\t<Title value='%s' />\n",hfta_title.c_str());
-                 if(hfta_namespace != "")
-                       fprintf(qtree_output,"\t\t<Namespace value='%s' />\n",hfta_namespace.c_str());
-                 fprintf(qtree_output,"\t\t<FileName value='%s' />\n",tmpstr);
-                 fprintf(qtree_output,"\t\t<Rate value='100' />\n");
-
-//                             write info about fields to qtree.xml
-                 vector<field_entry *> flds = hfta_list[i]->get_output_tabledef()->get_fields();
-                 int fi;
-                 for(fi=0;fi<flds.size();fi++){
-                       fprintf(qtree_output,"\t\t<Field name='%s' pos='%d' type='%s' ",flds[fi]->get_name().c_str(), fi, flds[fi]->get_type().c_str());
-                       if(flds[fi]->get_modifier_list()->size()){
-                               fprintf(qtree_output,"mods='%s' ", flds[fi]->get_modifier_list()->to_string().c_str());
-                       }
-                       fprintf(qtree_output," />\n");
-                 }
-
-                 // extract liveness timeout from query definition
-                 int liveness_timeout = atoi(hfta_list[i]->query_plan[hfta_list[i]->qhead]->get_val_of_def("liveness_timeout").c_str());
-                 if (!liveness_timeout) {
-//                 fprintf(stderr, "WARNING: No liveness timeout specified for hfta %s, using default value of %d\n",
-//                   hfta_list[i]->get_output_tabledef()->get_tbl_name().c_str(), DEFAULT_UDOP_LIVENESS_TIMEOUT);
-                   liveness_timeout = DEFAULT_UDOP_LIVENESS_TIMEOUT;
-                 }
-                 fprintf(qtree_output,"\t\t<LivenessTimeout value='%d' />\n", liveness_timeout);
-
-                 vector<tablevar_t *> tmp_tv = hfta_list[i]->get_input_tables();
-                 int itv;
-                 for(itv=0;itv<tmp_tv.size();++itv){
-                       fprintf(qtree_output,"\t\t<ReadsFrom value='%s' />\n",tmp_tv[itv]->get_schema_name().c_str());
-                 }
-                 string ifrs = hfta_list[i]->collect_refd_ifaces();
-                 if(ifrs != ""){
-                       fprintf(qtree_output,"\t\t<Ifaces_referenced value='%s'/>\n",ifrs.c_str());
-                 }
-                 fprintf(qtree_output,"\t</HFTA>\n");
-
-                 fclose(hfta_fl);
-               }else{
-//                                     debug only -- do code generation to catch generation-time errors.
-                 hfta_list[i]->generate_hfta(Schema, Ext_fcns,opviews, distributed_mode);
-               }
-
-               hfta_count++;   // for hfta file names with numeric suffixes
-
-               hfta_list[i]->get_external_libs(extra_external_libs);
-
-         }
-
-string ext_lib_string;
-set<string>::iterator ssi_el;
-for(ssi_el=extra_external_libs.begin();ssi_el!=extra_external_libs.end();++ssi_el)
-       ext_lib_string += (*ssi_el)+" ";
-
-
-
-//                     Report on the set of operator views
-  for(i=0;i<opviews.size();++i){
-       opview_entry *opve = opviews.get_entry(i);
-       fprintf(qtree_output,"\t<UDOP name='%s' >\n",opve->view_name.c_str());
-       fprintf(qtree_output,"\t\t<FileName value='%s' />\n",opve->exec_fl.c_str());
-       fprintf(qtree_output,"\t\t<Parent value='%s' />\n",opve->root_name.c_str());
-       fprintf(qtree_output,"\t\t<Alias value='%s' />\n",opve->udop_alias.c_str());
-       fprintf(qtree_output,"\t\t<Rate value='100' />\n");
-
-       if (!opve->liveness_timeout) {
-//             fprintf(stderr, "WARNING: No liveness timeout specified for view %s, using default value of %d\n",
-//                     opve->view_name.c_str(), DEFAULT_UDOP_LIVENESS_TIMEOUT);
-               opve->liveness_timeout = DEFAULT_UDOP_LIVENESS_TIMEOUT;
-       }
-       fprintf(qtree_output,"\t\t<LivenessTimeout value='%d' />\n", opve->liveness_timeout);
-    int j;
-       for(j=0;j<opve->subq_names.size();j++)
-               fprintf(qtree_output,"\t\t<ReadsFrom value='%s' />\n",opve->subq_names[j].c_str());
-       fprintf(qtree_output,"\t</UDOP>\n");
-  }
-
-
-//-----------------------------------------------------------------
-
-//                     Create interface-specific meta code files.
-//                             first, open and parse the interface resources file.
-       ifaces_db = new ifq_t();
-    ierr = "";
-       if(ifaces_db->load_ifaces(ifx_fname,use_live_hosts_file,distributed_mode,ierr)){
-               fprintf(stderr,"ERROR, can't load interface resource file %s :\n%s",
-                               ifx_fname.c_str(), ierr.c_str());
-               exit(1);
-       }
-
-       map<string, vector<stream_query *> >::iterator svsi;
-       for(svsi=lfta_mach_lists.begin(); svsi!=lfta_mach_lists.end(); ++svsi){
-               string lmach = (*svsi).first;
-
-       //              For this machine, create a set of lftas per interface.
-               vector<stream_query *> mach_lftas = (*svsi).second;
-               map<string, vector<stream_query *> > lfta_iface_lists;
-               int li;
-               for(li=0;li<mach_lftas.size();++li){
-                       vector<tablevar_t *> tvec =  mach_lftas[li]->query_plan[0]->get_input_tbls();
-                       string lfta_iface = tvec[0]->get_interface();
-                       lfta_iface_lists[lfta_iface].push_back(mach_lftas[li]);
-               }
-
-               map<string, vector<stream_query *> >::iterator lsvsi;
-               for(lsvsi=lfta_iface_lists.begin(); lsvsi!=lfta_iface_lists.end(); ++lsvsi){
-                       int erri;
-                       string liface = (*lsvsi).first;
-                       vector<stream_query *> iface_lftas = (*lsvsi).second;
-                       vector<string> iface_codegen_type = ifaces_db->get_iface_vals(lmach,liface,"iface_codegen_type",erri,err_str);
-                       if(iface_codegen_type.size()){
-                               nic_property *nicprop = npdb->get_nic_property(iface_codegen_type[0],erri);
-                               if(!nicprop){
-                                       fprintf(stderr,"ERROR cannot load nic properties %s for interface %s of machine %s\n",iface_codegen_type[0].c_str(), liface.c_str(), lmach.c_str());
-                                       exit(1);
-                               }
-                               string mcs = generate_nic_code(iface_lftas, nicprop);
-                               string mcf_flnm;
-                               if(lmach != "")
-                                 mcf_flnm = lmach + "_"+liface+".mcf";
-                               else
-                                 mcf_flnm = hostname + "_"+liface+".mcf";
-                               FILE *mcf_fl ;
-                               if((mcf_fl = fopen(mcf_flnm.c_str(),"w")) == NULL){
-                                       fprintf(stderr,"Can't open output file %s\n%s\n",mcf_flnm.c_str(),strerror(errno));
-                                       exit(1);
-                               }
-                               fprintf(mcf_fl,"%s",mcs.c_str());
-                               fclose(mcf_fl);
-//printf("mcs of machine %s, iface %s of type %s is \n%s\n",
-//lmach.c_str(), liface.c_str(),iface_codegen_type[0].c_str(), mcs.c_str());
-                       }
-               }
-
-
-       }
-
-
-
-//-----------------------------------------------------------------
-
-
-//                     Find common filter predicates in the LFTAs.
-//                     in addition generate structs to store the temporal attributes unpacked by prefilter
-       
-       map<string, vector<stream_query *> >::iterator ssqi;
-       for(ssqi=lfta_mach_lists.begin(); ssqi!=lfta_mach_lists.end(); ++ssqi){
-
-               string lmach = (*ssqi).first;
-               bool packed_return = false;
-               int li, erri;
-
-
-//     The LFTAs of this machine.
-               vector<stream_query *> mach_lftas = (*ssqi).second;
-//     break up on a per-interface basis.
-               map<string, vector<stream_query *> > lfta_iface_lists;
-               map<string, vector<int> > lfta_iface_qname_ix; // need the query name
-                                                        // for fta_init
-               for(li=0;li<mach_lftas.size();++li){
-                       vector<tablevar_t *> tvec =  mach_lftas[li]->query_plan[0]->get_input_tbls();
-                       string lfta_iface = tvec[0]->get_interface();
-                       lfta_iface_lists[lfta_iface].push_back(mach_lftas[li]);
-                       lfta_iface_qname_ix[lfta_iface].push_back(mach_query_names[lmach][li]);
-               }
-
-
-//     Are the return values "packed"?
-//     This should be done on a per-interface basis.
-//     But this is defunct code for gs-lite
-               for(li=0;li<mach_lftas.size();++li){
-                 vector<tablevar_t *> tvec =  mach_lftas[li]->query_plan[0]->get_input_tbls();
-                 string liface = tvec[0]->get_interface();
-                 vector<string> iface_codegen_type = ifaces_db->get_iface_vals(lmach,liface,"iface_codegen_type",erri,err_str);
-                 if(iface_codegen_type.size()){
-                       if(npdb->get_nic_prop_val(iface_codegen_type[0],"Return",erri) == "Packed"){
-                         packed_return = true;
-                       }
-                 }
-               }
-
-
-// Separate lftas by interface, collect results on a per-interface basis.
-
-               vector<cnf_set *> no_preds;     // fallback if there is no prefilter
-               map<string, vector<cnf_set *> > prefilter_preds;
-               set<unsigned int> pred_ids;     // this can be global for all interfaces
-               for(auto mvsi=lfta_iface_lists.begin(); mvsi!=lfta_iface_lists.end(); ++mvsi){
-                       string liface = (*mvsi).first;
-                       vector<cnf_set *> empty_list;
-                       prefilter_preds[liface] = empty_list;
-                       if(! packed_return){
-                               get_common_lfta_filter(lfta_iface_lists[liface], Schema,Ext_fcns, prefilter_preds[liface], pred_ids);
-                       }
-
-//                             get NIC capabilities.  (Is this needed?)
-                       nic_property *nicprop = NULL;
-                       vector<string> iface_codegen_type = ifaces_db->get_iface_vals(lmach,liface,"iface_codegen_type",erri,err_str);
-                       if(iface_codegen_type.size()){
-                               nicprop = npdb->get_nic_property(iface_codegen_type[0],erri);
-                               if(!nicprop){
-                                       fprintf(stderr,"ERROR cannot load nic properties %s for interface %s of machine %s for lfta codegen\n",iface_codegen_type[0].c_str(), liface.c_str(), lmach.c_str());
-                                       exit(1);
-                               }
-                       }
-               }
-
-
-//             Now that we know the prefilter preds, generate the lfta code.
-//     Do this for all lftas in this machine.
-               for(li=0;li<mach_lftas.size();++li){
-                       set<unsigned int> subsumed_preds;
-                       set<unsigned int>::iterator sii;
-#ifdef PREFILTER_OK
-                       for(sii=pred_ids.begin();sii!=pred_ids.end();++sii){
-                               int pid = (*sii);
-                               if((pid>>16) == li){
-                                       subsumed_preds.insert(pid & 0xffff);
-                               }
-                       }
-#endif
-                       string lfta_schema_str = mach_lftas[li]->make_schema();
-                       string lfta_schema_embed = make_C_embedded_string(lfta_schema_str);
-                       nic_property *nicprop = NULL; // no NIC properties?
-                       lfta_val[lmach] += generate_lfta_block(mach_lftas[li]->query_plan[0], Schema, mach_lftas[li]->get_gid(), Ext_fcns, lfta_schema_embed, ifaces_db,nicprop,subsumed_preds);
-               }
-
-
-//                     generate structs to store the temporal attributes
-//                     unpacked by prefilter
-               col_id_set temp_cids;
-               get_prefilter_temporal_cids(lfta_mach_lists[lmach], temp_cids);
-               lfta_prefilter_val[lmach] = generate_lfta_prefilter_struct(temp_cids, Schema);
-
-//                     Compute the lfta bit signatures and the lfta colrefs
-//     do this on a per-interface basis
-#ifdef PREFILTER_OK
-                       lfta_prefilter_val[lmach] += "#define PREFILTER_DEFINED 1;\n\n";
-#endif
-               map<string, vector<long long int> > lfta_sigs; // used again later
-               for(auto mvsi=lfta_iface_lists.begin(); mvsi!=lfta_iface_lists.end(); ++mvsi){
-                       string liface = (*mvsi).first;
-                       vector<long long int> empty_list;
-                       lfta_sigs[liface] = empty_list;
-
-                       vector<col_id_set> lfta_cols;
-                       vector<int> lfta_snap_length;
-                       for(li=0;li<lfta_iface_lists[liface].size();++li){
-                               unsigned long long int mask=0, bpos=1;
-                               int f_pos;
-                               for(f_pos=0;f_pos<prefilter_preds[liface].size();++f_pos){
-                                       if(prefilter_preds[liface][f_pos]->lfta_id.count(li))
-                                               mask |= bpos;
-                                       bpos = bpos << 1;
-                               }
-                               lfta_sigs[liface].push_back(mask);
-                               lfta_cols.push_back(lfta_iface_lists[liface][li]->query_plan[0]->get_colrefs(true,Schema));
-                               lfta_snap_length.push_back(compute_snap_len(lfta_iface_lists[liface][li]->query_plan[0], Schema));
-                       }
-
-//for(li=0;li<mach_lftas.size();++li){
-//printf("lfta %d, msak is %llu\n",li,lfta_sigs[li]);
-//col_id_set::iterator tcisi;
-//for(tcisi=lfta_cols[li].begin(); tcisi!=lfta_cols[li].end();++tcisi){
-//printf("\t%s %d (%d)\n",(*tcisi).field.c_str(),(*tcisi).schema_ref, (*tcisi).tblvar_ref);
-//}
-//}
-
-
-//                     generate the prefilter
-//     Do this on a per-interface basis, except for the #define
-#ifdef PREFILTER_OK
-//                     lfta_prefilter_val[lmach] += "#define PREFILTER_DEFINED 1;\n\n";
-                       lfta_val[lmach] += generate_lfta_prefilter(prefilter_preds[liface], temp_cids, Schema, Ext_fcns, lfta_cols, lfta_sigs[liface], lfta_snap_length, liface);
-#else
-                       lfta_val[lmach] += generate_lfta_prefilter(no_preds, temp_cids, Schema,Ext_fcns,  lfta_cols, lfta_sigs[liface], lfta_snap_length, liface);
-
-#endif
-               }
-
-//                     Generate interface parameter lookup function
-         lfta_val[lmach] += "// lookup interface properties by name\n";
-         lfta_val[lmach] += "// mulitple values of given property returned in the same string separated by commas\n";
-         lfta_val[lmach] += "// returns NULL if given property does not exist\n";
-         lfta_val[lmach] += "gs_sp_t get_iface_properties (const gs_sp_t iface_name, const gs_sp_t property_name) {\n";
-
-//       collect a lit of interface names used by queries running on this host
-         set<std::string> iface_names;
-         for(i=0;i<mach_query_names[lmach].size();i++){
-               int mi = mach_query_names[lmach][i];
-               stream_query *lfta_sq = lfta_mach_lists[lmach][i];
-
-               if(interface_names[mi]=="")
-                       iface_names.insert("DEFAULTDEV");
-               else
-                       iface_names.insert(interface_names[mi]);
-         }
-
-//       generate interface property lookup code for every interface
-         set<std::string>::iterator sir;
-         for (sir = iface_names.begin(); sir != iface_names.end(); sir++) {
-               if (sir == iface_names.begin())
-                       lfta_val[lmach] += "\tif (!strcmp(iface_name, \"" + *sir + "\")) {\n";
-               else
-                       lfta_val[lmach] += "\t} else if (!strcmp(iface_name, \"" + *sir + "\")) {\n";
-
-               // iterate through interface properties
-               vector<string> iface_properties = ifaces_db->get_iface_properties(lmach,*sir,erri,err_str);
-               if (erri) {
-                       fprintf(stderr,"ERROR cannot retrieve interface properties for %s.%s, %s\n",lmach.c_str(), sir->c_str(), err_str.c_str());
-                       exit(1);
-               }
-               if (iface_properties.empty())
-                       lfta_val[lmach] += "\t\treturn NULL;\n";
-               else {
-                       for (int i = 0; i < iface_properties.size(); ++i) {
-                               if (i == 0)
-                                       lfta_val[lmach] += "\t\tif (!strcmp(property_name, \"" + iface_properties[i] + "\")) {\n";
-                               else
-                                       lfta_val[lmach] += "\t\t} else if (!strcmp(property_name, \"" + iface_properties[i] + "\")) {\n";
-
-                               // combine all values for the interface property using comma separator
-                               vector<string> vals = ifaces_db->get_iface_vals(lmach,*sir,iface_properties[i],erri,err_str);
-                               for (int j = 0; j < vals.size(); ++j) {
-                                       lfta_val[lmach] += "\t\t\treturn \"" + vals[j];
-                                       if (j != vals.size()-1)
-                                               lfta_val[lmach] += ",";
-                               }
-                               lfta_val[lmach] += "\";\n";
-                       }
-                       lfta_val[lmach] += "\t\t} else\n";
-                       lfta_val[lmach] += "\t\t\treturn NULL;\n";
-               }
-         }
-         lfta_val[lmach] += "\t} else\n";
-         lfta_val[lmach] += "\t\treturn NULL;\n";
-         lfta_val[lmach] += "}\n\n";
-
-
-//                     Generate a full list of FTAs for clearinghouse reference
-         lfta_val[lmach] += "// list of FTAs clearinghouse expects to register themselves\n";
-         lfta_val[lmach] += "const gs_sp_t fta_names[] = {";
-
-         for (i = 0; i < query_names.size(); ++i) {
-                  if (i)
-                         lfta_val[lmach] += ", ";
-                  lfta_val[lmach] += "\"" + query_names[i] + "\"";
-         }
-         for (i = 0; i < hfta_list.size(); ++i) {
-                  lfta_val[lmach] += ", \"" + hfta_list[i]->query_name + "\"";
-         }
-         lfta_val[lmach] += ", NULL};\n\n";
-
-
-//                     Add the initialization function to lfta.c
-//     Change to accept the interface name, and 
-//     set the prefilter function accordingly.
-//     see the example in demo/err2
-         lfta_val[lmach] += "void fta_init(gs_sp_t device){\n";
-
-//       for(i=0;i<mach_query_names[lmach].size();i++)
-//             int mi = mach_query_names[lmach][i];
-//             stream_query *lfta_sq = lfta_mach_lists[lmach][i];
-
-         for(auto mvsi=lfta_iface_lists.begin(); mvsi!=lfta_iface_lists.end(); ++mvsi){
-               string liface = (*mvsi).first;
-               vector<stream_query *> lfta_list = (*mvsi).second;
-               for(i=0;i<lfta_list.size();i++){
-                       stream_query *lfta_sq = lfta_list[i];
-                       int mi = lfta_iface_qname_ix[liface][i];
-               
-                       fprintf(stderr,"interface %s, LFTA %d, snap length is %d\n",liface.c_str(),mi,snap_lengths[mi]);
-
-                       string this_iface = "DEFAULTDEV";
-                       if(interface_names[mi]!="")
-                               this_iface = '"'+interface_names[mi]+'"';
-                       lfta_val[lmach] += "\tif(!strcmp(device,"+this_iface+"))\n";
-               lfta_val[lmach] += "\t\tfta_register(\""+query_names[mi]+"\", " + (lfta_reuse_options[mi]?"1":"0") + ", ";
-//             if(interface_names[mi]=="")
-//                             lfta_val[lmach]+="DEFAULTDEV";
-//             else
-//                             lfta_val[lmach]+='"'+interface_names[mi]+'"';
-                       lfta_val[lmach] += this_iface;
-
-
-               lfta_val[lmach] += ", "+generate_alloc_name(query_names[mi])
-                       +"\n#ifndef LFTA_IN_NIC\n\t,"+generate_schema_string_name(query_names[mi])
-                       +"\n#endif\n";
-                               sprintf(tmpstr,",%d",snap_lengths[mi]);
-                       lfta_val[lmach] += tmpstr;
-
-//                     unsigned long long int mask=0, bpos=1;
-//                     int f_pos;
-//                     for(f_pos=0;f_pos<prefilter_preds.size();++f_pos){
-//                             if(prefilter_preds[f_pos]->lfta_id.count(i))
-//                                     mask |= bpos;
-//                             bpos = bpos << 1;
-//                     }
-
-#ifdef PREFILTER_OK
-//                     sprintf(tmpstr,",%lluull",mask);
-                       sprintf(tmpstr,",%lluull",lfta_sigs[liface][i]);
-                       lfta_val[lmach]+=tmpstr;
-#else
-                       lfta_val[lmach] += ",0ull";
-#endif
-
-                       lfta_val[lmach] += ");\n";
-
-
-
-//    End of lfta prefilter stuff
-// --------------------------------------------------
-
-//                     If there is a field verifier, warn about
-//                     lack of compatability
-                 string lfta_comment;
-                 string lfta_title;
-                 string lfta_namespace;
-                 map<string,string> ldefs = lfta_sq->query_plan[0]->get_definitions();
-                 if(ldefs.count("comment")>0)
-                       lfta_comment = lfta_sq->defines["comment"];
-                 if(ldefs.count("Comment")>0)
-                       lfta_comment = lfta_sq->defines["Comment"];
-                 if(ldefs.count("COMMENT")>0)
-                       lfta_comment = lfta_sq->defines["COMMENT"];
-                 if(ldefs.count("title")>0)
-                       lfta_title = lfta_sq->defines["title"];
-                 if(ldefs.count("Title")>0)
-                       lfta_title = lfta_sq->defines["Title"];
-                 if(ldefs.count("TITLE")>0)
-                       lfta_title = lfta_sq->defines["TITLE"];
-                 if(ldefs.count("NAMESPACE")>0)
-                       lfta_namespace = lfta_sq->defines["NAMESPACE"];
-                 if(ldefs.count("Namespace")>0)
-                       lfta_namespace = lfta_sq->defines["Namespace"];
-                 if(ldefs.count("namespace")>0)
-                       lfta_namespace = lfta_sq->defines["namespace"];
-
-                 string lfta_ht_size;
-                 if(lfta_sq->query_plan[0]->node_type()== "sgah_qpn" || lfta_sq->query_plan[0]->node_type()== "rsgah_qpn")
-                       lfta_ht_size = int_to_string(DEFAULT_LFTA_HASH_TABLE_SIZE);
-                 if(ldefs.count("aggregate_slots")>0){
-                       lfta_ht_size = ldefs["aggregate_slots"];
-                 }
-
-//                     NOTE : I'm assuming that visible lftas do not start with _fta.
-//                             -- will fail for non-visible simple selection queries.
-               if(field_verifier != NULL && query_names[mi].substr(0,1) != "_"){
-                       string warning_str;
-                       if(lfta_comment == "")
-                               warning_str += "\tcomment not found.\n";
-                       if(lfta_title == "")
-                               warning_str += "\ttitle not found.\n";
-                       if(lfta_namespace == "")
-                               warning_str += "\tnamespace not found.\n";
-
-                       vector<field_entry *> flds = lfta_sq->get_output_tabledef()->get_fields();
-                       int fi;
-                       for(fi=0;fi<flds.size();fi++){
-                               field_verifier->verify_field(flds[fi]->get_name(),flds[fi]->get_type(),warning_str);
-                       }
-                       if(warning_str != "")
-                               fprintf(stderr,"Warning, in LFTA stream %s:\n%s",
-                                       query_names[mi].c_str(),warning_str.c_str());
-               }
-
-
-//                     Create qtree output
-               fprintf(qtree_output,"\t<LFTA name='%s' >\n",query_names[mi].c_str());
-                  if(lfta_comment != "")
-                        fprintf(qtree_output,"\t\t<Description value='%s' />\n",lfta_comment.c_str());
-                  if(lfta_title != "")
-                        fprintf(qtree_output,"\t\t<Title value='%s' />\n",lfta_title.c_str());
-                  if(lfta_namespace != "")
-                        fprintf(qtree_output,"\t\t<Namespace value='%s' />\n",lfta_namespace.c_str());
-                  if(lfta_ht_size != "")
-                        fprintf(qtree_output,"\t\t<HtSize value='%s' />\n",lfta_ht_size.c_str());
-               if(lmach != "")
-                 fprintf(qtree_output,"\t\t<Host value='%s' />\n",lmach.c_str());
-               else
-                 fprintf(qtree_output,"\t\t<Host value='%s' />\n",hostname.c_str());
-               fprintf(qtree_output,"\t\t<Interface  value='%s' />\n",interface_names[mi].c_str());
-               fprintf(qtree_output,"\t\t<ReadsFrom value='%s' />\n",interface_names[mi].c_str());
-               fprintf(qtree_output,"\t\t<Rate value='100' />\n");
-               fprintf(qtree_output,"\t\t<LivenessTimeout value='%d' />\n", lfta_liveness_timeouts[mi]);
-//                             write info about fields to qtree.xml
-                 vector<field_entry *> flds = lfta_sq->get_output_tabledef()->get_fields();
-                 int fi;
-                 for(fi=0;fi<flds.size();fi++){
-                       fprintf(qtree_output,"\t\t<Field name='%s' pos='%d' type='%s' ",flds[fi]->get_name().c_str(), fi, flds[fi]->get_type().c_str());
-                       if(flds[fi]->get_modifier_list()->size()){
-                               fprintf(qtree_output,"mods='%s' ", flds[fi]->get_modifier_list()->to_string().c_str());
-                       }
-                       fprintf(qtree_output," />\n");
-                 }
-               fprintf(qtree_output,"\t</LFTA>\n");
-
-
-           }
-         }
-
-         for(auto mvsi=lfta_iface_lists.begin(); mvsi!=lfta_iface_lists.end(); ++mvsi){
-                       string liface = (*mvsi).first;
-                       lfta_val[lmach] += 
-"      if (!strcmp(device, \""+liface+"\")) \n"
-"              lfta_prefilter = &lfta_prefilter_"+liface+"; \n"
-;
-               }
-               lfta_val[lmach] += 
-"      if(lfta_prefilter == NULL){\n"
-"              fprintf(stderr, \"Error, interface %s not found in fta_init.\\n\",device);\n"
-"              exit(1);\n"
-"      }\n"
-;
-
-
-
-         lfta_val[lmach] += "}\n\n";
-
-      if(!(debug_only || hfta_only) ){
-               string lfta_flnm;
-               if(lmach != "")
-                 lfta_flnm = lmach + "_lfta.c";
-               else
-                 lfta_flnm = hostname + "_lfta.c";
-               if((lfta_out = fopen(lfta_flnm.c_str(),"w")) == NULL){
-                       fprintf(stderr,"Can't open output file %s\n%s\n","lfta.c",strerror(errno));
-                       exit(1);
-               }
-             fprintf(lfta_out,"%s",lfta_header.c_str());
-             fprintf(lfta_out,"%s",lfta_prefilter_val[lmach].c_str());
-             fprintf(lfta_out,"%s",lfta_val[lmach].c_str());
-               fclose(lfta_out);
-         }
-       }
-
-//             Say what are the operators which must execute
-       if(opviews.size()>0)
-               fprintf(stderr,"The queries use the following external operators:\n");
-       for(i=0;i<opviews.size();++i){
-               opview_entry *opv = opviews.get_entry(i);
-               fprintf(stderr,"\t%s\n",opv->view_name.c_str());
-       }
-
-       if(create_makefile)
-               generate_makefile(input_file_names, nfiles, hfta_names, opviews,
-               machine_names, schema_file_name,
-               interface_names,
-               ifaces_db, config_dir_path,use_pads,ext_lib_string, rts_hload);
-
-
-       fprintf(qtree_output,"</QueryNodes>\n");
-
-       return(0);
-}
-
-////////////////////////////////////////////////////////////
-
-void generate_makefile(vector<string> &input_file_names, int nfiles,
-                                          vector<string> &hfta_names, opview_set &opviews,
-                                               vector<string> &machine_names,
-                                               string schema_file_name,
-                                               vector<string> &interface_names,
-                                               ifq_t *ifdb, string &config_dir_path,
-                                               bool use_pads,
-                                               string extra_libs,
-                                               map<string, vector<int> > &rts_hload
-                                        ){
-       int i,j;
-
-       if(config_dir_path != ""){
-               config_dir_path = "-C "+config_dir_path;
-       }
-
-       struct stat sb;
-       bool libz_exists = stat((root_path+"/lib/libz.a").c_str(),&sb) >= 0;
-       bool libast_exists = stat((root_path+"/lib/libast.a").c_str(),&sb) >= 0;
-
-//     if(libz_exists && !libast_exists){
-//             fprintf(stderr,"Configuration ERROR: ../../lib/libz.a exists but ../../lib/libast.a dows not.\n");
-//             exit(1);
-//     }
-
-//                     Get set of operator executable files to run
-       set<string> op_fls;
-       set<string>::iterator ssi;
-       for(i=0;i<opviews.size();++i){
-               opview_entry *opv = opviews.get_entry(i);
-               if(opv->exec_fl != "") op_fls.insert(opv->exec_fl);
-       }
-
-       FILE *outfl = fopen("Makefile", "w");
-       if(outfl==NULL){
-               fprintf(stderr,"Can't open Makefile for write, exiting.\n");
-               exit(0);
-       }
-
-       fputs(
-("CPP= g++ -O3 -g -I "+root_path+"/include  -I "+root_path+"/include/hfta\n"
-"CC= gcc -O3 -g -I . -I "+root_path+"/include -I "+root_path+"/include/lfta"
-).c_str(), outfl
-);
-       if(generate_stats)
-               fprintf(outfl,"  -DLFTA_STATS");
-
-//             Gather the set of interfaces
-//             Also, gather "base interface names" for use in computing
-//             the hash splitting to virtual interfaces.
-//             TODO : must update to hanndle machines
-       set<string> ifaces;
-       set<string> base_vifaces;       // base interfaces of virtual interfaces
-       map<string, string> ifmachines;
-       map<string, string> ifattrs;
-       for(i=0;i<interface_names.size();++i){
-               ifaces.insert(interface_names[i]);
-               ifmachines[interface_names[i]] = machine_names[i];
-
-               size_t Xpos = interface_names[i].find_last_of("X");
-               if(Xpos!=string::npos){
-                       string iface = interface_names[i].substr(0,Xpos);
-                       base_vifaces.insert(iface);
-               }
-               // get interface attributes and add them to the list
-       }
-
-//             Do we need to include protobuf libraries?
-       bool use_proto = false;
-       int erri;
-       string err_str;
-       for(ssi=ifaces.begin();ssi!=ifaces.end();++ssi){
-               string ifnm = (*ssi);
-               vector<string> ift = ifdb->get_iface_vals(ifmachines[ifnm],ifnm, "InterfaceType", erri, err_str);
-               for(int ift_i=0;ift_i<ift.size();ift_i++){
-                       if(ift[ift_i]=="PROTO"){
-                               use_proto = true;
-                       }
-               }
-       }
-
-       fprintf(outfl,
-"\n"
-"\n"
-"all: rts");
-       for(i=0;i<hfta_names.size();++i)
-               fprintf(outfl," %s",hfta_names[i].c_str());
-       fputs(
-("\n"
-"\n"
-"rts: lfta.o "+root_path+"/lib/libgscphost.a "+root_path+"/lib/libgscplftaaux.a "+root_path+"/lib/libgscprts.a  "+root_path+"/lib/libclearinghouse.a\n"
-"\tg++ -O3 -g -o rts lfta.o ").c_str(), outfl);
-       if(use_pads)
-               fprintf(outfl,"-L. ");
-       fputs(
-("-L"+root_path+"/lib -lgscplftaaux ").c_str(), outfl);
-       if(use_pads)
-               fprintf(outfl,"-lgscppads -lpads ");
-       fprintf(outfl,
-"-lgscprts -lgscphost -lm -lgscpaux -lgscplftaaux  -lclearinghouse -lresolv -lpthread -lgscpinterface -lz");
-       if(use_pads)
-               fprintf(outfl, " -lpz -lz -lbz ");
-       if(libz_exists && libast_exists)
-               fprintf(outfl," -last ");
-       if(use_pads)
-               fprintf(outfl, " -ldll -ldl ");
-       if(use_proto)
-               fprintf(outfl, " -L/usr/local/lib/ -lprotobuf-c ");
-       fprintf(outfl," -lgscpaux");
-#ifdef GCOV
-       fprintf(outfl," -fprofile-arcs");
-#endif
-       fprintf(outfl,
-"\n"
-"\n"
-"lfta.o: %s_lfta.c\n"
-"\t$(CC) -o lfta.o -c %s_lfta.c\n"
-"\n"
-"%s_lfta.c: external_fcns.def %s ",hostname.c_str(), hostname.c_str(), hostname.c_str(),schema_file_name.c_str());
-       for(i=0;i<nfiles;++i)
-               fprintf(outfl," %s",input_file_names[i].c_str());
-       if(hostname == ""){
-               fprintf(outfl,"\n\t%s/bin/translate_fta %s %s ",root_path.c_str(), config_dir_path.c_str(),schema_file_name.c_str());
-       }else{
-               fprintf(outfl,"\n\t%s/bin/translate_fta -h %s %s %s ", root_path.c_str(), hostname.c_str(), config_dir_path.c_str(),schema_file_name.c_str());
-       }
-       for(i=0;i<nfiles;++i)
-               fprintf(outfl," %s",input_file_names[i].c_str());
-       fprintf(outfl,"\n");
-
-       for(i=0;i<hfta_names.size();++i)
-               fprintf(outfl,
-("%s: %s.o\n"
-"\t$(CPP) -o %s %s.o -L"+root_path+"/lib -lgscpapp -lgscphostaux -lgscphost -lgscpinterface -lgscphftaaux -lgscphostaux -lm -lgscpaux -lclearinghouse -lresolv -lpthread -lgscpaux -lgscphftaaux -lgscpaux %s\n"
-"\n"
-"%s.o: %s.cc\n"
-"\t$(CPP) -o %s.o -c %s.cc\n"
-"\n"
-"\n").c_str(),
-    hfta_names[i].c_str(), hfta_names[i].c_str(),
-       hfta_names[i].c_str(), hfta_names[i].c_str(), extra_libs.c_str(),
-       hfta_names[i].c_str(), hfta_names[i].c_str(),
-       hfta_names[i].c_str(), hfta_names[i].c_str()
-               );
-
-       fprintf(outfl,
-("\n"
-"packet_schema.txt:\n"
-"\tln -s "+root_path+"/cfg/packet_schema.txt .\n"
-"\n"
-"external_fcns.def:\n"
-"\tln -s "+root_path+"/cfg/external_fcns.def .\n"
-"\n"
-"clean:\n"
-"\trm -rf core rts *.o  %s_lfta.c  external_fcns.def packet_schema.txt").c_str(),hostname.c_str());
-       for(i=0;i<hfta_names.size();++i)
-               fprintf(outfl," %s %s.cc",hfta_names[i].c_str(),hfta_names[i].c_str());
-       fprintf(outfl,"\n");
-
-       fclose(outfl);
-
-
-
-//             Gather the set of interfaces
-//             TODO : must update to hanndle machines
-//             TODO : lookup interface attributes and add them as a parameter to rts process
-       outfl = fopen("runit", "w");
-       if(outfl==NULL){
-               fprintf(stderr,"Can't open runit for write, exiting.\n");
-               exit(0);
-       }
-
-
-       fputs(
-("#!/bin/sh\n"
-"./stopit\n"
-+root_path+"/bin/gshub.py> /dev/null 2>&1 &\n"
-"sleep 5\n"
-"if [ ! -f gshub.log ]\n"
-"then\n"
-"\techo \"Failed to start bin/gshub.py\"\n"
-"\texit -1\n"
-"fi\n"
-"ADDR=`cat gshub.log`\n"
-"ps opgid= $! >> gs.pids\n"
-"./rts $ADDR default ").c_str(), outfl);
-//     int erri;
-//     string err_str;
-       for(ssi=ifaces.begin();ssi!=ifaces.end();++ssi){
-               string ifnm = (*ssi);
-               fprintf(outfl, "%s ",ifnm.c_str());
-               vector<string> ifv = ifdb->get_iface_vals(ifmachines[ifnm],ifnm, "Command", erri, err_str);
-               for(j=0;j<ifv.size();++j)
-                       fprintf(outfl, "%s ",ifv[j].c_str());
-       }
-       fprintf(outfl, " &\n");
-       fprintf(outfl, "echo $! >> gs.pids\n");
-       for(i=0;i<hfta_names.size();++i)
-               fprintf(outfl,"./%s $ADDR default &\n",hfta_names[i].c_str());
-
-       for(j=0;j<opviews.opview_list.size();++j){
-               fprintf(outfl,"%s/views/%s %s &\n",root_path.c_str(),opviews.opview_list[j]->exec_fl.c_str(), opviews.opview_list[j]->mangler.c_str());
-       }
-
-       fclose(outfl);
-       system("chmod +x runit");
-
-       outfl = fopen("stopit", "w");
-       if(outfl==NULL){
-               fprintf(stderr,"Can't open stopit for write, exiting.\n");
-               exit(0);
-       }
-
-       fprintf(outfl,"#!/bin/sh\n"
-"rm -f gshub.log\n"
-"if [ ! -f gs.pids ]\n"
-"then\n"
-"exit\n"
-"fi\n"
-"for pgid in `cat gs.pids`\n"
-"do\n"
-"kill -TERM -$pgid\n"
-"done\n"
-"sleep 1\n"
-"for pgid in `cat gs.pids`\n"
-"do\n"
-"kill -9 -$pgid\n"
-"done\n"
-"rm gs.pids\n");
-
-       fclose(outfl);
-       system("chmod +x stopit");
-
-//-----------------------------------------------
-
-/* For now disable support for virtual interfaces
-       outfl = fopen("set_vinterface_hash.bat", "w");
-       if(outfl==NULL){
-               fprintf(stderr,"Can't open set_vinterface_hash.bat for write, exiting.\n");
-               exit(0);
-       }
-
-//             The format should be determined by an entry in the ifres.xml file,
-//             but for now hardcode the only example I have.
-       for(ssi=base_vifaces.begin();ssi!=base_vifaces.end();++ssi){
-               if(rts_hload.count((*ssi))){
-                       string iface_name = (*ssi);
-                       string iface_number = "";
-                       for(j=iface_name.size()-1; j>0 && iface_number == ""; j--){
-                               if(isdigit(iface_name[j])){
-                                       iface_number = iface_name[j];
-                                       if(j>0 && isdigit(iface_name[j-1]))
-                                               iface_number = iface_name[j-1] + iface_number;
-                               }
-                       }
-
-                       fprintf(outfl,"dagconfig -d%s -S hat_range=",iface_number.c_str());
-                       vector<int> halloc = rts_hload[iface_name];
-                       int prev_limit = 0;
-                       for(j=0;j<halloc.size();++j){
-                               if(j>0)
-                                       fprintf(outfl,":");
-                               fprintf(outfl,"%d-%d",prev_limit,halloc[j]);
-                               prev_limit = halloc[j];
-                       }
-                       fprintf(outfl,"\n");
-               }
-       }
-       fclose(outfl);
-       system("chmod +x set_vinterface_hash.bat");
-*/
-}
-
-//             Code for implementing a local schema
-/*
-               table_list qpSchema;
-
-//                             Load the schemas of any LFTAs.
-               int l;
-               for(l=0;l<hfta_nbr;++l){
-                       stream_query *sq0 = split_queries[l];
-                       table_def *td = sq0->get_output_tabledef();
-                       qpSchema.append_table(td);
-               }
-//                             load the schemas of any other ref'd tables.
-//                             (e.g., hftas)
-               vector<tablevar_t *>  input_tbl_names = split_queries[hfta_nbr]->get_input_tables();
-               int ti;
-               for(ti=0;ti<input_tbl_names.size();++ti){
-                       int tbl_ref = qpSchema.get_table_ref(input_tbl_names[ti]->get_schema_name());
-                       if(tbl_ref < 0){
-                               tbl_ref = Schema->get_table_ref(input_tbl_names[ti]->get_schema_name());
-                               if(tbl_ref < 0){
-                                       fprintf(stderr,"ERROR file %s references table %s, which is not in the schema.\n",input_file_names[i].c_str(), (input_tbl_names[ti]->get_schema_name()).c_str());
-                                       exit(1);
-                               }
-                               qpSchema.append_table(Schema->get_table(tbl_ref));
-                       }
-               }
-*/
-
-//             Functions related to parsing.
-
-/*
-static int split_string(char *instr,char sep, char **words,int max_words){
-   char *loc;
-   char *str;
-   int nwords = 0;
-
-   str = instr;
-   words[nwords++] = str;
-   while( (loc = strchr(str,sep)) != NULL){
-        *loc = '\0';
-        str = loc+1;
-        if(nwords >= max_words){
-                fprintf(stderr,"Error in split_string, too many words discovered (max is %d)\n",max_words);
-                nwords = max_words-1;
-        }
-        words[nwords++] = str;
-   }
-
-   return(nwords);
-}
-
-*/
-
+/* ------------------------------------------------\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<unistd.h>             // for gethostname\r
+\r
+#include <string>\r
+#include "parse_fta.h"\r
+#include "parse_schema.h"\r
+#include "parse_ext_fcns.h"\r
+#include"analyze_fta.h"\r
+#include"query_plan.h"\r
+#include"generate_lfta_code.h"\r
+#include"stream_query.h"\r
+#include"generate_utils.h"\r
+#include"nic_def.h"\r
+#include"generate_nic_code.h"\r
+\r
+#include <stdlib.h>\r
+#include <stdio.h>\r
+#include<ctype.h>\r
+#include<glob.h>\r
+#include<string.h>\r
+\r
+#include<list>\r
+\r
+//             for the scandir\r
+     #include <sys/types.h>\r
+     #include <dirent.h>\r
+\r
+\r
+#include<errno.h>\r
+\r
+//             to verify that some files exist.\r
+     #include <sys/types.h>\r
+     #include <sys/stat.h>\r
+\r
+#include "parse_partn.h"\r
+\r
+#include "print_plan.h"\r
+\r
+//             Interface to the xml parser\r
+\r
+#include"xml_t.h"\r
+#include"field_list.h"\r
+\r
+extern int xmlParserparse(void);\r
+extern FILE *xmlParserin;\r
+extern int xmlParserdebug;\r
+\r
+std::vector<std::string> xml_attr_vec;\r
+std::vector<std::string> xml_val_vec;\r
+std::string xml_a, xml_v;\r
+xml_t *xml_leaves = NULL;\r
+\r
+//     Interface to the field list verifier\r
+field_list *field_verifier = NULL;\r
+\r
+#define TMPSTRLEN 1000\r
+\r
+#ifndef PATH_DELIM\r
+  #define PATH_DELIM '/'\r
+#endif\r
+\r
+char tmp_schema_str[10000];\r
+\r
+// maximum delay between two hearbeats produced\r
+// by UDOP. Used when its not explicity\r
+// provided in udop definition\r
+#define DEFAULT_UDOP_LIVENESS_TIMEOUT 5\r
+\r
+//             Default lfta hash table size, must be power of 2.\r
+int DEFAULT_LFTA_HASH_TABLE_SIZE = 4096;\r
+\r
+//             Interface to FTA definition lexer and parser ...\r
+\r
+extern int FtaParserparse(void);\r
+extern FILE *FtaParserin;\r
+extern int FtaParserdebug;\r
+\r
+fta_parse_t *fta_parse_result;\r
+var_defs_t *fta_parse_defines;\r
+\r
+\r
+\r
+//             Interface to external function lexer and parser ...\r
+\r
+extern int Ext_fcnsParserparse(void);\r
+extern FILE *Ext_fcnsParserin;\r
+extern int Ext_fcnsParserdebug;\r
+\r
+ext_fcn_list *Ext_fcns;\r
+\r
+\r
+//             Interface to partition definition parser\r
+extern int PartnParserparse();\r
+partn_def_list_t *partn_parse_result = NULL;\r
+\r
+\r
+\r
+using namespace std;\r
+//extern int errno;\r
+\r
+\r
+//             forward delcaration of local utility function\r
+void generate_makefile(vector<string> &input_file_names, int nfiles,\r
+                                          vector<string> &hfta_names, opview_set &opviews,\r
+                                               vector<string> &machine_names,\r
+                                               string schema_file_name,\r
+                                               vector<string> &interface_names,\r
+                                               ifq_t *ifdb, string &config_dir_path,\r
+                                               bool use_pads,\r
+                                               string extra_libs,\r
+                                               map<string, vector<int> > &rts_hload\r
+                                       );\r
+\r
+//static int split_string(char *instr,char sep, char **words,int max_words);\r
+#define MAXFLDS 100\r
+\r
+  FILE *schema_summary_output = NULL;          // query names\r
+\r
+//                     Dump schema summary\r
+void dump_summary(stream_query *str){\r
+       fprintf(schema_summary_output,"%s\n",str->query_name.c_str());\r
+\r
+       table_def *sch = str->get_output_tabledef();\r
+\r
+       vector<field_entry *> flds = sch->get_fields();\r
+       int f;\r
+       for(f=0;f<flds.size();++f){\r
+               if(f>0) fprintf(schema_summary_output,"|");\r
+               fprintf(schema_summary_output,"%s",flds[f]->get_name().c_str());\r
+       }\r
+       fprintf(schema_summary_output,"\n");\r
+       for(f=0;f<flds.size();++f){\r
+               if(f>0) fprintf(schema_summary_output,"|");\r
+               fprintf(schema_summary_output,"%s",flds[f]->get_type().c_str());\r
+       }\r
+       fprintf(schema_summary_output,"\n");\r
+}\r
+\r
+//             Globals\r
+string hostname;               // name of current host.\r
+int hostname_len;\r
+bool generate_stats = false;\r
+string root_path = "../..";\r
+\r
+\r
+int main(int argc, char **argv){\r
+  char tmpstr[TMPSTRLEN];\r
+  string err_str;\r
+  int q,s,h,f;\r
+\r
+  set<int>::iterator si;\r
+\r
+  vector<string> query_names;                  // for lfta.c registration\r
+  map<string, vector<int> > mach_query_names;  // list queries of machine\r
+  vector<int> snap_lengths;                            // for lfta.c registration\r
+  vector<string> interface_names;                      // for lfta.c registration\r
+  vector<string> machine_names;                        // machine of interface\r
+  vector<bool> lfta_reuse_options;                     // for lfta.c registration\r
+  vector<int> lfta_liveness_timeouts;          // fot qtree.xml generation\r
+  vector<string> hfta_names;                   // hfta cource code names, for\r
+                                                                               // creating make file.\r
+  vector<string> qnames;                               // ensure unique names\r
+  map<string, int> lfta_names;                 // keep track of unique lftas.\r
+\r
+\r
+//                             set these to 1 to debug the parser\r
+  FtaParserdebug = 0;\r
+  Ext_fcnsParserdebug = 0;\r
+\r
+  FILE *lfta_out;                              // lfta.c output.\r
+  FILE *fta_in;                                        // input file\r
+  FILE *table_schemas_in;              // source tables definition file\r
+  FILE *query_name_output;             // query names\r
+  FILE *qtree_output;                  // interconnections of query nodes\r
+\r
+  // -------------------------------\r
+  // Handling of Input Arguments\r
+  // -------------------------------\r
+    char optstr[] = "BDpLC:l:HNQMf:PSh:n:cR:";\r
+       const char *usage_str = "Usage: %s [-B] [-D] [-p] [-L] [-N] [-H] [-Q] [-M] [-C <config directory>] [-l <library directory>] [-f] [-P] [-S] [-n n_virtual_interfaces] [-h hostname] [-R root_path] [schema_file] input_file [input file ...]\n"\r
+               "\t[-B] : debug only (don't create output files)\n"\r
+               "\t[-D] : distributed mode (will use cluster.ifq instead of local .ifq file)\n"\r
+               "\t[-p] : partitioned mode (will use partition information in partition.txt to drive query optimization)\n"\r
+               "\t[-L] : use live_hosts.txt file to restrict queries to a set of live hosts\n"\r
+               "\t[-C] : use <config directory> for definition files\n"\r
+               "\t[-l] : use <library directory> for library queries\n"\r
+               "\t[-N] : output query names in query_names.txt\n"\r
+               "\t[-H] : create HFTA only (no schema_file)\n"\r
+               "\t[-Q] : use query name for hfta suffix\n"\r
+               "\t[-M] : generate make file and runit, stopit scripts\n"\r
+               "\t[-S] : enable LFTA statistics (alters Makefile).\n"\r
+               "\t[-f] : Output schema summary to schema_summary.txt\n"\r
+               "\t[-P] : link with PADS\n"\r
+               "\t[-h] : override host name.\n"\r
+               "\t[-c] : clean out Makefile and hfta_*.cc first.\n"\r
+               "\t[-R] : path to root of GS-lite\n"\r
+;\r
+\r
+//             parameters gathered from command line processing\r
+       string external_fcns_path;\r
+//     string internal_fcn_path;\r
+       string config_dir_path;\r
+       string library_path = "./";\r
+       vector<string> input_file_names;\r
+       string schema_file_name;\r
+       bool debug_only = false;\r
+       bool hfta_only = false;\r
+       bool output_query_names = false;\r
+       bool output_schema_summary=false;\r
+       bool numeric_hfta_flname = true;\r
+       bool create_makefile = false;\r
+       bool distributed_mode = false;\r
+       bool partitioned_mode = false;\r
+       bool use_live_hosts_file = false;\r
+       bool use_pads = false;\r
+       bool clean_make = false;\r
+       int n_virtual_interfaces = 1;\r
+\r
+   char chopt;\r
+   while((chopt = getopt(argc,argv,optstr)) != -1){\r
+               switch(chopt){\r
+               case 'B':\r
+                       debug_only = true;\r
+                       break;\r
+               case 'D':\r
+                       distributed_mode = true;\r
+                       break;\r
+               case 'p':\r
+                       partitioned_mode = true;\r
+                       break;\r
+               case 'L':\r
+                       use_live_hosts_file = true;\r
+                       break;\r
+               case 'C':\r
+                               if(optarg != NULL)\r
+                                config_dir_path = string(optarg) + string("/");\r
+                       break;\r
+               case 'l':\r
+                               if(optarg != NULL)\r
+                                library_path = string(optarg) + string("/");\r
+                       break;\r
+               case 'N':\r
+                       output_query_names = true;\r
+                       break;\r
+               case 'Q':\r
+                       numeric_hfta_flname = false;\r
+                       break;\r
+               case 'H':\r
+                       if(schema_file_name == ""){\r
+                               hfta_only = true;\r
+                       }\r
+                       break;\r
+               case 'f':\r
+                       output_schema_summary=true;\r
+                       break;\r
+               case 'M':\r
+                       create_makefile=true;\r
+                       break;\r
+               case 'S':\r
+                       generate_stats=true;\r
+                       break;\r
+               case 'P':\r
+                       use_pads = true;\r
+                       break;\r
+               case 'c':\r
+                       clean_make = true;\r
+                       break;\r
+               case 'h':\r
+                       if(optarg != NULL)\r
+                               hostname = optarg;\r
+                       break;\r
+               case 'R':\r
+                       if(optarg != NULL)\r
+                               root_path = optarg;\r
+                       break;\r
+               case 'n':\r
+                       if(optarg != NULL){\r
+                               n_virtual_interfaces = atoi(optarg);\r
+                               if(n_virtual_interfaces < 1 || n_virtual_interfaces > 128){\r
+                                       fprintf(stderr,"Warning, %d virtual interfaces specified, valid values are between 1 and 128 inclusive\n",n_virtual_interfaces);\r
+                                       n_virtual_interfaces = 1;\r
+                               }\r
+                       }\r
+                       break;\r
+               case '?':\r
+                       fprintf(stderr,"Error, argument %c not recognized.\n",optopt);\r
+                       fprintf(stderr,"%s\n", usage_str);\r
+                       exit(1);\r
+               default:\r
+                       fprintf(stderr, "Argument was %c\n", optopt);\r
+                       fprintf(stderr,"Invalid arguments\n");\r
+                       fprintf(stderr,"%s\n", usage_str);\r
+                       exit(1);\r
+               }\r
+       }\r
+       argc -= optind;\r
+       argv += optind;\r
+       for (int i = 0; i < argc; ++i) {\r
+               if((schema_file_name == "") && !hfta_only){\r
+                       schema_file_name = argv[i];\r
+               }else{\r
+                       input_file_names.push_back(argv[i]);\r
+               }\r
+       }\r
+\r
+       if(input_file_names.size() == 0){\r
+               fprintf(stderr,"%s\n", usage_str);\r
+               exit(1);\r
+       }\r
+\r
+       if(clean_make){\r
+               string clean_cmd = "rm Makefile hfta_*.cc";\r
+               int clean_ret = system(clean_cmd.c_str());\r
+               if(clean_ret){\r
+                       fprintf(stderr,"Warning, return value %d when trying to clean out old source files.\n", clean_ret);\r
+               }\r
+       }\r
+\r
+\r
+       nic_prop_db *npdb = new nic_prop_db(config_dir_path);\r
+\r
+//                     Open globally used file names.\r
+\r
+       // prepend config directory to schema file\r
+       schema_file_name = config_dir_path + schema_file_name;\r
+       external_fcns_path = config_dir_path + string("external_fcns.def");\r
+    string ifx_fname = config_dir_path + string("ifres.xml");\r
+\r
+//             Find interface query file(s).\r
+       if(hostname == ""){\r
+               gethostname(tmpstr,TMPSTRLEN);\r
+               hostname = tmpstr;\r
+       }\r
+       hostname_len = strlen(tmpstr);\r
+    string ifq_fname = config_dir_path + (distributed_mode ? "cluster" : hostname) + string(".ifq");\r
+       vector<string> ifq_fls;\r
+\r
+               ifq_fls.push_back(ifq_fname);\r
+\r
+\r
+//                     Get the field list, if it exists\r
+       string flist_fl = config_dir_path + "field_list.xml";\r
+       FILE *flf_in = NULL;\r
+       if((flf_in = fopen(flist_fl.c_str(), "r")) != NULL) {\r
+               fprintf(stderr,"Found field list file %s\n",flist_fl.c_str());\r
+               xml_leaves = new xml_t();\r
+               xmlParser_setfileinput(flf_in);\r
+               if(xmlParserparse()){\r
+                       fprintf(stderr,"WARNING, could not parse field list file %s\n",flist_fl.c_str());\r
+               }else{\r
+                       field_verifier = new field_list(xml_leaves);\r
+               }\r
+       }\r
+\r
+       if(!hfta_only){\r
+         if((table_schemas_in = fopen(schema_file_name.c_str(), "r")) == NULL) {\r
+               fprintf(stderr,"Can't open schema file %s\n%s\n",schema_file_name.c_str(),strerror(errno));\r
+               exit(1);\r
+         }\r
+       }\r
+\r
+/*\r
+       if(!(debug_only || hfta_only)){\r
+         if((lfta_out = fopen("lfta.c","w")) == NULL){\r
+               fprintf(stderr,"Can't open output file %s\n%s\n","lfta.c",strerror(errno));\r
+               exit(1);\r
+         }\r
+       }\r
+*/\r
+\r
+//             Get the output specification file.\r
+//             format is\r
+//                     query, operator, operator_param, directory, bucketwidth, partitioning_se, n_partitions\r
+       string ospec_fl = "output_spec.cfg";\r
+       FILE *osp_in = NULL;\r
+       vector<ospec_str *> output_specs;\r
+       multimap<string, int> qname_to_ospec;\r
+       if((osp_in = fopen(ospec_fl.c_str(), "r")) != NULL) {\r
+               char *flds[MAXFLDS];\r
+               int o_lineno = 0;\r
+               while(fgets(tmpstr,TMPSTRLEN,osp_in)){\r
+                       o_lineno++;\r
+                       int nflds = split_string(tmpstr,',',flds,MAXFLDS);\r
+                       if(nflds == 7){\r
+//             make operator type lowercase\r
+                               char *tmpc;\r
+                               for(tmpc=flds[1];*tmpc!='\0';++tmpc)\r
+                                       *tmpc = tolower(*tmpc);\r
+\r
+                               ospec_str *tmp_ospec = new ospec_str();\r
+                               tmp_ospec->query = flds[0];\r
+                               tmp_ospec->operator_type = flds[1];\r
+                               tmp_ospec->operator_param = flds[2];\r
+                               tmp_ospec->output_directory = flds[3];\r
+                               tmp_ospec->bucketwidth = atoi(flds[4]);\r
+                               tmp_ospec->partitioning_flds = flds[5];\r
+                               tmp_ospec->n_partitions = atoi(flds[6]);\r
+                               qname_to_ospec.insert(pair<string,int>(tmp_ospec->query,output_specs.size()));\r
+                               output_specs.push_back(tmp_ospec);\r
+                       }else{\r
+                               fprintf(stderr,"Warning, line %d corrupted in output_spec.cfg, has %d fields.\n",o_lineno,nflds);\r
+                       }\r
+               }\r
+               fclose(osp_in);\r
+       }else{\r
+               fprintf(stderr,"output_spec.cfg not found.  The query set has no output.  exiting.\n");\r
+               exit(1);\r
+       }\r
+\r
+//             hfta parallelism\r
+       string pspec_fl = "hfta_parallelism.cfg";\r
+       FILE *psp_in = NULL;\r
+       map<string, int> hfta_parallelism;\r
+       if((psp_in = fopen(pspec_fl.c_str(), "r")) != NULL){\r
+               char *flds[MAXFLDS];\r
+               int o_lineno = 0;\r
+               while(fgets(tmpstr,TMPSTRLEN,psp_in)){\r
+                       bool good_entry = true;\r
+                       o_lineno++;\r
+                       int nflds = split_string(tmpstr,',',flds,MAXFLDS);\r
+                       if(nflds == 2){\r
+                               string hname = flds[0];\r
+                               int par = atoi(flds[1]);\r
+                               if(par <= 0 || par > n_virtual_interfaces){\r
+                                       fprintf(stderr,"Warning, line %d of %s is incorrectly formatted, parallelism is %d, must be between 1 and %d\n",o_lineno,pspec_fl.c_str(),par,n_virtual_interfaces);\r
+                                       good_entry = false;\r
+                               }\r
+                               if(good_entry && n_virtual_interfaces % par != 0){\r
+                                       fprintf(stderr,"Warning, line %d of %s is incorrectly formatted, parallelism is %d, must divide the number of virtual interfaces (%d), ignoring.\n",o_lineno,pspec_fl.c_str(),par,n_virtual_interfaces);\r
+                                       good_entry = false;\r
+                               }\r
+                               if(good_entry)\r
+                                       hfta_parallelism[hname] = par;\r
+                       }\r
+               }\r
+       }else{\r
+               fprintf(stderr,"WARNING, no file %s found, using single copies of hftas.\n",pspec_fl.c_str());\r
+       }\r
+\r
+\r
+//             LFTA hash table sizes\r
+       string htspec_fl = "lfta_htsize.cfg";\r
+       FILE *htsp_in = NULL;\r
+       map<string, int> lfta_htsize;\r
+       if((htsp_in = fopen(htspec_fl.c_str(), "r")) != NULL){\r
+               char *flds[MAXFLDS];\r
+               int o_lineno = 0;\r
+               while(fgets(tmpstr,TMPSTRLEN,htsp_in)){\r
+                       bool good_entry = true;\r
+                       o_lineno++;\r
+                       int nflds = split_string(tmpstr,',',flds,MAXFLDS);\r
+                       if(nflds == 2){\r
+                               string lfta_name = flds[0];\r
+                               int htsz = atoi(flds[1]);\r
+                               if(htsz>0){\r
+                                       lfta_htsize[lfta_name] = htsz;\r
+                               }else{\r
+                                       fprintf(stderr,"Warning, line %d of %s is incorrectly formatted, htsize is %d, must be larger than 0.\n",o_lineno,htspec_fl.c_str(),htsz);\r
+                               }\r
+                       }\r
+               }\r
+       }else{\r
+               fprintf(stderr,"WARNING, no file %s found, using default LFTA hash table sizes.\n",htspec_fl.c_str());\r
+       }\r
+\r
+//             LFTA vitual interface hash split\r
+       string rtlspec_fl = "rts_load.cfg";\r
+       FILE *rtl_in = NULL;\r
+       map<string, vector<int> > rts_hload;\r
+       if((rtl_in = fopen(rtlspec_fl.c_str(), "r")) != NULL){\r
+               char *flds[MAXFLDS];\r
+               int r_lineno = 0;\r
+               string iface_name;\r
+               vector<int> hload;\r
+               while(fgets(tmpstr,TMPSTRLEN,rtl_in)){\r
+                       bool good_entry = true;\r
+                       r_lineno++;\r
+                       iface_name = "";\r
+                       hload.clear();\r
+                       int nflds = split_string(tmpstr,',',flds,MAXFLDS);\r
+                       if(nflds >1){\r
+                               iface_name = flds[0];\r
+                               int cumm_h = 0;\r
+                               int j;\r
+                               for(j=1;j<nflds;++j){\r
+                                       int h = atoi(flds[j]);\r
+                                       if(h<=0)\r
+                                               good_entry = false;\r
+                                       cumm_h += h;\r
+                                       hload.push_back(cumm_h);\r
+                               }\r
+                       }else{\r
+                               good_entry = false;\r
+                       }\r
+                       if(good_entry){\r
+                               rts_hload[iface_name] = hload;\r
+                       }else{\r
+                               fprintf(stderr,"Warning, line %d of %s is malformed, skipping.\n",r_lineno, rtlspec_fl.c_str());\r
+                       }\r
+               }\r
+       }\r
+\r
+\r
+\r
+       if(output_query_names){\r
+         if((query_name_output = fopen("query_names.txt","w")) == NULL){\r
+               fprintf(stderr,"Can't open output file %s\n%s\n","query_names.txt",strerror(errno));\r
+               exit(1);\r
+         }\r
+       }\r
+\r
+       if(output_schema_summary){\r
+         if((schema_summary_output = fopen("schema_summary.txt","w")) == NULL){\r
+               fprintf(stderr,"Can't open output file %s\n%s\n","schema_summary.txt",strerror(errno));\r
+               exit(1);\r
+         }\r
+       }\r
+\r
+       if((qtree_output = fopen("qtree.xml","w")) == NULL){\r
+               fprintf(stderr,"Can't open output file %s\n%s\n","qtree.xml",strerror(errno));\r
+               exit(1);\r
+       }\r
+       fprintf(qtree_output,"<?xml version='1.0' encoding='ISO-8859-1'?>\n");\r
+       fprintf(qtree_output,"<?xml-stylesheet type='text/xsl' href='qtree.xsl'?>\n");\r
+       fprintf(qtree_output,"<QueryNodes>\n");\r
+\r
+\r
+//                     Get an initial Schema\r
+       table_list *Schema;\r
+       if(!hfta_only){\r
+//                     Parse the table schema definitions.\r
+         fta_parse_result = new fta_parse_t();\r
+         FtaParser_setfileinput(table_schemas_in);\r
+         if(FtaParserparse()){\r
+               fprintf(stderr,"Table schema parse failed.\n");\r
+               exit(1);\r
+         }\r
+         if(fta_parse_result->parse_type != TABLE_PARSE){\r
+               fprintf(stderr,"ERROR, file %s is not a table definition file.\n",schema_file_name.c_str());\r
+               exit(1);\r
+         }\r
+         Schema = fta_parse_result->tables;\r
+\r
+//                     Process schema field inheritance\r
+         int retval;\r
+         retval = Schema->unroll_tables(err_str);\r
+         if(retval){\r
+               fprintf(stderr,"Error processing schema filed inheritance:\n %s\n", err_str.c_str() );\r
+               exit(1);\r
+         }\r
+       }else{\r
+//                     hfta only => we will try to fetch schemas from the registry.\r
+//                     therefore, start off with an empty schema.\r
+         Schema = new table_list();\r
+       }\r
+\r
+\r
+//                     Open and parse the external functions file.\r
+       Ext_fcnsParserin = fopen(external_fcns_path.c_str(),"r");\r
+       if(Ext_fcnsParserin == NULL){\r
+               fprintf(stderr,"Warning, can't find external functions definition file (external_fcns.def).\n");\r
+               Ext_fcns = new ext_fcn_list();\r
+       }else{\r
+               if(Ext_fcnsParserparse()){\r
+                       fprintf(stderr,"Warning, error parsing external functions definition file (external_fcns.def).\n");\r
+                       Ext_fcns = new ext_fcn_list();\r
+               }\r
+       }\r
+       if(Ext_fcns->validate_fcns(err_str)){\r
+               fprintf(stderr,"Error processing external functions definition file (external_fcns.def):\n%s\n",err_str.c_str());\r
+               exit(1);\r
+       }\r
+\r
+//             Open and parse the interface resources file.\r
+//     ifq_t *ifaces_db = new ifq_t();\r
+//   string ierr;\r
+//     if(ifaces_db->load_ifaces(ifx_fname,use_live_hosts_file,distributed_mode,ierr)){\r
+//             fprintf(stderr,"ERROR, can't load interface resource file %s :\n%s",\r
+//                             ifx_fname.c_str(), ierr.c_str());\r
+//             exit(1);\r
+//     }\r
+//     if(ifaces_db->load_ifqs(ifq_fname, ierr)){\r
+//             fprintf(stderr,"ERROR, can't load interface query file %s :\n%s",\r
+//                             ifq_fname.c_str(), ierr.c_str());\r
+//             exit(1);\r
+//     }\r
+\r
+\r
+//                     The LFTA code string.\r
+//                     Put the standard preamble here.\r
+//                     NOTE: the hash macros, fcns should go into the run time\r
+  map<string, string> lfta_val;\r
+  map<string, string> lfta_prefilter_val;\r
+\r
+  string lfta_header =\r
+"#include <limits.h>\n\n"\r
+"#include \"rts.h\"\n"\r
+"#include \"fta.h\"\n"\r
+"#include \"lapp.h\"\n"\r
+"#include \"rts_udaf.h\"\n\n"\r
+;\r
+// Get any locally defined parsing headers\r
+    glob_t glob_result;\r
+    memset(&glob_result, 0, sizeof(glob_result));\r
+\r
+    // do the glob operation\r
+    int return_value = glob("../../include/lfta/local/*h", GLOB_TILDE, NULL, &glob_result);\r
+       if(return_value == 0){\r
+       for(size_t i = 0; i < glob_result.gl_pathc; ++i) {\r
+                       char *flds[1000];\r
+                       int nflds = split_string(glob_result.gl_pathv[i],'/',flds,1000);\r
+                       lfta_header += "#include \"local/"+string(flds[nflds-1])+"\"\n\n";\r
+       }\r
+       }else{\r
+               fprintf(stderr,"Warning, glob on ../../include/lfta/local/*h failed.\n");\r
+       }\r
+\r
+/*\r
+"#define IS_FILLED(bitmap,bucket) (bitmap[bucket >> 4] & (0x80000000 >> ((bucket & 15)<<1)))\n"\r
+"#define IS_NEW(bitmap,bucket) (bitmap[bucket >> 4] & (0x80000000 >> (((bucket & 15) << 1) + 1)))\n"\r
+"#define SET_EMPTY(bitmap,bucket) (bitmap[bucket >> 4] &= (~(0x80000000 >> ((bucket & 15)<<1))))\n"\r
+"#define SET_FILLED_AND_NEW(bitmap,bucket) (bitmap[bucket >> 4] |= (0xC0000000 >> ((bucket & 15)<<1)))\n"\r
+*/\r
+\r
+       lfta_header += \r
+"\n"\r
+"gs_uint64_t (*lfta_prefilter)(void *pkt) = NULL; // set at fta_init\n"\r
+"\n"\r
+"#define SLOT_FILLED 0x04\n"\r
+"#define SLOT_GEN_BITS 0x03\n"\r
+"#define SLOT_HASH_BITS 0xfffffff8\n"\r
+"#define SET_BF_BIT(bf_table, bf_num, bf_index, bucket) (bf_table[(((bucket) * (bf_num)) + (bf_index)) >> 3] |= (0x80 >> ((((bucket) * (bf_num)) + (bf_index)) & 7)))\n"\r
+"#define IS_BF_SET(bf_table, bf_num, bf_index, bucket) (bf_table[(((bucket) * (bf_num))+(bf_index)) >> 3] & (0x80 >> ((((bucket) * (bf_num))+(bf_index)) & 7)))\n"\r
+"#define SET_BF_EMPTY(bf_table, bf_num, bf_index, bucket) (bf_table[((bucket * bf_num)+bf_index) >> 3] &= (~0x80 >> (((bucket * bf_num)+bf_index) & 7)))\n"\r
+"\n\n"\r
+\r
+"#define lfta_BOOL_to_hash(x) (x)\n"\r
+"#define lfta_USHORT_to_hash(x) (x)\n"\r
+"#define lfta_UINT_to_hash(x) (x)\n"\r
+"#define lfta_IP_to_hash(x) (x)\n"\r
+"#define lfta_IPV6_to_hash(x) ( (x.v[0]) ^ (x.v[1]) ^ (x.v[2]) ^ (x.v[3]))\n"\r
+"#define lfta_INT_to_hash(x) (gs_uint32_t)(x)\n"\r
+"#define lfta_ULLONG_to_hash(x) ( (( (x) >>32)&0xffffffff) ^ ((x)&0xffffffff) )\n"\r
+"#define lfta_LLONG_to_hash(x) ( (( (x) >>32)&0xffffffff) ^ ((x)&0xffffffff) )\n"\r
+"#define lfta_FLOAT_to_hash(x) ( (( ((gs_uint64_t)(x)) >>32)&0xffffffff) ^ (((gs_uint64_t)(x))&0xffffffff) )\n"\r
+"static gs_uint32_t lfta_V_STR_to_hash(struct gs_string x){\n"\r
+"      gs_uint32_t i,ret=0,tmp_sum = 0;\n"\r
+"      for(i=0;i<x.length;++i){\n"\r
+"              tmp_sum |= (x.data[i]) << (8*(i%4));\n"\r
+"              if((i%4) == 3){\n"\r
+"                      ret ^= tmp_sum;\n"\r
+"                      tmp_sum = 0;\n"\r
+"              }\n"\r
+"      }\n"\r
+"      if((i%4)!=0) ret ^=tmp_sum;\n"\r
+"      return(ret);\n"\r
+"}\n\n\n";\r
+\r
+\r
+\r
+//////////////////////////////////////////////////////////////////\r
+/////                  Get all of the query parse trees\r
+\r
+\r
+  int i,p;\r
+  int hfta_count = 0;          // for numeric suffixes to hfta .cc files\r
+\r
+//---------------------------\r
+//             Global info needed for post processing.\r
+\r
+//                     Set of operator views ref'd in the query set.\r
+       opview_set opviews;\r
+//                     lftas on a per-machine basis.\r
+       map<string, vector<stream_query *> > lfta_mach_lists;\r
+       int nfiles = input_file_names.size();\r
+       vector<stream_query *> hfta_list;               // list of hftas.\r
+       map<string, stream_query *> sq_map;             // map from query name to stream query.\r
+\r
+\r
+//////////////////////////////////////////\r
+\r
+//             Open and parse the interface resources file.\r
+       ifq_t *ifaces_db = new ifq_t();\r
+    string ierr;\r
+       if(ifaces_db->load_ifaces(ifx_fname,use_live_hosts_file,distributed_mode,ierr)){\r
+               fprintf(stderr,"ERROR, can't load interface resource file %s :\n%s",\r
+                               ifx_fname.c_str(), ierr.c_str());\r
+               exit(1);\r
+       }\r
+       if(ifaces_db->load_ifqs(ifq_fls[0], ierr)){\r
+               fprintf(stderr,"ERROR, can't load interface query file %s :\n%s",\r
+                               ifq_fls[0].c_str(), ierr.c_str());\r
+               exit(1);\r
+       }\r
+\r
+  map<string, string> qname_to_flname; // for detecting duplicate query names\r
+\r
+\r
+\r
+//                     Parse the files to create a vector of parse trees.\r
+//                     Load qnodes with information to perform a topo sort\r
+//                     based on query dependencies.\r
+  vector<query_node *> qnodes;                         // for topo sort.\r
+  map<string,int> name_node_map;                       // map query name to qnodes entry\r
+  for(i=0;i<input_file_names.size();i++){\r
+\r
+         if((fta_in = fopen(input_file_names[i].c_str(), "r")) == NULL) {\r
+                 fprintf(stderr,"Can't open input file %s\n%s",input_file_names[i].c_str(),strerror(errno));\r
+                 continue;\r
+         }\r
+fprintf(stderr,"Parsing file %s\n",input_file_names[i].c_str());\r
+\r
+//                     Parse the FTA query\r
+         fta_parse_result = new fta_parse_t();\r
+         FtaParser_setfileinput(fta_in);\r
+         if(FtaParserparse()){\r
+               fprintf(stderr,"FTA parse failed.\n");\r
+               exit(1);\r
+         }\r
+         if(fta_parse_result->parse_type != QUERY_PARSE){\r
+               fprintf(stderr,"ERROR, file %s is not a query file.\n",input_file_names[i].c_str());\r
+               exit(1);\r
+         }\r
+\r
+//                     returns a list of parse trees\r
+         vector<table_exp_t *> qlist = fta_parse_result->parse_tree_list->qlist;\r
+         for(p=0;p<qlist.size();++p){\r
+           table_exp_t *fta_parse_tree = qlist[p];\r
+//             query_parse_trees.push_back(fta_parse_tree);\r
+\r
+//                     compute the default name -- extract from query name\r
+               strcpy(tmpstr,input_file_names[i].c_str());\r
+               char *qname = strrchr(tmpstr,PATH_DELIM);\r
+               if(qname == NULL)\r
+                       qname = tmpstr;\r
+               else\r
+                       qname++;\r
+               char *qname_end = strchr(qname,'.');\r
+               if(qname_end != NULL) *qname_end = '\0';\r
+               string qname_str = qname;\r
+               string imputed_qname = impute_query_name(fta_parse_tree, qname_str);\r
+\r
+//                     Deternmine visibility.  Should I be attaching all of the output methods?\r
+               if(qname_to_ospec.count(imputed_qname)>0)\r
+                       fta_parse_tree->set_visible(true);\r
+               else\r
+                       fta_parse_tree->set_visible(false);\r
+\r
+\r
+//                             Create a manipulable repesentation of the parse tree.\r
+//                             the qnode inherits the visibility assigned to the parse tree.\r
+           int pos = qnodes.size();\r
+               qnodes.push_back( new query_node(pos, imputed_qname, input_file_names[i], fta_parse_tree ));\r
+               name_node_map[ qnodes[pos]->name ] = pos;\r
+//printf("name_node_map[ %s ] = %d\n",qnodes[pos]->name.c_str(),pos);\r
+//             qnames.push_back(impute_query_name(fta_parse_tree, qname_str));\r
+//             qfiles.push_back(i);\r
+\r
+//                     Check for duplicate query names\r
+//                                     NOTE : in hfta-only generation, I should\r
+//                                     also check with the names of the registered queries.\r
+               if(qname_to_flname.count(qnodes[pos]->name) > 0){\r
+                       fprintf(stderr,"ERROR duplicate query name %s in files %s and %s.\n",\r
+                               qnodes[pos]->name.c_str(), (qname_to_flname[qnodes[pos]->name]).c_str(), input_file_names[i].c_str());\r
+                       exit(1);\r
+               }\r
+               if(Schema->find_tbl(qnodes[pos]->name) >= 0){\r
+                       fprintf(stderr,"ERROR duplicate query name %s (file %s) was already defined as a PROTOCOL.\n",\r
+                               qnodes[pos]->name.c_str(), input_file_names[i].c_str());\r
+                       exit(1);\r
+               }\r
+               qname_to_flname[qnodes[pos]->name] = input_file_names[i].c_str();\r
+\r
+\r
+       }\r
+  }\r
+\r
+//             Add the library queries\r
+\r
+  int pos;\r
+  for(pos=0;pos<qnodes.size();++pos){\r
+       int fi;\r
+       for(fi = 0;fi<qnodes[pos]->refd_tbls.size();++fi){\r
+               string src_tbl = qnodes[pos]->refd_tbls[fi];\r
+               if(qname_to_flname.count(src_tbl) == 0){\r
+                       int last_sep = src_tbl.find_last_of('/');\r
+                       if(last_sep != string::npos){\r
+fprintf(stderr,"Finding library query %s for query %s\n",src_tbl.c_str(),qnodes[pos]->name.c_str());\r
+                               string target_qname = src_tbl.substr(last_sep+1);\r
+                               string qpathname = library_path + src_tbl + ".gsql";\r
+                               if((fta_in = fopen(qpathname.c_str(), "r")) == NULL) {\r
+                                       fprintf(stderr,"Can't open library file %s, referenced by query %s in file %s\n\t%s\n",qpathname.c_str(),qnodes[pos]->name.c_str(), qname_to_flname[qnodes[pos]->name].c_str(), strerror(errno));\r
+                                       exit(1);\r
+                                       fprintf(stderr,"After exit\n");\r
+                               }\r
+fprintf(stderr,"Parsing file %s\n",qpathname.c_str());\r
+//                     Parse the FTA query\r
+                               fta_parse_result = new fta_parse_t();\r
+                               FtaParser_setfileinput(fta_in);\r
+                               if(FtaParserparse()){\r
+                                       fprintf(stderr,"FTA parse failed.\n");\r
+                                       exit(1);\r
+                               }\r
+                               if(fta_parse_result->parse_type != QUERY_PARSE){\r
+                                       fprintf(stderr,"ERROR, file %s is not a query file.\n",input_file_names[i].c_str());\r
+                                       exit(1);\r
+                               }\r
+\r
+                               map<string, int> local_query_map;\r
+                               vector<string> local_query_names;\r
+                               vector<table_exp_t *> qlist = fta_parse_result->parse_tree_list->qlist;\r
+                               for(p=0;p<qlist.size();++p){\r
+                               table_exp_t *fta_parse_tree = qlist[p];\r
+                                       fta_parse_tree->set_visible(false);             // assumed to not produce output\r
+                                       string imputed_qname = impute_query_name(fta_parse_tree, target_qname);\r
+                                       if(imputed_qname == target_qname)\r
+                                               imputed_qname = src_tbl;\r
+                                       if(local_query_map.count(imputed_qname)>0){\r
+                                               fprintf(stderr,"ERROR, multiple queries named %s in library file %s\n",imputed_qname.c_str(), qpathname.c_str());\r
+                                               exit(1);\r
+                                       }\r
+                                       local_query_map[ imputed_qname ] = p;\r
+                                       local_query_names.push_back(imputed_qname);\r
+                               }\r
+\r
+                               if(local_query_map.count(src_tbl)==0){\r
+                                       fprintf(stderr,"ERROR, library query file %s has no query named %s\n",qpathname.c_str(),target_qname.c_str());\r
+                                       exit(1);\r
+                               }\r
+\r
+                               vector<int> worklist;\r
+                               set<int> added_queries;\r
+                               vector<query_node *> new_qnodes;\r
+                               worklist.push_back(local_query_map[target_qname]);\r
+                               added_queries.insert(local_query_map[target_qname]);\r
+                               int qq;\r
+                               int qpos = qnodes.size();\r
+                               for(qq=0;qq<worklist.size();++qq){\r
+                                       int q_id = worklist[qq];\r
+                                       query_node *new_qnode = new query_node(qpos+qq, local_query_names[q_id], qpathname, qlist[q_id] );\r
+                                       new_qnodes.push_back( new_qnode);\r
+                                       vector<string> refd_tbls =  new_qnode->refd_tbls;\r
+                                       int ff;\r
+                                       for(ff = 0;ff<refd_tbls.size();++ff){\r
+                                               if(local_query_map.count(refd_tbls[ff])>0 && added_queries.count(local_query_map[refd_tbls[ff]])==0){\r
+\r
+                                                       if(name_node_map.count(refd_tbls[ff])>0){\r
+                                                               fprintf(stderr,"ERROR, query %s occurs both in the regular query set, file %s,  and in library file %s\n",refd_tbls[ff].c_str(), qname_to_flname[refd_tbls[ff]].c_str(), qpathname.c_str() );\r
+                                                               exit(1);\r
+                                                       }else{\r
+                                                               worklist.push_back(local_query_map[refd_tbls[ff]]);\r
+                                                       }\r
+                                               }\r
+                                       }\r
+                               }\r
+\r
+                               for(qq=0;qq<new_qnodes.size();++qq){\r
+                                       int qpos = qnodes.size();\r
+                                       qnodes.push_back(new_qnodes[qq]);\r
+                                       name_node_map[qnodes[qpos]->name ] = qpos;\r
+                                       qname_to_flname[qnodes[qpos]->name ] = qpathname;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+  }\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+//---------------------------------------\r
+\r
+\r
+//             Add the UDOPS.\r
+\r
+  string udop_missing_sources;\r
+  for(i=0;i<qnodes.size();++i){\r
+       int fi;\r
+       for(fi = 0;fi<qnodes[i]->refd_tbls.size();++fi){\r
+               int sid = Schema->find_tbl(qnodes[i]->refd_tbls[fi]);\r
+               if(sid >= 0){\r
+                       if(Schema->get_schema_type(sid) == OPERATOR_VIEW_SCHEMA){\r
+                               if(name_node_map.count(qnodes[i]->refd_tbls[fi]) == 0){\r
+                               int pos = qnodes.size();\r
+                                       qnodes.push_back( new query_node(pos, qnodes[i]->refd_tbls[fi], Schema));\r
+                                       name_node_map[ qnodes[pos]->name ] = pos;\r
+                                       qnodes[pos]->is_externally_visible = false;   // its visible\r
+       //                                      Need to mark the source queries as visible.\r
+                                       int si;\r
+                                       string missing_sources = "";\r
+                                       for(si=0;si<qnodes[pos]->refd_tbls.size();++si){\r
+                                               string src_tbl = qnodes[pos]->refd_tbls[si];\r
+                                               if(name_node_map.count(src_tbl)==0){\r
+                                                       missing_sources += src_tbl + " ";\r
+                                               }\r
+                                       }\r
+                                       if(missing_sources != ""){\r
+                                               udop_missing_sources += "\tUDOP "+qnodes[pos]->name+" references undefined tables "+missing_sources+"\n";\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+  }\r
+  if(udop_missing_sources != ""){\r
+       fprintf(stderr,"ERROR, User Defined OPerators reference source tables that are not part of the query set:\n%s",udop_missing_sources.c_str());\r
+       exit(1);\r
+  }\r
+\r
+\r
+\r
+////////////////////////////////////////////////////////////////////\r
+///                            Check parse trees to verify that some\r
+///                            global properties are met :\r
+///                            if q1 reads from q2, then\r
+///                              q2 is processed before q1\r
+///                              q1 can supply q2's parameters\r
+///                            Verify there is no cycle in the reads-from graph.\r
+\r
+//                     Compute an order in which to process the\r
+//                     queries.\r
+\r
+//                     Start by building the reads-from lists.\r
+//\r
+\r
+  for(i=0;i<qnodes.size();++i){\r
+       int qi, fi;\r
+       vector<string> refd_tbls =  qnodes[i]->refd_tbls;\r
+       for(fi = 0;fi<refd_tbls.size();++fi){\r
+               if(name_node_map.count(refd_tbls[fi])>0){\r
+//printf("query %d (%s) reads from %s (%d)\n", i, qnodes[i]->name.c_str(),refd_tbls[fi].c_str(),name_node_map[refd_tbls[fi]]);\r
+                       (qnodes[i]->reads_from).insert(name_node_map[refd_tbls[fi]]);\r
+               }\r
+       }\r
+  }\r
+\r
+\r
+//             If one query reads the result of another,\r
+//             check for parameter compatibility.  Currently it must\r
+//             be an exact match.  I will move to requiring\r
+//             containment after re-ordering, but will require\r
+//             some analysis for code generation which is not\r
+//             yet in place.\r
+//printf("There are %d query nodes.\n",qnodes.size());\r
+\r
+\r
+  for(i=0;i<qnodes.size();++i){\r
+       vector<var_pair_t *> target_params  = qnodes[i]->params;\r
+       for(si=qnodes[i]->reads_from.begin();si!=qnodes[i]->reads_from.end();++si){\r
+               vector<var_pair_t *> source_params  = qnodes[(*si)]->params;\r
+               if(target_params.size() != source_params.size()){\r
+                       fprintf(stderr,"ERROR, query %s (in file %s) reads from %s (in file %s), but they do not have identical parameters.\n",qnodes[i]->name.c_str(), qnodes[i]->file.c_str(), qnodes[(*si)]->name.c_str(), qnodes[(*si)]->file.c_str());\r
+                       exit(1);\r
+               }\r
+               int p;\r
+               for(p=0;p<target_params.size();++p){\r
+                       if(! (target_params[p]->name == source_params[p]->name &&\r
+                             target_params[p]->val == source_params[p]->val ) ){\r
+                       fprintf(stderr,"ERROR, query %s (in file %s) reads from %s (in file %s), but they do not have identical parameters.\n",qnodes[i]->name.c_str(), qnodes[i]->file.c_str(), qnodes[(*si)]->name.c_str(), qnodes[(*si)]->file.c_str());\r
+                               exit(1);\r
+                       }\r
+               }\r
+       }\r
+  }\r
+\r
+\r
+//             Find the roots.\r
+//             Start by counting inedges.\r
+  for(i=0;i<qnodes.size();++i){\r
+       for(si=qnodes[i]->reads_from.begin();si!=qnodes[i]->reads_from.end();++si){\r
+               qnodes[(*si)]->n_consumers++;\r
+       }\r
+  }\r
+\r
+//             The roots are the nodes with indegree zero.\r
+  set<int> roots;\r
+  for(i=0;i<qnodes.size();++i){\r
+       if(qnodes[i]->n_consumers == 0){\r
+               if(qnodes[i]->is_externally_visible == false){\r
+                       fprintf(stderr,"WARNING: query %s (file %s) is a root query but it isn't visible.  Ignored.\n",qnodes[i]->name.c_str(), qnodes[i]->file.c_str());\r
+               }\r
+               roots.insert(i);\r
+       }\r
+  }\r
+\r
+//             Remove the parts of the subtree that produce no output.\r
+  set<int> valid_roots;\r
+  set<int> discarded_nodes;\r
+  set<int> candidates;\r
+  while(roots.size() >0){\r
+       for(si=roots.begin();si!=roots.end();++si){\r
+               if(qnodes[(*si)]->is_externally_visible){\r
+                       valid_roots.insert((*si));\r
+               }else{\r
+                       discarded_nodes.insert((*si));\r
+                       set<int>::iterator sir;\r
+                       for(sir=qnodes[(*si)]->reads_from.begin(); sir!=qnodes[(*si)]->reads_from.end();++sir){\r
+                               qnodes[(*sir)]->n_consumers--;\r
+                               if(qnodes[(*sir)]->n_consumers == 0)\r
+                                       candidates.insert( (*sir));\r
+                       }\r
+               }\r
+       }\r
+       roots = candidates;\r
+       candidates.clear();\r
+  }\r
+  roots = valid_roots;\r
+  if(discarded_nodes.size()>0){\r
+       fprintf(stderr,"Warning, the following queries were discarded because they produce no output:\n");\r
+       int di = 0;\r
+       for(si=discarded_nodes.begin();si!=discarded_nodes.end();++si){\r
+               if(di>0 && (di%8)==0) fprintf(stderr,"\n");\r
+               di++;\r
+               fprintf(stderr," %s",qnodes[(*si)]->name.c_str());\r
+       }\r
+       fprintf(stderr,"\n");\r
+  }\r
+\r
+//             Compute the sources_to set, ignoring discarded nodes.\r
+  for(i=0;i<qnodes.size();++i){\r
+       if(discarded_nodes.count(i)==0)\r
+               for(si=qnodes[i]->reads_from.begin();si!=qnodes[i]->reads_from.end();++si){\r
+                       qnodes[(*si)]->sources_to.insert(i);\r
+       }\r
+  }\r
+\r
+\r
+//             Find the nodes that are shared by multiple visible subtrees.\r
+//             THe roots become inferred visible nodes.\r
+\r
+//             Find the visible nodes.\r
+       vector<int> visible_nodes;\r
+       for(i=0;i<qnodes.size();i++){\r
+               if(qnodes[i]->is_externally_visible){\r
+                       visible_nodes.push_back(i);\r
+               }\r
+       }\r
+\r
+//             Find UDOPs referenced by visible nodes.\r
+  list<int> workq;\r
+  for(i=0;i<visible_nodes.size();++i){\r
+       workq.push_back(visible_nodes[i]);\r
+  }\r
+  while(!workq.empty()){\r
+       int node = workq.front();\r
+       workq.pop_front();\r
+       set<int>::iterator children;\r
+       if(qnodes[node]->is_udop && qnodes[node]->is_externally_visible == false){\r
+               qnodes[node]->is_externally_visible = true;\r
+               visible_nodes.push_back(node);\r
+               for(children=qnodes[node]->reads_from.begin();children!=qnodes[node]->reads_from.end();++children){\r
+                       if(qnodes[(*children)]->is_externally_visible == false){\r
+                               qnodes[(*children)]->is_externally_visible = true;\r
+                               visible_nodes.push_back((*children));\r
+                       }\r
+               }\r
+       }\r
+       for(children=qnodes[node]->reads_from.begin();children!=qnodes[node]->reads_from.end();++children){\r
+               workq.push_back((*children));\r
+       }\r
+  }\r
+\r
+       bool done = false;\r
+       while(!done){\r
+//     reset the nodes\r
+               for(i=0;i<qnodes.size();i++){\r
+                       qnodes[i]->subtree_roots.clear();\r
+               }\r
+\r
+//             Walk the tree defined by a visible node, not descending into\r
+//             subtrees rooted by a visible node.  Mark the node visited with\r
+//             the visible node ID.\r
+               for(i=0;i<visible_nodes.size();++i){\r
+                       set<int> vroots;\r
+                       vroots.insert(visible_nodes[i]);\r
+                       while(vroots.size()>0){\r
+                               for(si=vroots.begin();si!=vroots.end();++si){\r
+                                       qnodes[(*si)]->subtree_roots.insert(visible_nodes[i]);\r
+\r
+                                       set<int>::iterator sir;\r
+                                       for(sir=qnodes[(*si)]->reads_from.begin(); sir!=qnodes[(*si)]->reads_from.end();++sir){\r
+                                               if(! qnodes[(*sir)]->is_externally_visible){\r
+                                                       candidates.insert( (*sir));\r
+                                               }\r
+                                       }\r
+                               }\r
+                               vroots = candidates;\r
+                               candidates.clear();\r
+                       }\r
+               }\r
+//             Find the nodes in multiple visible node subtrees, but with no parent\r
+//             that has is in multile visible node subtrees.  Mark these as inferred visible nodes.\r
+               done = true;    // until proven otherwise\r
+               for(i=0;i<qnodes.size();i++){\r
+                       if(qnodes[i]->subtree_roots.size()>1){\r
+                               bool is_new_root = true;\r
+                               set<int>::iterator sir;\r
+                               for(sir=qnodes[i]->sources_to.begin(); sir!=qnodes[i]->sources_to.end();++sir){\r
+                                       if(qnodes[(*sir)]->subtree_roots.size()>1)\r
+                                               is_new_root = false;\r
+                               }\r
+                               if(is_new_root){\r
+                                       qnodes[i]->is_externally_visible = true;\r
+                                       qnodes[i]->inferred_visible_node = true;\r
+                                       visible_nodes.push_back(i);\r
+                                       done = false;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+\r
+\r
+\r
+\r
+//             get visible nodes in topo ordering.\r
+//  for(i=0;i<qnodes.size();i++){\r
+//             qnodes[i]->n_consumers = qnodes[i]->sources_to.size();\r
+//  }\r
+  vector<int> process_order;\r
+  while(roots.size() >0){\r
+       for(si=roots.begin();si!=roots.end();++si){\r
+               if(discarded_nodes.count((*si))==0){\r
+                       process_order.push_back( (*si) );\r
+               }\r
+               set<int>::iterator sir;\r
+               for(sir=qnodes[(*si)]->reads_from.begin(); sir!=qnodes[(*si)]->reads_from.end();++sir){\r
+                       qnodes[(*sir)]->n_consumers--;\r
+                       if(qnodes[(*sir)]->n_consumers == 0)\r
+                               candidates.insert( (*sir));\r
+               }\r
+       }\r
+       roots = candidates;\r
+       candidates.clear();\r
+  }\r
+\r
+\r
+//printf("process_order.size() =%d\n",process_order.size());\r
+\r
+//             Search for cyclic dependencies\r
+  string found_dep;\r
+  for(i=0;i<qnodes.size();++i){\r
+       if(discarded_nodes.count(i)==0 && qnodes[i]->n_consumers > 0){\r
+               if(found_dep.size() != 0) found_dep += ", ";\r
+               found_dep += "query "+qnodes[i]->name+" (file "+qnodes[i]->file+")";\r
+       }\r
+  }\r
+  if(found_dep.size()>0){\r
+       fprintf(stderr,"ERROR, the following queries contain a cyclic reads-from dependency:\n%s\n",found_dep.c_str());\r
+       exit(1);\r
+  }\r
+\r
+//             Get a list of query sets, in the order to be processed.\r
+//             Start at visible root and do bfs.\r
+//             The query set includes queries referenced indirectly,\r
+//             as sources for user-defined operators.  These are needed\r
+//             to ensure that they are added to the schema, but are not part\r
+//             of the query tree.\r
+\r
+//             stream_node_sets contains queries reachable only through the\r
+//             FROM clause, so I can tell which queries to add to the stream\r
+//             query. (DISABLED, UDOPS are integrated, does this cause problems?)\r
+\r
+//                     NOTE: this code works because in order for data to be\r
+//                     read by multiple hftas, the node must be externally visible.\r
+//                     But visible nodes define roots of process sets.\r
+//                     internally visible nodes can feed data only\r
+//                     to other nodes in the same query file.\r
+//                     Therefore, any access can be restricted to a file,\r
+//                     hfta output sharing is done only on roots\r
+//                     never on interior nodes.\r
+\r
+\r
+\r
+\r
+//             Conpute the base collection of hftas.\r
+  vector<hfta_node *> hfta_sets;\r
+  map<string, int> hfta_name_map;\r
+//  vector< vector<int> > process_sets;\r
+//  vector< set<int> > stream_node_sets;\r
+  reverse(process_order.begin(), process_order.end());  // get listing in reverse order.\r
+                                                                                                               // i.e. process leaves 1st.\r
+  for(i=0;i<process_order.size();++i){\r
+       if(qnodes[process_order[i]]->is_externally_visible == true){\r
+//printf("Visible.\n");\r
+               int root = process_order[i];\r
+               hfta_node *hnode = new hfta_node();\r
+               hnode->name = qnodes[root]-> name;\r
+               hnode->source_name = qnodes[root]-> name;\r
+               hnode->is_udop = qnodes[root]->is_udop;\r
+               hnode->inferred_visible_node = qnodes[root]->inferred_visible_node;\r
+\r
+               vector<int> proc_list;  proc_list.push_back(root);\r
+//                     Ensure that nodes are added only once.\r
+               set<int> proc_set;      proc_set.insert(root);\r
+               roots.clear();                  roots.insert(root);\r
+               candidates.clear();\r
+               while(roots.size()>0){\r
+                       for(si=roots.begin();si!=roots.end();++si){\r
+//printf("Processing root %d\n",(*si));\r
+                               set<int>::iterator sir;\r
+                               for(sir=qnodes[(*si)]->reads_from.begin(); sir!=qnodes[(*si)]->reads_from.end();++sir){\r
+//printf("reads fom %d\n",(*sir));\r
+                                       if(qnodes[(*sir)]->is_externally_visible==false){\r
+                                               candidates.insert( (*sir) );\r
+                                               if(proc_set.count( (*sir) )==0){\r
+                                                       proc_set.insert( (*sir) );\r
+                                                       proc_list.push_back( (*sir) );\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+                       roots = candidates;\r
+                       candidates.clear();\r
+               }\r
+\r
+               reverse(proc_list.begin(), proc_list.end());\r
+               hnode->query_node_indices = proc_list;\r
+               hfta_name_map[hnode->name] = hfta_sets.size();\r
+               hfta_sets.push_back(hnode);\r
+       }\r
+  }\r
+\r
+//             Compute the reads_from / sources_to graphs for the hftas.\r
+\r
+  for(i=0;i<hfta_sets.size();++i){\r
+       hfta_node *hnode = hfta_sets[i];\r
+       for(q=0;q<hnode->query_node_indices.size();q++){\r
+               query_node *qnode = qnodes[hnode->query_node_indices[q]];\r
+               for(s=0;s<qnode->refd_tbls.size();++s){\r
+                       if(hfta_name_map.count(qnode->refd_tbls[s])){\r
+                               int other_hfta = hfta_name_map[qnode->refd_tbls[s]];\r
+                               hnode->reads_from.insert(other_hfta);\r
+                               hfta_sets[other_hfta]->sources_to.insert(i);\r
+                       }\r
+               }\r
+       }\r
+  }\r
+\r
+//             Compute a topological sort of the hfta_sets.\r
+\r
+  vector<int> hfta_topsort;\r
+  workq.clear();\r
+  int hnode_srcs[hfta_sets.size()];\r
+  for(i=0;i<hfta_sets.size();++i){\r
+       hnode_srcs[i] = 0;\r
+       if(hfta_sets[i]->sources_to.size() == 0)\r
+               workq.push_back(i);\r
+  }\r
+\r
+  while(! workq.empty()){\r
+       int     node = workq.front();\r
+       workq.pop_front();\r
+       hfta_topsort.push_back(node);\r
+       set<int>::iterator stsi;\r
+       for(stsi=hfta_sets[node]->reads_from.begin();stsi!=hfta_sets[node]->reads_from.end();++stsi){\r
+               int parent = (*stsi);\r
+               hnode_srcs[parent]++;\r
+               if(hnode_srcs[parent] == hfta_sets[parent]->sources_to.size()){\r
+                       workq.push_back(parent);\r
+               }\r
+       }\r
+  }\r
+\r
+//             Decorate hfta nodes with the level of parallelism given as input.\r
+\r
+  map<string, int>::iterator msii;\r
+  for(msii=hfta_parallelism.begin();msii!=hfta_parallelism.end();++msii){\r
+       string hfta_name = (*msii).first;\r
+       int par = (*msii).second;\r
+       if(hfta_name_map.count(hfta_name) > 0){\r
+               hfta_sets[ hfta_name_map[hfta_name] ]->n_parallel = par;\r
+       }else{\r
+               fprintf(stderr,"Warning, hfta_parallelism.cfg has an entry for %s, but its not a hfta.\n",hfta_name.c_str());\r
+       }\r
+  }\r
+\r
+//             Propagate levels of parallelism: children should have a level of parallelism\r
+//             as large as any of its parents.  Adjust children upwards to compensate.\r
+//             Start at parents and adjust children, auto-propagation will occur.\r
+\r
+  for(i=hfta_sets.size()-1;i>=0;i--){\r
+       set<int>::iterator stsi;\r
+       for(stsi=hfta_sets[i]->reads_from.begin();stsi!=hfta_sets[i]->reads_from.end();++stsi){\r
+               if(hfta_sets[i]->n_parallel > hfta_sets[ (*stsi) ]->n_parallel){\r
+                       hfta_sets[ (*stsi) ]->n_parallel = hfta_sets[i]->n_parallel;\r
+               }\r
+       }\r
+  }\r
+\r
+//             Before all the name mangling, check if therey are any output_spec.cfg\r
+//             or hfta_parallelism.cfg entries that do not have a matching query.\r
+\r
+       string dangling_ospecs = "";\r
+       for(msii=qname_to_ospec.begin();msii!=qname_to_ospec.end();++msii){\r
+               string oq = (*msii).first;\r
+               if(hfta_name_map.count(oq) == 0){\r
+                       dangling_ospecs += " "+(*msii).first;\r
+               }\r
+       }\r
+       if(dangling_ospecs!=""){\r
+               fprintf(stderr,"WARNING, the following entries in output_spec.cfg don't have a matching query: %s\n",dangling_ospecs.c_str());\r
+       }\r
+\r
+       string dangling_par = "";\r
+       for(msii=hfta_parallelism.begin();msii!=hfta_parallelism.end();++msii){\r
+               string oq = (*msii).first;\r
+               if(hfta_name_map.count(oq) == 0){\r
+                       dangling_par += " "+(*msii).first;\r
+               }\r
+       }\r
+       if(dangling_par!=""){\r
+               fprintf(stderr,"WARNING, the following entries in hfta_parallelism.cfg don't have a matching query: %s\n",dangling_par.c_str());\r
+       }\r
+\r
+\r
+\r
+//             Replicate parallelized hftas.  Do __copyX name mangling.  Adjust\r
+//             FROM clauses: retarget any name which is an internal node, and\r
+//             any which is in hfta_sets (and which is parallelized). Add Merge nodes\r
+//             when the source hfta has more parallelism than the target node.\r
+//             Add new nodes to qnodes and hfta_nodes wth the appropriate linkages.\r
+\r
+\r
+  int n_original_hfta_sets = hfta_sets.size();\r
+  for(i=0;i<n_original_hfta_sets;++i){\r
+       if(hfta_sets[i]->n_parallel > 1){\r
+               hfta_sets[i]->do_generation =false;     // set the deletion flag for this entry.\r
+               set<string> local_nodes;                // names of query nodes in the hfta.\r
+               for(h=0;h<hfta_sets[i]->query_node_indices.size();++h){\r
+                       local_nodes.insert(qnodes[ hfta_sets[i]->query_node_indices[h] ]->name);\r
+               }\r
+\r
+               for(p=0;p<hfta_sets[i]->n_parallel;++p){\r
+                       string mangler = "__copy"+int_to_string(p);\r
+                       hfta_node *par_hfta  = new hfta_node();\r
+                       par_hfta->name = hfta_sets[i]->name + mangler;\r
+                       par_hfta->source_name = hfta_sets[i]->name;\r
+                       par_hfta->is_udop = hfta_sets[i]->is_udop;\r
+                       par_hfta->inferred_visible_node = hfta_sets[i]->inferred_visible_node;\r
+                       par_hfta->n_parallel = hfta_sets[i]->n_parallel;\r
+                       par_hfta->parallel_idx = p;\r
+\r
+                       map<string, int> par_qnode_map; // qnode name-to-idx, aids dependency tracking.\r
+\r
+//     Is it a UDOP?\r
+                       if(hfta_sets[i]->is_udop){\r
+                               int root = hfta_sets[i]->query_node_indices[0];\r
+\r
+                               string unequal_par_sources;\r
+                               set<int>::iterator rfsii;\r
+                               for(rfsii=hfta_sets[i]->reads_from.begin();rfsii!=hfta_sets[i]->reads_from.end();++rfsii){\r
+                                       if(hfta_sets[(*rfsii)]->n_parallel != par_hfta->n_parallel){\r
+                                               unequal_par_sources = hfta_sets[(*rfsii)]->name+" ("+int_to_string(hfta_sets[(*rfsii)]->n_parallel)+") ";\r
+                                       }\r
+                               }\r
+                               if(unequal_par_sources != ""){\r
+                                       fprintf(stderr,"ERROR, UDOP %s has parallelism %d, but some of its sources have a different parallelism: %s\n",hfta_sets[i]->name.c_str(), hfta_sets[i]->n_parallel, unequal_par_sources.c_str());\r
+                                       exit(1);\r
+                               }\r
+\r
+                               int rti;\r
+                               vector<string> new_sources;\r
+                               for(rti=0;rti<qnodes[root]->refd_tbls.size();++rti){\r
+                                       new_sources.push_back(qnodes[root]->refd_tbls[rti]+mangler);\r
+                               }\r
+\r
+                               query_node *new_qn = new query_node(qnodes.size(), qnodes[root]->name, Schema);\r
+                               new_qn->name += mangler;\r
+                               new_qn->mangler = mangler;\r
+                               new_qn->refd_tbls = new_sources;\r
+                               par_hfta->query_node_indices.push_back(qnodes.size());\r
+                               par_qnode_map[new_qn->name] = qnodes.size();\r
+                               name_node_map[ new_qn->name ] = qnodes.size();\r
+                               qnodes.push_back(new_qn);\r
+                       }else{\r
+//             regular query node\r
+                         for(h=0;h<hfta_sets[i]->query_node_indices.size();++h){\r
+                               int hqn_idx = hfta_sets[i]->query_node_indices[h];\r
+                               table_exp_t *dup_pt = dup_table_exp(qnodes[hqn_idx]->parse_tree);\r
+//                                     rehome the from clause on mangled names.\r
+//                                     create merge nodes as needed for external sources.\r
+                               for(f=0;f<dup_pt->fm->tlist.size();++f){\r
+                                       if(local_nodes.count(dup_pt->fm->tlist[f]->schema_name)>0){\r
+                                               dup_pt->fm->tlist[f]->schema_name += mangler;\r
+                                       }else if(hfta_name_map.count(dup_pt->fm->tlist[f]->schema_name)>0){\r
+//                     Ref's an external HFTA.  No parallelism => leave as is.  Else, if level of parallelism of the two hftas is the same, rename by the mangler.  Else, there mnust be more sources, so create a merge node.\r
+                                               int other_hidx = hfta_name_map[dup_pt->fm->tlist[f]->schema_name];\r
+                                               if(par_hfta->n_parallel == hfta_sets[other_hidx]->n_parallel){\r
+                                                       dup_pt->fm->tlist[f]->schema_name += mangler;\r
+                                               }else{\r
+                                                       vector<string> src_tbls;\r
+                                                       int stride = hfta_sets[other_hidx]->n_parallel / par_hfta->n_parallel;\r
+                                                       if(stride == 0){\r
+                                                               fprintf(stderr,"INTERNAL ERROR, parent hfta %s has a larger parallelism than its child %s\n",par_hfta->name.c_str(), hfta_sets[other_hidx]->name.c_str());\r
+                                                               exit(1);\r
+                                                       }\r
+                                                       for(s=0;s<stride;++s){\r
+                                                               string ext_src_name = hfta_sets[other_hidx]->name+"__copy"+int_to_string(s+stride*p);\r
+                                                               src_tbls.push_back(ext_src_name);\r
+                                                       }\r
+                                                       table_exp_t *merge_pt = table_exp_t::make_deferred_merge(src_tbls);\r
+                                                       string merge_node_name = qnodes[hqn_idx]->name+"__copy"+int_to_string(p)+"__merge"+int_to_string(f);\r
+                                                       dup_pt->fm->tlist[f]->schema_name = merge_node_name;\r
+//                                     Make a qnode to represent the new merge node\r
+                                                       query_node *qn_pt = new query_node(qnodes.size(),merge_node_name, qnodes[hqn_idx]->file,merge_pt);\r
+                                                       qn_pt->refd_tbls = src_tbls;\r
+                                                       qn_pt->is_udop  = false;\r
+                                                       qn_pt->is_externally_visible = false;\r
+                                                       qn_pt->inferred_visible_node  = false;\r
+                                                       par_hfta->query_node_indices.push_back(qnodes.size());\r
+                                                       par_qnode_map[merge_node_name] = qnodes.size();\r
+                                                       name_node_map[ merge_node_name ] = qnodes.size();\r
+                                                       qnodes.push_back(qn_pt);\r
+                                               }\r
+                                       }\r
+                               }\r
+                               query_node *new_qn = new query_node(qnodes.size(),qnodes[hqn_idx]->name+"__copy"+int_to_string(p),qnodes[hqn_idx]->file,dup_pt);\r
+                               for(f=0;f<dup_pt->fm->tlist.size();++f){\r
+                                       new_qn->refd_tbls.push_back(dup_pt->fm->tlist[f]->schema_name);\r
+                               }\r
+                               new_qn->params = qnodes[hqn_idx]->params;\r
+                               new_qn->is_udop = false;\r
+                               new_qn->is_externally_visible = qnodes[hqn_idx]->is_externally_visible;\r
+                               new_qn->inferred_visible_node = qnodes[hqn_idx]->inferred_visible_node;\r
+                               par_hfta->query_node_indices.insert(par_hfta->query_node_indices.begin(),qnodes.size());\r
+                               par_qnode_map[new_qn->name] = qnodes.size();\r
+                               name_node_map[ new_qn->name ] = qnodes.size();\r
+                               qnodes.push_back(new_qn);\r
+                         }\r
+                       }\r
+                       hfta_name_map[par_hfta->name] = hfta_sets.size();\r
+                       hfta_sets.push_back(par_hfta);\r
+               }\r
+       }else{\r
+//             This hfta isn't being parallelized, but add merge nodes for any parallelized\r
+//             hfta sources.\r
+               if(!hfta_sets[i]->is_udop){\r
+                 for(h=0;h<hfta_sets[i]->query_node_indices.size();++h){\r
+                       int hqn_idx = hfta_sets[i]->query_node_indices[h];\r
+                       for(f=0;f<qnodes[hqn_idx]->parse_tree->fm->tlist.size();++f){\r
+                               if(hfta_name_map.count(qnodes[hqn_idx]->parse_tree->fm->tlist[f]->schema_name)>0){\r
+//                     Ref's an external HFTA.  No parallelism => leave as is.  Else, if level of parallelism of the two hftas is the same, rename by the mangler.  Else, there mnust be more sources, so create a merge node.\r
+                                       int other_hidx = hfta_name_map[qnodes[hqn_idx]->parse_tree->fm->tlist[f]->schema_name];\r
+                                       if(hfta_sets[i]->n_parallel != hfta_sets[other_hidx]->n_parallel){\r
+                                               vector<string> src_tbls;\r
+                                               for(s=0;s<hfta_sets[other_hidx]->n_parallel;++s){\r
+                                                       string ext_src_name = hfta_sets[other_hidx]->name+"__copy"+int_to_string(s);\r
+                                                       src_tbls.push_back(ext_src_name);\r
+                                               }\r
+                                               table_exp_t *merge_pt = table_exp_t::make_deferred_merge(src_tbls);\r
+                                               string merge_node_name = qnodes[hqn_idx]->name+"__merge"+int_to_string(f);\r
+                                               qnodes[hqn_idx]->parse_tree->fm->tlist[f]->schema_name = merge_node_name;\r
+//                                     Make a qnode to represent the new merge node\r
+                                               query_node *qn_pt = new query_node(qnodes.size(),merge_node_name, qnodes[hqn_idx]->file,merge_pt);\r
+                                               qn_pt->refd_tbls = src_tbls;\r
+                                               qn_pt->is_udop  = false;\r
+                                               qn_pt->is_externally_visible = false;\r
+                                               qn_pt->inferred_visible_node  = false;\r
+                                               hfta_sets[i]->query_node_indices.insert(hfta_sets[i]->query_node_indices.begin(),qnodes.size());\r
+                                               name_node_map[ merge_node_name ] = qnodes.size();\r
+                                               qnodes.push_back(qn_pt);\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+         }\r
+       }\r
+  }\r
+\r
+//                     Rebuild the reads_from / sources_to lists in the qnodes\r
+  for(q=0;q<qnodes.size();++q){\r
+       qnodes[q]->reads_from.clear();\r
+       qnodes[q]->sources_to.clear();\r
+  }\r
+  for(q=0;q<qnodes.size();++q){\r
+       for(s=0;s<qnodes[q]->refd_tbls.size();++s){\r
+               if(name_node_map.count(qnodes[q]->refd_tbls[s])>0){\r
+                       int rf = name_node_map[qnodes[q]->refd_tbls[s]];\r
+                       qnodes[q]->reads_from.insert(rf);\r
+                       qnodes[rf]->sources_to.insert(q);\r
+               }\r
+       }\r
+  }\r
+\r
+//                     Rebuild the reads_from / sources_to lists in hfta_sets\r
+  for(q=0;q<hfta_sets.size();++q){\r
+       hfta_sets[q]->reads_from.clear();\r
+       hfta_sets[q]->sources_to.clear();\r
+  }\r
+  for(q=0;q<hfta_sets.size();++q){\r
+       for(s=0;s<hfta_sets[q]->query_node_indices.size();++s){\r
+               int node = hfta_sets[q]->query_node_indices[s];\r
+               set<int>::iterator rfsii;\r
+               for(rfsii=qnodes[node]->reads_from.begin();rfsii!=qnodes[node]->reads_from.end();++rfsii){\r
+                       if(hfta_name_map.count(qnodes[(*rfsii)]->name)>0){\r
+                               hfta_sets[q]->reads_from.insert(hfta_name_map[qnodes[(*rfsii)]->name]);\r
+                               hfta_sets[hfta_name_map[qnodes[(*rfsii)]->name]]->sources_to.insert(q);\r
+                       }\r
+               }\r
+       }\r
+  }\r
+\r
+/*\r
+for(q=0;q<qnodes.size();++q){\r
+ printf("qnode %d reads-from %d:",q,qnodes[q]->reads_from.size());\r
+ set<int>::iterator rsii;\r
+ for(rsii=qnodes[q]->reads_from.begin();rsii!=qnodes[q]->reads_from.end();++rsii)\r
+  printf(" %d",(*rsii));\r
+  printf(", and sources-to %d:",qnodes[q]->sources_to.size());\r
+ for(rsii=qnodes[q]->sources_to.begin();rsii!=qnodes[q]->sources_to.end();++rsii)\r
+  printf(" %d",(*rsii));\r
+ printf("\n");\r
+}\r
+\r
+for(q=0;q<hfta_sets.size();++q){\r
+ if(hfta_sets[q]->do_generation==false)\r
+       continue;\r
+ printf("hfta %d (%s) reads-from %d:",q,hfta_sets[q]->name.c_str(),hfta_sets[q]->reads_from.size());\r
+ set<int>::iterator rsii;\r
+ for(rsii=hfta_sets[q]->reads_from.begin();rsii!=hfta_sets[q]->reads_from.end();++rsii)\r
+  printf(" %d",(*rsii));\r
+  printf(", and sources-to %d:",hfta_sets[q]->sources_to.size());\r
+ for(rsii=hfta_sets[q]->sources_to.begin();rsii!=hfta_sets[q]->sources_to.end();++rsii)\r
+  printf(" %d",(*rsii));\r
+ printf("\n");\r
+}\r
+*/\r
+\r
+\r
+\r
+//             Re-topo sort the hftas\r
+  hfta_topsort.clear();\r
+  workq.clear();\r
+  int hnode_srcs_2[hfta_sets.size()];\r
+  for(i=0;i<hfta_sets.size();++i){\r
+       hnode_srcs_2[i] = 0;\r
+       if(hfta_sets[i]->sources_to.size() == 0 && hfta_sets[i]->do_generation){\r
+               workq.push_back(i);\r
+       }\r
+  }\r
+\r
+  while(workq.empty() == false){\r
+       int     node = workq.front();\r
+       workq.pop_front();\r
+       hfta_topsort.push_back(node);\r
+       set<int>::iterator stsii;\r
+       for(stsii=hfta_sets[node]->reads_from.begin();stsii!=hfta_sets[node]->reads_from.end();++stsii){\r
+               int child = (*stsii);\r
+               hnode_srcs_2[child]++;\r
+               if(hnode_srcs_2[child] == hfta_sets[child]->sources_to.size()){\r
+                       workq.push_back(child);\r
+               }\r
+       }\r
+  }\r
+\r
+//             Ensure that all of the query_node_indices in hfta_sets are topologically\r
+//             sorted, don't rely on assumptions that all transforms maintain some kind of order.\r
+  for(i=0;i<hfta_sets.size();++i){\r
+       if(hfta_sets[i]->do_generation){\r
+               map<int,int> n_accounted;\r
+               vector<int> new_order;\r
+               workq.clear();\r
+               vector<int>::iterator vii;\r
+               for(vii=hfta_sets[i]->query_node_indices.begin();vii!=hfta_sets[i]->query_node_indices.end();++vii){\r
+                       n_accounted[(*vii)]= 0;\r
+               }\r
+               for(vii=hfta_sets[i]->query_node_indices.begin();vii!=hfta_sets[i]->query_node_indices.end();++vii){\r
+                       set<int>::iterator rfsii;\r
+                       for(rfsii=qnodes[(*vii)]->reads_from.begin();rfsii!=qnodes[(*vii)]->reads_from.end();++rfsii){\r
+                               if(n_accounted.count((*rfsii)) == 0){\r
+                                       n_accounted[(*vii)]++;\r
+                               }\r
+                       }\r
+                       if(n_accounted[(*vii)] == qnodes[(*vii)]->reads_from.size()){\r
+                               workq.push_back((*vii));\r
+                       }\r
+               }\r
+\r
+               while(workq.empty() == false){\r
+                       int node = workq.front();\r
+                       workq.pop_front();\r
+                       new_order.push_back(node);\r
+                       set<int>::iterator stsii;\r
+                       for(stsii=qnodes[node]->sources_to.begin();stsii!=qnodes[node]->sources_to.end();++stsii){\r
+                               if(n_accounted.count((*stsii))){\r
+                                       n_accounted[(*stsii)]++;\r
+                                       if(n_accounted[(*stsii)] == qnodes[(*stsii)]->reads_from.size()){\r
+                                               workq.push_back((*stsii));\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+               hfta_sets[i]->query_node_indices = new_order;\r
+       }\r
+  }\r
+\r
+\r
+\r
+\r
+\r
+///                    Global checkng is done, start the analysis and translation\r
+///                    of the query parse tree in the order specified by process_order\r
+\r
+\r
+//                     Get a list of the LFTAs for global lfta optimization\r
+//                             TODO: separate building operators from spliting lftas,\r
+//                                     that will make optimizations such as predicate pushing easier.\r
+       vector<stream_query *> lfta_list;\r
+\r
+       stream_query *rootq;\r
+\r
+    int qi,qj;\r
+\r
+       for(qi=hfta_topsort.size()-1;qi>=0;--qi){\r
+\r
+       int hfta_id = hfta_topsort[qi];\r
+    vector<int> curr_list = hfta_sets[hfta_id]->query_node_indices;\r
+\r
+\r
+\r
+//             Two possibilities, either its a UDOP, or its a collection of queries.\r
+//     if(qnodes[curr_list.back()]->is_udop)\r
+       if(hfta_sets[hfta_id]->is_udop){\r
+               int node_id = curr_list.back();\r
+               int udop_schref = Schema->find_tbl(qnodes[node_id]->file);\r
+               opview_entry *opv = new opview_entry();\r
+\r
+//                     Many of the UDOP properties aren't currently used.\r
+               opv->parent_qname = "no_parent";\r
+               opv->root_name = qnodes[node_id]->name;\r
+               opv->view_name = qnodes[node_id]->file;\r
+               opv->pos = qi;\r
+               sprintf(tmpstr,"%s_UDOP%d_%s",qnodes[node_id]->name.c_str(),qi,opv->view_name.c_str());\r
+               opv->udop_alias = tmpstr;\r
+               opv->mangler = qnodes[node_id]->mangler;\r
+\r
+               if(opv->mangler != ""){\r
+                       int new_udop_schref = Schema->add_duplicate_table(opv->view_name,opv->root_name);\r
+                       Schema->mangle_subq_names(new_udop_schref,opv->mangler);\r
+               }\r
+\r
+//                     This piece of code makes each hfta which referes to the same udop\r
+//                     reference a distinct running udop.  Do this at query optimization time?\r
+//             fmtbl->set_udop_alias(opv->udop_alias);\r
+\r
+               opv->exec_fl = Schema->get_op_prop(udop_schref, string("file"));\r
+               opv->liveness_timeout = atoi(Schema->get_op_prop(udop_schref, string("liveness_timeout")).c_str());\r
+\r
+               vector<subquery_spec *> subq = Schema->get_subqueryspecs(udop_schref);\r
+               int s,f,q;\r
+               for(s=0;s<subq.size();++s){\r
+//                             Validate that the fields match.\r
+                       subquery_spec *sqs = subq[s];\r
+                       string subq_name = sqs->name + opv->mangler;\r
+                       vector<field_entry *> flds = Schema->get_fields(subq_name);\r
+                       if(flds.size() == 0){\r
+                               fprintf(stderr,"INTERNAL ERROR: the subquery %s of view %s not found in Schema.\n",subq_name.c_str(), opv->view_name.c_str());\r
+                               return(1);\r
+                       }\r
+                       if(flds.size() < sqs->types.size()){\r
+                               fprintf(stderr,"ERROR: subquery %s of view %s does not have enough fields (%lu found, %lu expected).\n",subq_name.c_str(), opv->view_name.c_str(),flds.size(), sqs->types.size());\r
+                               return(1);\r
+                       }\r
+                       bool failed = false;\r
+                       for(f=0;f<sqs->types.size();++f){\r
+                               data_type dte(sqs->types[f],sqs->modifiers[f]);\r
+                               data_type dtf(flds[f]->get_type(),flds[f]->get_modifier_list());\r
+                               if(! dte.subsumes_type(&dtf) ){\r
+                                       fprintf(stderr,"ERROR: subquery %s of view %s does not have the correct type for field %d (%s found, %s expected).\n",subq_name.c_str(), opv->view_name.c_str(),f,dtf.to_string().c_str(), dte.to_string().c_str());\r
+                                       failed = true;\r
+                               }\r
+/*\r
+                               if(dte.is_temporal() && (dte.get_temporal() != dtf.get_temporal()) ){\r
+                                       string pstr = dte.get_temporal_string();\r
+                                       fprintf(stderr,"ERROR: subquery %s of view %s does not have the expected temporal value %s of field %d.\n",sqs->name.c_str(), opv->view_name.c_str(),pstr.c_str(),f);\r
+                                       failed = true;\r
+                               }\r
+*/\r
+                       }\r
+                       if(failed)\r
+                               return(1);\r
+///                            Validation done, find the subquery, make a copy of the\r
+///                            parse tree, and add it to the return list.\r
+                       for(q=0;q<qnodes.size();++q)\r
+                               if(qnodes[q]->name == subq_name)\r
+                                       break;\r
+                       if(q==qnodes.size()){\r
+                               fprintf(stderr,"INTERNAL ERROR: subquery %s of view %s not found in list of query names.\n",subq_name.c_str(), opv->view_name.c_str());\r
+                               return(1);\r
+                       }\r
+\r
+               }\r
+\r
+//                     Cross-link to from entry(s) in all sourced-to tables.\r
+               set<int>::iterator sii;\r
+               for(sii=qnodes[curr_list.back()]->sources_to.begin() ;sii!=qnodes[curr_list.back()]->sources_to.end();++sii){\r
+//printf("\tUDOP %s sources_to %d (%s)\n",hfta_sets[hfta_id]->name.c_str(),(*sii),hfta_sets[(*sii)]->name.c_str());\r
+                       vector<tablevar_t *> tblvars = qnodes[(*sii)]->parse_tree->get_from()->get_table_list();\r
+                       int ii;\r
+                       for(ii=0;ii<tblvars.size();++ii){\r
+                               if(tblvars[ii]->schema_name == opv->root_name){\r
+                                       tblvars[ii]->set_opview_idx(opviews.size());\r
+                               }\r
+\r
+                       }\r
+               }\r
+\r
+               opviews.append(opv);\r
+       }else{\r
+\r
+//                     Analyze the parse trees in this query,\r
+//                     put them in rootq\r
+//      vector<int> curr_list = process_sets[qi];\r
+\r
+\r
+////////////////////////////////////////\r
+\r
+         rootq = NULL;\r
+//printf("Process set %d, has %d queries\n",qi,curr_list.size());\r
+         for(qj=0;qj<curr_list.size();++qj){\r
+               i = curr_list[qj];\r
+       fprintf(stderr,"Processing query %s (file %s) is_udop = %d\n",qnodes[i]->name.c_str(), qnodes[i]->file.c_str(),qnodes[i]->is_udop);\r
+\r
+//                     Select the current query parse tree\r
+               table_exp_t *fta_parse_tree = qnodes[i]->parse_tree;\r
+\r
+//                     if hfta only, try to fetch any missing schemas\r
+//                     from the registry (using the print_schema program).\r
+//                     Here I use a hack to avoid analyzing the query -- all referenced\r
+//                     tables must be in the from clause\r
+//                     If there is a problem loading any table, just issue a warning,\r
+//\r
+               tablevar_list_t *fm = fta_parse_tree->get_from();\r
+               vector<string> refd_tbls =  fm->get_src_tbls(Schema);\r
+//                     iterate over all referenced tables\r
+               int t;\r
+               for(t=0;t<refd_tbls.size();++t){\r
+                 int tbl_ref = Schema->get_table_ref(refd_tbls[t]);\r
+\r
+                 if(tbl_ref < 0){      // if this table is not in the Schema\r
+\r
+                       if(hfta_only){\r
+                               string cmd="print_schema "+refd_tbls[t];\r
+                               FILE *schema_in = popen(cmd.c_str(), "r");\r
+                               if(schema_in == NULL){\r
+                                 fprintf(stderr,"ERROR: cannot execute command %s\n",cmd.c_str());\r
+                               }else{\r
+                                 string schema_instr;\r
+                                 while(fgets(tmpstr,TMPSTRLEN,schema_in)){\r
+                                       schema_instr += tmpstr;\r
+                                 }\r
+                         fta_parse_result = new fta_parse_t();\r
+                                 strcpy(tmp_schema_str,schema_instr.c_str());\r
+                                 FtaParser_setstringinput(tmp_schema_str);\r
+                         if(FtaParserparse()){\r
+                                       fprintf(stderr,"FTA parse failed on result from command %s.\n",cmd.c_str());\r
+                         }else{\r
+                                       if( fta_parse_result->tables != NULL){\r
+                                               int tl;\r
+                                               for(tl=0;tl<fta_parse_result->tables->size();++tl){\r
+                                                       Schema->add_table(fta_parse_result->tables->get_table(tl));\r
+                                               }\r
+                                       }else{\r
+                                               fprintf(stderr,"ERROR command %s returned no tables.\n",cmd.c_str());\r
+                                       }\r
+                               }\r
+                       }\r
+                 }else{\r
+                               fprintf(stderr,"ERROR, query %s (file %s) references stream %s, which is neither a PROTOCOL nor an externally visible query stream.\n", qnodes[i]->name.c_str(), qnodes[i]->file.c_str(), refd_tbls[t].c_str());\r
+                               exit(1);\r
+                 }\r
+\r
+               }\r
+         }\r
+\r
+\r
+//                             Analyze the query.\r
+         query_summary_class *qs = analyze_fta(fta_parse_tree, Schema, Ext_fcns, qnodes[i]->name);\r
+         if(qs == NULL){\r
+               fprintf(stderr,"analyze_fta failed on query %s (file %s) \n",qnodes[i]->name.c_str(),qnodes[i]->file.c_str());\r
+               exit(1);\r
+         }\r
+\r
+         stream_query new_sq(qs, Schema);\r
+         if(new_sq.error_code){\r
+                       fprintf(stderr,"ERROR, can't create query node for query %s (file %s):\n%s\n",qnodes[i]->name.c_str(),qnodes[i]->file.c_str(),new_sq.err_str.c_str());\r
+                       exit(1);\r
+         }\r
+\r
+//                     Add it to the Schema\r
+         table_def *output_td = new_sq.get_output_tabledef();\r
+         Schema->add_table(output_td);\r
+\r
+//                     Create a query plan from the analyzed parse tree.\r
+//                     If its a query referneced via FROM, add it to the stream query.\r
+         if(rootq){\r
+               rootq->add_query(new_sq);\r
+         }else{\r
+               rootq = new stream_query(new_sq);\r
+//                     have the stream query object inherit properties form the analyzed\r
+//                     hfta_node object.\r
+               rootq->set_nparallel(hfta_sets[hfta_id]->n_parallel,hfta_sets[hfta_id]->parallel_idx);\r
+               rootq->n_successors = hfta_sets[hfta_id]->sources_to.size();\r
+         }\r
+\r
+\r
+    }\r
+\r
+//             This stream query has all its parts\r
+//             Build and optimize it.\r
+//printf("translate_fta: generating plan.\n");\r
+       if(rootq->generate_plan(Schema)){\r
+               fprintf(stderr,"INTERNAL ERROR: Can't generate query plan for query %s.\n",rootq->query_name.c_str());\r
+               continue;\r
+       }\r
+\r
+//     If we've found the query plan head, so now add the output operators\r
+       if(qname_to_ospec.count(hfta_sets[hfta_id]->source_name)){\r
+               pair< multimap<string, int>::iterator, multimap<string, int>::iterator > oset;\r
+               multimap<string, int>::iterator mmsi;\r
+               oset = qname_to_ospec.equal_range(hfta_sets[hfta_id]->source_name);\r
+               for(mmsi=oset.first; mmsi!=oset.second; ++mmsi){\r
+                       rootq->add_output_operator(output_specs[(*mmsi).second]);\r
+               }\r
+       }\r
+\r
+\r
+\r
+//                             Perform query splitting if necessary.\r
+       bool hfta_returned;\r
+    vector<stream_query *> split_queries = rootq->split_query(Ext_fcns, Schema, hfta_returned, ifaces_db, n_virtual_interfaces, hfta_sets[hfta_id]->n_parallel, hfta_sets[hfta_id]->parallel_idx);\r
+\r
+       int l;\r
+//for(l=0;l<split_queries.size();++l){\r
+//printf("split query %d is %s\n",l,split_queries[l]->q`uery_name.c_str());\r
+//}\r
+\r
+\r
+\r
+\r
+    if(split_queries.size() > 0){      // should be at least one component.\r
+\r
+//                             Compute the number of LFTAs.\r
+         int n_lfta = split_queries.size();\r
+         if(hfta_returned) n_lfta--;\r
+\r
+\r
+//                             Process the LFTA components.\r
+         for(l=0;l<n_lfta;++l){\r
+          if(lfta_names.count(split_queries[l]->query_name) == 0){\r
+//                             Grab the lfta for global optimization.\r
+               vector<tablevar_t *> tvec =  split_queries[l]->query_plan[0]->get_input_tbls();\r
+               string liface = tvec[0]->get_interface();\r
+               string lmach = tvec[0]->get_machine();\r
+               if (lmach == "")\r
+                       lmach = hostname;\r
+               interface_names.push_back(liface);\r
+               machine_names.push_back(lmach);\r
+//printf("Machine is %s\n",lmach.c_str());\r
+\r
+//                     Set the ht size from the recommendation, if there is one in the rec file\r
+               if(lfta_htsize.count(split_queries[l]->query_name)>0){\r
+                       split_queries[l]->query_plan[0]->set_definition("aggregate_slots",int_to_string(lfta_htsize[split_queries[l]->query_name]));\r
+               }\r
+\r
+\r
+               lfta_names[split_queries[l]->query_name] = lfta_list.size();\r
+               split_queries[l]->set_gid(lfta_list.size());  // set lfta global id\r
+               lfta_list.push_back(split_queries[l]);\r
+               lfta_mach_lists[lmach].push_back(split_queries[l]);\r
+\r
+//                     THe following is a hack,\r
+//                     as I should be generating LFTA code through\r
+//                     the stream_query object.\r
+               split_queries[l]->query_plan[0]->bind_to_schema(Schema);\r
+//             split_queries[l]->query_plan[0]->definitions = split_queries[l]->defines;\r
+\r
+/*\r
+//                             Create query description to embed in lfta.c\r
+               string lfta_schema_str = split_queries[l]->make_schema();\r
+               string lfta_schema_embed = make_C_embedded_string(lfta_schema_str);\r
+\r
+//                             get NIC capabilities.\r
+               int erri;\r
+               nic_property *nicprop = NULL;\r
+               vector<string> iface_codegen_type = ifaces_db->get_iface_vals(lmach,liface,"iface_codegen_type",erri,err_str);\r
+               if(iface_codegen_type.size()){\r
+                       nicprop = npdb->get_nic_property(iface_codegen_type[0],erri);\r
+                       if(!nicprop){\r
+                               fprintf(stderr,"ERROR cannot load nic properties %s for interface %s of machine %s for lfta codegen\n",iface_codegen_type[0].c_str(), liface.c_str(), lmach.c_str());\r
+                                       exit(1);\r
+                       }\r
+               }\r
+\r
+               lfta_val[lmach] += generate_lfta_block(split_queries[l]->query_plan[0], Schema, split_queries[l]->get_gid(), Ext_fcns, lfta_schema_embed, ifaces_db,nicprop);\r
+*/\r
+\r
+               snap_lengths.push_back(compute_snap_len(split_queries[l]->query_plan[0], Schema));\r
+               query_names.push_back(split_queries[l]->query_name);\r
+               mach_query_names[lmach].push_back(query_names.size()-1);\r
+//                     NOTE: I will assume a 1-1 correspondance between\r
+//                     mach_query_names[lmach] and lfta_mach_lists[lmach]\r
+//                     where mach_query_names[lmach][i] contains the index into\r
+//                     query_names, which names the lfta, and\r
+//                     mach_query_names[lmach][i] is the stream_query * of the\r
+//                     corresponding lfta.\r
+//                     Later, lfta_iface_qnames are the query names matching lfta_iface_lists\r
+\r
+\r
+\r
+               // check if lfta is reusable\r
+               // FTA is reusable if reusable option is set explicitly or it doesn't have any parameters\r
+\r
+               bool lfta_reusable = false;\r
+               if (split_queries[l]->query_plan[0]->get_val_of_def("reusable") == "yes" ||\r
+                       split_queries[l]->query_plan[0]->get_param_tbl()->size() == 0) {\r
+                       lfta_reusable = true;\r
+               }\r
+               lfta_reuse_options.push_back(lfta_reusable);\r
+\r
+               // LFTA will inherit the liveness timeout specification from the containing query\r
+               // it is too conservative as lfta are expected to spend less time per tuple\r
+               // then full query\r
+\r
+               // extract liveness timeout from query definition\r
+               int liveness_timeout = atoi(split_queries[l]->query_plan[0]->get_val_of_def("liveness_timeout").c_str());\r
+               if (!liveness_timeout) {\r
+//                 fprintf(stderr, "WARNING: No liveness timeout specified for lfta %s, using default value of %d\n",\r
+//                   split_queries[l]->query_name.c_str(), DEFAULT_UDOP_LIVENESS_TIMEOUT);\r
+                   liveness_timeout = DEFAULT_UDOP_LIVENESS_TIMEOUT;\r
+               }\r
+               lfta_liveness_timeouts.push_back(liveness_timeout);\r
+\r
+//                     Add it to the schema\r
+               table_def *td = split_queries[l]->get_output_tabledef();\r
+               Schema->append_table(td);\r
+//printf("added lfta %d (%s)\n",l,split_queries[l]->query_name.c_str());\r
+\r
+         }\r
+        }\r
+\r
+//                             If the output is lfta-only, dump out the query name.\r
+      if(split_queries.size() == 1 && !hfta_returned){\r
+        if(output_query_names ){\r
+           fprintf(query_name_output,"%s L\n",split_queries[0]->query_name.c_str());\r
+               }\r
+/*\r
+else{\r
+           fprintf(stderr,"query name is %s\n",split_queries[0]->query_name.c_str());\r
+               }\r
+*/\r
+\r
+/*\r
+//                             output schema summary\r
+               if(output_schema_summary){\r
+                       dump_summary(split_queries[0]);\r
+               }\r
+*/\r
+      }\r
+\r
+\r
+         if(hfta_returned){            // query also has an HFTA component\r
+               int hfta_nbr = split_queries.size()-1;\r
+\r
+                       hfta_list.push_back(split_queries[hfta_nbr]);\r
+\r
+//                                     report on generated query names\r
+        if(output_query_names){\r
+                       string hfta_name =split_queries[hfta_nbr]->query_name;\r
+               fprintf(query_name_output,"%s H\n",hfta_name.c_str());\r
+                       for(l=0;l<hfta_nbr;++l){\r
+                               string lfta_name =split_queries[l]->query_name;\r
+                       fprintf(query_name_output,"%s L\n",lfta_name.c_str());\r
+                       }\r
+               }\r
+//             else{\r
+//             fprintf(stderr,"query names are ");\r
+//                     for(l=0;l<hfta_nbr;++l){\r
+//                             if(l>0) fprintf(stderr,",");\r
+//                             string fta_name =split_queries[l]->query_name;\r
+//                     fprintf(stderr," %s",fta_name.c_str());\r
+//                     }\r
+//                     fprintf(stderr,"\n");\r
+//             }\r
+         }\r
+\r
+  }else{\r
+         fprintf(stderr,"ERROR, query in file %s has a bug.\n",qnodes[i]->file.c_str());\r
+         fprintf(stderr,"%s\n",rootq->get_error_str().c_str());\r
+         exit(1);\r
+  }\r
+ }\r
+}\r
+\r
+\r
+//-----------------------------------------------------------------\r
+//             Compute and propagate the SE in PROTOCOL fields compute a field.\r
+//-----------------------------------------------------------------\r
+\r
+for(i=0;i<lfta_list.size();i++){\r
+       lfta_list[i]->generate_protocol_se(sq_map, Schema);\r
+       sq_map[lfta_list[i]->get_sq_name()] = lfta_list[i];\r
+}\r
+for(i=0;i<hfta_list.size();i++){\r
+       hfta_list[i]->generate_protocol_se(sq_map, Schema);\r
+       sq_map[hfta_list[i]->get_sq_name()] = hfta_list[i];\r
+}\r
+\r
+\r
+\r
+//------------------------------------------------------------------------\r
+//             Perform  individual FTA optimizations\r
+//-----------------------------------------------------------------------\r
+\r
+if (partitioned_mode) {\r
+\r
+       // open partition definition file\r
+       string part_fname = config_dir_path + "partition.txt";\r
+\r
+       FILE* partfd = fopen(part_fname.c_str(), "r");\r
+       if (!partfd) {\r
+               fprintf(stderr,"ERROR, unable to open partition definition file %s\n",part_fname.c_str());\r
+               exit(1);\r
+       }\r
+       PartnParser_setfileinput(partfd);\r
+       if (PartnParserparse()) {\r
+               fprintf(stderr,"ERROR, unable to parse partition definition file %s\n",part_fname.c_str());\r
+               exit(1);\r
+       }\r
+       fclose(partfd);\r
+}\r
+\r
+\r
+print_hftas("preopt_hfta_info.txt", hfta_list, lfta_names, query_names, interface_names);\r
+\r
+int num_hfta = hfta_list.size();\r
+for(i=0; i < hfta_list.size(); ++i){\r
+       hfta_list[i]->optimize(hfta_list, lfta_names, interface_names, machine_names, Ext_fcns, Schema, ifaces_db, partn_parse_result);\r
+}\r
+\r
+//                     Add all new hftas to schema\r
+for(i=num_hfta; i < hfta_list.size(); ++i){\r
+               table_def *td = hfta_list[i]->get_output_tabledef();\r
+               Schema->append_table(td);\r
+}\r
+\r
+print_hftas("postopt_hfta_info.txt", hfta_list, lfta_names, query_names, interface_names);\r
+\r
+\r
+\r
+//------------------------------------------------------------------------\r
+//             Do global (cross-fta) optimization\r
+//-----------------------------------------------------------------------\r
+\r
+\r
+\r
+\r
+\r
+\r
+set<string> extra_external_libs;\r
+\r
+for(i=0;i<hfta_list.size();++i){               // query also has an HFTA component\r
+\r
+               if(! debug_only){\r
+//                                     build hfta file name, create output\r
+           if(numeric_hfta_flname){\r
+            sprintf(tmpstr,"hfta_%d",hfta_count);\r
+                       hfta_names.push_back(tmpstr);\r
+            sprintf(tmpstr,"hfta_%d.cc",hfta_count);\r
+         }else{\r
+            sprintf(tmpstr,"hfta_%s",hfta_list[i]->query_name.c_str());\r
+                       hfta_names.push_back(tmpstr);\r
+            sprintf(tmpstr,"hfta_%s.cc",hfta_list[i]->query_name.c_str());\r
+          }\r
+                 FILE *hfta_fl = fopen(tmpstr,"w");\r
+                 if(hfta_fl == NULL){\r
+                       fprintf(stderr,"ERROR can't open fta output file %s\n",tmpstr);\r
+                       exit(1);\r
+                 }\r
+                 fprintf(hfta_fl,"%s\n\n",hfta_list[i]->generate_hfta(Schema, Ext_fcns, opviews, distributed_mode).c_str());\r
+\r
+//                     If there is a field verifier, warn about\r
+//                     lack of compatability\r
+//                             NOTE : this code assumes that visible non-lfta queries\r
+//                             are those at the root of a stream query.\r
+                 string hfta_comment;\r
+                 string hfta_title;\r
+                 string hfta_namespace;\r
+                 if(hfta_list[i]->defines.count("comment")>0)\r
+                       hfta_comment = hfta_list[i]->defines["comment"];\r
+                 if(hfta_list[i]->defines.count("Comment")>0)\r
+                       hfta_comment = hfta_list[i]->defines["Comment"];\r
+                 if(hfta_list[i]->defines.count("COMMENT")>0)\r
+                       hfta_comment = hfta_list[i]->defines["COMMENT"];\r
+                 if(hfta_list[i]->defines.count("title")>0)\r
+                       hfta_title = hfta_list[i]->defines["title"];\r
+                 if(hfta_list[i]->defines.count("Title")>0)\r
+                       hfta_title = hfta_list[i]->defines["Title"];\r
+                 if(hfta_list[i]->defines.count("TITLE")>0)\r
+                       hfta_title = hfta_list[i]->defines["TITLE"];\r
+                 if(hfta_list[i]->defines.count("namespace")>0)\r
+                       hfta_namespace = hfta_list[i]->defines["namespace"];\r
+                 if(hfta_list[i]->defines.count("Namespace")>0)\r
+                       hfta_namespace = hfta_list[i]->defines["Namespace"];\r
+                 if(hfta_list[i]->defines.count("Namespace")>0)\r
+                       hfta_namespace = hfta_list[i]->defines["Namespace"];\r
+\r
+                 if(field_verifier != NULL){\r
+                       string warning_str;\r
+                       if(hfta_comment == "")\r
+                               warning_str += "\tcomment not found.\n";\r
+                       if(hfta_title == "")\r
+                               warning_str += "\ttitle not found.\n";\r
+                       if(hfta_namespace == "")\r
+                               warning_str += "\tnamespace not found.\n";\r
+\r
+                       vector<field_entry *> flds = hfta_list[i]->get_output_tabledef()->get_fields();\r
+                       int fi;\r
+                       for(fi=0;fi<flds.size();fi++){\r
+                               field_verifier->verify_field(flds[fi]->get_name(),flds[fi]->get_type(),warning_str);\r
+                       }\r
+                       if(warning_str != "")\r
+                               fprintf(stderr,"Warning, in HFTA stream %s:\n%s",\r
+                                       hfta_list[i]->get_output_tabledef()->get_tbl_name().c_str(),warning_str.c_str());\r
+                 }\r
+\r
+                 fprintf(qtree_output,"\t<HFTA name='%s'>\n",hfta_list[i]->get_output_tabledef()->get_tbl_name().c_str());\r
+                 if(hfta_comment != "")\r
+                       fprintf(qtree_output,"\t\t<Description value='%s' />\n",hfta_comment.c_str());\r
+                 if(hfta_title != "")\r
+                       fprintf(qtree_output,"\t\t<Title value='%s' />\n",hfta_title.c_str());\r
+                 if(hfta_namespace != "")\r
+                       fprintf(qtree_output,"\t\t<Namespace value='%s' />\n",hfta_namespace.c_str());\r
+                 fprintf(qtree_output,"\t\t<FileName value='%s' />\n",tmpstr);\r
+                 fprintf(qtree_output,"\t\t<Rate value='100' />\n");\r
+\r
+//                             write info about fields to qtree.xml\r
+                 vector<field_entry *> flds = hfta_list[i]->get_output_tabledef()->get_fields();\r
+                 int fi;\r
+                 for(fi=0;fi<flds.size();fi++){\r
+                       fprintf(qtree_output,"\t\t<Field name='%s' pos='%d' type='%s' ",flds[fi]->get_name().c_str(), fi, flds[fi]->get_type().c_str());\r
+                       if(flds[fi]->get_modifier_list()->size()){\r
+                               fprintf(qtree_output,"mods='%s' ", flds[fi]->get_modifier_list()->to_string().c_str());\r
+                       }\r
+                       fprintf(qtree_output," />\n");\r
+                 }\r
+\r
+                 // extract liveness timeout from query definition\r
+                 int liveness_timeout = atoi(hfta_list[i]->query_plan[hfta_list[i]->qhead]->get_val_of_def("liveness_timeout").c_str());\r
+                 if (!liveness_timeout) {\r
+//                 fprintf(stderr, "WARNING: No liveness timeout specified for hfta %s, using default value of %d\n",\r
+//                   hfta_list[i]->get_output_tabledef()->get_tbl_name().c_str(), DEFAULT_UDOP_LIVENESS_TIMEOUT);\r
+                   liveness_timeout = DEFAULT_UDOP_LIVENESS_TIMEOUT;\r
+                 }\r
+                 fprintf(qtree_output,"\t\t<LivenessTimeout value='%d' />\n", liveness_timeout);\r
+\r
+                 vector<tablevar_t *> tmp_tv = hfta_list[i]->get_input_tables();\r
+                 int itv;\r
+                 for(itv=0;itv<tmp_tv.size();++itv){\r
+                       fprintf(qtree_output,"\t\t<ReadsFrom value='%s' />\n",tmp_tv[itv]->get_schema_name().c_str());\r
+                 }\r
+                 string ifrs = hfta_list[i]->collect_refd_ifaces();\r
+                 if(ifrs != ""){\r
+                       fprintf(qtree_output,"\t\t<Ifaces_referenced value='%s'/>\n",ifrs.c_str());\r
+                 }\r
+                 fprintf(qtree_output,"\t</HFTA>\n");\r
+\r
+                 fclose(hfta_fl);\r
+               }else{\r
+//                                     debug only -- do code generation to catch generation-time errors.\r
+                 hfta_list[i]->generate_hfta(Schema, Ext_fcns,opviews, distributed_mode);\r
+               }\r
+\r
+               hfta_count++;   // for hfta file names with numeric suffixes\r
+\r
+               hfta_list[i]->get_external_libs(extra_external_libs);\r
+\r
+         }\r
+\r
+string ext_lib_string;\r
+set<string>::iterator ssi_el;\r
+for(ssi_el=extra_external_libs.begin();ssi_el!=extra_external_libs.end();++ssi_el)\r
+       ext_lib_string += (*ssi_el)+" ";\r
+\r
+\r
+\r
+//                     Report on the set of operator views\r
+  for(i=0;i<opviews.size();++i){\r
+       opview_entry *opve = opviews.get_entry(i);\r
+       fprintf(qtree_output,"\t<UDOP name='%s' >\n",opve->view_name.c_str());\r
+       fprintf(qtree_output,"\t\t<FileName value='%s' />\n",opve->exec_fl.c_str());\r
+       fprintf(qtree_output,"\t\t<Parent value='%s' />\n",opve->root_name.c_str());\r
+       fprintf(qtree_output,"\t\t<Alias value='%s' />\n",opve->udop_alias.c_str());\r
+       fprintf(qtree_output,"\t\t<Rate value='100' />\n");\r
+\r
+       if (!opve->liveness_timeout) {\r
+//             fprintf(stderr, "WARNING: No liveness timeout specified for view %s, using default value of %d\n",\r
+//                     opve->view_name.c_str(), DEFAULT_UDOP_LIVENESS_TIMEOUT);\r
+               opve->liveness_timeout = DEFAULT_UDOP_LIVENESS_TIMEOUT;\r
+       }\r
+       fprintf(qtree_output,"\t\t<LivenessTimeout value='%d' />\n", opve->liveness_timeout);\r
+    int j;\r
+       for(j=0;j<opve->subq_names.size();j++)\r
+               fprintf(qtree_output,"\t\t<ReadsFrom value='%s' />\n",opve->subq_names[j].c_str());\r
+       fprintf(qtree_output,"\t</UDOP>\n");\r
+  }\r
+\r
+\r
+//-----------------------------------------------------------------\r
+\r
+//                     Create interface-specific meta code files.\r
+//                             first, open and parse the interface resources file.\r
+       ifaces_db = new ifq_t();\r
+    ierr = "";\r
+       if(ifaces_db->load_ifaces(ifx_fname,use_live_hosts_file,distributed_mode,ierr)){\r
+               fprintf(stderr,"ERROR, can't load interface resource file %s :\n%s",\r
+                               ifx_fname.c_str(), ierr.c_str());\r
+               exit(1);\r
+       }\r
+\r
+       map<string, vector<stream_query *> >::iterator svsi;\r
+       for(svsi=lfta_mach_lists.begin(); svsi!=lfta_mach_lists.end(); ++svsi){\r
+               string lmach = (*svsi).first;\r
+\r
+       //              For this machine, create a set of lftas per interface.\r
+               vector<stream_query *> mach_lftas = (*svsi).second;\r
+               map<string, vector<stream_query *> > lfta_iface_lists;\r
+               int li;\r
+               for(li=0;li<mach_lftas.size();++li){\r
+                       vector<tablevar_t *> tvec =  mach_lftas[li]->query_plan[0]->get_input_tbls();\r
+                       string lfta_iface = tvec[0]->get_interface();\r
+                       lfta_iface_lists[lfta_iface].push_back(mach_lftas[li]);\r
+               }\r
+\r
+               map<string, vector<stream_query *> >::iterator lsvsi;\r
+               for(lsvsi=lfta_iface_lists.begin(); lsvsi!=lfta_iface_lists.end(); ++lsvsi){\r
+                       int erri;\r
+                       string liface = (*lsvsi).first;\r
+                       vector<stream_query *> iface_lftas = (*lsvsi).second;\r
+                       vector<string> iface_codegen_type = ifaces_db->get_iface_vals(lmach,liface,"iface_codegen_type",erri,err_str);\r
+                       if(iface_codegen_type.size()){\r
+                               nic_property *nicprop = npdb->get_nic_property(iface_codegen_type[0],erri);\r
+                               if(!nicprop){\r
+                                       fprintf(stderr,"ERROR cannot load nic properties %s for interface %s of machine %s\n",iface_codegen_type[0].c_str(), liface.c_str(), lmach.c_str());\r
+                                       exit(1);\r
+                               }\r
+                               string mcs = generate_nic_code(iface_lftas, nicprop);\r
+                               string mcf_flnm;\r
+                               if(lmach != "")\r
+                                 mcf_flnm = lmach + "_"+liface+".mcf";\r
+                               else\r
+                                 mcf_flnm = hostname + "_"+liface+".mcf";\r
+                               FILE *mcf_fl ;\r
+                               if((mcf_fl = fopen(mcf_flnm.c_str(),"w")) == NULL){\r
+                                       fprintf(stderr,"Can't open output file %s\n%s\n",mcf_flnm.c_str(),strerror(errno));\r
+                                       exit(1);\r
+                               }\r
+                               fprintf(mcf_fl,"%s",mcs.c_str());\r
+                               fclose(mcf_fl);\r
+//printf("mcs of machine %s, iface %s of type %s is \n%s\n",\r
+//lmach.c_str(), liface.c_str(),iface_codegen_type[0].c_str(), mcs.c_str());\r
+                       }\r
+               }\r
+\r
+\r
+       }\r
+\r
+\r
+\r
+//-----------------------------------------------------------------\r
+\r
+\r
+//                     Find common filter predicates in the LFTAs.\r
+//                     in addition generate structs to store the temporal attributes unpacked by prefilter\r
+       \r
+       map<string, vector<stream_query *> >::iterator ssqi;\r
+       for(ssqi=lfta_mach_lists.begin(); ssqi!=lfta_mach_lists.end(); ++ssqi){\r
+\r
+               string lmach = (*ssqi).first;\r
+               bool packed_return = false;\r
+               int li, erri;\r
+\r
+\r
+//     The LFTAs of this machine.\r
+               vector<stream_query *> mach_lftas = (*ssqi).second;\r
+//     break up on a per-interface basis.\r
+               map<string, vector<stream_query *> > lfta_iface_lists;\r
+               map<string, vector<int> > lfta_iface_qname_ix; // need the query name\r
+                                                        // for fta_init\r
+               for(li=0;li<mach_lftas.size();++li){\r
+                       vector<tablevar_t *> tvec =  mach_lftas[li]->query_plan[0]->get_input_tbls();\r
+                       string lfta_iface = tvec[0]->get_interface();\r
+                       lfta_iface_lists[lfta_iface].push_back(mach_lftas[li]);\r
+                       lfta_iface_qname_ix[lfta_iface].push_back(mach_query_names[lmach][li]);\r
+               }\r
+\r
+\r
+//     Are the return values "packed"?\r
+//     This should be done on a per-interface basis.\r
+//     But this is defunct code for gs-lite\r
+               for(li=0;li<mach_lftas.size();++li){\r
+                 vector<tablevar_t *> tvec =  mach_lftas[li]->query_plan[0]->get_input_tbls();\r
+                 string liface = tvec[0]->get_interface();\r
+                 vector<string> iface_codegen_type = ifaces_db->get_iface_vals(lmach,liface,"iface_codegen_type",erri,err_str);\r
+                 if(iface_codegen_type.size()){\r
+                       if(npdb->get_nic_prop_val(iface_codegen_type[0],"Return",erri) == "Packed"){\r
+                         packed_return = true;\r
+                       }\r
+                 }\r
+               }\r
+\r
+\r
+// Separate lftas by interface, collect results on a per-interface basis.\r
+\r
+               vector<cnf_set *> no_preds;     // fallback if there is no prefilter\r
+               map<string, vector<cnf_set *> > prefilter_preds;\r
+               set<unsigned int> pred_ids;     // this can be global for all interfaces\r
+               for(auto mvsi=lfta_iface_lists.begin(); mvsi!=lfta_iface_lists.end(); ++mvsi){\r
+                       string liface = (*mvsi).first;\r
+                       vector<cnf_set *> empty_list;\r
+                       prefilter_preds[liface] = empty_list;\r
+                       if(! packed_return){\r
+                               get_common_lfta_filter(lfta_iface_lists[liface], Schema,Ext_fcns, prefilter_preds[liface], pred_ids);\r
+                       }\r
+\r
+//                             get NIC capabilities.  (Is this needed?)\r
+                       nic_property *nicprop = NULL;\r
+                       vector<string> iface_codegen_type = ifaces_db->get_iface_vals(lmach,liface,"iface_codegen_type",erri,err_str);\r
+                       if(iface_codegen_type.size()){\r
+                               nicprop = npdb->get_nic_property(iface_codegen_type[0],erri);\r
+                               if(!nicprop){\r
+                                       fprintf(stderr,"ERROR cannot load nic properties %s for interface %s of machine %s for lfta codegen\n",iface_codegen_type[0].c_str(), liface.c_str(), lmach.c_str());\r
+                                       exit(1);\r
+                               }\r
+                       }\r
+               }\r
+\r
+\r
+//             Now that we know the prefilter preds, generate the lfta code.\r
+//     Do this for all lftas in this machine.\r
+               for(li=0;li<mach_lftas.size();++li){\r
+                       set<unsigned int> subsumed_preds;\r
+                       set<unsigned int>::iterator sii;\r
+#ifdef PREFILTER_OK\r
+                       for(sii=pred_ids.begin();sii!=pred_ids.end();++sii){\r
+                               int pid = (*sii);\r
+                               if((pid>>16) == li){\r
+                                       subsumed_preds.insert(pid & 0xffff);\r
+                               }\r
+                       }\r
+#endif\r
+                       string lfta_schema_str = mach_lftas[li]->make_schema();\r
+                       string lfta_schema_embed = make_C_embedded_string(lfta_schema_str);\r
+                       nic_property *nicprop = NULL; // no NIC properties?\r
+                       lfta_val[lmach] += generate_lfta_block(mach_lftas[li]->query_plan[0], Schema, mach_lftas[li]->get_gid(), Ext_fcns, lfta_schema_embed, ifaces_db,nicprop,subsumed_preds);\r
+               }\r
+\r
+\r
+//                     generate structs to store the temporal attributes\r
+//                     unpacked by prefilter\r
+               col_id_set temp_cids;\r
+               get_prefilter_temporal_cids(lfta_mach_lists[lmach], temp_cids);\r
+               lfta_prefilter_val[lmach] = generate_lfta_prefilter_struct(temp_cids, Schema);\r
+\r
+//                     Compute the lfta bit signatures and the lfta colrefs\r
+//     do this on a per-interface basis\r
+#ifdef PREFILTER_OK\r
+                       lfta_prefilter_val[lmach] += "#define PREFILTER_DEFINED 1;\n\n";\r
+#endif\r
+               map<string, vector<long long int> > lfta_sigs; // used again later\r
+               for(auto mvsi=lfta_iface_lists.begin(); mvsi!=lfta_iface_lists.end(); ++mvsi){\r
+                       string liface = (*mvsi).first;\r
+                       vector<long long int> empty_list;\r
+                       lfta_sigs[liface] = empty_list;\r
+\r
+                       vector<col_id_set> lfta_cols;\r
+                       vector<int> lfta_snap_length;\r
+                       for(li=0;li<lfta_iface_lists[liface].size();++li){\r
+                               unsigned long long int mask=0, bpos=1;\r
+                               int f_pos;\r
+                               for(f_pos=0;f_pos<prefilter_preds[liface].size();++f_pos){\r
+                                       if(prefilter_preds[liface][f_pos]->lfta_id.count(li))\r
+                                               mask |= bpos;\r
+                                       bpos = bpos << 1;\r
+                               }\r
+                               lfta_sigs[liface].push_back(mask);\r
+                               lfta_cols.push_back(lfta_iface_lists[liface][li]->query_plan[0]->get_colrefs(true,Schema));\r
+                               lfta_snap_length.push_back(compute_snap_len(lfta_iface_lists[liface][li]->query_plan[0], Schema));\r
+                       }\r
+\r
+//for(li=0;li<mach_lftas.size();++li){\r
+//printf("lfta %d, msak is %llu\n",li,lfta_sigs[li]);\r
+//col_id_set::iterator tcisi;\r
+//for(tcisi=lfta_cols[li].begin(); tcisi!=lfta_cols[li].end();++tcisi){\r
+//printf("\t%s %d (%d)\n",(*tcisi).field.c_str(),(*tcisi).schema_ref, (*tcisi).tblvar_ref);\r
+//}\r
+//}\r
+\r
+\r
+//                     generate the prefilter\r
+//     Do this on a per-interface basis, except for the #define\r
+#ifdef PREFILTER_OK\r
+//                     lfta_prefilter_val[lmach] += "#define PREFILTER_DEFINED 1;\n\n";\r
+                       lfta_val[lmach] += generate_lfta_prefilter(prefilter_preds[liface], temp_cids, Schema, Ext_fcns, lfta_cols, lfta_sigs[liface], lfta_snap_length, liface);\r
+#else\r
+                       lfta_val[lmach] += generate_lfta_prefilter(no_preds, temp_cids, Schema,Ext_fcns,  lfta_cols, lfta_sigs[liface], lfta_snap_length, liface);\r
+\r
+#endif\r
+               }\r
+\r
+//                     Generate interface parameter lookup function\r
+         lfta_val[lmach] += "// lookup interface properties by name\n";\r
+         lfta_val[lmach] += "// mulitple values of given property returned in the same string separated by commas\n";\r
+         lfta_val[lmach] += "// returns NULL if given property does not exist\n";\r
+         lfta_val[lmach] += "gs_sp_t get_iface_properties (const gs_sp_t iface_name, const gs_sp_t property_name) {\n";\r
+\r
+//       collect a lit of interface names used by queries running on this host\r
+         set<std::string> iface_names;\r
+         for(i=0;i<mach_query_names[lmach].size();i++){\r
+               int mi = mach_query_names[lmach][i];\r
+               stream_query *lfta_sq = lfta_mach_lists[lmach][i];\r
+\r
+               if(interface_names[mi]=="")\r
+                       iface_names.insert("DEFAULTDEV");\r
+               else\r
+                       iface_names.insert(interface_names[mi]);\r
+         }\r
+\r
+//       generate interface property lookup code for every interface\r
+         set<std::string>::iterator sir;\r
+         for (sir = iface_names.begin(); sir != iface_names.end(); sir++) {\r
+               if (sir == iface_names.begin())\r
+                       lfta_val[lmach] += "\tif (!strcmp(iface_name, \"" + *sir + "\")) {\n";\r
+               else\r
+                       lfta_val[lmach] += "\t} else if (!strcmp(iface_name, \"" + *sir + "\")) {\n";\r
+\r
+               // iterate through interface properties\r
+               vector<string> iface_properties = ifaces_db->get_iface_properties(lmach,*sir,erri,err_str);\r
+               if (erri) {\r
+                       fprintf(stderr,"ERROR cannot retrieve interface properties for %s.%s, %s\n",lmach.c_str(), sir->c_str(), err_str.c_str());\r
+                       exit(1);\r
+               }\r
+               if (iface_properties.empty())\r
+                       lfta_val[lmach] += "\t\treturn NULL;\n";\r
+               else {\r
+                       for (int i = 0; i < iface_properties.size(); ++i) {\r
+                               if (i == 0)\r
+                                       lfta_val[lmach] += "\t\tif (!strcmp(property_name, \"" + iface_properties[i] + "\")) {\n";\r
+                               else\r
+                                       lfta_val[lmach] += "\t\t} else if (!strcmp(property_name, \"" + iface_properties[i] + "\")) {\n";\r
+\r
+                               // combine all values for the interface property using comma separator\r
+                               vector<string> vals = ifaces_db->get_iface_vals(lmach,*sir,iface_properties[i],erri,err_str);\r
+                               for (int j = 0; j < vals.size(); ++j) {\r
+                                       lfta_val[lmach] += "\t\t\treturn \"" + vals[j];\r
+                                       if (j != vals.size()-1)\r
+                                               lfta_val[lmach] += ",";\r
+                               }\r
+                               lfta_val[lmach] += "\";\n";\r
+                       }\r
+                       lfta_val[lmach] += "\t\t} else\n";\r
+                       lfta_val[lmach] += "\t\t\treturn NULL;\n";\r
+               }\r
+         }\r
+         lfta_val[lmach] += "\t} else\n";\r
+         lfta_val[lmach] += "\t\treturn NULL;\n";\r
+         lfta_val[lmach] += "}\n\n";\r
+\r
+\r
+//                     Generate a full list of FTAs for clearinghouse reference\r
+         lfta_val[lmach] += "// list of FTAs clearinghouse expects to register themselves\n";\r
+         lfta_val[lmach] += "const gs_sp_t fta_names[] = {";\r
+\r
+         for (i = 0; i < query_names.size(); ++i) {\r
+                  if (i)\r
+                         lfta_val[lmach] += ", ";\r
+                  lfta_val[lmach] += "\"" + query_names[i] + "\"";\r
+         }\r
+         for (i = 0; i < hfta_list.size(); ++i) {\r
+                  lfta_val[lmach] += ", \"" + hfta_list[i]->query_name + "\"";\r
+         }\r
+         lfta_val[lmach] += ", NULL};\n\n";\r
+\r
+\r
+//                     Add the initialization function to lfta.c\r
+//     Change to accept the interface name, and \r
+//     set the prefilter function accordingly.\r
+//     see the example in demo/err2\r
+         lfta_val[lmach] += "void fta_init(gs_sp_t device){\n";\r
+\r
+//       for(i=0;i<mach_query_names[lmach].size();i++)\r
+//             int mi = mach_query_names[lmach][i];\r
+//             stream_query *lfta_sq = lfta_mach_lists[lmach][i];\r
+\r
+         for(auto mvsi=lfta_iface_lists.begin(); mvsi!=lfta_iface_lists.end(); ++mvsi){\r
+               string liface = (*mvsi).first;\r
+               vector<stream_query *> lfta_list = (*mvsi).second;\r
+               for(i=0;i<lfta_list.size();i++){\r
+                       stream_query *lfta_sq = lfta_list[i];\r
+                       int mi = lfta_iface_qname_ix[liface][i];\r
+               \r
+                       fprintf(stderr,"interface %s, LFTA %d, snap length is %d\n",liface.c_str(),mi,snap_lengths[mi]);\r
+\r
+                       string this_iface = "DEFAULTDEV";\r
+                       if(interface_names[mi]!="")\r
+                               this_iface = '"'+interface_names[mi]+'"';\r
+                       lfta_val[lmach] += "\tif(!strcmp(device,"+this_iface+"))\n";\r
+               lfta_val[lmach] += "\t\tfta_register(\""+query_names[mi]+"\", " + (lfta_reuse_options[mi]?"1":"0") + ", ";\r
+//             if(interface_names[mi]=="")\r
+//                             lfta_val[lmach]+="DEFAULTDEV";\r
+//             else\r
+//                             lfta_val[lmach]+='"'+interface_names[mi]+'"';\r
+                       lfta_val[lmach] += this_iface;\r
+\r
+\r
+               lfta_val[lmach] += ", "+generate_alloc_name(query_names[mi])\r
+                       +"\n#ifndef LFTA_IN_NIC\n\t,"+generate_schema_string_name(query_names[mi])\r
+                       +"\n#endif\n";\r
+                               sprintf(tmpstr,",%d",snap_lengths[mi]);\r
+                       lfta_val[lmach] += tmpstr;\r
+\r
+//                     unsigned long long int mask=0, bpos=1;\r
+//                     int f_pos;\r
+//                     for(f_pos=0;f_pos<prefilter_preds.size();++f_pos){\r
+//                             if(prefilter_preds[f_pos]->lfta_id.count(i))\r
+//                                     mask |= bpos;\r
+//                             bpos = bpos << 1;\r
+//                     }\r
+\r
+#ifdef PREFILTER_OK\r
+//                     sprintf(tmpstr,",%lluull",mask);\r
+                       sprintf(tmpstr,",%lluull",lfta_sigs[liface][i]);\r
+                       lfta_val[lmach]+=tmpstr;\r
+#else\r
+                       lfta_val[lmach] += ",0ull";\r
+#endif\r
+\r
+                       lfta_val[lmach] += ");\n";\r
+\r
+\r
+\r
+//    End of lfta prefilter stuff\r
+// --------------------------------------------------\r
+\r
+//                     If there is a field verifier, warn about\r
+//                     lack of compatability\r
+                 string lfta_comment;\r
+                 string lfta_title;\r
+                 string lfta_namespace;\r
+                 map<string,string> ldefs = lfta_sq->query_plan[0]->get_definitions();\r
+                 if(ldefs.count("comment")>0)\r
+                       lfta_comment = lfta_sq->defines["comment"];\r
+                 if(ldefs.count("Comment")>0)\r
+                       lfta_comment = lfta_sq->defines["Comment"];\r
+                 if(ldefs.count("COMMENT")>0)\r
+                       lfta_comment = lfta_sq->defines["COMMENT"];\r
+                 if(ldefs.count("title")>0)\r
+                       lfta_title = lfta_sq->defines["title"];\r
+                 if(ldefs.count("Title")>0)\r
+                       lfta_title = lfta_sq->defines["Title"];\r
+                 if(ldefs.count("TITLE")>0)\r
+                       lfta_title = lfta_sq->defines["TITLE"];\r
+                 if(ldefs.count("NAMESPACE")>0)\r
+                       lfta_namespace = lfta_sq->defines["NAMESPACE"];\r
+                 if(ldefs.count("Namespace")>0)\r
+                       lfta_namespace = lfta_sq->defines["Namespace"];\r
+                 if(ldefs.count("namespace")>0)\r
+                       lfta_namespace = lfta_sq->defines["namespace"];\r
+\r
+                 string lfta_ht_size;\r
+                 if(lfta_sq->query_plan[0]->node_type()== "sgah_qpn" || lfta_sq->query_plan[0]->node_type()== "rsgah_qpn")\r
+                       lfta_ht_size = int_to_string(DEFAULT_LFTA_HASH_TABLE_SIZE);\r
+                 if(ldefs.count("aggregate_slots")>0){\r
+                       lfta_ht_size = ldefs["aggregate_slots"];\r
+                 }\r
+\r
+//                     NOTE : I'm assuming that visible lftas do not start with _fta.\r
+//                             -- will fail for non-visible simple selection queries.\r
+               if(field_verifier != NULL && query_names[mi].substr(0,1) != "_"){\r
+                       string warning_str;\r
+                       if(lfta_comment == "")\r
+                               warning_str += "\tcomment not found.\n";\r
+                       if(lfta_title == "")\r
+                               warning_str += "\ttitle not found.\n";\r
+                       if(lfta_namespace == "")\r
+                               warning_str += "\tnamespace not found.\n";\r
+\r
+                       vector<field_entry *> flds = lfta_sq->get_output_tabledef()->get_fields();\r
+                       int fi;\r
+                       for(fi=0;fi<flds.size();fi++){\r
+                               field_verifier->verify_field(flds[fi]->get_name(),flds[fi]->get_type(),warning_str);\r
+                       }\r
+                       if(warning_str != "")\r
+                               fprintf(stderr,"Warning, in LFTA stream %s:\n%s",\r
+                                       query_names[mi].c_str(),warning_str.c_str());\r
+               }\r
+\r
+\r
+//                     Create qtree output\r
+               fprintf(qtree_output,"\t<LFTA name='%s' >\n",query_names[mi].c_str());\r
+                  if(lfta_comment != "")\r
+                        fprintf(qtree_output,"\t\t<Description value='%s' />\n",lfta_comment.c_str());\r
+                  if(lfta_title != "")\r
+                        fprintf(qtree_output,"\t\t<Title value='%s' />\n",lfta_title.c_str());\r
+                  if(lfta_namespace != "")\r
+                        fprintf(qtree_output,"\t\t<Namespace value='%s' />\n",lfta_namespace.c_str());\r
+                  if(lfta_ht_size != "")\r
+                        fprintf(qtree_output,"\t\t<HtSize value='%s' />\n",lfta_ht_size.c_str());\r
+               if(lmach != "")\r
+                 fprintf(qtree_output,"\t\t<Host value='%s' />\n",lmach.c_str());\r
+               else\r
+                 fprintf(qtree_output,"\t\t<Host value='%s' />\n",hostname.c_str());\r
+               fprintf(qtree_output,"\t\t<Interface  value='%s' />\n",interface_names[mi].c_str());\r
+               fprintf(qtree_output,"\t\t<ReadsFrom value='%s' />\n",interface_names[mi].c_str());\r
+               fprintf(qtree_output,"\t\t<Rate value='100' />\n");\r
+               fprintf(qtree_output,"\t\t<LivenessTimeout value='%d' />\n", lfta_liveness_timeouts[mi]);\r
+//                             write info about fields to qtree.xml\r
+                 vector<field_entry *> flds = lfta_sq->get_output_tabledef()->get_fields();\r
+                 int fi;\r
+                 for(fi=0;fi<flds.size();fi++){\r
+                       fprintf(qtree_output,"\t\t<Field name='%s' pos='%d' type='%s' ",flds[fi]->get_name().c_str(), fi, flds[fi]->get_type().c_str());\r
+                       if(flds[fi]->get_modifier_list()->size()){\r
+                               fprintf(qtree_output,"mods='%s' ", flds[fi]->get_modifier_list()->to_string().c_str());\r
+                       }\r
+                       fprintf(qtree_output," />\n");\r
+                 }\r
+               fprintf(qtree_output,"\t</LFTA>\n");\r
+\r
+\r
+           }\r
+         }\r
+\r
+         for(auto mvsi=lfta_iface_lists.begin(); mvsi!=lfta_iface_lists.end(); ++mvsi){\r
+                       string liface = (*mvsi).first;\r
+                       lfta_val[lmach] += \r
+"      if (!strcmp(device, \""+liface+"\")) \n"\r
+"              lfta_prefilter = &lfta_prefilter_"+liface+"; \n"\r
+;\r
+               }\r
+               lfta_val[lmach] += \r
+"      if(lfta_prefilter == NULL){\n"\r
+"              fprintf(stderr, \"Error, interface %s not found in fta_init.\\n\",device);\n"\r
+"              exit(1);\n"\r
+"      }\n"\r
+;\r
+\r
+\r
+\r
+         lfta_val[lmach] += "}\n\n";\r
+\r
+      if(!(debug_only || hfta_only) ){\r
+               string lfta_flnm;\r
+               if(lmach != "")\r
+                 lfta_flnm = lmach + "_lfta.c";\r
+               else\r
+                 lfta_flnm = hostname + "_lfta.c";\r
+               if((lfta_out = fopen(lfta_flnm.c_str(),"w")) == NULL){\r
+                       fprintf(stderr,"Can't open output file %s\n%s\n","lfta.c",strerror(errno));\r
+                       exit(1);\r
+               }\r
+             fprintf(lfta_out,"%s",lfta_header.c_str());\r
+             fprintf(lfta_out,"%s",lfta_prefilter_val[lmach].c_str());\r
+             fprintf(lfta_out,"%s",lfta_val[lmach].c_str());\r
+               fclose(lfta_out);\r
+         }\r
+       }\r
+\r
+//             Say what are the operators which must execute\r
+       if(opviews.size()>0)\r
+               fprintf(stderr,"The queries use the following external operators:\n");\r
+       for(i=0;i<opviews.size();++i){\r
+               opview_entry *opv = opviews.get_entry(i);\r
+               fprintf(stderr,"\t%s\n",opv->view_name.c_str());\r
+       }\r
+\r
+       if(create_makefile)\r
+               generate_makefile(input_file_names, nfiles, hfta_names, opviews,\r
+               machine_names, schema_file_name,\r
+               interface_names,\r
+               ifaces_db, config_dir_path,use_pads,ext_lib_string, rts_hload);\r
+\r
+\r
+       fprintf(qtree_output,"</QueryNodes>\n");\r
+\r
+       return(0);\r
+}\r
+\r
+////////////////////////////////////////////////////////////\r
+\r
+void generate_makefile(vector<string> &input_file_names, int nfiles,\r
+                                          vector<string> &hfta_names, opview_set &opviews,\r
+                                               vector<string> &machine_names,\r
+                                               string schema_file_name,\r
+                                               vector<string> &interface_names,\r
+                                               ifq_t *ifdb, string &config_dir_path,\r
+                                               bool use_pads,\r
+                                               string extra_libs,\r
+                                               map<string, vector<int> > &rts_hload\r
+                                        ){\r
+       int i,j;\r
+\r
+       if(config_dir_path != ""){\r
+               config_dir_path = "-C "+config_dir_path;\r
+       }\r
+\r
+       struct stat sb;\r
+       bool libz_exists = stat((root_path+"/lib/libz.a").c_str(),&sb) >= 0;\r
+       bool libast_exists = stat((root_path+"/lib/libast.a").c_str(),&sb) >= 0;\r
+\r
+//     if(libz_exists && !libast_exists){\r
+//             fprintf(stderr,"Configuration ERROR: ../../lib/libz.a exists but ../../lib/libast.a dows not.\n");\r
+//             exit(1);\r
+//     }\r
+\r
+//                     Get set of operator executable files to run\r
+       set<string> op_fls;\r
+       set<string>::iterator ssi;\r
+       for(i=0;i<opviews.size();++i){\r
+               opview_entry *opv = opviews.get_entry(i);\r
+               if(opv->exec_fl != "") op_fls.insert(opv->exec_fl);\r
+       }\r
+\r
+       FILE *outfl = fopen("Makefile", "w");\r
+       if(outfl==NULL){\r
+               fprintf(stderr,"Can't open Makefile for write, exiting.\n");\r
+               exit(0);\r
+       }\r
+\r
+       fputs(\r
+("CPP= g++ -O3 -g -I "+root_path+"/include  -I "+root_path+"/include/hfta\n"\r
+"CC= gcc -O3 -g -I . -I "+root_path+"/include -I "+root_path+"/include/lfta"\r
+).c_str(), outfl\r
+);\r
+       if(generate_stats)\r
+               fprintf(outfl,"  -DLFTA_STATS");\r
+\r
+//             Gather the set of interfaces\r
+//             Also, gather "base interface names" for use in computing\r
+//             the hash splitting to virtual interfaces.\r
+//             TODO : must update to hanndle machines\r
+       set<string> ifaces;\r
+       set<string> base_vifaces;       // base interfaces of virtual interfaces\r
+       map<string, string> ifmachines;\r
+       map<string, string> ifattrs;\r
+       for(i=0;i<interface_names.size();++i){\r
+               ifaces.insert(interface_names[i]);\r
+               ifmachines[interface_names[i]] = machine_names[i];\r
+\r
+               size_t Xpos = interface_names[i].find_last_of("X");\r
+               if(Xpos!=string::npos){\r
+                       string iface = interface_names[i].substr(0,Xpos);\r
+                       base_vifaces.insert(iface);\r
+               }\r
+               // get interface attributes and add them to the list\r
+       }\r
+\r
+//             Do we need to include protobuf libraries?\r
+       bool use_proto = false;\r
+       int erri;\r
+       string err_str;\r
+       for(ssi=ifaces.begin();ssi!=ifaces.end();++ssi){\r
+               string ifnm = (*ssi);\r
+               vector<string> ift = ifdb->get_iface_vals(ifmachines[ifnm],ifnm, "InterfaceType", erri, err_str);\r
+               for(int ift_i=0;ift_i<ift.size();ift_i++){\r
+                       if(ift[ift_i]=="PROTO"){\r
+                               use_proto = true;\r
+                       }\r
+               }\r
+       }\r
+\r
+       fprintf(outfl,\r
+"\n"\r
+"\n"\r
+"all: rts");\r
+       for(i=0;i<hfta_names.size();++i)\r
+               fprintf(outfl," %s",hfta_names[i].c_str());\r
+       fputs(\r
+("\n"\r
+"\n"\r
+"rts: lfta.o "+root_path+"/lib/libgscphost.a "+root_path+"/lib/libgscplftaaux.a "+root_path+"/lib/libgscprts.a  "+root_path+"/lib/libclearinghouse.a\n"\r
+"\tg++ -O3 -g -o rts lfta.o ").c_str(), outfl);\r
+       if(use_pads)\r
+               fprintf(outfl,"-L. ");\r
+       fputs(\r
+("-L"+root_path+"/lib -lgscplftaaux ").c_str(), outfl);\r
+       if(use_pads)\r
+               fprintf(outfl,"-lgscppads -lpads ");\r
+       fprintf(outfl,\r
+"-lgscprts -lgscphost -lm -lgscpaux -lgscplftaaux  -lclearinghouse -lresolv -lpthread -lgscpinterface -lz");\r
+       if(use_pads)\r
+               fprintf(outfl, " -lpz -lz -lbz ");\r
+       if(libz_exists && libast_exists)\r
+               fprintf(outfl," -last ");\r
+       if(use_pads)\r
+               fprintf(outfl, " -ldll -ldl ");\r
+       if(use_proto)\r
+               fprintf(outfl, " -L/usr/local/lib/ -lprotobuf-c ");\r
+       fprintf(outfl," -lgscpaux");\r
+#ifdef GCOV\r
+       fprintf(outfl," -fprofile-arcs");\r
+#endif\r
+       fprintf(outfl,\r
+"\n"\r
+"\n"\r
+"lfta.o: %s_lfta.c\n"\r
+"\t$(CC) -o lfta.o -c %s_lfta.c\n"\r
+"\n"\r
+"%s_lfta.c: external_fcns.def %s ",hostname.c_str(), hostname.c_str(), hostname.c_str(),schema_file_name.c_str());\r
+       for(i=0;i<nfiles;++i)\r
+               fprintf(outfl," %s",input_file_names[i].c_str());\r
+       if(hostname == ""){\r
+               fprintf(outfl,"\n\t%s/bin/translate_fta %s %s ",root_path.c_str(), config_dir_path.c_str(),schema_file_name.c_str());\r
+       }else{\r
+               fprintf(outfl,"\n\t%s/bin/translate_fta -h %s %s %s ", root_path.c_str(), hostname.c_str(), config_dir_path.c_str(),schema_file_name.c_str());\r
+       }\r
+       for(i=0;i<nfiles;++i)\r
+               fprintf(outfl," %s",input_file_names[i].c_str());\r
+       fprintf(outfl,"\n");\r
+\r
+       for(i=0;i<hfta_names.size();++i)\r
+               fprintf(outfl,\r
+("%s: %s.o\n"\r
+"\t$(CPP) -o %s %s.o -L"+root_path+"/lib -lgscpapp -lgscphostaux -lgscphost -lgscpinterface -lgscphftaaux -lgscphostaux -lm -lgscpaux -lclearinghouse -lresolv -lpthread -lgscpaux -lgscphftaaux -lgscpaux %s\n"\r
+"\n"\r
+"%s.o: %s.cc\n"\r
+"\t$(CPP) -o %s.o -c %s.cc\n"\r
+"\n"\r
+"\n").c_str(),\r
+    hfta_names[i].c_str(), hfta_names[i].c_str(),\r
+       hfta_names[i].c_str(), hfta_names[i].c_str(), extra_libs.c_str(),\r
+       hfta_names[i].c_str(), hfta_names[i].c_str(),\r
+       hfta_names[i].c_str(), hfta_names[i].c_str()\r
+               );\r
+\r
+       fprintf(outfl,\r
+("\n"\r
+"packet_schema.txt:\n"\r
+"\tln -s "+root_path+"/cfg/packet_schema.txt .\n"\r
+"\n"\r
+"external_fcns.def:\n"\r
+"\tln -s "+root_path+"/cfg/external_fcns.def .\n"\r
+"\n"\r
+"clean:\n"\r
+"\trm -rf core rts *.o  %s_lfta.c  external_fcns.def packet_schema.txt").c_str(),hostname.c_str());\r
+       for(i=0;i<hfta_names.size();++i)\r
+               fprintf(outfl," %s %s.cc",hfta_names[i].c_str(),hfta_names[i].c_str());\r
+       fprintf(outfl,"\n");\r
+\r
+       fclose(outfl);\r
+\r
+\r
+\r
+//             Gather the set of interfaces\r
+//             TODO : must update to hanndle machines\r
+//             TODO : lookup interface attributes and add them as a parameter to rts process\r
+       outfl = fopen("runit", "w");\r
+       if(outfl==NULL){\r
+               fprintf(stderr,"Can't open runit for write, exiting.\n");\r
+               exit(0);\r
+       }\r
+\r
+\r
+       fputs(\r
+("#!/bin/sh\n"\r
+"./stopit\n"\r
++root_path+"/bin/gshub.py> /dev/null 2>&1 &\n"\r
+"sleep 5\n"\r
+"if [ ! -f gshub.log ]\n"\r
+"then\n"\r
+"\techo \"Failed to start bin/gshub.py\"\n"\r
+"\texit -1\n"\r
+"fi\n"\r
+"ADDR=`cat gshub.log`\n"\r
+"ps opgid= $! >> gs.pids\n"\r
+"./rts $ADDR default ").c_str(), outfl);\r
+//     int erri;\r
+//     string err_str;\r
+       for(ssi=ifaces.begin();ssi!=ifaces.end();++ssi){\r
+               string ifnm = (*ssi);\r
+               fprintf(outfl, "%s ",ifnm.c_str());\r
+               vector<string> ifv = ifdb->get_iface_vals(ifmachines[ifnm],ifnm, "Command", erri, err_str);\r
+               for(j=0;j<ifv.size();++j)\r
+                       fprintf(outfl, "%s ",ifv[j].c_str());\r
+       }\r
+       fprintf(outfl, " &\n");\r
+       fprintf(outfl, "echo $! >> gs.pids\n");\r
+       for(i=0;i<hfta_names.size();++i)\r
+               fprintf(outfl,"./%s $ADDR default &\n",hfta_names[i].c_str());\r
+\r
+       for(j=0;j<opviews.opview_list.size();++j){\r
+               fprintf(outfl,"%s/views/%s %s &\n",root_path.c_str(),opviews.opview_list[j]->exec_fl.c_str(), opviews.opview_list[j]->mangler.c_str());\r
+       }\r
+\r
+       fclose(outfl);\r
+       system("chmod +x runit");\r
+\r
+       outfl = fopen("stopit", "w");\r
+       if(outfl==NULL){\r
+               fprintf(stderr,"Can't open stopit for write, exiting.\n");\r
+               exit(0);\r
+       }\r
+\r
+       fprintf(outfl,"#!/bin/sh\n"\r
+"rm -f gshub.log\n"\r
+"if [ ! -f gs.pids ]\n"\r
+"then\n"\r
+"exit\n"\r
+"fi\n"\r
+"for pgid in `cat gs.pids`\n"\r
+"do\n"\r
+"kill -TERM -$pgid\n"\r
+"done\n"\r
+"sleep 1\n"\r
+"for pgid in `cat gs.pids`\n"\r
+"do\n"\r
+"kill -9 -$pgid\n"\r
+"done\n"\r
+"rm gs.pids\n");\r
+\r
+       fclose(outfl);\r
+       system("chmod +x stopit");\r
+\r
+//-----------------------------------------------\r
+\r
+/* For now disable support for virtual interfaces\r
+       outfl = fopen("set_vinterface_hash.bat", "w");\r
+       if(outfl==NULL){\r
+               fprintf(stderr,"Can't open set_vinterface_hash.bat for write, exiting.\n");\r
+               exit(0);\r
+       }\r
+\r
+//             The format should be determined by an entry in the ifres.xml file,\r
+//             but for now hardcode the only example I have.\r
+       for(ssi=base_vifaces.begin();ssi!=base_vifaces.end();++ssi){\r
+               if(rts_hload.count((*ssi))){\r
+                       string iface_name = (*ssi);\r
+                       string iface_number = "";\r
+                       for(j=iface_name.size()-1; j>0 && iface_number == ""; j--){\r
+                               if(isdigit(iface_name[j])){\r
+                                       iface_number = iface_name[j];\r
+                                       if(j>0 && isdigit(iface_name[j-1]))\r
+                                               iface_number = iface_name[j-1] + iface_number;\r
+                               }\r
+                       }\r
+\r
+                       fprintf(outfl,"dagconfig -d%s -S hat_range=",iface_number.c_str());\r
+                       vector<int> halloc = rts_hload[iface_name];\r
+                       int prev_limit = 0;\r
+                       for(j=0;j<halloc.size();++j){\r
+                               if(j>0)\r
+                                       fprintf(outfl,":");\r
+                               fprintf(outfl,"%d-%d",prev_limit,halloc[j]);\r
+                               prev_limit = halloc[j];\r
+                       }\r
+                       fprintf(outfl,"\n");\r
+               }\r
+       }\r
+       fclose(outfl);\r
+       system("chmod +x set_vinterface_hash.bat");\r
+*/\r
+}\r
+\r
+//             Code for implementing a local schema\r
+/*\r
+               table_list qpSchema;\r
+\r
+//                             Load the schemas of any LFTAs.\r
+               int l;\r
+               for(l=0;l<hfta_nbr;++l){\r
+                       stream_query *sq0 = split_queries[l];\r
+                       table_def *td = sq0->get_output_tabledef();\r
+                       qpSchema.append_table(td);\r
+               }\r
+//                             load the schemas of any other ref'd tables.\r
+//                             (e.g., hftas)\r
+               vector<tablevar_t *>  input_tbl_names = split_queries[hfta_nbr]->get_input_tables();\r
+               int ti;\r
+               for(ti=0;ti<input_tbl_names.size();++ti){\r
+                       int tbl_ref = qpSchema.get_table_ref(input_tbl_names[ti]->get_schema_name());\r
+                       if(tbl_ref < 0){\r
+                               tbl_ref = Schema->get_table_ref(input_tbl_names[ti]->get_schema_name());\r
+                               if(tbl_ref < 0){\r
+                                       fprintf(stderr,"ERROR file %s references table %s, which is not in the schema.\n",input_file_names[i].c_str(), (input_tbl_names[ti]->get_schema_name()).c_str());\r
+                                       exit(1);\r
+                               }\r
+                               qpSchema.append_table(Schema->get_table(tbl_ref));\r
+                       }\r
+               }\r
+*/\r
+\r
+//             Functions related to parsing.\r
+\r
+/*\r
+static int split_string(char *instr,char sep, char **words,int max_words){\r
+   char *loc;\r
+   char *str;\r
+   int nwords = 0;\r
+\r
+   str = instr;\r
+   words[nwords++] = str;\r
+   while( (loc = strchr(str,sep)) != NULL){\r
+        *loc = '\0';\r
+        str = loc+1;\r
+        if(nwords >= max_words){\r
+                fprintf(stderr,"Error in split_string, too many words discovered (max is %d)\n",max_words);\r
+                nwords = max_words-1;\r
+        }\r
+        words[nwords++] = str;\r
+   }\r
+\r
+   return(nwords);\r
+}\r
+\r
+*/\r
+\r