int main() {
   int i,j;
   if (!sql_database("sah2b@sci_master_tcp")) exit(1);
   if (!getenv("S4_RECEIVER_CONFIG"))
	putenv("S4_RECEIVER_CONFIG="S4_RECEIVER_CONFIG_FILE);

   for (i=0;i<3;i++)  {
     memset(&input,0,sizeof(input));
     s4cfg_GetReceiverConfig(i, &input);
     output.s4_id=input.ReceiverID;
     strncpy(output.name,input.ReceiverName,255);
     output.name[254]=0;
     output.beam_width=input.BeamWidth;
     output.center_freq=input.CenterFreq;
     output.latitude=input.Latitude;
     output.longitude=input.Longitude;
     output.elevation=input.Elevation;
     output.diameter=input.Diameter;
     output.az_orientation=input.AzOrientation;
     output.zen_corr_coeff.clear();
     output.az_corr_coeff.clear();
     for (j=0;j<13;j++) {
       output.zen_corr_coeff.push_back(input.ZenCorrCoeff[j]);
       output.az_corr_coeff.push_back(input.AzCorrCoeff[j]);
     }
     db_change("sah2b@sci_master_tcp");
     output.id=0;
     if (output.insert()) {
       std::cout << "inserted row (id=" << output.id << ")" << std::endl;
     } else {
       std::cout << "insert failed, sql_error_code =" << sql_error_code() << " sql_last_error_code =" << sql_last_error_code() << std::endl;
     }
   }
}       
int main(int argc, char **argv) {
   int  i=0;
   
   if (argc != 2) {
     fprintf(stderr,"Usage:\n  insert_splitter_config filename\n");
     exit(1);
   }

   std::ifstream f(argv[1]);
   
   if (!f.is_open()) {
     fprintf(stderr,"File not found!\n");
     exit(1);
   }

   db_change("sah2b@sah_master_tcp");
   
   while (!f.eof()) {
     f >> cfg;
     if (!f.eof()) {
       i++;
       cfg.insert();
     }
   } 
  
   std::cout << "Found " << i << " splitter configs." << std::endl;
}       
// assimilate_handler() is called by BOINC code and is passed the canonical 
// result for a workunit.  assimilate_handler() reads the referenced result
// file and inserts the result and its signals into the master science DB.
// BOINC also passes the workunit (as it appears in the BOINC DB) and a vector
// containing all results (including the canonical one) for that workunit.
// We use the workunit to determine if there is an error condition.
int assimilate_handler(
    WORKUNIT& boinc_wu, vector<RESULT>& boinc_results, RESULT& boinc_canonical_result
) {
    int retval=0;
    int spike_count=0, spike_inserted_count=0, gaussian_count=0, gaussian_inserted_count=0, pulse_count=0, pulse_inserted_count=0, triplet_count=0, triplet_inserted_count=0;
    static receiver_config receiver_cfg;
    static analysis_config analysis_cfg;
    workunit s_wu;
    workunit_grp s_wu_grp;
    result sah_result;
    spike sah_spike;
    gaussian sah_gaussian;
    pulse sah_pulse;
    triplet sah_triplet;
    char filename[256];
    char * path;
    std::string path_str;
    long sah_result_id;
    sqlint8_t sah_spike_id, sah_gaussian_id, sah_pulse_id, sah_triplet_id;
    static bool first_time = true;
    int sql_error_code;
    long long seti_wu_id;
    time_t now;
    int hotpix_update_count;
    int hotpix_insert_count;

    APP_CONFIG sah_config;

    hotpix hotpix;
    list<long> qpixlist;            // will be a unique list of qpixes for
                                    // updating the hotpix table
    list<long>::iterator qpix_i;

    nanotime.tv_sec = 0;
    nanotime.tv_nsec = 1000000;


    // app specific configuration
    if (first_time) {
	first_time = false;
	receiver_cfg.id = 0;
	analysis_cfg.id   = 0;
    	retval = sah_config.parse_file("..");
    	if (retval) {
      		log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,
       	     	"First entrance to handler : can't parse config file. Exiting.\n"
      		);
  		return(retval);
	} else {
		retval = db_change(sah_config.scidb_name); 
		if (!retval) {
      			log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,
       	     		"First entrance to handler : could not open science DB %s. Exiting.\n",
			sah_config.scidb_name
      			);
  			return(retval);
		} else {
      			log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,
       	     		"First entrance to handler : using science DB %s\n",
			sah_config.scidb_name
      			);
		}
	}
    	// Sometimes we want to perform all assimilation functions
    	// *except* insertion into the science master DB.
    	if (noinsert) {
      		log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,
      		"[%s] assimilator is in noinsert mode.\n",
      		boinc_wu.name
      		);
    	}
    } else {
/*
	retval = db_change(sah_config.scidb_name);
        if (!retval) {
              log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,
                  "First entrance to handler : could not open science DB %s. Exiting.\n",
                  sah_config.scidb_name
              );
              return(retval);
        } else {
              log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,
                  "First entrance to handler : using science DB %s\n",
                  sah_config.scidb_name
              );
        }
*/
   }
   if (noinsert) return 0;   	// Note that this will result in the WU being marked as assimilated - 
				// we will not see it again.

    // translate seti wuid for thos wus that changed ids during the DB merge
    seti_wu_id = new_wu_id((long long)boinc_wu.opaque);
   log_messages.printf(SCHED_MSG_LOG::MSG_DEBUG,
         	"[%s] old seti WU id is : %lld  new seti WU id is : %lld\n", 
            boinc_wu.name, (long long)boinc_wu.opaque, seti_wu_id
   );

    if (boinc_wu.canonical_resultid) {
      log_messages.printf(SCHED_MSG_LOG::MSG_DEBUG,
            "[%s] Canonical result is %d.  SETI workunit ID is %lld.\n", 
	    boinc_wu.name,  boinc_wu.canonical_resultid, seti_wu_id
      );
    } else {
      log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,
            "[%s] No canonical result\n", boinc_wu.name
      );
    }

    if (!boinc_wu.canonical_resultid) {
	return 0;		// Note that this will result in the WU being marked as assimilated - 
                                // we will not see it again.  No canonical result means that
				// too many results were returned with no concensus. 

    }

    // Obtain and check the full path to the boinc result file.
    retval = get_output_file_path(boinc_canonical_result, path_str);
    if (retval) {
	if (retval == ERR_XML_PARSE) {
		log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,
			"[%s] Cannot extract filename from canonical result %ld.\n",
            		boinc_wu.name,  boinc_wu.canonical_resultid);
        	return(retval);
	} else {
		log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,
                        "[%s] unknown error from get_output_file_path() for result %ld.\n",
                        boinc_wu.name,  boinc_wu.canonical_resultid);
                return(retval);
   	}
     } else {
     	path = (char *)path_str.c_str();
     	if (!boinc_file_exists(path)) {
		log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,
        		"[%s] Output file %s does not exist for result %ld.\n",
               	  	boinc_wu.name, path,  boinc_wu.canonical_resultid);
        	return(-1);
     	} else {
		log_messages.printf(SCHED_MSG_LOG::MSG_DEBUG,
                        "[%s] Result %ld : using upload file %s\n",
               	  	boinc_wu.name, boinc_wu.canonical_resultid, path);
	}
    }

    // Open it.
    std::ifstream result_file(path, ios_base::in);
    if (!result_file.is_open()) {
      log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,
           "[%s] open error for result file %s : errno %d\n", 
           boinc_wu.name, path, errno
      );
      return -1;
    }

    retval = get_science_configs(boinc_wu, seti_wu_id, receiver_cfg, analysis_cfg);
    if (retval) {
	if (retval == 100) {
		return (0);
	} else {
		return (-1);
 	}
    }
    log_messages.printf(SCHED_MSG_LOG::MSG_DEBUG,
                        "[%s] Result %ld : using receiver_cfg %d and analysis_cfg %d\n",
               	  	boinc_wu.name, boinc_wu.canonical_resultid, receiver_cfg.id, analysis_cfg.id);

    // Insert a sah result
    retval = populate_seti_result(sah_result, boinc_canonical_result, boinc_wu, seti_wu_id);
    sah_result_id = sah_result.insert();
    if (sah_result_id) {
    	log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,
         		"[%s] Inserted result.  Boinc result id is %d.  Sah result id is %lld.\n", 
	 		boinc_wu.name, boinc_canonical_result.id, 
			(long long)sah_result_id
   	);
    } else {
	if (sql_last_error_code() == -239 || sql_last_error_code() == -268) {
		log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,
                        "[%s] Could not insert duplicate result.  SQLCODE is %ld.  SQLMSG is %s.\n",
                        boinc_wu.name, sql_last_error_code(), sql_error_message()
        	);
		return 0; 	// non-fatal - we will never see this result again
	} else {
		log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,
                        "[%s] Could not insert result.  SQLCODE is %ld.  SQLMSG is %s.\n",
                        boinc_wu.name, sql_last_error_code(), sql_error_message()
        	);
        	return -1;	// fatal - non-dup error
	}
    }

    // Insert all sah signals in turn
    insert_signals( sah_spike, 
                    "spike", 
                    boinc_wu.name, 
                    sah_result_id,
                    result_file, 
                    receiver_cfg, 
                    boinc_canonical_result.appid, 
                    analysis_cfg.max_spikes,
                    qpixlist);

    insert_signals( sah_gaussian, 
                    "gaussian", 
                    boinc_wu.name, 
                    sah_result_id,
                    result_file, 
                    receiver_cfg, 
                    boinc_canonical_result.appid, 
                    analysis_cfg.max_gaussians,
                    qpixlist);

    insert_signals( sah_pulse, 
                    "pulse", 
                    boinc_wu.name, 
                    sah_result_id,
                    result_file, 
                    receiver_cfg, 
                    boinc_canonical_result.appid, 
                    analysis_cfg.max_pulses,
                    qpixlist);

    insert_signals( sah_triplet, 
                    "triplet", 
                    boinc_wu.name, 
                    sah_result_id,
                    result_file, 
                    receiver_cfg, 
                    boinc_canonical_result.appid, 
                    analysis_cfg.max_triplets,
                    qpixlist);

    // update last hit time to now for each qpix hit
    qpixlist.unique();
    hotpix_update_count = 0;
    hotpix_insert_count = 0;
    time(&now); 
    for(qpix_i = qpixlist.begin(); qpix_i != qpixlist.end(); qpix_i++) {
        if (hotpix.fetch(*qpix_i)) {
            hotpix.last_hit_time = now;
            hotpix.update();
            hotpix_update_count++;
        } else {
            hotpix.id = *qpix_i;
            hotpix.last_hit_time = now;
            hotpix.insert(*qpix_i);
            hotpix_insert_count++;
        }
    }
    log_messages.printf(SCHED_MSG_LOG::MSG_DEBUG,
             "[%s] Updated %d rows and inserted %d rows in the hotpix table\n",
             boinc_wu.name, hotpix_update_count, hotpix_insert_count
    );

    

    return 0;   // the successful assimilation of one WU
}