[boinc-app-seti] 01/03: Imported Upstream version 7.28~svn2385

Gianfranco Costamagna locutusofborg-guest at moszumanska.debian.org
Thu Jun 5 17:38:23 UTC 2014


This is an automated email from the git hooks/post-receive script.

locutusofborg-guest pushed a commit to branch master
in repository boinc-app-seti.

commit f02069e04f1670410935d15fb5e57312bab8677e
Author: Gianfranco Costamagna <costamagnagianfranco at yahoo.it>
Date:   Thu Jun 5 19:17:57 2014 +0200

    Imported Upstream version 7.28~svn2385
---
 client/analyzeFuncs.cpp                      |  21 +-
 client/analyzePoT.cpp                        |   6 +-
 client/analyzePoT.h                          |   2 +
 client/analyzeReport.cpp                     |  28 +
 client/chirpfft.cpp                          |  35 +
 client/classes/ICoreSigProc/ICoreSigProc.cpp |  53 ++
 client/classes/ICoreSigProc/ICoreSigProc.h   |  43 ++
 client/classes/classes_history.txt           |  48 ++
 gbt_splitter/Makefile.am                     |  66 ++
 gbt_splitter/angdist.cpp                     |  79 +++
 gbt_splitter/angdist.h                       |  33 +
 gbt_splitter/cmap_interp.cpp                 |  40 ++
 gbt_splitter/cmap_interp.h                   |   6 +
 gbt_splitter/coordcvt.cpp                    | 179 +++++
 gbt_splitter/coordcvt.h                      |  40 ++
 gbt_splitter/db_fns.cpp                      | 199 ++++++
 gbt_splitter/db_fns.h                        |  48 ++
 gbt_splitter/dotransform.cpp                 | 218 ++++++
 gbt_splitter/dotransform.h                   |  56 ++
 gbt_splitter/encode.cpp                      |  93 +++
 gbt_splitter/encode.h                        |  39 ++
 gbt_splitter/fftw.h                          | 413 ++++++++++++
 gbt_splitter/four1.cpp                       |  88 +++
 gbt_splitter/four1.h                         |  31 +
 gbt_splitter/gencoeff.py                     | 143 ++++
 gbt_splitter/hr_min_sec.cpp                  | 131 ++++
 gbt_splitter/hr_min_sec.h                    | 106 +++
 gbt_splitter/makebufs.cpp                    | 139 ++++
 gbt_splitter/makebufs.h                      |  38 ++
 gbt_splitter/mb_angdist.cpp                  |  88 +++
 gbt_splitter/mb_angdist.h                    |  36 +
 gbt_splitter/mb_dotransform.cpp              | 511 ++++++++++++++
 gbt_splitter/mb_dotransform.h                |  73 ++
 gbt_splitter/mb_message.cpp                  |  73 ++
 gbt_splitter/mb_polyphase.cpp                | 150 +++++
 gbt_splitter/mb_splitter.cpp                 | 966 +++++++++++++++++++++++++++
 gbt_splitter/mb_splitter.h                   | 145 ++++
 gbt_splitter/mb_splittypes.h                 | 114 ++++
 gbt_splitter/mb_validrun.cpp                 | 147 ++++
 gbt_splitter/mb_validrun.h                   |  35 +
 gbt_splitter/mb_wufiles.cpp                  | 689 +++++++++++++++++++
 gbt_splitter/mb_wufiles.h                    |  46 ++
 gbt_splitter/message.cpp                     |  65 ++
 gbt_splitter/message.h                       |  40 ++
 gbt_splitter/polyphase.cpp                   | 149 +++++
 gbt_splitter/polyphase.h                     |  26 +
 gbt_splitter/randomdata.cpp                  |  77 +++
 gbt_splitter/readheader.cpp                  | 225 +++++++
 gbt_splitter/readheader.h                    |  42 ++
 gbt_splitter/readtape.cpp                    | 333 +++++++++
 gbt_splitter/readtape.h                      |  85 +++
 gbt_splitter/splitparms.h                    | 145 ++++
 gbt_splitter/splitter.cpp                    | 717 ++++++++++++++++++++
 gbt_splitter/splitter.h                      | 132 ++++
 gbt_splitter/splittypes.h                    | 111 +++
 gbt_splitter/squarewave.cpp                  |  75 +++
 gbt_splitter/tags                            | 463 +++++++++++++
 gbt_splitter/tools/disksplitter              | 121 ++++
 gbt_splitter/tools/sah_splitter.sh           | 150 +++++
 gbt_splitter/uttolst.h                       |   2 +
 gbt_splitter/validrun.cpp                    | 181 +++++
 gbt_splitter/validrun.h                      |  33 +
 gbt_splitter/writeheader.cpp                 | 105 +++
 gbt_splitter/writeheader.h                   |  39 ++
 gbt_splitter/wufiles.cpp                     | 679 +++++++++++++++++++
 gbt_splitter/wufiles.h                       |  39 ++
 66 files changed, 9518 insertions(+), 10 deletions(-)

diff --git a/client/analyzeFuncs.cpp b/client/analyzeFuncs.cpp
index 46f745d..552dad3 100644
--- a/client/analyzeFuncs.cpp
+++ b/client/analyzeFuncs.cpp
@@ -654,15 +654,18 @@ int seti_analyze (ANALYSIS_STATE& state) {
             // If PoT freq bin is non-negative, we are into PoT analysis
             // for this cfft pair and need not redo spike and autocorr finding.
             if (state.PoT_freq_bin == -1) {
-                state.FLOP_counter+=(double)fftlen;
-                retval = FindSpikes(
-                             &PowerSpectrum[CurrentSub],
-                             fftlen,
-                             ifft,
-                             swi
-                         );
-                if (retval) SETIERROR(retval,"from FindSpikes");
-                
+                //JWS: Don't look for Spikes at too short FFT lengths. 
+                if (fftlen >= PoTInfo.SpikeMin) {
+                  state.FLOP_counter+=(double)fftlen;
+                  retval = FindSpikes(
+                               &PowerSpectrum[CurrentSub],
+                               fftlen,
+                               ifft,
+                               swi
+                           );
+                  if (retval) SETIERROR(retval,"from FindSpikes");
+                }
+
                 if (fftlen==ac_fft_len) {
                   retval = FindAutoCorrelation(
                                AutoCorrelation,
diff --git a/client/analyzePoT.cpp b/client/analyzePoT.cpp
index 4888eea..1358121 100644
--- a/client/analyzePoT.cpp
+++ b/client/analyzePoT.cpp
@@ -600,7 +600,11 @@ void ComputePoTInfo(int num_cfft, int NumDataPoints) {
     PoTInfo.PulseFftMax  = swi.analysis_cfg.pulse_fft_max;
     PoTInfo.TripletThresh  = swi.analysis_cfg.triplet_thresh;
     PoTInfo.TripletMax  = swi.analysis_cfg.triplet_max;
-    PoTInfo.TripletMin  = swi.analysis_cfg.triplet_min;
+    //JWS: Don't process Triplet PoTs too short to produce a reportable signal.
+    PoTInfo.TripletMin           	= std::max((int)swi.analysis_cfg.triplet_min,
+                                 	           (int)(ceil(3.0 * swi.analysis_cfg.triplet_thresh)));
+    //JWS: Nor Spike PoFs.
+    PoTInfo.SpikeMin             	= (int)(ceil(swi.analysis_cfg.spike_thresh));
     PoTInfo.GaussChiSqThresh      = swi.analysis_cfg.gauss_chi_sq_thresh;
     PoTInfo.GaussPowerThresh      = swi.analysis_cfg.gauss_power_thresh;
     PoTInfo.GaussPeakPowerThresh  = swi.analysis_cfg.gauss_peak_power_thresh;
diff --git a/client/analyzePoT.h b/client/analyzePoT.h
index a58d917..6e230c0 100644
--- a/client/analyzePoT.h
+++ b/client/analyzePoT.h
@@ -65,6 +65,8 @@ typedef struct {
   double TripletThresh;
   int   TripletMax;
   int   TripletMin;
+
+  int   SpikeMin;
 }
 PoTInfo_t;
 
diff --git a/client/analyzeReport.cpp b/client/analyzeReport.cpp
index 7fd3d8f..524e53d 100644
--- a/client/analyzeReport.cpp
+++ b/client/analyzeReport.cpp
@@ -173,6 +173,12 @@ int result_spike(SPIKE_INFO &si) {
 #endif 
   int retval=0;
 
+  //R: & JWS: sanity check for found result
+  if(si.s.peak_power > si.s.fft_len){
+    boinc_temporary_exit(5*60,"Impossible Spike, retrying from checkpoint.");
+  }
+
+
   retval = outfile.printf("%s", si.s.print_xml(0,0,1).c_str());
 
   if (retval < 0) {
@@ -197,6 +203,12 @@ int result_autocorr(AUTOCORR_INFO &ai) {
   call_stack.enter("result_autocorr()");
 #endif 
 
+  //R: & JWS: sanity check for found result
+  if(ai.a.peak_power > 100.0){
+    boinc_temporary_exit(5*60,"Improbable Autocorr, retrying from checkpoint.");
+  }
+
+
   int retval=0;
 
   retval = outfile.printf("%s", ai.a.print_xml(0,0,1).c_str());
@@ -223,6 +235,11 @@ int result_gaussian(GAUSS_INFO &gi) {
   call_stack.enter("result_gaussian()");
 #endif 
 
+  //R: & JWS: sanity check for found result
+  if(gi.g.peak_power > swi.analysis_cfg.gauss_pot_length){
+    boinc_temporary_exit(5*60,"Improbable Gaussian, retrying from checkpoint.");}
+
+
   int retval=0;
 
   retval = outfile.printf("%s", gi.g.print_xml(0,0,1).c_str());
@@ -269,6 +286,11 @@ int ReportTripletEvent(
 BOINCASSERT(_CrtCheckMemory());
 #endif
 
+  //JWS: sanity check for found result.
+  if(Power > (float)pot_len){
+    boinc_temporary_exit(5*60,"Impossible Triplet, retrying from checkpoint.");
+  }
+
   if (!inv) inv = (int*)calloc_a(swi.analysis_cfg.triplet_pot_length, sizeof(int), MEM_ALIGN);
 
   // triplet info
@@ -390,6 +412,12 @@ int ReportPulseEvent(float PulsePower,float MeanPower, float period,
 BOINCASSERT(_CrtCheckMemory());
 #endif
 
+  //JWS: sanity check for found result. The limit would be 4/3 * period,
+  // but discrete math and short PoTs can exceed that slightly.
+  if(PulsePower > 1.4 * period){
+    boinc_temporary_exit(5*60,"Impossible Pulse, retrying from checkpoint.");
+  }
+
   // pulse info
   pi.score=snr/thresh;
   pi.p.peak_power=PulsePower-1;
diff --git a/client/chirpfft.cpp b/client/chirpfft.cpp
index 62e1812..e91ece9 100644
--- a/client/chirpfft.cpp
+++ b/client/chirpfft.cpp
@@ -49,6 +49,7 @@
 #include "s_util.h"
 #include "analyze.h"
 #include "worker.h"
+#include "lcgamm.h"
 #include "chirpfft.h"
 #ifdef __arm__
 #include "vector/fp_arm.h"
@@ -81,6 +82,38 @@ size_t GenChirpFftPairs(
   long MaxPulseFFTLen=
     std::min((unsigned long)(swi.nsamples/(swi.analysis_cfg.pulse_min*swi.analysis_cfg.pulse_beams*BeamsPerWU)),
              (unsigned long)swi.analysis_cfg.pulse_fft_max);
+
+  //JWS: Adjustment to avoid Pulse finding for short PoT lengths which cannot
+  // produce a reportable signal. The adjustment is not applied until after a
+  // chirp/fft table entry has been generated using the original logic, otherwise
+  // it could affect Spikes and Triplets too.
+  long MaxPulseFFTLenAlt;
+  if(MaxPulseFFTLen < swi.analysis_fft_lengths[0]) {
+    // If motion is so extreme we already know there will be no pulsefinds, skip.
+    MaxPulseFFTLenAlt = MaxPulseFFTLen;
+  } else {
+    // Find actual longest allowed FFT length
+    for (i = swi.num_fft_lengths; i ; i--) {
+      MaxPulseFFTLenAlt = swi.analysis_fft_lengths[i - 1];
+      if (MaxPulseFFTLenAlt <= MaxPulseFFTLen) break;
+    }
+    // An ideal folded pulse PoT would have all power in one element, That won't ever
+    // happen with real data, but simulation by putting all power into the first or second
+    // element of the original PulsePoT makes all folded PoTs ideal. Under those conditions,
+    // the shortest period tested at fold by 3 is seen as the best of the folded PoTs. Thus,
+    // to check whether a particular PulsePotLen can or cannot produce a reportable pulse
+    // the math for that fold level is used to determine if the threshold is low enough
+    // that an ideal PoT would be reportable.
+    while (MaxPulseFFTLenAlt > 1) {
+      int PulsePotLen = (int)(((NumSamples / MaxPulseFFTLenAlt)  / (swi.analysis_cfg.pulse_beams*BeamsPerWU)) + 0.5);
+      int di = (PulsePotLen / 2 + 1) / 2;
+      float thresh = invert_lcgf((float)(-swi.analysis_cfg.pulse_thresh - log((float)di)), 3.0f, 0.0001f);
+      if (thresh <= (float)PulsePotLen) break;
+      if (i) MaxPulseFFTLenAlt = swi.analysis_fft_lengths[--i];
+      else MaxPulseFFTLenAlt /= 2;
+    }
+  }
+
   long  NumLimits = (long)swi.analysis_cfg.chirps.size();
   double * ChirpSteps ;
   ChirpFftPair_t tmp;
@@ -128,6 +161,8 @@ size_t GenChirpFftPairs(
           sh_sint8_t key=static_cast<sh_sint8_t>(floor(CRate/(*MinChirpStep)+0.5))*2;
           key*=max_fft_len*2;
           key+=tmp.FftLen;
+          //JWS: Finally, reset PulseFind if a reportable pulse cannot be found.
+          if (tmp.FftLen > MaxPulseFFTLenAlt) tmp.PulseFind=0;
           // Insert the positive chirp overwriting any existing with this
           // key value;
           ChirpFftMap[key]=tmp;
diff --git a/client/classes/ICoreSigProc/ICoreSigProc.cpp b/client/classes/ICoreSigProc/ICoreSigProc.cpp
new file mode 100644
index 0000000..5cd5e22
--- /dev/null
+++ b/client/classes/ICoreSigProc/ICoreSigProc.cpp
@@ -0,0 +1,53 @@
+#include "ICoreSigProc.h"
+
+template class ICoreSigProc<float,float>;
+
+template< class _Tin, class _Tout >
+ICoreSigProc<_Tin,_Tout>::ICoreSigProc()
+: m_name("ICoreSigProc Class"),
+m_description("Abstract Signal processor class"),
+m_n(DEFAULT_SIZE), m_batch(1), m_self_allocated_arrays(true)
+{
+  this->Alloc_new(m_n,m_batch);
+}
+
+template< class _Tin, class _Tout >
+ICoreSigProc<_Tin,_Tout>::ICoreSigProc( int n, int batch, _Tin* idata, _Tout* odata)
+: m_name("ICoreSigProc Class"),
+m_description("Abstract Signal processor class"),
+m_n(n), m_batch(batch), m_self_allocated_arrays(false)
+{
+    m_idata = idata;
+    m_odata = odata;
+}
+
+template< class _Tin, class _Tout >
+void ICoreSigProc<_Tin,_Tout>::Alloc_new(int n, int batch)
+{
+    m_self_allocated_arrays = true;
+    m_idata = new _Tin[n*batch];
+    m_odata = new _Tout[n*batch];
+}
+
+template< class _Tin, class _Tout >
+ICoreSigProc<_Tin,_Tout>::~ICoreSigProc()
+{
+    if (m_self_allocated_arrays)
+    {
+        delete[] m_idata;
+        delete[] m_odata;
+    }
+}
+
+/*
+template <class _Tin,class _Tout>
+ICoreSigProc<_Tin,_Tout>::ICoreSigProc()
+: m_name("ICoreSigProc Class"),
+m_description("Abstract Signal processor class"),
+m_n(DEFAULT_SIZE), m_batch(1)
+{
+    FILE_LOG(logDEBUG1) << "ICoreSigProc::ICoreSigProc() called, for " << m_name << endl;
+    this->Alloc_new(m_n,m_batch);
+}
+*/
+
diff --git a/client/classes/ICoreSigProc/ICoreSigProc.h b/client/classes/ICoreSigProc/ICoreSigProc.h
new file mode 100644
index 0000000..9e49456
--- /dev/null
+++ b/client/classes/ICoreSigProc/ICoreSigProc.h
@@ -0,0 +1,43 @@
+#ifndef ICORESIGPROC_H
+#define ICORESIGPROC_H
+
+#include <string>
+#include <vector>
+
+using namespace std;
+
+#define DEFAULT_SIZE 1024
+
+template <class _Tin, class _Tout>
+class ICoreSigProc
+{
+    public:
+        /** Default constructor */
+        ICoreSigProc(void); // for performance, avoid the default destructor, which uses new/delete for data arrays
+        ICoreSigProc(int n, int batch, _Tin* idata, _Tout* odata);
+        ~ICoreSigProc(void);
+
+        virtual void execute()=0;
+
+    // member getters & setters
+        string Getname() { return m_name; }
+        void Setname(string val) { m_name = val; }
+        string Getdescription() { return m_description; }
+        void Setdescription(string val) { m_description = val; }
+        size_t Getn() { return m_n; }
+  //      void Setn(size_t val) { m_n = val; }
+        size_t Getbatch() { return m_batch; }
+  //      void Setbatch(size_t val) { m_batch = val; }
+    protected:
+        void Alloc_new(int n, int batch);
+        string m_name; //!< Member variable "m_name"
+        string m_description;
+        size_t m_n;
+        size_t m_batch;
+        _Tin *m_idata;
+        _Tout *m_odata;
+    private:
+        bool m_self_allocated_arrays;
+};
+
+#endif // ICORESIGPROC_H
diff --git a/client/classes/classes_history.txt b/client/classes/classes_history.txt
new file mode 100644
index 0000000..634aa71
--- /dev/null
+++ b/client/classes/classes_history.txt
@@ -0,0 +1,48 @@
+-----------------------------------------------------------------------------------------------------------
+31st May 2014 - Added folder structure for ITranspose and IPowerspectrum abstract base classes
+-----------------------------------------------------------------------------------------------------------
+30th May 2014 - Initial cut, for refinement as derived classes take shape 
+(FFT's will be first cab off the rank, via IFFT abstract class deriving from this, followed by fftw, oura,
+cufft, oclfft and naive dft implementation classes)
+- ICoreSigProc: Abstract (pure virtual) base template class
+template parameters <_Tin, _Tout> are input and output types respectively.
+execute() member function is pure virtual, for polymorphic use of derived classes in pipelines.
+derived classes, abstract or otherwise, should either feed pointers through using the fully
+specified constructor, or the fairly useless default constructor will be used.  Will probably disable that default constructor later.
+- Fully templatised so that higher & possibly arbitrary precision gold reference implementations
+can be easily injected in test pieces, regression tests etc, while using the same class library.
+-----------------------------------------------------------------------------------------------------------
+24th May 2014, (Part 2) [Added IPulse base class, derived from ISearch]
+- Folders for some candidate derived generic classes, for devices, signal processors, and pipelines.
+IDevices:  CPUs, GPUs, and Remote nodes (future RPC)
+ICoreSigProcs: Generalisations of major search algorithm processing steps.
+IPipelineSigProcs: Generalises different levels of parallelism that may be used
+-- IFFTPipeline: Might be asked to process one or more FFT's in a given CFFT pair, up to a whole CFFT
+-- ICFFTPipeline: Might be asked to process from one CFFT up to a whole Chirp full.
+-- IChirpPipeline: Might be asked to process from one Chirp, up to a whole task.
+-- ITaskPipeline:  Might process from one to many tasks at once (future)
+
+Jason Groothuis ( contact at jgopt dot org )
+-----------------------------------------------------------------------------------------------------------
+24th May 2014, (Part 1)
+ Initial trial folder structure (only), mirroring top level of proposed class hierarchy (currently inactive/unused).  For dropping in candidate classes for refinement and future use. 
+
+Due to a lack of naming convention for C++ Abstract Classes, I'll use common capitalisation for implementation classes, and prefix with 'I' for abstract ones.  Will stay fairly flexible this early, should namespace conflicts arise here. (i.e. don't expect stable interfaces yet )
+
+Expect containers/enumeration at high level for easing future development.
+
+ICoreSigProc- Abstract signal processor class,
+- parent/ancestor of all derived FFT, Chirp, Spike, Triplet, Pulse, Gaussian and Autocorrelation generic classes.
+- Another generic abstraction level under this one for wrapping implementations below.
+
+IDevice- Abstract Processing resource class,
+- parent/ancestor of all compute devices capable of processing any portion of core signal processing in any fashion
+- Another generic abstraction level under this one, for wrapping different kinds of device.
+
+IPipelineSigProc- Abstract class pipelining of ICoreSigProcs and IDevices
+- Abstracts allowable processing order/reductions of results etc, and devices
+- represents the processing algorithm at the highest levels
+- implementations and generalisations underneath may represent totally different 'ways' of arriving at a reference 'answer'.
+
+Jason Groothuis ( contact at jgopt dot org )
+-----------------------------------------------------------------------------------------------------------
\ No newline at end of file
diff --git a/gbt_splitter/Makefile.am b/gbt_splitter/Makefile.am
new file mode 100644
index 0000000..990f9ef
--- /dev/null
+++ b/gbt_splitter/Makefile.am
@@ -0,0 +1,66 @@
+CC=gcc
+BOINCDIR=@BOINCDIR@
+INFORMIXDIR=@INFORMIXDIR@
+SETILIB_PATH=@SETILIB_PATH@
+SETILIB_LIBS=@SETILIB_LIBS@
+SETIHOME=..
+
+LINKOPTIONS=
+
+GSL_LIBS = -lgsl -lgslcblas -lgsl
+
+DBLIBS=@INFORMIX_LIBS@ -lm -lstdc++
+
+
+LINKOPTIONS=-Xlinker -R -Xlinker $(INFORMIXDIR)/lib:$(INFORMIXDIR)/lib/esql:$(LD_LIBRARY_PATH)
+
+
+AM_CFLAGS= -g -O3 -Wall $(INCLUDE_DIRS) -DUSE_INFORMIX @PTHREAD_CFLAGS@ -ISETILIB_PATH/include
+
+
+SYSLIBS = -lcrypto -ldl
+
+BOINCLIBS= -L$(BOINCDIR)/sched -lsched @MYSQL_LIBS@ @PTHREAD_LIBS@ -L$(BOINCDIR)/lib -lboinc_crypt -lboinc -L$(SSLDIR) -lcrypto -lssl
+
+SPLITLIBS= $(SETILIB_LIBS) \
+        $(DBLIBS) \
+	$(BOINCLIBS) \
+        $(SYSLIBS) \
+	-lchealpix \
+	-lfftw3f
+
+noinst_PROGRAMS = mb_splitter
+
+
+mb_splitter_SOURCES=mb_angdist.cpp \
+		    mb_message.cpp \
+		    mb_splitter.cpp \
+		    mb_wufiles.cpp \
+		    mb_dotransform.cpp \
+		    mb_validrun.cpp \
+		    cmap_interp.cpp \
+		    ../db/schema_master.cpp \
+	            ../db/sqlifx.cpp \
+		    ../db/sqlrow.cpp \
+	            ../db/sqlblob.cpp ../db/sqlint8.cpp \
+	            ../db/xml_util.cpp \
+	            ../db/app_config.cpp  \
+	             ../client/seti_header.cpp \
+	             ../client/timecvt.cpp \
+	             ../client/lcgamm.cpp \
+		     ../client/hr_min_sec.o
+
+mb_splitter_CXXFLAGS= \
+	   -O3 \
+       -I$(SETIHOME) -I$(SETIHOME)/client -I$(SETIHOME)/db \
+       @MYSQL_CFLAGS@ -I$(HEALPIX)/include \
+       @INFORMIX_CFLAGS@ @SETILIB_CFLAGS@ \
+       @BOINC_CFLAGS@ -I$(BOINCDIR)/tools -I$(BOINCDIR)/sched -I$(BOINCDIR)/db
+mb_splitter_CFLAGS=$(mb_splitter_CXXFLAGS)
+mb_splitter_LDFLAGS=-static $(AM_LDFLAGS) -L$(HEALPIX)/lib $(LINKOPTIONS)
+mb_splitter_LDADD=$(SPLITLIBS) $(GSL_LIBS)
+
+../db/sqlifx.cpp: ../db/sqlifx.ec
+	$(INFORMIXDIR)/bin/esql -e $<
+	mv sqlifx.c $*.cpp
+
diff --git a/gbt_splitter/angdist.cpp b/gbt_splitter/angdist.cpp
new file mode 100644
index 0000000..a4d9cf2
--- /dev/null
+++ b/gbt_splitter/angdist.cpp
@@ -0,0 +1,79 @@
+/*
+ * angdist.c
+ *
+ *  Computes angular distance between two lat/lon points
+ *
+ * $Id: angdist.cpp,v 1.3.4.1 2006/12/14 22:24:37 korpela Exp $
+ *
+ */
+
+#include "sah_config.h"
+#include <cstdio>
+#include <cstdlib>
+#include <math.h>
+#include "seti_header.h"
+
+#define DTOR (M_PI/180)
+
+double angdist(double r1, double d1, double r2, double d2) {
+  double alpha,dist,d;
+
+  r1*=DTOR;
+  r2*=DTOR;
+  d1*=DTOR;
+  d2*=DTOR;
+  alpha=r1-r2;
+  dist=sin(d2)*sin(d1)+cos(d1)*cos(d2)*cos(alpha);
+  if ((dist*dist)<1) {
+    d=sqrt(1.0-dist*dist);
+  } else {
+    dist=1.0;
+    d=0.0;
+  }
+  dist=atan2(d,dist);
+  dist=dist/DTOR;
+  return (dist);
+}
+
+double angdist(const SCOPE_STRING &a, const SCOPE_STRING &b) {
+  return angdist(a.ra*15,a.dec,b.ra*15,b.dec);
+}
+
+/*
+ * $Log: angdist.cpp,v $
+ * Revision 1.3.4.1  2006/12/14 22:24:37  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.3  2003/09/11 18:53:37  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.2  2003/08/05 17:23:39  korpela
+ * More work on database stuff.
+ * Further tweaks.
+ *
+ * Revision 1.1  2003/07/29 20:35:31  korpela
+ *
+ * renames .C files to .cpp
+ *
+ * Revision 1.2  2003/06/03 01:01:15  korpela
+ *
+ * First working splitter under CVS.
+ *
+ * Revision 1.1  2003/06/03 00:16:08  korpela
+ *
+ * Initial splitter under CVS control.
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.1  1998/11/02 16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.1  1998/10/27  00:47:33  korpela
+ * Initial revision
+ *
+ *
+ */
diff --git a/gbt_splitter/angdist.h b/gbt_splitter/angdist.h
new file mode 100644
index 0000000..c3fc069
--- /dev/null
+++ b/gbt_splitter/angdist.h
@@ -0,0 +1,33 @@
+/*
+ *  angdist.h
+ *
+ *  Computes angular distance between two lat/lon points
+ *
+ * $Id: angdist.h,v 1.1 2003/06/03 00:16:09 korpela Exp $
+ *
+ */
+
+double angdist(double r1, double d1, double r2, double d2) ;
+double angdist(const SCOPE_STRING &a,const SCOPE_STRING &b);
+
+/*
+ * $Log: angdist.h,v $
+ * Revision 1.1  2003/06/03 00:16:09  korpela
+ *
+ * Initial splitter under CVS control.
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.1  1998/11/02 16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.1  1998/10/27  01:03:21  korpela
+ * Initial revision
+ *
+ *
+ */
+
diff --git a/gbt_splitter/cmap_interp.cpp b/gbt_splitter/cmap_interp.cpp
new file mode 100644
index 0000000..d431f92
--- /dev/null
+++ b/gbt_splitter/cmap_interp.cpp
@@ -0,0 +1,40 @@
+#include <map>
+#include <math.h>
+#include "setilib.h"
+#include "sqlrow.h"
+#include "sqlblob.h"
+#include "sqlapi.h"
+#include "db_table.h"
+#include "schema_master.h"
+
+coordinate_t cmap_interp(std::map<seti_time,coordinate_t> &map, seti_time &t) {
+  std::map<seti_time,coordinate_t>::iterator above(map.upper_bound(t));
+  std::map<seti_time,coordinate_t>::iterator below;
+  below=above;
+  if (above==map.begin()) {
+    above++;
+  } else {
+    below--;
+  }
+  if (above==map.end()) {
+    above--;
+    below--;
+  }
+  coordinate_t upper(above->second);
+  coordinate_t lower(below->second);
+  coordinate_t rv;
+  
+  if ((upper.ra-lower.ra)>23) lower.ra+=24;
+  if ((lower.ra-upper.ra)>23) upper.ra+=24;
+  rv.time=t.jd().uval();
+  double f=(seti_time(t.jd()-JD1970,JD1970)-seti_time(days(lower.time)))/
+                days(upper.time-lower.time);
+  rv.ra=(upper.ra-lower.ra)*f+lower.ra;
+  rv.ra=fmod(rv.ra,24.0);
+  rv.dec=(upper.dec-lower.dec)*f+lower.dec;
+  return rv;
+}
+
+
+
+  
diff --git a/gbt_splitter/cmap_interp.h b/gbt_splitter/cmap_interp.h
new file mode 100644
index 0000000..37ee520
--- /dev/null
+++ b/gbt_splitter/cmap_interp.h
@@ -0,0 +1,6 @@
+
+extern coordinate_t cmap_interp(std::map<seti_time,coordinate_t> &map, seti_time &t);
+
+
+
+  
diff --git a/gbt_splitter/coordcvt.cpp b/gbt_splitter/coordcvt.cpp
new file mode 100644
index 0000000..959f231
--- /dev/null
+++ b/gbt_splitter/coordcvt.cpp
@@ -0,0 +1,179 @@
+/*
+ * coordcvt.c
+ *
+ * Celestial coordinate conversion routines.
+ *
+ * $Id: coordcvt.cpp,v 1.2.4.1 2006/12/14 22:24:37 korpela Exp $
+ *
+ */
+
+#include "sah_config.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <math.h>
+
+#include "sqlrow.h"
+#include "sqlblob.h"
+#include "sqlapi.h"
+#include "db_table.h"
+#include "schema_master.h"
+
+#include <seti_tel.h>
+#include <seti_cfg.h>
+#include <seti_coord.h>
+
+#include "splitparms.h"
+#include "splittypes.h"
+#include "coordcvt.h"
+
+extern int gregorian;
+
+namespace SPLITTER {
+
+double jd_to_lmst(double jd, double longitude) {
+/*
+ * converts from julian date/time to local mean siderial time
+ *
+ */
+
+  double tu;    /* time, in centuries from Jan 0, 2000      */
+  double tusqr;
+  double tucb;
+  double g;     /* derrived from tu, used to calculate gmst */
+  double gmst;  /* Greenwich Mean Sidereal Time             */
+  double lmst;  /* Local Mean Sidereal Time                 */
+  double jd0=floor(jd+0.5)-0.5;             /* jd at noon GMT */
+  double ddtime=fmod((jd-jd0)*24,24);       /* GMT hours      */
+
+  tu     = (jd0 - 2451545.0)/36525;
+  tusqr  = tu * tu;
+  tucb   = tusqr * tu;
+
+/* computation of the gmst at ddtime UT */
+
+  g   = 24110.54841 + 8640184.812866 * tu + 0.093104 * tusqr - 6.62E-6 * tucb;
+
+  for (gmst = g; gmst < 0; gmst += 86400) ;
+
+  gmst /= 3600;    /* GMST at 0h UT */
+  gmst += (1.0027379093 * ddtime);  /* GMST at utime UT */
+  
+  gmst=fmod(gmst,24);
+
+/* computation of lmst given gmst and longitude */
+
+  lmst = gmst + ((longitude/360) * 24);
+ 
+  if (lmst < 0)
+      lmst += 24;
+  lmst = fmod(lmst,24);
+  return(lmst);    
+}
+
+
+void horz_to_equatorial(double alt, double azimuth, double lsthour,
+                        double lat, double *ra, double *dec) {
+   double dec_rad, hour_ang_rad, zenith_ang=90.0-alt;
+   double temp;
+
+   zenith_ang*=(M_PI/180.0);
+   azimuth*=(M_PI/180.0);
+
+   dec_rad = asin ((cos(zenith_ang) * sin(lat*M_PI/180)) +
+		    (sin(zenith_ang) * cos(lat*M_PI/180) * cos(azimuth)));
+
+  *dec = dec_rad * 180.0/M_PI;   /* radians to decimal degrees */
+
+  temp = (cos(zenith_ang) - sin(lat*M_PI/180) * sin(dec_rad)) /
+                       (cos(lat*M_PI/180) * cos(dec_rad));
+  if (temp > 1)
+    temp = 1;
+  else if (temp < -1)
+    temp = -1;
+  hour_ang_rad = acos (temp);
+
+  if (sin(azimuth) > 0.0)         /* insure correct quadrant */
+    hour_ang_rad = (2 * M_PI) - hour_ang_rad;
+ 
+ 
+                 /* to get ra, we convert hour angle to decimal degrees, */
+                 /* convert degrees to decimal hours, and subtract the   */
+                 /* result from local sidereal decimal hours.            */
+  *ra = lsthour - ((hour_ang_rad * 180.0/M_PI) / 15.0);
+
+  // Take care of wrap situations in RA
+  if (*ra < 0.0)
+    *ra += 24.0;
+  *ra=fmod(*ra,24);
+}                     
+#define D2R  0.017453292
+
+void AltAzCorrection(double *alt, double *az) {
+  double zen=90-*alt;
+  co_ZenAzCorrection((telescope_id)(gregorian?AOGREG_1420:AO_1420),&zen,az);
+  *alt=90-zen;
+}
+
+}
+
+void telstr_coord_convert(SCOPE_STRING *telstr, double lat, double lon) {
+ 
+  double lmst=SPLITTER::jd_to_lmst(telstr->st.jd,lon);
+
+  SPLITTER::AltAzCorrection(&(telstr->alt),&(telstr->az));
+  SPLITTER::horz_to_equatorial(telstr->alt, telstr->az, lmst, lat, &(telstr->ra),
+		     &(telstr->dec));
+}
+
+/*
+ * $Log: coordcvt.cpp,v $
+ * Revision 1.2.4.1  2006/12/14 22:24:37  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.2  2003/09/11 18:53:37  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.1  2003/07/29 20:35:33  korpela
+ *
+ * renames .C files to .cpp
+ *
+ * Revision 1.3  2003/06/05 19:01:45  korpela
+ *
+ * Fixed coordiate bug that allowed RA>24 hours.
+ *
+ * Revision 1.2  2003/06/05 15:52:46  korpela
+ *
+ * Fixed coordinate bug that was using the wrong zenith angle from the telescope
+ * strings when handling units from the gregorian.
+ *
+ * Revision 1.1  2003/06/03 00:16:09  korpela
+ *
+ * Initial splitter under CVS control.
+ *
+ * Revision 3.1  2003/05/20 16:01:54  eheien
+ * *** empty log message ***
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.3  1999/03/05 01:47:18  korpela
+ * New zenith angle correction.
+ *
+ * Revision 2.2  1999/02/22  22:21:09  korpela
+ * Fixed half-day error.
+ *
+ * Revision 2.1  1998/11/02 16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.2  1998/10/27  00:48:48  korpela
+ * Bug fixes.
+ *
+ * Revision 1.1  1998/10/19  23:02:43  korpela
+ * Initial revision
+ *
+ *
+ */
+
diff --git a/gbt_splitter/coordcvt.h b/gbt_splitter/coordcvt.h
new file mode 100644
index 0000000..5595f06
--- /dev/null
+++ b/gbt_splitter/coordcvt.h
@@ -0,0 +1,40 @@
+/*
+ * coordcvt.h
+ *
+ * Celestial coordinate conversion routines.
+ *
+ * $Id: coordcvt.h,v 1.1 2003/06/03 00:16:09 korpela Exp $
+ *
+ */
+
+#ifndef COORDCVT_H
+#define COORDCVT_H
+
+double jd_to_lmst(double jd, double longitude);
+
+void horz_to_equatorial(double alt, double azimuth, double lsthour,
+                        double lat, double *ra, double *dec);
+
+void telstr_coord_convert(SCOPE_STRING *telstr, double lat, double lon);
+
+#endif
+
+/*
+ * $Log: coordcvt.h,v $
+ * Revision 1.1  2003/06/03 00:16:09  korpela
+ *
+ * Initial splitter under CVS control.
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.1  1998/11/02 16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.1  1998/10/19  23:03:18  korpela
+ * Initial revision
+ *
+ */
diff --git a/gbt_splitter/db_fns.cpp b/gbt_splitter/db_fns.cpp
new file mode 100644
index 0000000..9234ed3
--- /dev/null
+++ b/gbt_splitter/db_fns.cpp
@@ -0,0 +1,199 @@
+/* 
+ * $Id: db_fns.cpp,v 1.3.4.2 2006/12/14 22:24:37 korpela Exp $
+ *
+ */
+  
+
+#include "sah_config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "splitparms.h"
+#include "splittypes.h"
+#include "splitter.h"
+#include "message.h"
+#include "readtape.h"
+#include "sqlrow.h"
+#include "sqlblob.h"
+#include "db_table.h"
+#include "schema_master.h"
+
+
+static tape tape_struct;
+
+int update_tape_entry( tapeheader_t *tapeheader) ;
+
+int get_last_block(tapeheader_t *tapeheader) {
+    int err;
+  strncat(tape_struct.tapename,tapeheader->name,20);
+  if (!db_tape_lookup_name(&tape_struct)) {
+    return(tape_struct.last_block_done/TAPE_FRAMES_PER_RECORD);
+  } else {
+      if ((err=db_tape_new(&tape_struct))) {
+        log_messages.printf( SCHED_MSG_LOG::MSG_CRITICAL,"Unable to create db entry for tape %s error %d.\n",tapeheader->name,err);      
+        exit(1);
+      }
+    return 0;
+  }
+}
+  
+
+/* returns id number of tape db entry or zero if failure */
+/*int update_tape_entry( tapeheader_t *tapeheader) {
+  if (strncmp(tapeheader->name,tape_struct.tapename,20)) {
+    strncat(tape_struct.tapename,tapeheader->name,20);
+    if (db_tape_lookup_name(&tape_struct)) {
+      tape_struct.id=0;
+      strncpy(tape_struct.tapename,tapeheader->name,20);
+      tape_struct.start_time=tapeheader->st.jd;
+      tape_struct.last_block_time=tapeheader->st.jd;
+      tape_struct.last_block_done=tapeheader->frameseq;
+      if (db_tape_new(&tape_struct)) {
+	char tmpstr[256];
+        fprintf( stderr, "Point 2\n" );
+	sprintf(tmpstr,"Unable to create db entry for tape %s.",tapeheader->name);
+	message(tmpstr);
+        return(0);
+      } 
+    }
+  }
+  tape_struct.last_block_time=tapeheader->st.jd;
+  tape_struct.last_block_done=tapeheader->frameseq;
+  if (db_tape_update(&tape_struct)) {
+    char tmpstr[256];
+    sprintf(tmpstr,"Unable to update db entry for tape %s.",tapeheader->name);
+    message(tmpstr);
+    return(0);
+  }
+  return(tape_struct.id);
+}
+*/
+
+/* returns workunit group id number on success, 0 on failure */
+/*
+int create_wugrp_entry(workunit_grp &wugrp, int tapenum, tapeheader_t *tapeheader) {
+   int i,n;
+
+   wugrp.tapenum=tapenum;
+   strncpy(wugrp.wugrpname,wugrpname,64);
+   wugrp.splitter_version=wuheader->wuinfo.splitter_version;
+   wugrp.start_ra=wuheader->wuinfo.start_ra;
+   wugrp.start_dec=wuheader->wuinfo.start_dec;
+   wugrp.end_ra=wuheader->wuinfo.end_ra;
+   wugrp.end_dec=wuheader->wuinfo.end_dec;
+   wugrp.angle_range=wuheader->wuinfo.angle_range;
+   wugrp.true_angle_range=wuheader->wuinfo.true_angle_range;
+   wugrp.beam_width=wuheader->wuinfo.beam_width;
+   wugrp.time_recorded=wuheader->wuinfo.time_recorded;
+   wugrp.fft_len=wuheader->wuinfo.fft_len;
+   wugrp.ifft_len=wuheader->wuinfo.ifft_len;
+   wugrp.receiver=wuheader->wuinfo.source;
+   wugrp.nsamples=wuheader->wuinfo.nsamples;
+   wugrp.sample_rate=tapeheader->samplerate;
+   wugrp.data_class=wuheader->wuinfo.data_class;
+   strncpy(wugrp.tape_version,wuheader->wuinfo.tape_version,13);
+   wugrp.num_positions=wuheader->wuinfo.num_positions;
+   if (db_workunit_grp_new(&wugrp)) {
+     char tmpstr[256];
+     sprintf(tmpstr,"Unable to create db entry for workunit_grp %s\n",wugrpname);
+     message(tmpstr);
+     return(0);
+   }
+   for (i=0;i<wugrp.num_positions;i++) {
+     char tmpstr[34];
+     sprintf(tmpstr,"%14.5f %6.3f %6.2f",
+       wuheader->wuinfo.position_history[i].st.jd,
+       wuheader->wuinfo.position_history[i].ra,
+       wuheader->wuinfo.position_history[i].dec
+     );
+     if (n=db_workunit_grp_update_position(wugrp.id,i,tmpstr)) {
+         fprintf( stderr, "%d\n", n );
+       sprintf(tmpstr,"Unable to add position %d to workunit_grp %s\n",i,wugrpname);
+       message(tmpstr);
+     }
+   }
+   return (wugrp.id);
+}
+
+int create_workunit_entry(wuheader_t *wuheader, int wugrpid, int subband_number) {
+  WORKUNIT wu;
+
+  memset(&wu,0,sizeof(wu));
+  strncpy(wu.name,wuheader->wuhead.name,63);
+  wu.grpnum=wugrpid;
+  wu.subb_center=wuheader->wuinfo.subband_center;
+  wu.subb_base=wuheader->wuinfo.subband_base;
+  wu.subb_sample_rate=wuheader->wuinfo.subband_sample_rate;
+  wu.subband_number=subband_number;
+  wu.data_class=wuheader->wuinfo.data_class;
+  if (db_workunit_new(&wu)) {
+    char tmpstr[256];
+    sprintf(tmpstr,"Unable to create workunit entry %s\n",wu.name);
+    message(tmpstr);
+    return(0);
+  }
+  return(wu.id);
+}
+*/
+
+/*
+ * $Log: db_fns.cpp,v $
+ * Revision 1.3.4.2  2006/12/14 22:24:37  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.3.4.1  2006/01/13 00:37:56  korpela
+ * Moved splitter to using standard BOINC logging mechanisms.  All stderr now
+ * goes to "error.log"
+ *
+ * Added command line parameters "-iterations=" (number of workunit groups to
+ * create before exiting), "-trigger_file_path=" (path to the splitter_stop trigger
+ * file.  Default is /disks/setifiler1/wutape/tapedir/splitter_stop).
+ *
+ * Reduced deadlines by a factor of three.  We now need a 30 MFLOP machine to meet
+ * the deadline.
+ *
+ * Revision 1.3  2003/09/11 18:53:37  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.2  2003/08/05 17:23:40  korpela
+ * More work on database stuff.
+ * Further tweaks.
+ *
+ * Revision 1.1  2003/07/29 20:35:35  korpela
+ *
+ * renames .C files to .cpp
+ *
+ * Revision 1.2  2003/06/03 01:01:16  korpela
+ *
+ * First working splitter under CVS.
+ *
+ * Revision 1.1  2003/06/03 00:16:10  korpela
+ *
+ * Initial splitter under CVS control.
+ *
+ * Revision 3.2  2003/05/19 17:40:59  eheien
+ * *** empty log message ***
+ *
+ * Revision 3.1  2001/11/07 00:51:47  korpela
+ * Added splitter version to database.
+ * Added max_wus_ondisk option.
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 1.4  2000/12/01 01:13:29  korpela
+ * *** empty log message ***
+ *
+// Revision 1.3  1999/03/05  01:47:18  korpela
+// Added data_class field.
+//
+// Revision 1.2  1999/02/22  22:21:09  korpela
+// Fixed half-day error.
+//
+// Revision 1.1  1999/02/11  16:46:28  korpela
+// Initial revision
+//
+ * 
+ */
diff --git a/gbt_splitter/db_fns.h b/gbt_splitter/db_fns.h
new file mode 100644
index 0000000..3ccf871
--- /dev/null
+++ b/gbt_splitter/db_fns.h
@@ -0,0 +1,48 @@
+/*
+ * $Id: db_fns.h,v 1.3 2003/08/05 17:23:40 korpela Exp $
+ *
+ */
+
+
+#ifndef DB_FNS_H
+#define DB_FNS_H
+
+#include "schema_master.h"
+
+int get_last_block(tapeheader_t *tapeheader) ;
+
+//int update_tape_entry( tapeheader_t *tapeheader) ;
+
+/* returns workunit group id number on success, 0 on failure */
+//int create_wugrp_entry(char *wugrpname,wuheader_t *wuheader, int tapenum, tapeheader_t *tapeheader) ;
+
+//int create_workunit_entry(wuheader_t *wuheader, int wugrpid, int subband_number) ;
+
+#endif
+
+/*
+ * 
+ * $Log: db_fns.h,v $
+ * Revision 1.3  2003/08/05 17:23:40  korpela
+ * More work on database stuff.
+ * Further tweaks.
+ *
+ * Revision 1.2  2003/06/03 01:01:16  korpela
+ *
+ * First working splitter under CVS.
+ *
+ * Revision 1.1  2003/06/03 00:16:10  korpela
+ *
+ * Initial splitter under CVS control.
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 1.2  1999/02/22 22:21:09  korpela
+ * added -nodb option
+ *
+ * Revision 1.1  1999/02/11  16:46:28  korpela
+ * Initial revision
+ *
+ *
+ */
diff --git a/gbt_splitter/dotransform.cpp b/gbt_splitter/dotransform.cpp
new file mode 100644
index 0000000..1663a50
--- /dev/null
+++ b/gbt_splitter/dotransform.cpp
@@ -0,0 +1,218 @@
+/*
+ * 
+ * dotransform.c
+ *
+ * Functions for division by frequency into work units.
+ *
+ * $Id: dotransform.cpp,v 1.2.4.1 2006/12/14 22:24:38 korpela Exp $
+ *
+ */
+
+#include "sah_config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <unistd.h>
+#include <limits.h>
+#include <assert.h>
+#include <math.h>
+
+#include "splitparms.h"
+#include "splittypes.h"
+#include "splitter.h"
+#include "fftw.h"
+#include "wufiles.h"
+
+/* buffer for fft input/output */
+float databuf[FFT_LEN*2];
+
+/* buffer for ftt output before data writes, needs to be multiple
+ * of three bytes long for encode to work.
+ */
+#define SAMPLES_PER_OBUF (FFT_LEN*2*3/CHAR_BIT)
+unsigned char output_buf[NSTRIPS][SAMPLES_PER_OBUF];  
+
+
+int obuf_pos; /* Tracks current postition in the output buffers */
+
+
+void output_samples(float *data, int i, int buf_pos) {
+  int j,k;
+  unsigned short s;
+  float *p=data;
+
+  for (j=0;j<2;j++) {
+    s=0;
+    for (k=0; k<8; k++) {
+        s >>= 2;
+        if (*p>0) s |= 0x8000;
+	if (*(p+1)>0) s |= 0x4000;
+        p+=2;
+    }
+    output_buf[i][buf_pos++]=*(char *)(&s);
+    output_buf[i][buf_pos++]=*(((char *)(&s))+1);
+  }
+}
+
+void splitter_bits_to_float(unsigned short *raw, float *data, int nsamples) {
+    unsigned int i, j;
+    unsigned short s;
+    static int first_time=1;
+    static float lut[65536][16];
+
+    assert(!(nsamples % 8));
+
+    if (first_time) {
+      for (i=0;i<65536;i++) {
+	s=(unsigned short)i;
+	for (j=0;j<8;j++) {
+	    lut[i][j*2]=(float)2*(s & 1)-1;
+	    s >>= 1;
+	    lut[i][j*2+1]=(float)2*(s & 1)-1;
+            s >>= 1;
+        }
+      }
+      first_time--;
+    }
+
+    for (i=0;i<(nsamples/8);i++) {
+      memcpy(data+16*i,lut[raw[i]],16*sizeof(float));
+    }
+}
+
+void process_seg(float* data) {
+    int i;
+    float* p = data;
+    static float dbuff[FFT_LEN*2];
+    static fftw_plan  planfwd,planinverse;
+
+    if (!planfwd) {
+      planfwd=fftw_create_plan(FFT_LEN, FFTW_BACKWARD, 
+		FFTW_MEASURE | FFTW_IN_PLACE | FFTW_USE_WISDOM );
+      planinverse=fftw_create_plan(IFFT_LEN, FFTW_FORWARD,
+		FFTW_MEASURE | FFTW_IN_PLACE | FFTW_USE_WISDOM );
+    }
+
+    fftw_one(planfwd, (fftw_complex *)data, (fftw_complex *)NULL);
+    data[0]=0;
+    data[1]=0;
+    fftw(planinverse, NSTRIPS, (fftw_complex *)data, 1, IFFT_LEN, 
+  			(fftw_complex *)NULL, 1, IFFT_LEN);
+    for (i=0; i<NSTRIPS; i++) {
+        output_samples(p, i, obuf_pos);
+        p += IFFT_LEN*2;
+    }
+    obuf_pos+=IFFT_LEN*2/CHAR_BIT;
+}
+
+#define TBUF_OFFSET(frame,byte) (tapebuffer+(frame)*TAPE_FRAME_SIZE+(byte)+TAPE_HEADER_SIZE)
+
+void do_transform(buffer_pos_t *start_of_wu, buffer_pos_t *end_of_wu) {
+   buffer_pos_t end_trans,start_trans=*start_of_wu;
+   int i,nsamp;
+   do {
+     obuf_pos=0;  /* reset to the beginning of the output buffer */
+     for (i=0;i<768;i++) {
+       end_trans.frame=start_trans.frame;
+       end_trans.byte=start_trans.byte+(FFT_LEN*2/CHAR_BIT);
+       if (end_trans.byte > TAPE_DATA_SIZE) {
+       /* End of frame crossed need to trasfer correctly */
+          end_trans.frame++;
+          end_trans.byte-=TAPE_DATA_SIZE;
+          nsamp=(TAPE_DATA_SIZE-start_trans.byte)*(CHAR_BIT/2);
+          assert((nsamp+end_trans.byte*(CHAR_BIT/2)) == FFT_LEN);
+          splitter_bits_to_float((unsigned short *)TBUF_OFFSET(start_trans.frame,start_trans.byte),
+                        databuf, nsamp);
+          splitter_bits_to_float((unsigned short *)TBUF_OFFSET(end_trans.frame,0),databuf+nsamp*2,
+                        end_trans.byte*(CHAR_BIT/2));
+       } else {
+          splitter_bits_to_float((unsigned short *)TBUF_OFFSET(start_trans.frame,start_trans.byte),
+                        databuf,FFT_LEN);
+       }
+       process_seg(databuf);
+       /* Go on to next transform */
+       start_trans=end_trans;
+     }
+     /* Check if we're at the end of the wu file. If so we print less bytes */
+     if ((end_trans.frame>=end_of_wu->frame) && 
+			 (end_trans.byte>=end_of_wu->byte)) {
+       write_wufile_blocks(NBYTES % SAMPLES_PER_OBUF);
+     } else {
+       write_wufile_blocks(SAMPLES_PER_OBUF);
+     }
+   } while (!((end_trans.frame>=end_of_wu->frame) && (end_trans.byte>=end_of_wu->byte)));
+
+   /* Move the data in the buffer so we don't have to reread portions of the
+    * tape.
+    */
+   { 
+     unsigned char *record_offset;
+     int copysize;
+     end_of_wu->frame-=WU_OVERLAP_FRAMES;
+     records_in_buffer=TAPE_RECORDS_IN_BUFFER-
+			 (end_of_wu->frame/TAPE_FRAMES_PER_RECORD);
+     record_offset=tapebuffer+
+             (end_of_wu->frame/TAPE_FRAMES_PER_RECORD)*TAPE_RECORD_SIZE;
+     copysize=records_in_buffer*TAPE_RECORD_SIZE;
+     bcopy(record_offset,tapebuffer,copysize);
+   }
+}
+
+/*
+ *
+ * $Log: dotransform.cpp,v $
+ * Revision 1.2.4.1  2006/12/14 22:24:38  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.2  2003/09/11 18:53:37  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.1  2003/07/29 20:35:36  korpela
+ *
+ * renames .C files to .cpp
+ *
+ * Revision 1.1  2003/06/03 00:16:10  korpela
+ *
+ * Initial splitter under CVS control.
+ *
+ * Revision 3.2  2003/05/19 17:40:59  eheien
+ * *** empty log message ***
+ *
+ * Revision 3.1  2003/04/10 22:09:00  korpela
+ * *** empty log message ***
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.7  1999/03/27 16:19:35  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.6  1999/02/22  19:02:50  korpela
+ * Revered input real & imaginary.
+ *
+ * Revision 2.5  1999/02/10  21:49:44  korpela
+ * Zeroed DC component of forward transform.
+ *
+ * Revision 2.4  1999/02/01  22:28:52  korpela
+ * FFTW version.
+ *
+ * Revision 2.3  1998/12/14  23:41:44  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.2  1998/11/04 23:08:25  korpela
+ * Byte and bit order change.
+ *
+ * Revision 2.1  1998/11/02  16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.2  1998/10/30  20:26:03  korpela
+ * Bug Fixes.  Now mostly working.
+ *
+ * Revision 1.1  1998/10/27  00:51:08  korpela
+ * Initial revision
+ *
+ *
+ */
diff --git a/gbt_splitter/dotransform.h b/gbt_splitter/dotransform.h
new file mode 100644
index 0000000..5b3136d
--- /dev/null
+++ b/gbt_splitter/dotransform.h
@@ -0,0 +1,56 @@
+/*
+ * 
+ * dotransform.h
+ *
+ * Functions for division by frequency into work units.
+ *
+ * $Id: dotransform.h,v 1.1 2003/06/03 00:16:11 korpela Exp $
+ *
+ */
+
+/* buffer for fft input/output */
+extern float databuf[FFT_LEN*2];
+
+/* buffer for ftt output before data writes, needs to be multiple
+ * of three bytes long for encode to work.
+ */
+#define SAMPLES_PER_OBUF (FFT_LEN*2*3/CHAR_BIT)
+#define TBUF_OFFSET(frame,byte) (tapebuffer+(frame)*TAPE_FRAME_SIZE+(byte))
+extern unsigned char output_buf[NSTRIPS][SAMPLES_PER_OBUF];  
+
+
+extern int obuf_pos; /* Tracks current postition in the output buffers */
+
+
+void output_samples(float *data, int i, int buf_pos);
+void splitter_bits_to_float(unsigned short *raw, float *data, int nsamples) ;
+void process_seg(float* data) ;
+void do_transform(buffer_pos_t *start_of_wu, buffer_pos_t *end_of_wu) ;
+
+/*
+ *
+ * $Log: dotransform.h,v $
+ * Revision 1.1  2003/06/03 00:16:11  korpela
+ *
+ * Initial splitter under CVS control.
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.3  1999/02/01 22:28:52  korpela
+ * FFTW version.
+ *
+ * Revision 2.2  1998/11/04  23:08:25  korpela
+ * Byte and bit order change.
+ *
+ * Revision 2.1  1998/11/02  16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.1  1998/10/27  01:05:22  korpela
+ * Initial revision
+ *
+ *
+ */
diff --git a/gbt_splitter/encode.cpp b/gbt_splitter/encode.cpp
new file mode 100644
index 0000000..579697b
--- /dev/null
+++ b/gbt_splitter/encode.cpp
@@ -0,0 +1,93 @@
+/*
+ *
+ * binary to ascii encoding for work unit files
+ *
+ * $Id: encode.cpp,v 1.2.4.2 2007/06/01 03:29:25 korpela Exp $
+ *
+ */
+
+#include "sah_config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <assert.h>
+
+/* Write a range of bytes encoded into printable chars.
+ * Encodes 3 bytes into 4 chars.
+ * May read up to two bytes past end
+ */
+
+void splitter_encode(unsigned char *bin, int nbytes, FILE *f) {
+    int count=0, offset=0, nleft, count1=0;
+    unsigned char c[4*1024+64];
+    unsigned char nl=10;
+    assert(nbytes<=(3*1024));
+    for (nleft = nbytes; nleft > 0; nleft -= 3) {
+        c[0+count1] = bin[offset]&0x3f;                                  // 6
+        c[1+count1] = (bin[offset]>>6) | (bin[offset+1]<<2)&0x3f;        // 2+4
+        c[2+count1] = ((bin[offset+1]>>4)&0xf) | (bin[offset+2]<<4)&0x3f;// 4+2
+        c[3+count1] = bin[offset+2]>>2;                          // 6
+        c[0+count1] += 0x20;
+        c[1+count1] += 0x20;
+        c[2+count1] += 0x20;
+        c[3+count1] += 0x20;
+        offset += 3;
+        count += 4;
+	count1 +=4;
+        if (count == 64) {
+            count = 0;
+	    c[count1++]=nl;
+        }
+    }
+    write(fileno(f),c,count1);
+}
+
+/*
+ *
+ * $Log: encode.cpp,v $
+ * Revision 1.2.4.2  2007/06/01 03:29:25  korpela
+ * Fixes for linux build of Joe's updated code.
+ *
+ * Probably not working yet.
+ *
+ * Revision 1.2.4.1  2006/12/14 22:24:38  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.2  2003/09/11 18:53:37  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.1  2003/07/29 20:35:37  korpela
+ *
+ * renames .C files to .cpp
+ *
+ * Revision 1.1  2003/06/03 00:16:11  korpela
+ *
+ * Initial splitter under CVS control.
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.3  1998/11/04 23:08:25  korpela
+ * Byte and bit order change.
+ *
+ * Revision 2.2  1998/11/02  21:20:58  korpela
+ * changed function name from encode() to splitter_encode() to avoid
+ * conflict with encode routine in ../client/util.C.  Will investigate
+ * if merging of two functions is possible.
+ *
+ * Revision 2.1  1998/11/02  16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.2  1998/10/30  20:26:03  korpela
+ * Bug Fixes.  Now mostly working.
+ *
+ * Revision 1.1  1998/10/27  00:52:56  korpela
+ * Initial revision
+ *
+ *
+ */
+
+
diff --git a/gbt_splitter/encode.h b/gbt_splitter/encode.h
new file mode 100644
index 0000000..d17775f
--- /dev/null
+++ b/gbt_splitter/encode.h
@@ -0,0 +1,39 @@
+/*
+ *
+ * binary to ascii encoding for work unit files
+ *
+ * $Id: encode.h,v 1.1 2003/06/03 00:16:11 korpela Exp $
+ *
+ */
+
+/* Write a range of bytes encoded into printable chars.
+ * Encodes 3 bytes into 4 chars.
+ * May read up to two bytes past end
+ */
+
+void splitter_encode(unsigned char *bin, int nbytes, FILE *f);
+
+/*
+ * $Log: encode.h,v $
+ * Revision 1.1  2003/06/03 00:16:11  korpela
+ *
+ * Initial splitter under CVS control.
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.2  1998/11/02 21:20:58  korpela
+ * Changed routine name from encode() to splitter_encode().  See encode.C
+ * for details.
+ *
+ * Revision 2.1  1998/11/02  16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.1  1998/10/27  01:06:46  korpela
+ * Initial revision
+ *
+ *
+ */
diff --git a/gbt_splitter/fftw.h b/gbt_splitter/fftw.h
new file mode 100644
index 0000000..41698f7
--- /dev/null
+++ b/gbt_splitter/fftw.h
@@ -0,0 +1,413 @@
+/* fftw/fftw.h.  Generated automatically by configure.  */
+/* -*- C -*- */
+/*
+ * Copyright (c) 1997,1998 Massachusetts Institute of Technology
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/* fftw.h -- system-wide definitions */
+/* $Id: fftw.h,v 1.1 2003/06/03 00:16:12 korpela Exp $ */
+
+#ifndef FFTW_H
+#define FFTW_H
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif				/* __cplusplus */
+
+/* Define for using single precision */
+/*
+ * If you can, use configure --enable-float instead of changing this
+ * flag directly 
+ */
+#define FFTW_ENABLE_FLOAT 1
+
+/* our real numbers */
+#ifdef FFTW_ENABLE_FLOAT
+typedef float fftw_real;
+#else
+typedef double fftw_real;
+#endif
+
+/*********************************************
+ * Complex numbers and operations 
+ *********************************************/
+typedef struct {
+     fftw_real re, im;
+} fftw_complex;
+
+#define c_re(c)  ((c).re)
+#define c_im(c)  ((c).im)
+
+typedef enum {
+     FFTW_FORWARD = -1, FFTW_BACKWARD = 1
+} fftw_direction;
+
+/* backward compatibility with FFTW-1.3 */
+typedef fftw_complex FFTW_COMPLEX;
+typedef fftw_real FFTW_REAL;
+
+#ifndef FFTW_1_0_COMPATIBILITY
+#define FFTW_1_0_COMPATIBILITY 0
+#endif
+
+#if FFTW_1_0_COMPATIBILITY
+/* backward compatibility with FFTW-1.0 */
+#define REAL fftw_real
+#define COMPLEX fftw_complex
+#endif
+
+/*********************************************
+ * Success or failure status
+ *********************************************/
+
+typedef enum {
+     FFTW_SUCCESS = 0, FFTW_FAILURE = -1
+} fftw_status;
+
+/*********************************************
+ *              Codelets
+ *********************************************/
+typedef void (fftw_notw_codelet) 
+     (const fftw_complex *, fftw_complex *, int, int);
+typedef void (fftw_twiddle_codelet)
+     (fftw_complex *, const fftw_complex *, int,
+      int, int);
+typedef void (fftw_generic_codelet) 
+     (fftw_complex *, const fftw_complex *, int,
+      int, int, int);
+typedef void (fftw_real2hc_codelet)
+     (const fftw_real *, fftw_real *, fftw_real *,
+      int, int, int);
+typedef void (fftw_hc2real_codelet)
+     (const fftw_real *, const fftw_real *,
+      fftw_real *, int, int, int);
+typedef void (fftw_hc2hc_codelet)
+     (fftw_real *, const fftw_complex *,
+      int, int, int);
+typedef void (fftw_rgeneric_codelet)
+     (fftw_real *, const fftw_complex *, int,
+      int, int, int);
+
+/*********************************************
+ *     Configurations
+ *********************************************/
+/*
+ * A configuration is a database of all known codelets
+ */
+
+enum fftw_node_type {
+     FFTW_NOTW, FFTW_TWIDDLE, FFTW_GENERIC, FFTW_RADER,
+     FFTW_REAL2HC, FFTW_HC2REAL, FFTW_HC2HC, FFTW_RGENERIC
+};
+
+/* description of a codelet */
+typedef struct {
+     const char *name;		/* name of the codelet */
+     void (*codelet) ();	/* pointer to the codelet itself */
+     int size;			/* size of the codelet */
+     fftw_direction dir;	/* direction */
+     enum fftw_node_type type;	/* TWIDDLE or NO_TWIDDLE */
+     int signature;		/* unique id */
+     int ntwiddle;		/* number of twiddle factors */
+     const int *twiddle_order;	/* 
+				 * array that determines the order 
+				 * in which the codelet expects
+				 * the twiddle factors
+				 */
+} fftw_codelet_desc;
+
+/* On Win32, you need to do funny things to access global variables
+   in shared libraries.  Thanks to Andrew Sterian for this hack. */
+#if defined(__WIN32__) || defined(WIN32) || defined(_WINDOWS)
+#  if defined(BUILD_FFTW_DLL)
+#    define DL_IMPORT(type) __declspec(dllexport) type
+#  elif defined(USE_FFTW_DLL)
+#    define DL_IMPORT(type) __declspec(dllimport) type
+#  else
+#    define DL_IMPORT(type) type
+#  endif
+#else
+#  define DL_IMPORT(type) type
+#endif
+
+extern DL_IMPORT(const char *) fftw_version;
+
+/*****************************
+ *        Plans
+ *****************************/
+/*
+ * A plan is a sequence of reductions to compute a FFT of
+ * a given size.  At each step, the FFT algorithm can:
+ *
+ * 1) apply a notw codelet, or
+ * 2) recurse and apply a twiddle codelet, or
+ * 3) apply the generic codelet.
+ */
+
+/* structure that contains twiddle factors */
+typedef struct fftw_twiddle_struct {
+     int n;
+     const fftw_codelet_desc *cdesc;
+     fftw_complex *twarray;
+     struct fftw_twiddle_struct *next;
+     int refcnt;
+} fftw_twiddle;
+
+typedef struct fftw_rader_data_struct {
+     struct fftw_plan_struct *plan;
+     fftw_complex *omega;
+     int g, ginv;
+     int p, flags, refcount;
+     struct fftw_rader_data_struct *next;
+     fftw_codelet_desc *cdesc;
+} fftw_rader_data;
+
+typedef void (fftw_rader_codelet) 
+     (fftw_complex *, const fftw_complex *, int,
+      int, int, fftw_rader_data *);
+
+/* structure that holds all the data needed for a given step */
+typedef struct fftw_plan_node_struct {
+     enum fftw_node_type type;
+
+     union {
+	  /* nodes of type FFTW_NOTW */
+	  struct {
+	       int size;
+	       fftw_notw_codelet *codelet;
+	       const fftw_codelet_desc *codelet_desc;
+	  } notw;
+
+	  /* nodes of type FFTW_TWIDDLE */
+	  struct {
+	       int size;
+	       fftw_twiddle_codelet *codelet;
+	       fftw_twiddle *tw;
+	       struct fftw_plan_node_struct *recurse;
+	       const fftw_codelet_desc *codelet_desc;
+	  } twiddle;
+
+	  /* nodes of type FFTW_GENERIC */
+	  struct {
+	       int size;
+	       fftw_generic_codelet *codelet;
+	       fftw_twiddle *tw;
+	       struct fftw_plan_node_struct *recurse;
+	  } generic;
+
+	  /* nodes of type FFTW_RADER */
+	  struct {
+	       int size;
+	       fftw_rader_codelet *codelet;
+	       fftw_rader_data *rader_data;
+	       fftw_twiddle *tw;
+	       struct fftw_plan_node_struct *recurse;
+	  } rader;
+
+	  /* nodes of type FFTW_REAL2HC */
+	  struct {
+	       int size;
+	       fftw_real2hc_codelet *codelet;
+	       const fftw_codelet_desc *codelet_desc;
+	  } real2hc;
+
+	  /* nodes of type FFTW_HC2REAL */
+	  struct {
+	       int size;
+	       fftw_hc2real_codelet *codelet;
+	       const fftw_codelet_desc *codelet_desc;
+	  } hc2real;
+
+	  /* nodes of type FFTW_HC2HC */
+	  struct {
+	       int size;
+	       fftw_direction dir;
+	       fftw_hc2hc_codelet *codelet;
+	       fftw_twiddle *tw;
+	       struct fftw_plan_node_struct *recurse;
+	       const fftw_codelet_desc *codelet_desc;
+	  } hc2hc;
+
+	  /* nodes of type FFTW_RGENERIC */
+	  struct {
+	       int size;
+	       fftw_direction dir;
+	       fftw_rgeneric_codelet *codelet;
+	       fftw_twiddle *tw;
+	       struct fftw_plan_node_struct *recurse;
+	  } rgeneric;
+     } nodeu;
+
+     int refcnt;
+} fftw_plan_node;
+
+struct fftw_plan_struct {
+     int n;
+     int refcnt;
+     fftw_direction dir;
+     int flags;
+     int wisdom_signature;
+     enum fftw_node_type wisdom_type;
+     struct fftw_plan_struct *next;
+     fftw_plan_node *root;
+     double cost;
+};
+
+/* a plan is just an array of instructions */
+typedef struct fftw_plan_struct *fftw_plan;
+
+/* flags for the planner */
+#define  FFTW_ESTIMATE (0)
+#define  FFTW_MEASURE  (1)
+
+#define FFTW_OUT_OF_PLACE (0)
+#define FFTW_IN_PLACE (8)
+#define FFTW_USE_WISDOM (16)
+
+#define FFTW_THREADSAFE (128)  /* guarantee plan is read-only so that the
+				  same plan can be used in parallel by
+				  multiple threads */
+
+#define FFTWND_FORCE_BUFFERED (256)	/* internal, undocumented flag */
+
+extern fftw_plan fftw_create_plan_specific(int n, fftw_direction dir,
+					   int flags,
+					   fftw_complex *in, int istride,
+					 fftw_complex *out, int ostride);
+#define FFTW_HAS_PLAN_SPECIFIC
+extern fftw_plan fftw_create_plan(int n, fftw_direction dir, int flags);
+extern void fftw_print_plan(fftw_plan plan);
+extern void fftw_destroy_plan(fftw_plan plan);
+extern void fftw(fftw_plan plan, int howmany, fftw_complex *in, int istride,
+		 int idist, fftw_complex *out, int ostride, int odist);
+extern void fftw_one(fftw_plan plan, fftw_complex *in, fftw_complex *out);
+extern void fftw_die(const char *s);
+extern void *fftw_malloc(size_t n);
+extern void fftw_free(void *p);
+extern void fftw_check_memory_leaks(void);
+extern void fftw_print_max_memory_usage(void);
+
+typedef void *(*fftw_malloc_type_function) (size_t n);
+typedef void  (*fftw_free_type_function) (void *p);
+typedef void  (*fftw_die_type_function) (const char *errString);
+extern DL_IMPORT(fftw_malloc_type_function) fftw_malloc_hook;
+extern DL_IMPORT(fftw_free_type_function) fftw_free_hook;
+extern DL_IMPORT(fftw_die_type_function) fftw_die_hook;
+
+extern size_t fftw_sizeof_fftw_real(void);
+
+/* Wisdom: */
+/*
+ * define this symbol so that users know we are using a version of FFTW
+ * with wisdom
+ */
+#define FFTW_HAS_WISDOM
+extern void fftw_forget_wisdom(void);
+extern void fftw_export_wisdom(void (*emitter) (char c, void *), void *data);
+extern fftw_status fftw_import_wisdom(int (*g) (void *), void *data);
+extern void fftw_export_wisdom_to_file(FILE *output_file);
+extern fftw_status fftw_import_wisdom_from_file(FILE *input_file);
+extern char *fftw_export_wisdom_to_string(void);
+extern fftw_status fftw_import_wisdom_from_string(const char *input_string);
+
+/*
+ * define symbol so we know this function is available (it is not in
+ * older FFTWs)
+ */
+#define FFTW_HAS_FPRINT_PLAN
+extern void fftw_fprint_plan(FILE *f, fftw_plan plan);
+
+/*****************************
+ *    N-dimensional code
+ *****************************/
+typedef struct {
+     int is_in_place;		/* 1 if for in-place FFTs, 0 otherwise */
+
+     int rank;			/* 
+				 * the rank (number of dimensions) of the
+				 * array to be FFTed 
+				 */
+     int *n;			/*
+				 * the dimensions of the array to the
+				 * FFTed 
+				 */
+     fftw_direction dir;
+
+     int *n_before;		/*
+				 * n_before[i] = product of n[j] for j < i 
+				 */
+     int *n_after;		/* n_after[i] = product of n[j] for j > i */
+
+     fftw_plan *plans;		/* 1d fftw plans for each dimension */
+
+     int nbuffers, nwork;
+     fftw_complex *work;	/* 
+				 * work array big enough to hold
+				 * nbuffers+1 of the largest dimension 
+				 * (has nwork elements)
+				 */
+} fftwnd_data;
+
+typedef fftwnd_data *fftwnd_plan;
+
+/* Initializing the FFTWND plan: */
+extern fftwnd_plan fftw2d_create_plan(int nx, int ny, fftw_direction dir,
+				      int flags);
+extern fftwnd_plan fftw3d_create_plan(int nx, int ny, int nz,
+				      fftw_direction dir, int flags);
+extern fftwnd_plan fftwnd_create_plan(int rank, const int *n,
+				      fftw_direction dir,
+				      int flags);
+
+extern fftwnd_plan fftw2d_create_plan_specific(int nx, int ny,
+					       fftw_direction dir,
+					       int flags,
+					   fftw_complex *in, int istride,
+					 fftw_complex *out, int ostride);
+extern fftwnd_plan fftw3d_create_plan_specific(int nx, int ny, int nz,
+					   fftw_direction dir, int flags,
+					   fftw_complex *in, int istride,
+					 fftw_complex *out, int ostride);
+extern fftwnd_plan fftwnd_create_plan_specific(int rank, const int *n,
+					       fftw_direction dir,
+					       int flags,
+					   fftw_complex *in, int istride,
+					 fftw_complex *out, int ostride);
+
+/* Freeing the FFTWND plan: */
+extern void fftwnd_destroy_plan(fftwnd_plan plan);
+
+/* Printing the plan: */
+extern void fftwnd_fprint_plan(FILE *f, fftwnd_plan p);
+extern void fftwnd_print_plan(fftwnd_plan p);
+#define FFTWND_HAS_PRINT_PLAN
+
+/* Computing the N-Dimensional FFT */
+extern void fftwnd(fftwnd_plan plan, int howmany,
+		   fftw_complex *in, int istride, int idist,
+		   fftw_complex *out, int ostride, int odist);
+extern void fftwnd_one(fftwnd_plan p, fftw_complex *in, fftw_complex *out);
+
+#ifdef __cplusplus
+}                               /* extern "C" */
+
+#endif				/* __cplusplus */
+#endif				/* FFTW_H */
diff --git a/gbt_splitter/four1.cpp b/gbt_splitter/four1.cpp
new file mode 100644
index 0000000..f775a98
--- /dev/null
+++ b/gbt_splitter/four1.cpp
@@ -0,0 +1,88 @@
+/*
+ *
+ * Fourier transform routine from numerical recipes.
+ *
+ * $Id: four1.cpp,v 1.2.4.1 2006/12/14 22:24:38 korpela Exp $
+ *
+ */
+
+#include "sah_config.h"
+#include <math.h>
+#define SWAP(a,b) tempr=(a);(a)=(b);(b)=tempr
+
+void four1(float data[], unsigned long nn, int isign) {
+    unsigned long n,mmax,m,j,istep,i;
+    double wtemp,wr,wpr,wpi,wi,theta;
+    float tempr,tempi;
+
+    n=nn << 1;
+    j=1;
+    for (i=1;i<n;i+=2) {
+        if (j > i) {
+            SWAP(data[j],data[i]);
+            SWAP(data[j+1],data[i+1]);
+        }
+        m=n >> 1;
+        while (m >= 2 && j > m) {
+            j -= m;
+            m >>= 1;
+        }
+        j += m;
+    }
+    mmax=2;
+    while (n > mmax) {
+        istep=mmax << 1;
+        theta=isign*(6.28318530717959/mmax);
+        wtemp=sin(0.5*theta);
+        wpr = -2.0*wtemp*wtemp;
+        wpi=sin(theta);
+        wr=1.0;
+        wi=0.0;
+        for (m=1;m<mmax;m+=2) {
+            for (i=m;i<=n;i+=istep) {
+                j=i+mmax;
+                tempr=(float)(wr*data[j]-wi*data[j+1]);
+                tempi=(float)(wr*data[j+1]+wi*data[j]);
+                data[j]=data[i]-tempr;
+                data[j+1]=data[i+1]-tempi;
+                data[i] += tempr;
+                data[i+1] += tempi;
+            }
+            wr=(wtemp=wr)*wpr-wi*wpi+wr;
+            wi=wi*wpr+wtemp*wpi+wi;
+        }
+        mmax=istep;
+    }
+}
+#undef SWAP
+
+/*
+ * $Log: four1.cpp,v $
+ * Revision 1.2.4.1  2006/12/14 22:24:38  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.2  2003/09/11 18:53:37  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.1  2003/07/29 20:35:39  korpela
+ *
+ * renames .C files to .cpp
+ *
+ * Revision 1.1  2003/06/03 00:16:13  korpela
+ *
+ * Initial splitter under CVS control.
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.1  1998/11/02 16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.1  1998/10/27  00:54:59  korpela
+ * Initial revision
+ *
+ *
+ */
diff --git a/gbt_splitter/four1.h b/gbt_splitter/four1.h
new file mode 100644
index 0000000..7d6e5b9
--- /dev/null
+++ b/gbt_splitter/four1.h
@@ -0,0 +1,31 @@
+/*
+ *
+ * Fourier transform routine from numerical recipes.
+ *
+ * $Id: four1.h,v 1.1 2003/06/03 00:16:13 korpela Exp $
+ *
+ */
+
+
+void four1(float data[], unsigned long nn, int isign); 
+
+/*
+ * $Log: four1.h,v $
+ * Revision 1.1  2003/06/03 00:16:13  korpela
+ *
+ * Initial splitter under CVS control.
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.1  1998/11/02 16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.1  1998/10/27  01:08:21  korpela
+ * Initial revision
+ *
+ *
+ */
diff --git a/gbt_splitter/gencoeff.py b/gbt_splitter/gencoeff.py
new file mode 100755
index 0000000..3af6e75
--- /dev/null
+++ b/gbt_splitter/gencoeff.py
@@ -0,0 +1,143 @@
+#!/usr/bin/python2.6
+
+# vegas_gencoeff.py
+# Generate PFB filter coefficients for VEGAS HPC low-bandwidth modes. The
+#   filter coefficients array contains duplicates for optimised reading
+#   from the GPU.
+#
+# Created by Jayanth Chennamangalam based on code by Sean McHugh, UCSB
+
+import sys
+import getopt
+import math
+import numpy
+import matplotlib.pyplot as plotter
+
+# function definitions
+def PrintUsage(ProgName):
+    "Prints usage information."
+    print "Usage: " + ProgName + " [options]"
+    print "    -h  --help                 Display this usage information"
+    print "    -n  --nfft <value>         Number of points in FFT"
+    print "    -t  --taps <value>         Number of taps in PFB"
+    print "    -b  --sub-bands <value>    Number of sub-bands in data"
+    print "    -w  --width-factor <value> width factor for sinc(x) call"
+    print "    -d  --data-type <value>    Data type - \"float\" or "          \
+          + "\"signedchar\""
+    print "    -p  --no-plot              Do not plot coefficients"
+    return
+
+# default values
+NFFT = 32768                # number of points in FFT
+NTaps = 8                   # number of taps in PFB
+NSubBands = 1               # number of sub-bands in data
+WidthFactor = 1.05          # width factor for sinc(x) call
+DataType = "signedchar"     # data type - "float" or "signedchar"
+Plot = True                 # plot flag
+
+# get the command line arguments
+ProgName = sys.argv[0]
+OptsShort = "hn:t:b:w:d:p"
+OptsLong = ["help", "nfft=", "taps=", "sub-bands=", "width-factor=", "data-type=", "no-plot"]
+
+# check if the minimum expected number of arguments has been passed
+# to the program
+if (1 == len(sys.argv)):
+    sys.stderr.write("ERROR: No arguments passed to the program!\n")
+    PrintUsage(ProgName)
+    sys.exit(1)
+
+# get the arguments using the getopt module
+try:
+    (Opts, Args) = getopt.getopt(sys.argv[1:], OptsShort, OptsLong)
+except getopt.GetoptError, ErrMsg:
+    # print usage information and exit
+    sys.stderr.write("ERROR: " + str(ErrMsg) + "!\n")
+    PrintUsage(ProgName)
+    sys.exit(1)
+
+# parse the arguments
+for o, a in Opts:
+    if o in ("-h", "--help"):
+        PrintUsage(ProgName)
+        sys.exit()
+    elif o in ("-n", "--nfft"):
+        NFFT = int(a)
+    elif o in ("-t", "--taps"):
+        NTaps = int(a)
+    elif o in ("-b", "--sub-bands"):
+        NSubBands = int(a)
+    elif o in ("-w", "--width-factor"):
+        WidthFactor = float(a)
+    elif o in ("-d", "--data-type"):
+        DataType = a
+    elif o in ("-p", "--no-plot"):
+        Plot = False
+    else:
+        PrintUsage(ProgName)
+        sys.exit(1)
+
+M = NTaps * NFFT
+
+# the filter-coefficient-generation section -->
+X = numpy.array([(float(i) / NFFT) - (float(NTaps) / 2) for i in range(M)])
+PFBCoeff = numpy.sinc(X * WidthFactor) * numpy.hanning(M)
+# <-- the filter-coefficient-generation section
+
+# create conversion map
+if ("signedchar" == DataType):
+    Map = numpy.zeros(256, numpy.float32)
+    for i in range(0, 128):
+        Map[i] = float(i) / 128
+    for i in range(128, 256):
+        Map[i] = - (float(256 -i) / 128)
+
+# 32-bit (float) coefficients
+PFBCoeffFloat32 = numpy.zeros(M * NSubBands, numpy.float32)
+# 8-bit (signedchar) coefficients
+if ("signedchar" == DataType):
+    PFBCoeffInt8 = numpy.zeros(M * NSubBands, numpy.int8)
+k = 0
+for i in range(len(PFBCoeff)):
+    Coeff = float(PFBCoeff[i])
+    if ("signedchar" == DataType):
+        for j in range(256):
+            #if (math.fabs(Coeff - Map[j]) <= (0.0078125 / 2)):
+            if (math.fabs(Coeff - Map[j]) <= 0.0078125):
+                for m in range(NSubBands):
+                    PFBCoeffInt8[k+m] = j
+                break
+    elif ("float" == DataType):
+        for m in range(NSubBands):
+            PFBCoeffFloat32[k+m] = Coeff
+    else:
+        # print usage information and exit
+        sys.stderr.write("ERROR: Invalid data type!\n")
+        PrintUsage(ProgName)
+        sys.exit(1)
+    k = k + NSubBands
+
+# write the coefficients to disk and also plot it
+FileCoeff = open("coeff_"                                                     \
+                  + DataType + "_"                                            \
+                  + str(NTaps) + "_"                                          \
+                  + str(NFFT) + "_"                                           \
+                  + str(NSubBands) + "_"                                      \
+                  + str(WidthFactor) + ".dat",                                \
+                 "wb")
+if ("signedchar" == DataType):
+    FileCoeff.write(PFBCoeffInt8)
+    # plot the coefficients
+    if (Plot):
+        plotter.plot(PFBCoeffInt8)
+else:
+    FileCoeff.write(PFBCoeffFloat32)
+    # plot the coefficients
+    if (Plot):
+        plotter.plot(PFBCoeffFloat32)
+
+FileCoeff.close()
+
+if (Plot):
+    plotter.show()
+
diff --git a/gbt_splitter/hr_min_sec.cpp b/gbt_splitter/hr_min_sec.cpp
new file mode 100644
index 0000000..63a7eea
--- /dev/null
+++ b/gbt_splitter/hr_min_sec.cpp
@@ -0,0 +1,131 @@
+/*
+ *
+ * timecvt.c
+ *
+ * Time conversion routines.
+ *
+ * $Id: hr_min_sec.cpp,v 1.2.4.1 2006/12/14 22:24:39 korpela Exp $
+ *
+ */
+
+#include "sah_config.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+char* hr_min_sec (double x) {
+    static char buf[256];
+    int hr = (int)(x / 3600);
+    int min = (int)((x/3600-(double)hr)*60);
+    float s = (float)(x - ((double)hr)*3600 - ((double)min)*60); 
+
+    // the "-.05" below is to prevent it from printing 60.0 sec
+    // when the real value is e.g. 59.91
+    //
+    sprintf(buf, "%d hr %02d min %04.1f sec", hr, min, s-.05);
+    return buf;
+}
+
+
+/*
+ * $Log: hr_min_sec.cpp,v $
+ * Revision 1.2.4.1  2006/12/14 22:24:39  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.2  2003/09/11 18:53:38  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.1  2003/07/29 20:35:40  korpela
+ *
+ * renames .C files to .cpp
+ *
+ * Revision 1.1  2003/06/03 01:01:16  korpela
+ *
+ * First working splitter under CVS.
+ *
+ * Revision 4.4  2003/03/10 02:50:03  jeffc
+ * jeffc - t_strncpy()
+ *
+ * Revision 4.3  2003/01/22 20:51:58  korpela
+ * Changed all strcpy to strncpy.
+ * Changed all gets to fgets.
+ *
+ * Revision 4.2  2001/12/27 21:35:57  davea
+ * *** empty log message ***
+ *
+ * Revision 4.1  2001/09/10 00:25:17  davea
+ * *** empty log message ***
+ *
+ * Revision 4.0  2000/10/05 18:12:12  korpela
+ * Synchronized versions to 4.0 following release of 3.0 client
+ *
+ * Revision 3.8  2000/09/14 01:01:31  korpela
+ * *** empty log message ***
+ *
+ * Revision 3.7  2000/04/24 08:39:06  charlief
+ * eliminate compiler warning in hr_min_sec() function.
+ *
+ * Revision 3.6  2000/01/19 08:32:32  davea
+ * *** empty log message ***
+ *
+ * Revision 3.5  1999/10/19 08:07:24  davea
+ * *** empty log message ***
+ *
+ * Revision 3.4  1999/06/26 06:56:44  hiramc
+ * Hiram 99/06/25 23:59 moved the include <string.h> out of the
+ * ifdef _WIN32 to define strcpy() for all compiles
+ *
+ * Revision 3.3  1999/06/22 09:40:36  charlief
+ * Reverse last change:restore jd_string() as it was before.
+ * Add new function short_jd_string(), which does not print
+ * Julian Date as a floating point value.
+ *
+ * Revision 3.1  1999/06/10 00:44:11  korpela
+ * *** empty log message ***
+ *
+ * Revision 3.0  1999/05/14 19:17:35  korpela
+ * 1.0(Win/Mac) 1.1(Unix) Release Version
+ *
+ * Revision 2.11  1999/03/14 00:23:02  davea
+ * *** empty log message ***
+ *
+ * Revision 2.10  1999/03/11 21:46:58  korpela
+ * Fixed rounding error in st_to_ut().
+ *
+ * Revision 2.9  1999/03/05  09:15:07  kyleg
+ * *** empty log message ***
+ *
+ * Revision 2.8  1999/02/18  19:36:49  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.7  1999/02/13  23:54:44  kyleg
+ * *** empty log message ***
+ *
+ * Revision 2.6  1999/02/11 08:36:54  davea
+ * *** empty log message ***
+ *
+ * Revision 2.5  1998/11/17 21:47:02  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.4  1998/11/05  21:25:21  davea
+ * replace floor() with (int)
+ *
+ * Revision 2.3  1998/11/05 02:00:06  kyleg
+ * *** empty log message ***
+ *
+ * Revision 2.2  1998/11/02 17:59:06  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.1  1998/11/02  17:23:29  korpela
+ * .`
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.2  1998/10/27  00:58:56  korpela
+ * Bug fixes.
+ *
+ * Revision 1.1  1998/10/19  18:57:56  korpela
+ * Initial revision
+ *
+ *
+ */
diff --git a/gbt_splitter/hr_min_sec.h b/gbt_splitter/hr_min_sec.h
new file mode 100644
index 0000000..062a2c3
--- /dev/null
+++ b/gbt_splitter/hr_min_sec.h
@@ -0,0 +1,106 @@
+/*
+ *
+ * timecvt.c
+ *
+ * Time conversion routines.
+ *
+ * $Id: hr_min_sec.h,v 1.1 2003/06/03 01:01:16 korpela Exp $
+ *
+ */
+
+char* hr_min_sec (double x) ;
+
+
+/*
+ * $Log: hr_min_sec.h,v $
+ * Revision 1.1  2003/06/03 01:01:16  korpela
+ *
+ * First working splitter under CVS.
+ *
+ * Revision 4.4  2003/03/10 02:50:03  jeffc
+ * jeffc - t_strncpy()
+ *
+ * Revision 4.3  2003/01/22 20:51:58  korpela
+ * Changed all strcpy to strncpy.
+ * Changed all gets to fgets.
+ *
+ * Revision 4.2  2001/12/27 21:35:57  davea
+ * *** empty log message ***
+ *
+ * Revision 4.1  2001/09/10 00:25:17  davea
+ * *** empty log message ***
+ *
+ * Revision 4.0  2000/10/05 18:12:12  korpela
+ * Synchronized versions to 4.0 following release of 3.0 client
+ *
+ * Revision 3.8  2000/09/14 01:01:31  korpela
+ * *** empty log message ***
+ *
+ * Revision 3.7  2000/04/24 08:39:06  charlief
+ * eliminate compiler warning in hr_min_sec() function.
+ *
+ * Revision 3.6  2000/01/19 08:32:32  davea
+ * *** empty log message ***
+ *
+ * Revision 3.5  1999/10/19 08:07:24  davea
+ * *** empty log message ***
+ *
+ * Revision 3.4  1999/06/26 06:56:44  hiramc
+ * Hiram 99/06/25 23:59 moved the include <string.h> out of the
+ * ifdef _WIN32 to define strcpy() for all compiles
+ *
+ * Revision 3.3  1999/06/22 09:40:36  charlief
+ * Reverse last change:restore jd_string() as it was before.
+ * Add new function short_jd_string(), which does not print
+ * Julian Date as a floating point value.
+ *
+ * Revision 3.1  1999/06/10 00:44:11  korpela
+ * *** empty log message ***
+ *
+ * Revision 3.0  1999/05/14 19:17:35  korpela
+ * 1.0(Win/Mac) 1.1(Unix) Release Version
+ *
+ * Revision 2.11  1999/03/14 00:23:02  davea
+ * *** empty log message ***
+ *
+ * Revision 2.10  1999/03/11 21:46:58  korpela
+ * Fixed rounding error in st_to_ut().
+ *
+ * Revision 2.9  1999/03/05  09:15:07  kyleg
+ * *** empty log message ***
+ *
+ * Revision 2.8  1999/02/18  19:36:49  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.7  1999/02/13  23:54:44  kyleg
+ * *** empty log message ***
+ *
+ * Revision 2.6  1999/02/11 08:36:54  davea
+ * *** empty log message ***
+ *
+ * Revision 2.5  1998/11/17 21:47:02  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.4  1998/11/05  21:25:21  davea
+ * replace floor() with (int)
+ *
+ * Revision 2.3  1998/11/05 02:00:06  kyleg
+ * *** empty log message ***
+ *
+ * Revision 2.2  1998/11/02 17:59:06  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.1  1998/11/02  17:23:29  korpela
+ * .`
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.2  1998/10/27  00:58:56  korpela
+ * Bug fixes.
+ *
+ * Revision 1.1  1998/10/19  18:57:56  korpela
+ * Initial revision
+ *
+ *
+ */
diff --git a/gbt_splitter/makebufs.cpp b/gbt_splitter/makebufs.cpp
new file mode 100644
index 0000000..c7b5140
--- /dev/null
+++ b/gbt_splitter/makebufs.cpp
@@ -0,0 +1,139 @@
+/*
+ * makebuf.c
+ *
+ * Creates temporary files and buffers for use in processing....
+ *
+ * $Id: makebufs.cpp,v 1.3.2.2 2006/12/14 22:24:39 korpela Exp $
+ *
+ */
+
+#include "sah_config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <errno.h>
+
+#include "splitparms.h"
+#include "splittypes.h"
+#include "splitter.h"
+#include "message.h"
+ 
+int tapebuffd;
+char tapebufname[30];
+
+void delbuffer(void) {
+  munmap((char *)tapebuffer,TAPE_BUFFER_SIZE);
+  close(tapebuffd);
+  unlink(tapebufname);
+}
+
+void delbuffer_sig(int i) {
+    munmap((char *)tapebuffer,TAPE_BUFFER_SIZE); 
+    close(tapebuffd);
+    unlink(tapebufname);
+    exit(1);
+}
+
+
+
+void makebuffers(unsigned char **tapebuffer) {
+  char buf[1024];
+/* 
+ * Allocate temp files for tape and wu buffers.  Memory mapping these
+ * files will prevent us from running out of virtual memory
+ */
+/*  sprintf(tapebufname,"tape%d",getpid());
+  
+  if ((tapebuffd=open(tapebufname,O_RDWR|O_CREAT,0777))==-1) {
+    fprintf(stderr,"Unable to open temp file!\n");
+    fprintf(errorlog,"Unable to open temp file!\n");
+    exit(EXIT_FAILURE);
+  }
+  
+  if (ftruncate(tapebuffd,TAPE_BUFFER_SIZE) == -1) {
+    fprintf(stderr,"ftruncate failure\n");
+    fprintf(stderr," errno=%d\n",errno);
+    fprintf(errorlog,"ftruncate failure\n");
+    fprintf(errorlog," errno=%d\n",errno);
+    exit(EXIT_FAILURE);
+  }
+
+  if (((*tapebuffer=
+     mmap(0,TAPE_BUFFER_SIZE,PROT_READ|PROT_WRITE,MAP_SHARED,tapebuffd,0))==(char *)-1))
+  { 
+    fprintf(stderr,"mmap failure\n");
+    fprintf(errorlog,"mmap failure\n");
+    exit(EXIT_FAILURE);
+  }
+
+  atexit(delbuffer);
+  signal(SIGINT,delbuffer_sig);
+*/
+  if (!(*tapebuffer=(unsigned char *)malloc(TAPE_BUFFER_SIZE))) {
+    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"unable to allocate memory for tape buffer\n");
+    exit(0);
+  }
+}
+
+/*
+ * $Log: makebufs.cpp,v $
+ * Revision 1.3.2.2  2006/12/14 22:24:39  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.3.2.1  2006/01/13 00:37:57  korpela
+ * Moved splitter to using standard BOINC logging mechanisms.  All stderr now
+ * goes to "error.log"
+ *
+ * Added command line parameters "-iterations=" (number of workunit groups to
+ * create before exiting), "-trigger_file_path=" (path to the splitter_stop trigger
+ * file.  Default is /disks/setifiler1/wutape/tapedir/splitter_stop).
+ *
+ * Reduced deadlines by a factor of three.  We now need a 30 MFLOP machine to meet
+ * the deadline.
+ *
+ * Revision 1.3  2004/06/16 20:57:18  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.2  2003/09/11 18:53:38  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.1  2003/07/29 20:35:42  korpela
+ *
+ * renames .C files to .cpp
+ *
+ * Revision 1.1  2003/06/03 00:16:13  korpela
+ *
+ * Initial splitter under CVS control.
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.3  1998/12/14 23:41:44  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.2  1998/11/02 21:20:58  korpela
+ * Added signal handler for removal of temporary files on SIGINT.
+ *
+ * Revision 2.1  1998/11/02  16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.4  1998/10/30  20:26:03  korpela
+ * Bug Fixes.  Now mostly working.
+ *
+ * Revision 1.3  1998/10/27  00:55:43  korpela
+ * Bug Fixes
+ *
+ * Revision 1.2  1998/10/20  20:40:54  korpela
+ * Removed wu buffer.
+ *
+ * Revision 1.1  1998/10/19  19:01:56  korpela
+ * Initial revision
+ *
+ */
diff --git a/gbt_splitter/makebufs.h b/gbt_splitter/makebufs.h
new file mode 100644
index 0000000..3e1aa59
--- /dev/null
+++ b/gbt_splitter/makebufs.h
@@ -0,0 +1,38 @@
+/*
+ * makebufs.h
+ *
+ * Creates temporary files and buffers for use in processing....
+ *
+ * $Id: makebufs.h,v 1.1 2003/06/03 00:16:14 korpela Exp $
+ *
+ */
+
+#ifndef MAKEBUFS_H
+#define MAKEBUFS_H
+
+void makebuffers(unsigned char **tapebuffer);
+
+#endif
+
+/*
+ * $Log: makebufs.h,v $
+ * Revision 1.1  2003/06/03 00:16:14  korpela
+ *
+ * Initial splitter under CVS control.
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.1  1998/11/02 16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.2  1998/10/20  20:41:45  korpela
+ * Remove wu buffer.
+ *
+ * Revision 1.1  1998/10/19  19:02:36  korpela
+ * Initial revision
+ *
+ */
diff --git a/gbt_splitter/mb_angdist.cpp b/gbt_splitter/mb_angdist.cpp
new file mode 100644
index 0000000..02f5bd9
--- /dev/null
+++ b/gbt_splitter/mb_angdist.cpp
@@ -0,0 +1,88 @@
+/*
+ * angdist.c
+ *
+ *  Computes angular distance between two lat/lon points
+ *
+ * $Id: mb_angdist.cpp,v 1.1.2.1 2006/12/14 22:24:39 korpela Exp $
+ *
+ */
+
+#include "sah_config.h"
+#include <cstdio>
+#include <cstdlib>
+#include <math.h>
+#include "seti_header.h"
+#include "sqlrow.h"
+#include "sqlblob.h"
+#include "sqlapi.h"
+#include "db_table.h"
+#include "schema_master.h"
+#include "xml_util.h"
+#include "db/app_config.h"
+
+
+#define DTOR (M_PI/180)
+
+double angdist(double r1, double d1, double r2, double d2) {
+  double alpha,dist,d;
+
+  r1*=DTOR;
+  r2*=DTOR;
+  d1*=DTOR;
+  d2*=DTOR;
+  alpha=r1-r2;
+  dist=sin(d2)*sin(d1)+cos(d1)*cos(d2)*cos(alpha);
+  if ((dist*dist)<1) {
+    d=sqrt(1.0-dist*dist);
+  } else {
+    dist=1.0;
+    d=0.0;
+  }
+  dist=atan2(d,dist);
+  dist=dist/DTOR;
+  return (dist);
+}
+
+double angdist(const coordinate_t &a, const coordinate_t &b) {
+  return angdist(a.ra*15,a.dec,b.ra*15,b.dec);
+}
+
+
+/*
+ * $Log: mb_angdist.cpp,v $
+ * Revision 1.1.2.1  2006/12/14 22:24:39  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.3  2003/09/11 18:53:37  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.2  2003/08/05 17:23:39  korpela
+ * More work on database stuff.
+ * Further tweaks.
+ *
+ * Revision 1.1  2003/07/29 20:35:31  korpela
+ *
+ * renames .C files to .cpp
+ *
+ * Revision 1.2  2003/06/03 01:01:15  korpela
+ *
+ * First working splitter under CVS.
+ *
+ * Revision 1.1  2003/06/03 00:16:08  korpela
+ *
+ * Initial splitter under CVS control.
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.1  1998/11/02 16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.1  1998/10/27  00:47:33  korpela
+ * Initial revision
+ *
+ *
+ */
diff --git a/gbt_splitter/mb_angdist.h b/gbt_splitter/mb_angdist.h
new file mode 100644
index 0000000..c96b664
--- /dev/null
+++ b/gbt_splitter/mb_angdist.h
@@ -0,0 +1,36 @@
+/*
+ *  angdist.h
+ *
+ *  Computes angular distance between two lat/lon points
+ *
+ * $Id: mb_angdist.h,v 1.1.2.1 2006/12/14 22:24:40 korpela Exp $
+ *
+ */
+
+double angdist(double r1, double d1, double r2, double d2) ;
+double angdist(const coordinate_t &a,const coordinate_t &b);
+
+/*
+ * $Log: mb_angdist.h,v $
+ * Revision 1.1.2.1  2006/12/14 22:24:40  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.1  2003/06/03 00:16:09  korpela
+ *
+ * Initial splitter under CVS control.
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.1  1998/11/02 16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.1  1998/10/27  01:03:21  korpela
+ * Initial revision
+ *
+ *
+ */
+
diff --git a/gbt_splitter/mb_dotransform.cpp b/gbt_splitter/mb_dotransform.cpp
new file mode 100644
index 0000000..753f7dc
--- /dev/null
+++ b/gbt_splitter/mb_dotransform.cpp
@@ -0,0 +1,511 @@
+/*
+ * 
+ * dotransform.c
+ *
+ * Functions for division by frequency into work units.
+ *
+ * $Id: mb_dotransform.cpp,v 1.1.2.3 2007/06/06 15:58:29 korpela Exp $
+ *
+ */
+
+#include "sah_config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <unistd.h>
+#include <limits.h>
+#include <assert.h>
+#include <math.h>
+#include <gsl/gsl_sf_trig.h>
+
+#include "setilib.h"
+#include "splitparms.h"
+#include "splittypes.h"
+#include "mb_splitter.h"
+#include "fftw3.h"
+#include "mb_wufiles.h"
+
+#include <sys/types.h>      /* for open() */
+#include <sys/stat.h>       /* for open() */
+#include <fcntl.h>          /* for open() */
+#include "mb_dotransform.h" /* for new function declarations and macro
+                               definitions */
+
+// PFB parameters
+int   g_iNTaps;
+float g_fWidthFactor;
+
+/* the PFB data structure */
+typedef struct 
+{
+    complex<float>* pcfData;                        // stores the data for one polyphase filtering; PFB_FFT_LEN complex floats 
+    fftwf_complex* pfcData;                         // points to the above data 
+} PFB_DATA;
+PFB_DATA* g_astPFBData;                             // points to g_iNTaps PFB_DATA's
+
+
+fftwf_plan g_stPlan = {0};                          // FFT plan 
+fftwf_complex* g_pfcFFTArray = NULL;                // FFT input/output; PFB_FFT_LEN complex floats
+
+static complex<float>* g_pcfPackedDataOut = NULL;   // packed FFT output, for the benefit of output_samples();
+                                                    //  PFB_OUTPUT_STACK_SIZE * PFB_FFT_LEN * 2 floats
+
+float* g_pfPFBCoeff = NULL;                         // filter coefficients; g_iNTaps * PFB_FFT_LEN floats
+int g_iIsFirstRun = TRUE;
+
+void gen_coeff(float * coeff, int num_coeff) {
+
+  int i;
+  float hanning_window[num_coeff];
+  float work_array[num_coeff];
+
+  seti_hanning_window(hanning_window, num_coeff);
+
+  for(i=0; i<num_coeff; i++) {
+	coeff[i] = (float(i) / PFB_FFT_LEN) - (float(g_iNTaps) / 2.0);
+  }
+
+  for(i=0; i<num_coeff; i++) {
+	coeff[i] = gsl_sf_sinc(coeff[i] * g_fWidthFactor) * hanning_window[i];
+  }
+}
+
+void output_samples(float *data, int i) {
+// outputs 8 complex samples per call (8 cplx floats -> 8 cplx chars, or 16 floats -> 16 chars)
+  int j,k;
+  unsigned short s=0;
+  float *p=data;
+
+  for (k=0; k<8; k++) {
+      s >>= 2;
+      if (*p>0) s |= 0x8000;
+      if (*(p+1)>0) s |= 0x4000;
+      p+=2;
+  }
+  // bin_data is defined in mb_wufiles.cpp as a vector<unsigned char>
+  bin_data[i].push_back((s>>8) & 0xff);
+  bin_data[i].push_back(s & 0xff);
+}
+
+void splitter_bits_to_float(unsigned short *raw, float *data, int nsamples) {
+    unsigned int i, j;
+    unsigned short s;
+    static int first_time=1;
+    static float lut[65536][16];
+
+    assert(!(nsamples % 8));
+
+    if (first_time) {
+      for (i=0;i<65536;i++) {
+	s=(unsigned short)i;
+	for (j=0;j<8;j++) {
+	    lut[i][j*2]=(float)2*(s & 1)-1;
+	    s >>= 1;
+	    lut[i][j*2+1]=(float)2*(s & 1)-1;
+            s >>= 1;
+        }
+      }
+      first_time--;
+    }
+
+    for (i=0;i<(nsamples/8);i++) {
+      memcpy(data+16*i,lut[raw[i]],16*sizeof(float));
+    }
+}
+
+
+float randu() {
+// Uniform random numbers between 0 and 1
+  static bool first=true;
+  if (first) {
+    srand(time(0));
+    first=false;
+  }
+  return static_cast<float>(rand())/RAND_MAX;
+}
+
+float randn() {
+// normally distributed random numbers
+  static float last=0;
+  float a,b,h=0;
+  if (last==0) {
+    while (h==0 || h>=1) {
+      a=2*randu()-1;
+      b=2*randu()-1;
+      h=a*a+b*b;
+    }
+    h=sqrt(-2*log(h)/h);
+    last=a*h;
+    return b*h;
+  } else {
+    a=last;
+    last=0;
+    return a;
+  }
+}
+
+int set_iDataIdx(int iDataIdx, int &iTapeBufferIdx, int iPrevTapeBufferIdx) {
+    /* NOTE: for the last tape buffer, the last polyphase filtering we perform is for the
+       last consecutive g_iNTaps blocks */
+    /* rewind the data index by (g_iNTaps - 1) blocks */
+    iDataIdx -= ((g_iNTaps - 1) * PFB_FFT_LEN);
+    if (iTapeBufferIdx != iPrevTapeBufferIdx) {
+        if (iDataIdx != 0) {  /* data index can only be negative or zero at this point */
+            /* if rewinding takes us back to the previous tapebuffer,
+               change the tapebuffer index and data index accordingly */
+            iTapeBufferIdx = iPrevTapeBufferIdx;
+            /* NOTE: data index is negative, hence the addition */
+            iDataIdx = tapebuffer[iTapeBufferIdx].data.size() + iDataIdx;
+        }
+    }
+
+    return(iDataIdx);
+}
+
+inline int inc_iDataIdx(int &iTapeBufferIdx, int &iDataIdx) {
+
+    int iFlagBreak = FALSE;
+
+    iDataIdx = (iDataIdx + 1) % tapebuffer[iTapeBufferIdx].data.size();
+    if (0 == iDataIdx) {
+        /* move to the next tapebuffer */
+        ++iTapeBufferIdx;
+        if (tapebuffer.size() == iTapeBufferIdx) {
+            log_messages.printf(SCHED_MSG_LOG::MSG_DEBUG, "End of tape buffer.\n");
+            iFlagBreak = TRUE;
+            /* NOTE: do not return here, as we still need to process the current block */
+        }
+    }
+
+    return(iFlagBreak);
+}
+
+inline int load_pfb_data(int &iTapeBufferIdx, int &iDataIdx, int &i, int &k) {
+
+    g_astPFBData[i].pcfData[k] = complex<float>(
+        // The PFB has the opposite notion of i and q than that of the data recorder.
+        // To account for this, we flip real and imag here.
+        static_cast<float>(tapebuffer[iTapeBufferIdx].data[iDataIdx].imag()),
+        static_cast<float>(tapebuffer[iTapeBufferIdx].data[iDataIdx].real())
+    );
+
+    return(inc_iDataIdx(iTapeBufferIdx, iDataIdx));
+}
+
+void reorder_data(fftwf_complex *pfcPackedDataOut, int iPFBTapIdx) {
+
+    int i;
+
+    /* re-order the output data in such a way that at the end of this loop,
+       output is in the same form as before the PFB implementation,
+       so output_samples() can be used the same way as before.
+       (in the above output, frequency is the fastest-changing index,
+       but output_samples() requires data with time as the fastest-changing
+       index.) */
+    for (i = 0; i < PFB_FFT_LEN; ++i) {
+        // The PFB has the opposite notion of i and q than that of the workunit.
+        // To account for this, we flip real and imag here.
+        /* imaginary part of g_pfcFFTArray[][] */
+        pfcPackedDataOut[(i*PFB_OUTPUT_STACK_SIZE)+iPFBTapIdx][0] = g_pfcFFTArray[i][1];
+        /* real part of g_pfcFFTArray[][] */
+        pfcPackedDataOut[(i*PFB_OUTPUT_STACK_SIZE)+iPFBTapIdx][1] = g_pfcFFTArray[i][0];
+
+    }
+}
+
+
+void process_seg() {
+    int iTapeBufferIdx = 0;
+    signed int iDataIdx = 0;
+    int iFlagBreak = FALSE;
+
+    while (iTapeBufferIdx < tapebuffer.size()) {                        // walk tape blocks
+        while (iDataIdx < tapebuffer[iTapeBufferIdx].data.size()) {     // walk data within a tape block
+            int i;
+            float* fbuff = (float*) g_pcfPackedDataOut;
+            fftwf_complex *pfcPackedDataOut = (fftwf_complex*) g_pcfPackedDataOut;
+            float r_total=0, r_mean=0, i_total=0, i_mean=0;     // used for nulling the DC bin
+            int iPrevTapeBufferIdx = 0; /* to keep track of tapebuffer-index-change */
+            int iPFBOutputStackIdx;
+            int iPFBTapIdx;
+            int iPFBFftIdx;
+
+            // this outer loop just stacks up the amout of data required by output_samples()
+            for(iPFBOutputStackIdx=0; iPFBOutputStackIdx<PFB_OUTPUT_STACK_SIZE; iPFBOutputStackIdx++) { 
+
+                iPrevTapeBufferIdx = iTapeBufferIdx;   // save the current tapebuffer index, to check if it has changed in this read
+
+                // load the data on which the PFB + FFT will operate
+                for (iPFBTapIdx = 0; iPFBTapIdx < g_iNTaps; ++iPFBTapIdx) {
+                    for (iPFBFftIdx = 0; iPFBFftIdx < PFB_FFT_LEN;iPFBFftIdx ++) {
+                        iFlagBreak = load_pfb_data(iTapeBufferIdx, iDataIdx, iPFBTapIdx, iPFBFftIdx);
+                    }  
+                } 
+
+                iDataIdx = set_iDataIdx(iDataIdx, iTapeBufferIdx, iPrevTapeBufferIdx);
+
+                DoPFB(0);                       // use the PFB to filter data for FFT; 
+                                                //  data set is g_iNTaps*PFB_FFT_LEN in size
+
+                fftwf_execute(g_stPlan);        // this is an in-place FFT so output in g_pfcFFTArray itself;
+                                                //  data set is now PFB_FFT_LEN in size
+
+                reorder_data(pfcPackedDataOut, iPFBOutputStackIdx);
+
+                if (iFlagBreak) break;
+            }  // end stack data for output_samples()
+
+            // effectively null the DC bin.  The initial complex data point in each spectra
+            // of the output stack is time domain data for subband 0, which contains the DC bin.
+            for(i=0; i<PFB_OUTPUT_STACK_SIZE; i++) {
+                r_total += pfcPackedDataOut[i*PFB_FFT_LEN][0];         // (real part)
+                i_total += pfcPackedDataOut[i*PFB_FFT_LEN][1];         // (imaginary part)
+            }
+            r_mean = r_total/PFB_OUTPUT_STACK_SIZE;
+            i_mean = i_total/PFB_OUTPUT_STACK_SIZE;
+            for(i=0; i<PFB_OUTPUT_STACK_SIZE; i++) {
+                pfcPackedDataOut[i*PFB_FFT_LEN][0] -= r_mean;          // (real part) 
+                pfcPackedDataOut[i*PFB_FFT_LEN][1] -= i_mean;          // (imaginary part) 
+            }
+            
+
+            for (i=0; i<NSTRIPS; i++) {                 // NSTRIPS = 256 WUs in 1 WUG
+                output_samples(fbuff, i);               // output_samples() outputs 8 complex samples per call
+                fbuff += PFB_OUTPUT_STACK_SIZE*2;       // ..so, we move fbuff ahead by PFB_OUTPUT_STACK_SIZE (8) complex (via *2) floats
+            }
+
+            if (iFlagBreak) break;
+        }  // end, walk data within a tape block 
+
+        if (iFlagBreak) break;
+    }  // end, walk tape blocks
+
+    return;
+}
+
+void do_transform(std::vector<dr2_compact_block_t> &tapebuffer) {
+    int iRet = EXIT_SUCCESS;
+
+    /* initialise PFB-related stuff */
+    if (g_iIsFirstRun)
+    {
+        iRet = InitPFB();
+        if (iRet != EXIT_SUCCESS)
+        {
+       	    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL, "InitPFB() failed\n");
+            PFBCleanUp();
+            return;
+        }
+        log_messages.printf(SCHED_MSG_LOG::MSG_DEBUG, "PFB initialised.\n");
+        g_iIsFirstRun = FALSE;
+    }
+
+    process_seg();
+
+   /* Move the data in the buffer so we don't have to reread portions of the
+    * tape.  Leave a 20% overlap.
+    */
+   tapebuffer.erase(tapebuffer.begin(),tapebuffer.begin()+tapebuffer.size()*8/10);
+
+}
+
+/* function that allocates memory, reads filter coefficients, creates FFT plan,
+   etc. */
+int InitPFB()
+{
+    int iRet = EXIT_SUCCESS;
+    int iFileCoeff = 0;
+    int i = 0;
+
+    g_iNTaps       = splitter_settings.splitter_cfg->pfb_ntaps;
+    g_fWidthFactor = splitter_settings.splitter_cfg->pfb_width_factor;
+
+
+    /* allocate memory for the filter coefficients */
+    g_pfPFBCoeff = (float *) malloc(g_iNTaps 
+                                    * PFB_FFT_LEN
+                                    * sizeof(float));
+    if (NULL == g_pfPFBCoeff)
+    {
+        log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL, "InitPFB(): Memory allocation failed with %s\n", 
+                       strerror(errno));
+        return EXIT_FAILURE;
+    }
+
+    gen_coeff(g_pfPFBCoeff, g_iNTaps * PFB_FFT_LEN);	// generate the coefficients
+
+    /* allocate memory for the PFB data arrays */
+    g_astPFBData = (PFB_DATA *) malloc(g_iNTaps * sizeof(PFB_DATA)); 
+    if (NULL == g_astPFBData)
+    {
+        log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL, "InitPFB(): Memory allocation failed with %s\n", 
+                       strerror(errno));
+        return EXIT_FAILURE;
+    }
+    for (i = 0; i < g_iNTaps; ++i)
+    {
+        g_astPFBData[i].pcfData
+            = (complex<float>*) fftwf_malloc(PFB_FFT_LEN * sizeof(complex<float>));
+        if (NULL == g_astPFBData[i].pcfData)
+        {
+        log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL, "InitPFB(): Memory allocation failed with %s\n", 
+                           strerror(errno));
+            return EXIT_FAILURE;
+        }
+        /* pointer of type fftwf_complex */
+        g_astPFBData[i].pfcData = (fftwf_complex*) g_astPFBData[i].pcfData;
+    }
+
+    /* allocate memory for FFT input/output array */
+    g_pfcFFTArray = (fftwf_complex *) fftwf_malloc(PFB_FFT_LEN
+                                                 * sizeof(fftwf_complex));
+    if (NULL == g_pfcFFTArray)
+    {
+        log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL, "InitPFB(): Memory allocation failed with %s\n", 
+                       strerror(errno));
+        return EXIT_FAILURE;
+    }
+
+    /* create FFT plan */
+    g_stPlan = fftwf_plan_dft_1d(PFB_FFT_LEN,
+                                 g_pfcFFTArray,
+                                 g_pfcFFTArray,
+                                 FFTW_FORWARD,
+                                 FFTW_MEASURE);
+
+    /* allocate memory to pack the output of g_iNTaps FFTs in the PFB
+       loop in the process_seg() function, so that the output data structure
+       remains same as before PFB implementation */
+    g_pcfPackedDataOut = (complex<float> *) fftwf_malloc(PFB_OUTPUT_STACK_SIZE
+                                                         * PFB_FFT_LEN
+                                                         * sizeof(complex<float>));
+    if (NULL == g_pcfPackedDataOut)
+    {
+        log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL, "InitPFB(): Memory allocation failed with %s\n", 
+                       strerror(errno));
+        return EXIT_FAILURE;
+    }
+
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL, "InitPFB(): Configured with NTaps %d WidthFactor %f\n", 
+	      	   g_iNTaps, g_fWidthFactor);
+    return EXIT_SUCCESS;
+}
+
+/* function that performs the PFB */
+void DoPFB(int iPFBReadIdx)
+{
+    int i = 0;
+    int j = 0;
+    int k = 0;
+    int iCoeffStartIdx = 0;
+
+    /* reset memory */
+    (void) memset(g_pfcFFTArray, '\0', PFB_FFT_LEN * sizeof(fftw_complex));
+
+    /* perform polyphase filtering, starting from the read index */
+    i = iPFBReadIdx; 
+    for (j = 0; j < g_iNTaps; ++j)
+    {
+        iCoeffStartIdx = j * PFB_FFT_LEN;
+        for (k = 0; k < PFB_FFT_LEN; ++k)
+        {
+            /* real part */
+            g_pfcFFTArray[k][0] += g_astPFBData[i].pfcData[k][0]
+                                   * g_pfPFBCoeff[iCoeffStartIdx+k];
+            /* imaginary part */
+            g_pfcFFTArray[k][1] += g_astPFBData[i].pfcData[k][1]
+                                   * g_pfPFBCoeff[iCoeffStartIdx+k];
+        }
+        i = (i + 1) % g_iNTaps;
+    }
+
+    return;
+}
+
+/* function that frees resources */
+void PFBCleanUp()
+{
+    int i = 0;
+
+    /* free resources */
+    for (i = 0; i < g_iNTaps; ++i)
+    {
+        free(g_astPFBData[i].pcfData);
+    }
+
+    fftwf_free(g_pfcFFTArray);
+    free(g_pfPFBCoeff);
+
+    /* destroy plans */
+    fftwf_destroy_plan(g_stPlan);
+
+    fftwf_cleanup();
+
+    return;
+}
+
+/*
+ *
+ * $Log: mb_dotransform.cpp,v $
+ * Revision 1.1.2.3  2007/06/06 15:58:29  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.1.2.2  2007/04/25 17:27:30  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.1.2.1  2006/12/14 22:24:40  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.2  2003/09/11 18:53:37  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.1  2003/07/29 20:35:36  korpela
+ *
+ * renames .C files to .cpp
+ *
+ * Revision 1.1  2003/06/03 00:16:10  korpela
+ *
+ * Initial splitter under CVS control.
+ *
+ * Revision 3.2  2003/05/19 17:40:59  eheien
+ * *** empty log message ***
+ *
+ * Revision 3.1  2003/04/10 22:09:00  korpela
+ * *** empty log message ***
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.7  1999/03/27 16:19:35  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.6  1999/02/22  19:02:50  korpela
+ * Revered input real & imaginary.
+ *
+ * Revision 2.5  1999/02/10  21:49:44  korpela
+ * Zeroed DC component of forward transform.
+ *
+ * Revision 2.4  1999/02/01  22:28:52  korpela
+ * FFTW version.
+ *
+ * Revision 2.3  1998/12/14  23:41:44  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.2  1998/11/04 23:08:25  korpela
+ * Byte and bit order change.
+ *
+ * Revision 2.1  1998/11/02  16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.2  1998/10/30  20:26:03  korpela
+ * Bug Fixes.  Now mostly working.
+ *
+ * Revision 1.1  1998/10/27  00:51:08  korpela
+ * Initial revision
+ *
+ *
+ */
+
diff --git a/gbt_splitter/mb_dotransform.h b/gbt_splitter/mb_dotransform.h
new file mode 100644
index 0000000..a531c89
--- /dev/null
+++ b/gbt_splitter/mb_dotransform.h
@@ -0,0 +1,73 @@
+/*
+ * 
+ * dotransform.h
+ *
+ * Functions for division by frequency into work units.
+ *
+ * $Id: mb_dotransform.h,v 1.1.2.2 2007/04/25 17:20:28 korpela Exp $
+ *
+ */
+
+
+/* buffer for ftt output before data writes, needs to be multiple
+ * of three bytes long for encode to work.
+ */
+#define SAMPLES_PER_OBUF (FFT_LEN*2*3/CHAR_BIT)
+#define TBUF_OFFSET(frame,byte) (tapebuffer+(frame)*TAPE_FRAME_SIZE+(byte))
+
+#define FALSE               0
+#define TRUE                1
+
+#define FILE_COEFF_PREFIX           "coeff"
+#define FILE_COEFF_DATATYPE         "float"
+#define FILE_COEFF_SUFFIX           ".dat"
+
+#define PFB_OUTPUT_STACK_SIZE     8         // this has to be 8 for the benefit of output_samples()      
+#define PFB_FFT_LEN             256
+
+//extern int obuf_pos; /* Tracks current postition in the output buffers */
+
+
+void output_samples(float *data, int i, int buf_pos);
+void splitter_bits_to_float(unsigned short *raw, float *data, int nsamples) ;
+void process_seg(void);
+void do_transform(std::vector<dr2_compact_block_t> &tapebuffer) ;
+
+int InitPFB(void);
+void DoPFB(int iReadIdx);
+void PFBCleanUp(void);
+
+/*
+ *
+ * $Log: mb_dotransform.h,v $
+ * Revision 1.1.2.2  2007/04/25 17:20:28  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.1.2.1  2006/12/14 22:24:41  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.1  2003/06/03 00:16:11  korpela
+ *
+ * Initial splitter under CVS control.
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.3  1999/02/01 22:28:52  korpela
+ * FFTW version.
+ *
+ * Revision 2.2  1998/11/04  23:08:25  korpela
+ * Byte and bit order change.
+ *
+ * Revision 2.1  1998/11/02  16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.1  1998/10/27  01:05:22  korpela
+ * Initial revision
+ *
+ *
+ */
+
diff --git a/gbt_splitter/mb_message.cpp b/gbt_splitter/mb_message.cpp
new file mode 100644
index 0000000..022fbf7
--- /dev/null
+++ b/gbt_splitter/mb_message.cpp
@@ -0,0 +1,73 @@
+/*
+ *  Functions for sending messages to stderr and log files.
+ *
+ *  $Id: mb_message.cpp,v 1.1.2.1 2006/12/14 22:24:42 korpela Exp $
+ */
+
+#include "sah_config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "setilib.h"
+#include "sqlrow.h"
+#include "sqlblob.h"
+#include "sqlapi.h"
+#include "db_table.h"
+#include "schema_master.h"
+#include "xml_util.h"
+
+
+#include "boinc_db.h"
+#include "sched_config.h"
+#include "sched_msgs.h"
+#include "mb_splitter.h"
+
+void message(char *msg) {
+  log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"%s %s",tapebuffer[0].header.name,msg);
+}
+
+
+
+/*
+ * $Log: mb_message.cpp,v $
+ * Revision 1.1.2.1  2006/12/14 22:24:42  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.2.4.1  2006/01/13 00:37:57  korpela
+ * Moved splitter to using standard BOINC logging mechanisms.  All stderr now
+ * goes to "error.log"
+ *
+ * Added command line parameters "-iterations=" (number of workunit groups to
+ * create before exiting), "-trigger_file_path=" (path to the splitter_stop trigger
+ * file.  Default is /disks/setifiler1/wutape/tapedir/splitter_stop).
+ *
+ * Reduced deadlines by a factor of three.  We now need a 30 MFLOP machine to meet
+ * the deadline.
+ *
+ * Revision 1.2  2003/09/11 18:53:38  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.1  2003/07/29 20:35:43  korpela
+ *
+ * renames .C files to .cpp
+ *
+ * Revision 1.1  2003/06/03 00:16:14  korpela
+ *
+ * Initial splitter under CVS control.
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.2  2000/12/01 01:13:29  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.1  1998/11/02 16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.1  1998/10/27  00:56:16  korpela
+ * Initial revision
+ *
+ */
diff --git a/gbt_splitter/mb_polyphase.cpp b/gbt_splitter/mb_polyphase.cpp
new file mode 100644
index 0000000..6df3548
--- /dev/null
+++ b/gbt_splitter/mb_polyphase.cpp
@@ -0,0 +1,150 @@
+
+#include "sah_config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <unistd.h>
+#include <limits.h>
+#include <assert.h>
+#include <math.h>
+#include "setilib.h"
+
+#include "splitparms.h"
+#include "splittypes.h"
+#include "mb_splitter.h"
+#include "mb_fftw.h"
+#include "mb_wufiles.h"
+#include "mb_polyphase.h"
+#include "mb_dotransform.h"
+
+/* buffer for fft input/output */
+//float databuf[FFT_LEN*2];
+
+/* buffer for ftt output before data writes, needs to be multiple
+ * of three bytes long for encode to work.
+ */
+#define SAMPLES_PER_OBUF (FFT_LEN*2*3/CHAR_BIT)
+
+extern unsigned char output_buf[NSTRIPS][SAMPLES_PER_OBUF];
+
+double *filter_r, *filter_i;
+float *f_data;
+
+extern int obuf_pos; /* Tracks current postition in the output buffers */
+
+void make_FIR (int n_points, int M, int window, double *output) {
+  /* Create Mth band lowpass FIR filter, n_points long. */
+
+  /* Modify this to give 8-bit quantized filter. */
+  /* Also generate Hilbert transformed filter */
+
+  int n;
+  double q, p;
+
+  for (n=0; n<n_points; n++) {
+    if (n == n_points/2) {
+      output[n] = 1;
+    } else {
+      q = n-(n_points/2);
+      p = n_points/M;
+      output[n] = sin(M_PI*q/p)/(M_PI*q/p);
+    }
+  }
+  if (window == HANNING) {
+    for (n=0; n<n_points; n++) {
+      output[n] = output[n]*.5*(1 - cos(2*M_PI*n/(n_points-1)));
+    }
+  }
+  else if (window == WELCH) {
+    for (n=0; n<n_points; n++) {
+      output[n] = output[n]*(1 - ((n-.5*(n_points-1))/(.5*(n_points+1)))*((n-.5*(n_points-1))/(.5*(n_points+1))));
+    }
+  }
+}
+
+
+void polyphase_seg(float* data) {
+    int i,n;
+    static fftw_plan planfwd;
+    float *p;
+
+    if (!planfwd) {
+      planfwd=fftw_create_plan(P_FFT_LEN, FFTW_FORWARD, 
+		FFTW_MEASURE | FFTW_IN_PLACE | FFTW_USE_WISDOM );
+    }
+
+    for (i=0;i<P_FFT_LEN;i++) {
+        f_data[2*i] = 0;
+        f_data[2*i+1] = 0;
+        for (n=0;n<N_WINDOWS;n++) {
+            f_data[2*i] += data[2*i+2*n*P_FFT_LEN]*filter_r[P_FFT_LEN*n + i];
+            f_data[2*i+1] += data[2*i+2*n*P_FFT_LEN+1]*filter_i[P_FFT_LEN*n + i];
+        }
+    }
+    fftw_one(planfwd, (fftw_complex *)f_data, (fftw_complex *)NULL);
+    /*for (i=0;i<P_FFT_LEN;i++) {
+        fprintf( stderr, "%f %f\n", f_data[2*i], f_data[2*i+1]);
+    }*/
+    //fprintf( stderr, "%f %f ", f_data[2*3], f_data[2*3+1] );
+    p = f_data;
+    for (i=0; i<P_FFT_LEN; i++) {
+        output_samples(p, i, obuf_pos);
+        p += IFFT_LEN*2;
+    }
+    obuf_pos+=IFFT_LEN*2/CHAR_BIT;
+}
+
+#define TBUF_OFFSET(frame,byte) (tapebuffer+(frame)*TAPE_FRAME_SIZE+(byte)+TAPE_HEADER_SIZE)
+
+void do_polyphase(buffer_pos_t *start_of_wu, buffer_pos_t *end_of_wu) {
+   buffer_pos_t end_trans,start_trans=*start_of_wu;
+   int i,nsamp;
+   do {
+     obuf_pos=0;  // reset to the beginning of the output buffer
+     for (i=0;i<768;i++) {
+       end_trans.frame=start_trans.frame;
+       end_trans.byte=start_trans.byte+(FFT_LEN*2/CHAR_BIT);
+       if (end_trans.byte > TAPE_DATA_SIZE) {
+       // End of frame crossed need to trasfer correctly
+          end_trans.frame++;
+          end_trans.byte-=TAPE_DATA_SIZE;
+          nsamp=(TAPE_DATA_SIZE-start_trans.byte)*(CHAR_BIT/2);
+          assert((nsamp+end_trans.byte*(CHAR_BIT/2)) == FFT_LEN);
+          splitter_bits_to_float((unsigned short *)TBUF_OFFSET(start_trans.frame,start_trans.byte),
+                        databuf, nsamp);
+          splitter_bits_to_float((unsigned short *)TBUF_OFFSET(end_trans.frame,0),databuf+nsamp*2,
+                        end_trans.byte*(CHAR_BIT/2));
+       } else {
+          splitter_bits_to_float((unsigned short *)TBUF_OFFSET(start_trans.frame,start_trans.byte),
+                        databuf,FFT_LEN);
+       }
+       polyphase_seg(databuf);
+       // Go on to next transform
+       start_trans=end_trans;
+     }
+     // Check if we're at the end of the wu file. If so we print less bytes
+     if ((end_trans.frame>=end_of_wu->frame) && 
+			 (end_trans.byte>=end_of_wu->byte)) {
+       write_wufile_blocks(NBYTES % SAMPLES_PER_OBUF);
+     } else {
+       write_wufile_blocks(SAMPLES_PER_OBUF);
+     }
+   } while (!((end_trans.frame>=end_of_wu->frame) && (end_trans.byte>=end_of_wu->byte)));
+
+   // Move the data in the buffer so we don't have to reread portions of the
+   // tape.
+   //
+   { 
+     unsigned char *record_offset;
+     int copysize;
+     end_of_wu->frame-=WU_OVERLAP_FRAMES;
+     records_in_buffer=TAPE_RECORDS_IN_BUFFER-
+			 (end_of_wu->frame/TAPE_FRAMES_PER_RECORD);
+     record_offset=tapebuffer+
+             (end_of_wu->frame/TAPE_FRAMES_PER_RECORD)*TAPE_RECORD_SIZE;
+     copysize=records_in_buffer*TAPE_RECORD_SIZE;
+     bcopy(record_offset,tapebuffer,copysize);
+   }
+}
+
+
diff --git a/gbt_splitter/mb_splitter.cpp b/gbt_splitter/mb_splitter.cpp
new file mode 100644
index 0000000..6479b5c
--- /dev/null
+++ b/gbt_splitter/mb_splitter.cpp
@@ -0,0 +1,966 @@
+/*
+ *
+ *  The splitter main program.  
+ *
+ * $Id: mb_splitter.cpp,v 1.1.2.6 2007/08/16 23:03:19 jeffc Exp $
+ *
+ */
+
+#include "sah_config.h"
+#undef USE_MYSQL
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <strings.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/statvfs.h>
+#include <sys/wait.h>
+#include <errno.h>
+
+#include "boinc_db.h"
+#include "backend_lib.h"
+#include "sched_config.h"
+#include "setilib.h"
+#include "str_util.h"
+#include "str_replace.h"
+#include "splitparms.h"
+#include "splittypes.h"
+#include "mb_splitter.h"
+#include "mb_validrun.h"
+#include "mb_wufiles.h"
+#include "mb_dotransform.h"
+#include "message.h"
+#include "sqlrow.h"
+#include "sqlapi.h"
+#include "db/db_table.h"
+#include "db/schema_master.h"
+#include "db/app_config.h"
+
+extern "C" {
+  int sqldetach();
+}
+
+char trigger_file_path[1024]="/disks/setifiler1/wutape/tapedir/splitter_stop";
+
+SCHED_CONFIG boinc_config;
+DB_APP app;
+R_RSA_PRIVATE_KEY key;
+
+// configuration tables
+receiver_config rcvr;
+settings splitter_settings;
+
+// TEMPLATE DEFS ------------------------------------------------------
+// IMPORTANT: a change to a template should *always* include a change
+// to the template filename.  Only the result template is used now.
+const char *wu_template_filename_id = "wu_0.xml";
+const char *wu_template=
+  "<file_info>\n"
+  "  <number>0</number>\n"
+  "</file_info>\n"
+  "<workunit>\n"
+  "  <file_ref>\n"
+  "    <file_number>0</file_number>\n"
+  "    <open_name>work_unit.sah</open_name>\n"
+  "  </file_ref>\n"
+  "</workunit>\n";
+
+const char *result_template_filename_id = "result_0.xml";
+const char *result_template=
+  "<file_info>\n"
+  "  <name><OUTFILE_0/></name>\n"
+  "  <generated_locally/>\n"
+  "  <upload_when_present/>\n"
+  "  <max_nbytes>65536</max_nbytes>\n"
+  "  <url>http://setiboincdata.ssl.berkeley.edu/sah_cgi/file_upload_handler</url>\n"
+  "</file_info>\n"
+  "<result>\n"
+  "  <file_ref>\n"
+  "    <file_name><OUTFILE_0/></file_name>\n"
+  "    <open_name>result.sah</open_name>\n"
+  "  </file_ref>\n"
+  "</result>\n";
+// END TEMPLATE DEFS --------------------------------------------------
+
+std::vector<dr2_compact_block_t> tapebuffer;
+std::map<seti_time,coordinate_t> coord_history;
+std::vector<workunit> wuheaders;
+char appname[256]; 
+int max_wus_ondisk=MAX_WUS_ONDISK;
+int nodb;
+int noencode;
+int resumetape;
+int norewind;
+int startblock;
+int dataclass;
+int atnight;
+int gregorian;
+int output_xml;
+int polyphase;
+int iters=-1;
+int beam;
+int pol;
+int alfa;
+int useanalysiscfgid = 0;
+int usereceivercfgid = 0;
+int userecordercfgid = 0;
+int usesplittercfgid = 0;
+int filter_window = 0;
+double start_time;
+double stop_time;
+unsigned long minvfsbuf=-1;
+char wd[1024];
+//char * scidb = NULL;
+char * projectdir = NULL;
+
+APP_CONFIG sah_config;
+
+//const char *result_template_filename="projectdir"/"SAH_APP_NAME"_result.tpl";
+char result_template_filename[1024];
+char result_template_filepath[1024];
+char wu_template_filename[1024];
+
+int check_for_halt();
+int wait_until_night();
+int check_free_disk_space();
+int wait_for_db_wus_ondisk();
+
+void cprint(char *p) {
+  printf("%s\n",p);
+}
+
+/*  wulog: File for logging names of completed wu files */
+/*  errorlog: File for logging errors                   */
+
+FILE *wulog,*errorlog;
+buffer_pos_t start_of_wu,end_of_wu;  /* position of start and end of wu in
+                                      tape buffer */
+int seqno;
+
+void cleanup(void) {
+  FILE *tmpfile;
+  if ((tmpfile=fopen("seqno.dat","w"))) {
+    fprintf(tmpfile,"%d\n",seqno);
+    fclose(tmpfile);
+  } else {
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Unable to open seqno.dat for write\n");
+  }
+}
+
+
+int process_command_line(int argc, char *argv[],char **tape_device,
+                         int *norewind, int *startblock, int *resumetape,
+                         int *nodb, int *dataclass, int *atnight,
+                         int *max_wus_ondisk, char **projectdir,
+			 int *iters, int *beam, int *pol, int *alfa,
+                         int *useanalysiscfgid, int *usereceivercfgid,
+                         int *userecordercfgid, int *usesplittercfgid) {
+  int nargs=0,i;
+  char *ep;
+  strcpy(appname,SAH_APP_NAME);
+  for (i=1;i<argc;i++) {
+    if (argv[i][0]=='-') {
+        if (!strncmp(argv[i],"-hanning",MAX(strlen(argv[i]),3))) {
+          filter_window=2;
+        } else
+          if (!strncmp(argv[i],"-welch",MAX(strlen(argv[i]),3))) {
+            filter_window=1;
+          } else
+            if (!strncmp(argv[i],"-xml",MAX(strlen(argv[i]),3))) {
+              output_xml=1;
+            } else
+              if (!strncmp(argv[i],"-atnight",MAX(strlen(argv[i]),7))) {
+                *atnight=1;
+              } else
+                if (!strncmp(argv[i],"-nodb",MAX(strlen(argv[i]),4))) {
+                  if (*resumetape) {
+                    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"-nodb and -resumetape are exclusive\n");
+                    return(1);
+                  }
+                  *nodb=1;
+                } else
+                  if (!strncmp(argv[i],"-gregorian",MAX(strlen(argv[i]),2))) {
+                    gregorian=1;
+                  } else
+                    if (!strncmp(argv[i],"-resumetape",MAX(strlen(argv[i]),2))) {
+                      if (*startblock || *norewind) {
+		        log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"-startblock and -norewind can\'t be used with -resumetape\n");
+                        return(1);
+                      }
+                      if (*nodb) {
+                        log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"-nodb and -resumetape are exclusive\n");
+                        return(1);
+                      }
+                      *resumetape=1;
+                    } else
+                      if (!strncmp(argv[i],"-norewind",MAX(strlen(argv[i]),4))) {
+                        if (*startblock || *resumetape) {
+                          return(1);
+                        }
+                        *norewind=1;
+                      } else
+                        if ((ep=strchr(argv[i],'='))) {
+                          if (!strncmp(argv[i],"-appname",MAX(ep-argv[i],3))) { 
+ 		                    strlcpy(appname,ep+1,sizeof(appname)); 
+ 		                   } else if (!strncmp(argv[i],"-trigger_file_path",MAX(ep-argv[i],2))) {
+			    char *fe=ep+1;
+			    memset(trigger_file_path,0,sizeof(trigger_file_path));
+			    while (isgraph(*(fe++))) trigger_file_path[fe-ep-2]=*fe ;
+                          } else if (!strncmp(argv[i],"-alfa",MAX(ep-argv[i],3))) {
+			    sscanf(ep+1,"%d,%d",beam,pol);
+			    if (((*beam<0) || (*beam>6)) ||
+			        ((*pol<0) || (*pol>1))) {
+                                 log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"ALFA receivers must be specified with beam (0-6) and polarization (0-1), i.e. -alfa=4,0\n");
+				 exit(EXIT_FAILURE);
+		            }
+
+			    *alfa=1;
+                          } else if (!strncmp(argv[i],"-iterations",MAX(ep-argv[i],2))) {
+			    sscanf(ep+1,"%d",iters);
+			  } else if (!strncmp(argv[i],"-startblock",MAX(ep-argv[i],2))) {
+                            if (*norewind || *resumetape) {
+                              return(1);
+                            }
+                            sscanf(ep+1,"%d",startblock);
+                          } else if (!strncmp(argv[i],"-max_wus_ondisk",MAX(ep-argv[i],2))) {
+                              sscanf(ep+1,"%d",max_wus_ondisk);
+                          } else if (!strncmp(argv[i],"-dataclass",MAX(ep-argv[i],2))) {
+                                sscanf(ep+1,"%d",dataclass);
+                          } else if (!strncmp(argv[i],"-projectdir",MAX(ep-argv[i],2))) {
+			          *projectdir=(char *)calloc(strlen(ep+1)+5,1);
+				  strlcpy(*projectdir,ep+1,strlen(ep+1)+5);
+                                  strlcat(*projectdir,"/",strlen(ep+1)+5);
+                          } else if (!strncmp(argv[i],"-analysis_config",MAX(ep-argv[i],2))) {
+                              sscanf(ep+1,"%d",useanalysiscfgid);
+                          } else if (!strncmp(argv[i],"-recorder_config",MAX(ep-argv[i],2))) {
+                              sscanf(ep+1,"%d",userecordercfgid);
+                          } else if (!strncmp(argv[i],"-receiver_config",MAX(ep-argv[i],2))) {
+                              sscanf(ep+1,"%d",usereceivercfgid);
+                          } else if (!strncmp(argv[i],"-splitter_config",MAX(ep-argv[i],2))) {
+                              sscanf(ep+1,"%d",usesplittercfgid);
+                          } else {
+                            return(1);
+                          }
+                        } else {
+                          return(1);
+                        }
+    } else {
+      *tape_device=argv[i];
+      nargs++;
+    }
+  }
+  //return(nargs!=1);
+
+  // check for required cmd line 
+  //if (! *scidb) return (1);
+  if (! *projectdir) return (1);
+  if (! *tape_device) return (1);
+
+  return 0;
+}
+
+int main(int argc, char *argv[]) {
+  int tape_fd;
+  char *tape_device;
+  FILE *tmpfile;
+  int retval;
+  char keyfile[1024];
+  char tmpstr[1024];
+  char buf[1024];
+
+
+  /* Process command line arguments */
+  if (process_command_line(argc,argv,&tape_device,&norewind,&startblock,&resumetape,
+                           &nodb,&dataclass,&atnight,&max_wus_ondisk,&projectdir,&iters,
+			   &beam,&pol,&alfa,&useanalysiscfgid,&usereceivercfgid,
+                           &userecordercfgid,&usesplittercfgid))  {
+    fprintf(stderr,"Usage: splitter tape_device -projectdir=s [-atnight] [-nodb]\n"
+    "[-xml] [-gregorian] [-resumetape | -norewind | -startblock=n] [-dataclass=n]\n"
+    "[-max_wus_on_disk=n] [-iterations=n] [-trigger_file_path=filename]\n"
+    "[-alfa=beam,pol] [-analysis_config=id] [-receiver_config=id]\n"
+    "[-recorder_config=id] [-splitter_config=id]\n");
+    exit(EXIT_FAILURE);
+  }
+
+  // MATTL
+  if (blanking_bit == SOFTWARE_BLANKING_BIT) log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"blanking bit: %d (SOFTWARE)\n",blanking_bit);
+  else log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"blanking bit: %d (HARDWARE)\n",blanking_bit);
+
+  /* Open log files */
+  log_messages.set_debug_level(3);
+
+  retval = sah_config.parse_file(projectdir);
+  if (retval) {
+    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Can't parse config file\n");
+    exit(EXIT_FAILURE);
+  } else {
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Using configuration:\n");
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"scidb_name          = %s\n", sah_config.scidb_name);
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"max_wus_ondisk      = %d\n", sah_config.max_wus_ondisk);
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"min_quorum          = %d\n", sah_config.min_quorum);
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"target_nresults     = %d\n", sah_config.target_nresults);
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"max_error_results   = %d\n", sah_config.max_error_results);
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"max_success_results = %d\n", sah_config.max_success_results);
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"max_total_results   = %d\n", sah_config.max_total_results);
+  }
+
+  // Will initially open 
+  if (!db_change(sah_config.scidb_name)) {
+    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Could not open science database %s\n", sah_config.scidb_name);
+    if (!nodb) exit(EXIT_FAILURE);
+  } else {
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Using science database %s\n", sah_config.scidb_name);
+  }
+
+
+  boinc_config.parse_file(projectdir);
+  log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Using boinc config dir  %s\n", projectdir);
+  log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Using boinc database %s\n", boinc_config.db_name);
+
+  // check / commit result template
+  strcpy(result_template_filename, "templates/"); 
+  strcat(result_template_filename, appname); 
+  strcat(result_template_filename, "_");
+  strcat(result_template_filename, result_template_filename_id);
+  strcpy(result_template_filepath, projectdir);
+  strcat(result_template_filepath, result_template_filename);
+  log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"%s %s\n", result_template_filename, result_template_filepath);
+  if (!(tmpfile=fopen(result_template_filepath,"r"))) {
+    if (!(tmpfile=fopen(result_template_filepath,"w"))) {
+      log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Cannot open result file template : %s\n", result_template_filepath);
+      exit(1);
+    }
+    fprintf(tmpfile,result_template);
+  }
+  fclose(tmpfile);
+
+  if (boinc_db.open(boinc_config.db_name,boinc_config.db_host,boinc_config.db_user,boinc_config.db_passwd)) {
+    boinc_db.print_error("boinc_db.open");
+    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"boinc_db.open\n");
+    exit(1);
+  }
+
+  char tmpquery[128]; 
+  sprintf(tmpquery,"where name ='%s'",appname); 
+  if (app.lookup(tmpquery)) { 
+    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Error looking up appname\n");
+    boinc_db.print_error("boinc_app lookup");
+    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"boinc_app lookup\n");
+    exit(1);
+  } else {
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Splitting for application %s (ID = %d)\n", appname, app.id);
+  }
+
+  boinc_db.close();
+
+  telescope_id tel=
+           channel_to_receiverid[beam_pol_to_channel[bmpol_t(beam,pol)]];
+
+  sprintf(buf,"where active=%d and receiver_cfg=(select id from receiver_config where s4_id=%d)",app.id,AO_ALFA_0_0);
+  if (usereceivercfgid > 0) { 
+    sprintf(buf,"where active=%d and receiver_cfg=%d",app.id,usereceivercfgid);
+    }
+  if (!splitter_settings.fetch(std::string(buf))) {
+    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Unable to find active settings for app.id=%d\n",app.id);
+    exit(1);
+  }
+
+  sprintf(buf,"where s4_id=%d and id>=%d",tel,splitter_settings.receiver_cfg.id);
+  if (usereceivercfgid > 0) { sprintf(buf,"where id=%d",usereceivercfgid); }
+  rcvr.fetch(buf);
+  if (usereceivercfgid > 0) { 
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Using receiver cfg id: %d (set by user)\n",usereceivercfgid);
+    splitter_settings.receiver_cfg = usereceivercfgid; 
+    splitter_settings.receiver_cfg->fetch();
+  } else { 
+    splitter_settings.receiver_cfg->fetch(buf);
+  }
+  if (userecordercfgid > 0) { 
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Using recorder cfg id: %d (set by user)\n",userecordercfgid);
+    splitter_settings.recorder_cfg = userecordercfgid; 
+  }
+  splitter_settings.recorder_cfg->fetch(); 
+  if (usesplittercfgid > 0) { 
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Using splitter cfg id: %d (set by user)\n",usesplittercfgid);
+    splitter_settings.splitter_cfg = usesplittercfgid; 
+  }
+  splitter_settings.splitter_cfg->fetch();
+  if (useanalysiscfgid > 0) { 
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Using analysis cfg id: %d (set by user)\n",useanalysiscfgid);
+    splitter_settings.analysis_cfg = useanalysiscfgid;
+  } 
+  splitter_settings.analysis_cfg->fetch();
+
+  log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL, "settings: \n\n%s\n", splitter_settings.print_xml(1,1,0).c_str());
+ 
+  strcpy(keyfile, projectdir);
+  strcat(keyfile, "/keys/upload_private");
+  if (read_key_file(keyfile,key)) {
+    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Error reading keyfile.\n");
+    exit(1);
+  }
+
+  check_for_halt();
+
+  if ((tape_fd=open(tape_device,O_RDONLY|0x2000, 0777))<0) {
+    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Unable to open tape device\n");
+    exit(EXIT_FAILURE);
+  }
+
+  // In early tapes there was a bug where the first N blocks would be duplicates
+  // of data from previous files.  So we need to fast forward until we see a
+  // frame sequence number of 1.
+  int i,readbytes=HeaderSize;
+  dataheader_t header;
+  header.frameseq=100000;
+
+  while ((readbytes==HeaderSize) && (header.frameseq>10)) {
+    char buffer[HeaderSize];
+    int nread;
+    readbytes=0;
+    while ((readbytes!=HeaderSize) && (nread = read(tape_fd,buffer,HeaderSize-readbytes))) { 
+	    readbytes+=nread;
+    }
+    if (nread < 0) {
+	log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"File error %d.\n", errno);
+	exit(1);
+    }
+    if (readbytes == HeaderSize) {
+      header.populate_from_data(buffer);
+      if (header.frameseq>10) {
+        lseek64(tape_fd,DataSize,SEEK_CUR);
+      } else {
+        lseek64(tape_fd,-1*(off64_t)HeaderSize,SEEK_CUR);
+      }
+    }
+  }
+
+  if (readbytes != HeaderSize) {
+    // we fast forwarded through the entire tape without finding the first frame
+    // maybe this is one of the really early tapes that was split into chunks.
+    lseek64(tape_fd,0,SEEK_SET);
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Warning: First block not found\n");
+  }
+
+  if (resumetape) {
+    tape thistape;
+    thistape.id=0; 
+    readbytes=HeaderSize;
+    sprintf(buf,"%d",rcvr.s4_id-AO_ALFA_0_0);
+    if (thistape.fetch(std::string("where name=\'")+header.name+"\' and beam="+buf)) {
+      log_messages.printf(SCHED_MSG_LOG::MSG_DEBUG,"Resuming tape %s beam %d pol %d\n",thistape.name,beam,pol );
+      while ((readbytes==HeaderSize) && (header.dataseq!=thistape.last_block_done)) {
+        int nread=0;
+        char buffer[HeaderSize];
+        readbytes=0;
+        while ((readbytes!=HeaderSize) &&
+	      ((nread = read(tape_fd,buffer,HeaderSize-readbytes)) > 0 )) {
+	    readbytes+=nread;
+        }
+        if (readbytes == HeaderSize) {
+          header.populate_from_data(buffer);
+          if (header.dataseq!=thistape.last_block_done) {
+            lseek64(tape_fd,(off64_t)(DataSize+HeaderSize)*(thistape.last_block_done-header.dataseq)-HeaderSize,SEEK_CUR);
+          } else {
+            lseek64(tape_fd,-1*(off_t)HeaderSize,SEEK_CUR);
+            log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Found starting point");
+          }
+	}
+	if (nread == 0) {
+	  log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"End of file.\n");
+	  exit(0);
+        }
+        if (nread < 0) {
+	  log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"File error %d.\n",errno);
+	  exit(1);
+	}
+      }
+    }
+  }
+
+  /* Start of main loop */
+
+
+  atexit(cleanup);
+
+  getcwd(wd,1024);
+
+  if (polyphase) {
+    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Polyphase not implemented\n" );
+    exit(1);
+#if 0
+    int filter_len;
+
+    filter_len = P_FFT_LEN*N_WINDOWS;
+
+    filter_r = (double *)malloc(sizeof(double)*filter_len);
+    filter_i = (double *)malloc(sizeof(double)*filter_len);
+
+    f_data = (float *)malloc(sizeof(float)*P_FFT_LEN*2);
+
+    make_FIR(filter_len, N_WINDOWS, filter_window, filter_r);
+    make_FIR(filter_len, N_WINDOWS, filter_window, filter_i);
+
+    /*
+    int i;
+    float *data;
+    data = (float*)malloc(sizeof(float)*2*2048);
+    for (double n=-20;n<20;n+=.05) {
+    for (i=0;i<2*2048;i+=2) {
+        data[i] = cos(2*(24+n)*3.1415926535*i/(2*2048));
+        data[i+1] = sin(2*(24+n)*3.1415926535*i/(2*2048));
+    }
+    polyphase_seg(data);
+    //fprintf( stderr, "%f\n", 3+n/8);
+    }
+    exit(0);
+    for(i=0;i<filter_len;i++)
+      printf( "%f\n", filter_r[i] );
+    exit(0);*/
+#endif
+  }
+  log_messages.printf(SCHED_MSG_LOG::MSG_DEBUG,"Entering loop\n" );
+
+  blanking_filter<complex<signed char> > blanker_filter;
+  if (strcmp(splitter_settings.splitter_cfg->blanker_filter, "randomize") == 0) {
+    log_messages.printf(SCHED_MSG_LOG::MSG_DEBUG,"Setting blanker filter to randomize\n" );
+    blanker_filter = randomize;
+  } else {
+    log_messages.printf(SCHED_MSG_LOG::MSG_DEBUG,"Setting blanker filter to null\n" );
+    blanker_filter = NULLC;      // no blanking
+  }
+  while (iters-- && 
+    ((512-tapebuffer.size())==seti_StructureDr2Data(tape_fd, beam, pol,
+            512-tapebuffer.size(), tapebuffer, blanker_filter))) {
+    /* check if we should be running now */
+    fflush(stderr);
+    if (atnight) wait_until_night();
+
+  sprintf(buf,"where active=%d and receiver_cfg=(select id from receiver_config where s4_id=%d)",app.id,AO_ALFA_0_0);
+  if (usereceivercfgid > 0) { 
+    sprintf(buf,"where active=%d and receiver_cfg=%d",app.id,usereceivercfgid);
+    }
+  if (!splitter_settings.fetch(std::string(buf))) {
+    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Unable to find active settings for app.id=%d\n",app.id);
+    exit(1);
+  }
+
+  sprintf(buf,"where s4_id=%d and id>=%d",tel,splitter_settings.receiver_cfg.id);
+  if (usereceivercfgid > 0) { sprintf(buf,"where id=%d",usereceivercfgid); }
+  rcvr.fetch(buf);
+  if (usereceivercfgid > 0) { 
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Using receiver cfg id: %d (set by user)\n",usereceivercfgid);
+    splitter_settings.receiver_cfg = usereceivercfgid; 
+    splitter_settings.receiver_cfg->fetch();
+  } else { 
+    splitter_settings.receiver_cfg->fetch(buf);
+  }
+  if (userecordercfgid > 0) { 
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Using recorder cfg id: %d (set by user)\n",userecordercfgid);
+    splitter_settings.recorder_cfg = userecordercfgid; 
+  }
+  splitter_settings.recorder_cfg->fetch(); 
+  if (usesplittercfgid > 0) { 
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Using splitter cfg id: %d (set by user)\n",usesplittercfgid);
+    splitter_settings.splitter_cfg = usesplittercfgid; 
+  }
+  splitter_settings.splitter_cfg->fetch();
+  if (useanalysiscfgid > 0) { 
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Using analysis cfg id: %d (set by user)\n",useanalysiscfgid);
+    splitter_settings.analysis_cfg = useanalysiscfgid;
+  } 
+  splitter_settings.analysis_cfg->fetch();
+
+  log_messages.printf(SCHED_MSG_LOG::MSG_DEBUG, "settings: \n\n%s\n", splitter_settings.print_xml(1,1,0).c_str());
+
+    check_for_halt();
+
+    // Make sure we have enough free disk space
+    check_free_disk_space();
+
+    // Wait for ondisk wus in the database to drop below the threshold
+    if (!nodb) wait_for_db_wus_ondisk();
+    //fprintf( stderr, "Read data\n" );
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"less than max wus on disk, continuing\n" );
+    fflush(stderr);
+
+    //printf( "Read tape data, analyzing\n" );
+    check_for_halt();
+    
+    //check for an uninterrupted run
+    if (valid_run(tapebuffer,splitter_settings.receiver_cfg->min_vgc)) {
+      std::vector<dr2_compact_block_t>::iterator i=tapebuffer.begin();
+      // insert telescope coordinates into the coordinate history.
+      // this should be converted to a more accurate routine.
+      for (;i!=tapebuffer.end();i++) {
+        coord_history[i->header.coord_time].ra   = i->header.ra;
+        coord_history[i->header.coord_time].dec  = i->header.dec;
+        coord_history[i->header.coord_time].time = i->header.coord_time.jd().uval();
+      }
+      if (make_wu_headers(tapebuffer,tel,wuheaders)) {
+        int child_pid=-1;
+        switch (polyphase) {
+          case 1:
+	    #if 0
+            do_polyphase(&start_of_wu,&end_of_wu);
+	    #endif
+            break;
+          default:
+            log_messages.printf(SCHED_MSG_LOG::MSG_DEBUG,"doing transform..." );
+            do_transform(tapebuffer);
+            log_messages.printf(SCHED_MSG_LOG::MSG_DEBUG," done\n" );
+        }
+        wait(0);
+        if (!nodb) sql_finish();
+
+        do {
+          sleep(1);
+          child_pid=fork();
+	  if (child_pid<0) log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"splitter cannot fork");
+          //fprintf( stderr, "child pid: %d\n", child_pid);
+        } while (child_pid<0);
+
+        if (!child_pid) {
+          if (!nodb) {
+            sqldetach();
+            while (!sql_database(sah_config.scidb_name)) {
+		//fprintf(stderr,"child sleeping\n");
+		sleep(10);
+	    }
+          }
+          rename_wu_files();
+          if (!nodb) sql_finish();
+          _exit(0);
+        }
+
+        if (!nodb) {
+          while (!sql_database(sah_config.scidb_name)) {
+		//fprintf(stderr,"parent sleeping\n");
+		sleep(10);
+	      }
+        }
+      }
+    }
+  }
+
+  // iters is initalized to -1.  If the -iters flag is specified on the command
+  // line, iters is re-initialized to the user desired number of interations.
+  // Each time a WUG is proccessed iters is decremineted.  If the user specifies
+  // iters and we do that number of iterations without reaching EOF then iters
+  // here will be zero.  !Zero means we have reached EOF prior to performing the user 
+  // desired number of iterations.  
+  //
+  // On the other hand, if iters is not specified by the user, iters is decrmented 
+  // downward from -1. It will never be zero in this case.  But since we are not 
+  // limiting the number of iterations, the only way will get here is if we reach EOF.  
+  //
+  // Thus in both cases, a non-zero iters means we have reached EOF.
+  if (iters != 0) {
+    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"End of file.\n");
+    // clean stop at EOF
+    return (EXIT_NORMAL_EOF);
+  } else {
+    // clean stop, but not EOF (iters satisfied or triggered stop)
+    // (A return of 1 is an error exit somewhere else in the code.)
+    return(EXIT_NORMAL_NOT_EOF); 
+  }
+}
+
+int check_for_halt() {
+  FILE *tf;
+
+  tf = fopen(trigger_file_path, "r");
+  // tf=0;
+  if (tf != NULL) {  // Stop program
+    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Found splitter_stop, exiting.\n" );
+    exit(EXIT_NORMAL_NOT_EOF);
+  }
+  return(0); // Keep going
+}
+
+int wait_until_night() {
+  time_t t;
+  struct tm *lt;
+  do {
+    t=time(0);
+    lt=localtime(&t);
+    // Don't run M-F 8AM-6PM
+    if ((lt->tm_wday>0) && (lt->tm_wday<6) && (lt->tm_hour>8) && (lt->tm_hour<18)) {
+      sleep(100);
+    }
+  } while ((lt->tm_wday>0) && (lt->tm_wday<6) && (lt->tm_hour>8) && (lt->tm_hour<18));
+  return 0;
+}
+
+int check_free_disk_space() {
+  struct statvfs vfsbuf;
+
+  /* check disk free space in working directory */
+  statvfs("wu_inbox/.",&vfsbuf);
+  if (vfsbuf.f_frsize==0) vfsbuf.f_frsize=512;
+  if (vfsbuf.f_bavail < (100000*1024/vfsbuf.f_frsize)) {
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Not enough free disk space in working directory to continue\n");
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Not enough free disk space in working directory to continue\n");
+    exit(EXIT_FAILURE);
+  }
+  
+  /* check free disk space in download directory tree */
+  std::string download_dir(boinc_config.download_dir);
+  int waited=0;
+  download_dir+="/.";
+  /* wait here if the disk is more than N% full */ 
+  statvfs(download_dir.c_str(),&vfsbuf);
+  if (vfsbuf.f_blocks > vfsbuf.f_bfree*100/sah_config.min_disk_free_pct) {
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Waiting for free space in download directory\n");
+    while (vfsbuf.f_blocks > vfsbuf.f_bfree*100/sah_config.min_disk_free_pct) {
+      waited+=10;
+      sleep(10);
+      statvfs(download_dir.c_str(),&vfsbuf);
+    }
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Waited %d seconds\n", waited);
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Continuing...\n");
+  }
+  return 0;
+}
+
+int wait_for_db_wus_ondisk() {
+  //int wus_ondisk,rv;
+  DB_STATE_COUNTS state_counts;
+  int retval;
+
+  // No need to check the DB for every single WUG iteration.
+  static int check_count = 100;
+  if (check_count < 100) {
+	check_count++;
+	return 0;
+  } else {
+	check_count = 0;
+  } 
+	
+  if (boinc_db.open(boinc_config.db_name,boinc_config.db_host,boinc_config.db_user,boinc_config.db_passwd)) {
+    boinc_db.print_error("boinc_db.open");
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"boinc_db.open\n");
+    exit(1);
+  }
+#if 0
+  retval = boinc_db.set_isolation_level(READ_UNCOMMITTED);
+  if (retval) {
+    log_messages.printf(MSG_CRITICAL, "boinc_db.set_isolation_level: %d; %s\n", rv, boinc_db.error_string());
+    exit(EXIT_FAILURE);
+  }
+  else {
+    log_messages.printf(MSG_NORMAL, "setting read uncommitted isolation level\n");
+  }
+#endif
+  do {
+    char query[1024];
+    sprintf(query,"where appid=%d",app.id);
+    retval=state_counts.lookup(query);
+    if (retval) {
+      boinc_db.print_error("state_counts.lookup");
+      log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"DB Error, unable to count workunits on disk\n");
+      exit(EXIT_FAILURE);
+    }
+    check_for_halt();
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"%d WUs ondisk which is greater than the max of %d\n", 
+                        state_counts.result_server_state_2, sah_config.max_wus_ondisk);
+    if (state_counts.result_server_state_2>sah_config.max_wus_ondisk) sleep(600);
+
+#if 0
+    sprintf(query,"where appid=%d and server_state=2",app.id);
+    rv=boinc_result.count(wus_ondisk,query);
+    if (rv) {
+      boinc_db.print_error("boinc_result.count");
+      log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"DB Error, unable to count workunits on disk\n");
+      exit(EXIT_FAILURE);
+    }
+    check_for_halt();
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"%d WUs ondisk\n", wus_ondisk);
+    if (wus_ondisk>sah_config.max_wus_ondisk) sleep(600);
+  } while (wus_ondisk>sah_config.max_wus_ondisk);
+#endif
+
+  } while (state_counts.result_server_state_2>sah_config.max_wus_ondisk);
+
+  boinc_db.close();
+  return 0;
+}
+
+/*
+ * $Log: mb_splitter.cpp,v $
+ * Revision 1.1.2.6  2007/08/16 23:03:19  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.1.2.5  2007/08/10 19:29:40  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.1.2.4  2007/06/07 20:01:52  mattl
+ * *** empty log message ***
+ *
+ * Revision 1.1.2.3  2007/06/06 15:58:29  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.1.2.2  2007/04/25 17:27:30  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.1.2.1  2006/12/14 22:24:43  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.22.2.4  2006/11/08 20:16:26  vonkorff
+ * Fixes an error message.
+ *
+ * Revision 1.22.2.3  2006/11/07 19:26:37  vonkorff
+ * Fixed lcgf
+ *
+ * Revision 1.22.2.2  2006/01/13 00:37:58  korpela
+ * Moved splitter to using standard BOINC logging mechanisms.  All stderr now
+ * goes to "error.log"
+ *
+ * Added command line parameters "-iterations=" (number of workunit groups to
+ * create before exiting), "-trigger_file_path=" (path to the splitter_stop trigger
+ * file.  Default is /disks/setifiler1/wutape/tapedir/splitter_stop).
+ *
+ * Reduced deadlines by a factor of three.  We now need a 30 MFLOP machine to meet
+ * the deadline.
+ *
+ * Revision 1.22.2.1  2005/08/01 21:16:25  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.22  2005/01/27 23:03:27  mattl
+ *
+ * commented out tf=0 in check_for_halt
+ *
+ * Revision 1.21  2004/12/27 20:48:54  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.20  2004/08/12 15:45:41  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.19  2004/07/09 22:35:39  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.18  2004/06/27 21:07:04  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.17  2004/06/20 18:56:48  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.16  2004/06/18 23:23:32  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.15  2004/06/16 20:57:19  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.14  2004/04/08 22:25:47  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.13  2004/01/22 00:57:53  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.12  2004/01/01 18:42:01  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.11  2003/12/03 23:46:41  korpela
+ * WU count is now only for SAH workunits.
+ *
+ * Revision 1.10  2003/11/25 21:59:52  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.9  2003/11/01 20:54:02  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.8  2003/10/24 16:57:03  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.7  2003/09/26 20:48:51  jeffc
+ * jeffc - merge in branch setiathome-4_all_platforms_beta.
+ *
+ * Revision 1.5.2.2  2003/09/23 00:49:12  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.5.2.1  2003/09/22 17:39:34  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.6  2003/09/22 17:05:38  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.5  2003/09/13 20:48:38  korpela
+ * directory reorg.  Moved client files to ./client
+ *
+ * Revision 1.4  2003/09/11 18:53:38  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.3  2003/08/13 23:18:47  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.2  2003/08/05 17:23:42  korpela
+ * More work on database stuff.
+ * Further tweaks.
+ *
+ * Revision 1.1  2003/07/29 20:35:50  korpela
+ *
+ * renames .C files to .cpp
+ *
+ * Revision 1.2  2003/06/03 01:01:17  korpela
+ *
+ * First working splitter under CVS.
+ *
+ * Revision 1.1  2003/06/03 00:23:40  korpela
+ *
+ * Again
+ *
+ * Revision 3.6  2003/05/21 00:41:42  korpela
+ * *** empty log message ***
+ *
+ * Revision 3.5  2003/05/19 17:40:59  eheien
+ * *** empty log message ***
+ *
+ * Revision 3.4  2003/04/09 17:46:54  korpela
+ * *** empty log message ***
+ *
+ * Revision 3.3  2002/06/20 22:09:17  eheien
+ * *** empty log message ***
+ *
+ * Revision 3.2  2001/11/07 00:51:47  korpela
+ * Added splitter version to database.
+ * Added max_wus_ondisk option.
+ *
+ * Revision 3.1  2001/08/16 23:42:08  korpela
+ * Mods for splitter to make binary workunits.
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.7  2000/12/01 01:13:29  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.6  1999/06/07 21:00:52  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.5  1999/03/27  16:19:35  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.4  1999/03/05  01:47:18  korpela
+ * Added dataclass paramter.
+ *
+ * Revision 2.3  1999/02/22  22:21:09  korpela
+ * added -nodb option
+ *
+ * Revision 2.2  1999/02/11  16:46:28  korpela
+ * Added some db access functions.
+ *
+ * Revision 2.1  1998/11/02  16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.2  1998/10/30  20:26:03  korpela
+ * Bug Fixes.  Now mostly working.
+ *
+ * Revision 1.1  1998/10/27  00:58:16  korpela
+ * Initial revision
+ *
+ *
+ */
diff --git a/gbt_splitter/mb_splitter.h b/gbt_splitter/mb_splitter.h
new file mode 100644
index 0000000..6b52bc3
--- /dev/null
+++ b/gbt_splitter/mb_splitter.h
@@ -0,0 +1,145 @@
+/*
+ *  splitter.h 
+ *
+ *  Global definitions from the splitter main program.  
+ *
+ * $Id: mb_splitter.h,v 1.1.2.2 2007/04/25 17:20:28 korpela Exp $
+ *
+ */
+
+#ifndef SPLITTER_H
+#define SPLITTER_H
+
+#include "splitparms.h"
+#include "splittypes.h"
+
+#define MAX(x,y)  ( ((x)<(y)) ? (y) : (x)  )
+#define MIN(x,y)  ( ((y)<(x)) ? (y) : (x)  )
+
+/*  wulog: File for logging names of completed wu files */
+/*  errorlog: File for logging errors                   */
+#include "boinc_db.h"
+#include "crypt.h"
+#include "backend_lib.h"
+#include "sched_config.h"
+
+extern SCHED_CONFIG boinc_config;
+extern DB_APP app;
+extern R_RSA_PRIVATE_KEY key;
+extern FILE *wulog,*errorlog;
+extern std::vector<workunit> wuheaders;
+extern int noencode;
+extern int dataclass;
+extern char appname[256];
+extern int nodb;
+extern int resumetape;
+extern int startblock;
+extern int norewind;
+extern int output_xml;
+extern int polyphase;
+extern std::vector<long long> wu_database_id;
+extern int gregorian;
+extern char * projectdir;
+extern char trigger_file_name[1024];
+extern receiver_config rcvr;
+extern settings splitter_settings;
+
+
+/* Buffer that holds tape data */
+extern std::vector<dr2_compact_block_t> tapebuffer;
+extern std::map<seti_time,coordinate_t> coord_history;
+
+/* Number of records remaining in the buffer after WU creations is complete */
+extern int records_in_buffer;
+
+extern const char *wu_template;
+extern const char *result_template;
+// jeffc
+//extern const char *result_template_filename;
+extern char result_template_filename[];
+extern char result_template_filepath[];
+extern char wu_template_filename[];
+
+// exit values not defined elsewhere
+const int EXIT_NORMAL_EOF       = 0;
+const int EXIT_NORMAL_NOT_EOF   = 2;
+
+/* Persistant sequence number of wu file */
+extern int seqno;
+
+#endif
+
+/* 
+ * $Log: mb_splitter.h,v $
+ * Revision 1.1.2.2  2007/04/25 17:20:28  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.1.2.1  2006/12/14 22:24:43  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.6.2.1  2006/01/13 00:37:58  korpela
+ * Moved splitter to using standard BOINC logging mechanisms.  All stderr now
+ * goes to "error.log"
+ *
+ * Added command line parameters "-iterations=" (number of workunit groups to
+ * create before exiting), "-trigger_file_path=" (path to the splitter_stop trigger
+ * file.  Default is /disks/setifiler1/wutape/tapedir/splitter_stop).
+ *
+ * Reduced deadlines by a factor of three.  We now need a 30 MFLOP machine to meet
+ * the deadline.
+ *
+ * Revision 1.6  2004/07/09 22:35:39  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.5  2004/06/16 20:57:19  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.4  2003/09/26 20:48:52  jeffc
+ * jeffc - merge in branch setiathome-4_all_platforms_beta.
+ *
+ * Revision 1.2.2.1  2003/09/22 17:39:35  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.3  2003/09/22 17:05:38  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.2  2003/08/05 17:23:42  korpela
+ * More work on database stuff.
+ * Further tweaks.
+ *
+ * Revision 1.1  2003/06/03 00:23:40  korpela
+ *
+ * Again
+ *
+ * Revision 3.2  2003/05/19 17:40:59  eheien
+ * *** empty log message ***
+ *
+ * Revision 3.1  2001/08/16 23:42:08  korpela
+ * Mods for splitter to make binary workunits.
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.5  1999/10/20 19:20:26  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.4  1999/03/05 01:47:18  korpela
+ * Added data_class field.
+ *
+ * Revision 2.3  1999/02/22  22:21:09  korpela
+ * Added nodb option
+ *
+ * Revision 2.2  1999/02/11  16:46:28  korpela
+ * Added startblock and norewind support, and wu_database_id.
+ *
+ * Revision 2.1  1998/11/02 16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.1  1998/10/27  01:10:32  korpela
+ * Initial revision
+ *
+ *
+ */
diff --git a/gbt_splitter/mb_splittypes.h b/gbt_splitter/mb_splittypes.h
new file mode 100644
index 0000000..540fd74
--- /dev/null
+++ b/gbt_splitter/mb_splittypes.h
@@ -0,0 +1,114 @@
+/*  splittypes.h
+ *  
+ *  Type definitions specific to the splitter. 
+ *
+ *
+ *  $Id: mb_splittypes.h,v 1.1.2.1 2006/12/14 22:24:44 korpela Exp $
+ *
+ */
+#ifndef SPLITTYPES_H
+#define SPLITTYPES_H
+
+#include <stdio.h>
+
+#include "splitparms.h"
+#include "s_util.h"
+#include "seti_header.h"
+
+//typedef struct wuheader {
+  //WU_INFO wuhead;
+  //SETI_WU_INFO wuinfo;
+//} wuheader_t;
+
+typedef struct tapeheader {
+  char name[36];
+  int rcdtype;
+  int numringbufs;
+  int numdiskbufs;
+  unsigned long frameseq;
+  unsigned long dataseq;
+  int missed;
+  TIME st;
+  SCOPE_STRING telstr;
+  int source;
+  double centerfreq,samplerate;
+  char version[16];
+} tapeheader_t;
+
+typedef struct buffer_pos {
+  int frame;
+  long offset;
+} buffer_pos_t;
+
+#endif
+/*
+ * $Log: mb_splittypes.h,v $
+ * Revision 1.1.2.1  2006/12/14 22:24:44  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.4  2003/08/05 17:23:43  korpela
+ * More work on database stuff.
+ * Further tweaks.
+ *
+ * Revision 1.3  2003/07/29 20:35:51  korpela
+ *
+ * renames .C files to .cpp
+ *
+ * Revision 1.2  2003/06/03 01:01:17  korpela
+ *
+ * First working splitter under CVS.
+ *
+ * Revision 1.1  2003/06/03 00:23:41  korpela
+ *
+ * Again
+ *
+ * Revision 3.1  2003/05/19 17:40:59  eheien
+ * *** empty log message ***
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.5  1999/02/11 16:46:28  korpela
+ * Added startblock and norewind support, and wu_database_id.
+ *
+ * Revision 2.4  1998/11/10 00:02:44  korpela
+ * Moved remaining wuheader fields into a WU_INFO structure.
+ *
+ * Revision 2.3  1998/11/05  21:18:41  korpela
+ * Moved name field from header to seti header.
+ *
+ * Revision 2.2  1998/11/02  21:20:58  korpela
+ * Moved tape_version and encoding_type into SETI_WU_INFO.
+ *
+ * Revision 2.1  1998/11/02  16:38:29  korpela
+ * Variable type changes.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.7  1998/10/30  21:01:13  davea
+ * *** empty log message ***
+ *
+ * Revision 1.6  1998/10/27 01:10:58  korpela
+ * Modified tapeheader_t to match new tape header fields.
+ *
+ * Revision 1.5  1998/10/19  23:04:32  korpela
+ * Moved times in telstr_t into an st_t.
+ * Changed name of ast_t to st_t.
+ * Added time zone (tz) field to ast_t.
+ *
+ * Revision 1.4  1998/10/15  19:13:30  korpela
+ * Renamed "unix" fields to "unix_time" because of GCC #define.
+ * Added position_history field to wuheader_t.
+ *
+ * Revision 1.3  1998/10/15  18:58:50  korpela
+ * Added time_t unix to ast_t and telstr_t types.
+ * Changed times in wuheader_t to time_t types.
+ *
+ * Revision 1.2  1998/10/15  18:01:19  korpela
+ * Removed month field from ast_t and telstr_t.
+ *
+ * Revision 1.1  1998/10/15  16:20:24  korpela
+ * Initial revision
+ *
+ */
diff --git a/gbt_splitter/mb_validrun.cpp b/gbt_splitter/mb_validrun.cpp
new file mode 100644
index 0000000..9bf7230
--- /dev/null
+++ b/gbt_splitter/mb_validrun.cpp
@@ -0,0 +1,147 @@
+/*
+ * validrun.c
+ *
+ * Functions for determining if a section of the tape buffer can be
+ * turned into a valid work unit
+ *
+ * $Id: mb_validrun.cpp,v 1.1.2.1 2006/12/14 22:24:45 korpela Exp $
+ *
+ */
+
+#include "sah_config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <assert.h>
+#include "setilib.h"
+#include "splitparms.h"
+#include "splittypes.h"
+#include "splitter.h"
+#include "message.h"
+
+
+bool valid_run(std::vector<dr2_compact_block_t> &tapebuffer, int min_vgc) {
+  unsigned long start_dataseq=tapebuffer[0].header.dataseq;
+  unsigned long end_dataseq=tapebuffer[tapebuffer.size()-1].header.dataseq;
+  bool valid=true;
+  int i;
+
+  // check for missing frames
+  if(!(end_dataseq-start_dataseq)==(tapebuffer.size()-1)) {
+    valid = false;
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Missing frames between %lu and %lu\n",
+        tapebuffer[0].header.dataseq,tapebuffer[tapebuffer.size()-1].header.dataseq);
+    for (i=tapebuffer.size()-1;i>0;i--) {                           // find the last "in sequence" frame    
+      if (tapebuffer[i-1].header.dataseq != (tapebuffer[i].header.dataseq-1)) {
+	    tapebuffer.erase(tapebuffer.begin(),tapebuffer.begin()+i);  // delete all frames prior to the miss
+      }
+    }
+  }
+
+  // if still valid, check for failed blanking signal acquisition
+  if (valid) {
+    for (i=0;valid && (i<tapebuffer.size());i++) {
+      if (tapebuffer[i].header.blanking_failed) {
+        valid = false;
+        log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Failed blanking at dataseq %lu (between %lu and %lu)\n",
+            tapebuffer[i].header.dataseq, tapebuffer[0].header.dataseq,tapebuffer[tapebuffer.size()-1].header.dataseq);
+        tapebuffer.erase(tapebuffer.begin(),tapebuffer.begin()+i+1);  // delete all frames through the fail 
+      }
+    }
+  }
+
+  // if still valid, check for changed frequency
+  if (valid) {
+    for (i=0;valid && (i<tapebuffer.size());i++) {
+      if (tapebuffer[i].header.sky_freq != tapebuffer[0].header.sky_freq) {
+        valid = false;
+        log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Frequency changed from %f to %f at dataseq %lu (between %lu and %lu)\n",
+            tapebuffer[i].header.sky_freq,tapebuffer[0].header.sky_freq,
+            tapebuffer[i].header.dataseq, tapebuffer[0].header.dataseq,tapebuffer[tapebuffer.size()-1].header.dataseq);
+        tapebuffer.erase(tapebuffer.begin(),tapebuffer.begin()+i+1);   // delete all frames through the change 
+      }
+    }
+  }
+
+  // if still valid, check we are above minimum vgc values
+  if (valid && min_vgc > 0) {
+    for (i=0;valid && (i<tapebuffer.size());i++) {
+      if (get_vgc_for_channel(tapebuffer[i].header.channel,tapebuffer[i].header) < min_vgc) {
+        valid = false;
+        log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"VGC value %d is below minimum (%d) at dataseq %lu\n",
+            get_vgc_for_channel(tapebuffer[i].header.channel,tapebuffer[i].header), min_vgc, tapebuffer[i].header.dataseq);
+        // tapebuffer.erase(tapebuffer.begin(),tapebuffer.begin()+i+1);   // delete all frames through the change 
+        tapebuffer.erase(tapebuffer.begin(),tapebuffer.end()-1);   // delete all frames in entire tapebuffer (except last)!
+      }
+    }
+  }
+ 
+  return(valid);
+}
+
+
+/*
+ * $Log: mb_validrun.cpp,v $
+ * Revision 1.1.2.1  2006/12/14 22:24:45  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.2.4.1  2006/01/13 00:37:58  korpela
+ * Moved splitter to using standard BOINC logging mechanisms.  All stderr now
+ * goes to "error.log"
+ *
+ * Added command line parameters "-iterations=" (number of workunit groups to
+ * create before exiting), "-trigger_file_path=" (path to the splitter_stop trigger
+ * file.  Default is /disks/setifiler1/wutape/tapedir/splitter_stop).
+ *
+ * Reduced deadlines by a factor of three.  We now need a 30 MFLOP machine to meet
+ * the deadline.
+ *
+ * Revision 1.2  2003/09/11 18:53:38  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.1  2003/07/29 20:35:57  korpela
+ *
+ * renames .C files to .cpp
+ *
+ * Revision 1.1  2003/06/03 00:23:43  korpela
+ *
+ * Again
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.7  2000/12/01 01:13:29  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.6  1999/06/07 21:00:52  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.5  1999/03/27  16:19:35  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.4  1999/02/22  22:21:09  korpela
+ * added -nodb option
+ *
+ * Revision 2.3  1999/02/11  16:46:28  korpela
+ * Added checkpointing.
+ *
+ * Revision 2.2  1998/11/04  23:08:25  korpela
+ * Byte and bit order change.
+ *
+ * Revision 2.1  1998/11/02  16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.3  1998/10/30  20:26:03  korpela
+ * Bug Fixes.  Now mostly working.
+ *
+ * Revision 1.2  1998/10/27  00:59:22  korpela
+ * Bug fixes.
+ *
+ * Revision 1.1  1998/10/22  17:48:20  korpela
+ * Initial revision
+ *
+ *
+ */
diff --git a/gbt_splitter/mb_validrun.h b/gbt_splitter/mb_validrun.h
new file mode 100644
index 0000000..1f6482d
--- /dev/null
+++ b/gbt_splitter/mb_validrun.h
@@ -0,0 +1,35 @@
+/*
+ * validrun.h
+ *
+ * Functions for determining if a section of the tape buffer can be
+ * turned into a valid work unit
+ *
+ * $Id: mb_validrun.h,v 1.1.2.1 2006/12/14 22:24:45 korpela Exp $
+ *
+ */
+
+int valid_run(std::vector<dr2_compact_block_t> &tapebuffer, int min_vgc);
+
+/*
+ * $Log: mb_validrun.h,v $
+ * Revision 1.1.2.1  2006/12/14 22:24:45  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.1  2003/06/03 00:23:43  korpela
+ *
+ * Again
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.1  1998/11/02 16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.1  1998/10/22  17:49:15  korpela
+ * Initial revision
+ *
+ *
+ */
diff --git a/gbt_splitter/mb_wufiles.cpp b/gbt_splitter/mb_wufiles.cpp
new file mode 100644
index 0000000..7247eb5
--- /dev/null
+++ b/gbt_splitter/mb_wufiles.cpp
@@ -0,0 +1,689 @@
+/*
+ *
+ * Functions for managing wufiles and their data
+ *
+ * $Id: mb_wufiles.cpp,v 1.1.2.6 2007/08/10 18:21:13 korpela Exp $
+ *
+ */
+
+#include "sah_config.h"
+#undef USE_MYSQL
+#include <cstdio>
+#include <cstdlib>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <iostream>
+#include <string>
+#include <algorithm>
+#include <vector>
+#include <map>
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "boinc_db.h"
+#include "sched_util.h"
+#include "setilib.h"
+#include "splitparms.h"
+#include "splittypes.h"
+#include "s_util.h"
+#include "util.h"
+#include "str_util.h"
+#include "str_replace.h"
+#include "mb_splitter.h"
+#include "message.h"
+#include "mb_angdist.h"
+#include "cmap_interp.h"
+#include "lcgamm.h"
+#include "sqlrow.h"
+#include "sqlblob.h"
+#include "sqlapi.h"
+#include "db_table.h"
+#include "schema_master.h"
+#include "xml_util.h"
+#include "db/app_config.h"
+#include "str_util.h"
+
+std::vector<long long> wu_database_id;
+std::vector<std::vector<unsigned char> > bin_data;
+
+extern APP_CONFIG sah_config;
+
+int make_wu_headers(std::vector<dr2_compact_block_t> &tapebuffer, telescope_id
+tel, std::vector<workunit> &wuheader) {
+  int procid=getpid();
+  double receiver_freq;
+  int bandno;
+  FILE *tmpfile;
+  char tmpstr[256];
+  char buf[64];
+  static const receiver_config &r(rcvr);
+  static const settings &s(splitter_settings);
+  bool group_is_vlar;
+
+  if (!strncmp(s.splitter_cfg->data_type,"encoded",
+     std::min(static_cast<size_t>(7),sizeof(s.splitter_cfg->data_type)))) {
+    noencode=0;
+  } else {
+      noencode=1;
+  }
+
+  tapebuffer[0].header.samplerate*=1e+6;
+  seconds sample_time(1.0/tapebuffer[0].header.samplerate);
+  seti_time start_time(tapebuffer[0].header.data_time
+           -tapebuffer[0].data.size()*0.5*sample_time);
+  seti_time end_time(tapebuffer[tapebuffer.size()-1].header.data_time);
+
+
+  workunit_grp wugrp;
+  sprintf(wugrp.name,"%s.%ld.%d.%d.%d",
+    tapebuffer[0].header.name,
+    procid, 
+    tapebuffer[0].header.dataseq,
+    tel-AO_430,
+    s.id);
+  wugrp.receiver_cfg=r; 
+  wugrp.recorder_cfg=s.recorder_cfg; 
+  wugrp.splitter_cfg=s.splitter_cfg; 
+  wugrp.analysis_cfg=s.analysis_cfg; 
+
+  wugrp.data_desc.nsamples=NSAMPLES;
+  wugrp.data_desc.true_angle_range=0;
+  coordinate_t start_coord(cmap_interp(coord_history,start_time));
+  coordinate_t end_coord(cmap_interp(coord_history,end_time));
+  wugrp.data_desc.start_ra=start_coord.ra;
+  wugrp.data_desc.end_ra=end_coord.ra;
+  wugrp.data_desc.start_dec=start_coord.dec;
+  wugrp.data_desc.end_dec=end_coord.dec;
+  coordinate_t last_coord=start_coord;
+  double sample_rate=tapebuffer[0].header.samplerate/NSTRIPS;
+
+  // find the bracketing entries in the coordinate history
+  std::map<seti_time,coordinate_t>::iterator above(coord_history.upper_bound(end_time));
+  std::map<seti_time,coordinate_t>::iterator below(coord_history.lower_bound(start_time));
+  std::map<seti_time,coordinate_t>::iterator p;
+  if (above==coord_history.begin()) {
+    above++;
+  }
+  if (below==coord_history.end()) {
+    below=above;
+    below--;
+  }
+  if (above==below) {
+    below--;
+  }
+  // Calculate the angular distance the beam has traveled
+  for (p=below;p!=above;p++)
+  {
+    wugrp.data_desc.true_angle_range+=angdist(last_coord,p->second);
+    last_coord=p->second;
+  }
+  wugrp.data_desc.true_angle_range+=angdist(last_coord,end_coord);
+  if (wugrp.data_desc.true_angle_range==0) wugrp.data_desc.true_angle_range=1e-10;
+  // Calculate the number of unique signals that could be found in a workunit.
+  // We will use these numbers to calculate thresholds.
+  double numgauss=2.36368e+08/std::min(wugrp.data_desc.true_angle_range,10.0);
+  double numpulse=std::min(4.52067e+10/std::min(wugrp.data_desc.true_angle_range,10.0),2.00382e+11);
+  double numtrip=std::min(3.25215e+12/std::min(wugrp.data_desc.true_angle_range,10.0),1.44774e+13);
+
+  // check for VLAR workunits
+  if (wugrp.data_desc.true_angle_range < 0.12) {
+    group_is_vlar=true;
+  } else {
+    group_is_vlar=false;
+  }
+    
+
+  // if (useanalysiscfgid > 0) { 
+  //   log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Re-reading analysis cfg id: %d (set by user):\n",useanalysiscfgid);
+  //   s.analysis_cfg = useanalysiscfgid;
+  //   }
+
+  // Calculate a unique key to describe this analysis config.
+  long keyuniq=floor(std::min(wugrp.data_desc.true_angle_range*100,1000.0)+0.5)+
+    s.analysis_cfg.id*1024;
+  if ((keyuniq>((s.analysis_cfg.id+1)*1024)) ||(keyuniq<(s.analysis_cfg.id)*1024)) {
+     log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Invalid keyuniq value!\n");
+     log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"%d %d %f\n",keyuniq,s.analysis_cfg.id,wugrp.data_desc.true_angle_range);
+     exit(1);
+  }
+
+  keyuniq*=-1;
+  long save_keyuniq=keyuniq;
+  splitter_settings.analysis_cfg=wugrp.analysis_cfg;
+  sprintf(tmpstr,"where keyuniq=%d",keyuniq); 
+  // Check if we've already done this analysis_config...
+  // Fetch through splitter_settings, since it's alias (s) is const.
+  splitter_settings.analysis_cfg.id=0;
+  splitter_settings.analysis_cfg->fetch(tmpstr);
+
+  if (s.analysis_cfg->id==0) {
+    if (keyuniq != save_keyuniq) {
+      log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"keyuniq value changed!\n");
+      exit(1);
+    }
+
+    // If not calculate the thresholds based upon the input analysis_config
+    // Triplets are distributed exponentially...
+    wugrp.analysis_cfg->triplet_thresh+=(log(numtrip)-29.0652);
+
+    // Gaussians are based upon chisqr...
+    double p_gauss=lcgf(32.0,wugrp.analysis_cfg->gauss_null_chi_sq_thresh*32.0);
+    p_gauss-=(log(numgauss)-19.5358);
+    wugrp.analysis_cfg->gauss_null_chi_sq_thresh=invert_lcgf(p_gauss,32,1e-4)*0.03125;
+
+    // Pulses thresholds are log of the probability
+    wugrp.analysis_cfg->pulse_thresh+=(log(numpulse)-24.7894);
+
+    wugrp.analysis_cfg->keyuniq=keyuniq;
+    wugrp.analysis_cfg->insert();
+  } else {
+    wugrp.analysis_cfg=s.analysis_cfg;
+  }
+
+  strlcpy(wugrp.data_desc.time_recorded,
+      short_jd_string(start_time.jd().uval()),
+      sizeof(wugrp.data_desc.time_recorded));
+  wugrp.data_desc.time_recorded_jd=start_time.jd().uval();
+  wugrp.data_desc.coords.clear();
+
+  wugrp.data_desc.coords.push_back(start_coord);  
+  for (p=below;p!=above;p++)
+  {
+     wugrp.data_desc.coords.push_back(p->second);  
+  }
+  wugrp.data_desc.coords.push_back(end_coord);
+
+  // indicate the state of the alfa filter bank
+  wugrp.alfa_filter_bank = tapebuffer[0].header.scram_if1.alfaFb ? 1 : 0; 
+
+  wugrp.tape_info->id=0;
+  sprintf(buf,"%d",tel-AO_ALFA_0_0);
+  wugrp.tape_info->fetch(std::string("where name=\'")+tapebuffer[0].header.name+"\' and beam="+buf);
+  wugrp.tape_info->start_time=tapebuffer[0].header.data_time.jd().uval();
+  wugrp.tape_info->last_block_time=wugrp.tape_info->start_time;
+  wugrp.tape_info->last_block_done=tapebuffer[0].header.dataseq;
+  wugrp.tape_info->beam=tel-AO_ALFA_0_0;
+
+  if (!nodb) {
+    if (wugrp.tape_info.id) {
+      if (!(wugrp.tape_info->update())) {
+        char buf[1024];
+        log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"%s",sql_error_message());
+	exit(1);
+      }
+    } else {
+      strlcpy(wugrp.tape_info->name,tapebuffer[0].header.name,sizeof(wugrp.tape_info->name));
+      wugrp.tape_info->insert();
+    }
+  }
+
+  if (!nodb) {
+    sqlint8_t wgid;
+    if ((wgid=wugrp.insert())<=0) {
+      log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Workunit_grp insert failed\nwgid=%d\nSQLCODE=%d\nLAST_NON_ZERO_SQLCODE=%d\n",wgid,sql_error_code(),sql_last_error_code());
+      exit( 1 );
+    }
+    wugrp.id=wgid;
+  }
+  int i; 
+  wu_database_id.resize(NSTRIPS);
+  bin_data.resize(NSTRIPS);
+  wuheader.resize(NSTRIPS);
+  for (i=0;i<NSTRIPS;i++) {
+    bin_data[i].clear();
+    wuheader[i].group_info=wugrp;
+    wuheader[i].group_info.id=wugrp.id;
+    sprintf(wuheader[i].name,"%s.%ld.%d.%ld.%d.%d",tapebuffer[0].header.name,
+       procid, tapebuffer[0].header.dataseq,
+       tel-AO_430,s.id,i);
+    if (group_is_vlar) {
+      strlcat(wuheader[i].name,".vlar",sizeof(wuheader[i].name));
+    }
+    wuheader[i].subband_desc.sample_rate=tapebuffer[0].header.samplerate/NSTRIPS;
+ 
+    receiver_freq=tapebuffer[0].header.sky_freq;
+
+    bandno=((i+NSTRIPS/2)%NSTRIPS)-NSTRIPS/2;
+
+    wuheader[i].subband_desc.base=receiver_freq+
+	       (double)(bandno)*wuheader[i].subband_desc.sample_rate;
+    // for FFT based splitter:
+    //wuheader[i].subband_desc.center=receiver_freq+wuheader[i].subband_desc.sample_rate*NSTRIPS*((double)IFFT_LEN*bandno/FFT_LEN+(double)IFFT_LEN/(2*FFT_LEN)-1.0/(2*FFT_LEN));
+
+    // for PFB splitter:
+    //wuheader[i].subband_desc.center=receiver_freq+wuheader[i].subband_desc.sample_rate*NSTRIPS;
+    wuheader[i].subband_desc.center=wuheader[i].subband_desc.base;
+    wuheader[i].subband_desc.number=i;
+
+    if (!nodb ) {
+      if (!(wu_database_id[i]=wuheader[i].id=wuheader[i].insert())) {
+        log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Database error in make_wu_headers()\n");
+        exit(EXIT_FAILURE);
+      }
+    }
+	
+    sprintf(tmpstr,"./wu_inbox/%s",wuheader[i].name);
+    if ((tmpfile=fopen(tmpstr,"w"))) {
+      fprintf(tmpfile,"<workunit>\n");
+      fprintf(tmpfile,wuheader[i].print_xml().c_str());
+      fclose(tmpfile);
+    } else {
+      log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Unable to open file ./wu_inbox/%s, errno=%d\n",wuheader[i].name,errno);
+      exit(1);
+    }
+    bin_data[i].reserve(wuheaders[i].group_info->recorder_cfg->bits_per_sample*
+       wuheaders[i].group_info->data_desc.nsamples/8);
+  }
+  return(1);
+}
+
+
+void write_wufile_blocks(int nbytes) {
+  // doesn't do anything anymore.  What was done here is done in output_samples.
+}
+
+int filecopy(char *oldname,char *newname) {
+  FILE *oldfile,*newfile;
+  char buffer[16384];
+  int nread;
+  if ((oldfile=fopen(oldname,"rb")) && (newfile=fopen(newname,"wb"))) {
+      do {
+	nread=fread(buffer,1,16384,oldfile);
+	fwrite(buffer,1,nread,newfile);
+      } while (nread>0);
+      fclose(oldfile);
+      fclose(newfile);
+      return 0;
+  } else {
+    return 1;
+  }
+}
+      
+
+
+void rename_wu_files() {
+  int i, retval;
+  char oldname[256],newname[1024];
+  unsigned long sz;
+  DB_WORKUNIT db_wu;
+  const char *name[1];
+  char *wudir="./wu_inbox";
+  xml_encoding encoding=(noencode?_binary:_x_setiathome);
+  FILE *tmpfile;
+
+  if (boinc_db.open(boinc_config.db_name,boinc_config.db_host,boinc_config.db_user,boinc_config.db_passwd)) {
+    boinc_db.print_error("boinc_db.open");
+    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Fatal error in boinc_db.open\n");
+    exit(1);
+  }
+
+  for (i=0;i<NSTRIPS;i++) {
+    name[0]=wuheaders[i].name;
+    sprintf(oldname,"%s/%s",wudir,name[0]);
+
+    //sprintf(newname,"%s%s/%s",projectdir,WU_SUBDIR,name[0]);
+    retval = dir_hier_path(name[0],
+                           boinc_config.download_dir,
+                           boinc_config.uldl_dir_fanout,
+                           newname,
+			   true
+    );
+    if (retval) {
+        char buf[1024];
+        log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"[%s] dir_hier_path() failed: %d\n", name[0], retval);
+	exit(1);
+    } 
+
+    struct stat sbuf;
+    if (!stat(oldname,&sbuf) && (tmpfile=fopen(oldname,"a"))) {
+       std::string tmpstr=xml_encode_string(bin_data[i],encoding);
+       fprintf(tmpfile,"<data length=%ld encoding=\"%s\">",tmpstr.size(),
+            xml_encoding_names[encoding]);
+       fwrite(tmpstr.c_str(),tmpstr.size(),1,tmpfile);
+       fprintf(tmpfile,"</data>\n");
+       fprintf(tmpfile,"</workunit>\n");
+       sz=bin_data[i].size();
+
+       fclose(tmpfile);
+    } else {
+        log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Header file no longer exists! splitter start script may be failing\n ");
+	exit(1);
+    }  
+    if (!nodb) {
+      if (!filecopy(oldname,newname)) {
+        db_wu.clear();
+        db_wu.opaque=wuheaders[i].id;
+        strncpy(db_wu.name,name[0],sizeof(db_wu.name)-2);
+        db_wu.appid=app.id;
+        //db_wu.rsc_fpops_est=2.79248e+13*6;
+        //db_wu.rsc_fpops_bound=4.46797e+14*6;
+	double beam=wuheaders[i].group_info->receiver_cfg->beam_width;
+        double ar=wuheaders[i].group_info->data_desc.true_angle_range;
+        double dur=(double)(wuheaders[i].group_info->data_desc.nsamples)/wuheaders[i].subband_desc.sample_rate;
+        double min_slew=wuheaders[i].group_info->analysis_cfg->pot_min_slew;
+        double max_slew=wuheaders[i].group_info->analysis_cfg->pot_max_slew;
+        double autocorr_len=wuheaders[i].group_info->analysis_cfg->autocorr_fftlen;
+        double autocorr_flops=0;
+        if (autocorr_len) autocorr_flops=7.5e+06*autocorr_len*log(autocorr_len);
+	if ( ar <= beam ) {
+	  db_wu.rsc_fpops_est=8.036e+13+autocorr_flops;
+	} else if ( ar <= ( dur*min_slew ) ) {
+          db_wu.rsc_fpops_est=4.805e+13+autocorr_flops+2.296e+12/ar;
+        } else if ( ar <= ( dur*max_slew ) ) {
+          db_wu.rsc_fpops_est=4.592e+13+autocorr_flops+1.476e+13/ar;
+        } else {
+          db_wu.rsc_fpops_est=2.378e+13+autocorr_flops;
+        }
+	db_wu.rsc_fpops_est*=(0.333/wuheaders[i].group_info->analysis_cfg->chirp_resolution);
+        db_wu.rsc_fpops_bound=db_wu.rsc_fpops_est*20;
+        db_wu.rsc_memory_bound=33554432;
+        db_wu.rsc_disk_bound=33554432;
+        // Our minimum is a 40 MFLOP machine
+        db_wu.delay_bound=std::max(86400.0*7,db_wu.rsc_fpops_est/4e+7);
+        db_wu.min_quorum=sah_config.min_quorum;
+        db_wu.target_nresults=sah_config.target_nresults;
+        db_wu.max_error_results=sah_config.max_error_results;
+        db_wu.max_total_results=sah_config.max_total_results;
+        db_wu.max_success_results=sah_config.max_success_results;
+        strncpy(db_wu.app_name,appname,sizeof(db_wu.app_name)-2);
+        if (create_work(db_wu,
+                        wu_template,
+                        result_template_filename,
+                        result_template_filepath,
+                        name,
+                        1,
+		        boinc_config,
+		        NULL
+                       )
+           ) {
+          log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"create work failed\n");
+          exit(1);
+        }
+        //unlink(oldname);   // we now *always* unlink
+      } else {
+	  log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"file copy failed\n");
+          exit(1);
+      }
+      unlink(oldname);
+    }
+  }
+  boinc_db.close();
+}
+
+/*
+ * $Log: mb_wufiles.cpp,v $
+ * Revision 1.1.2.6  2007/08/10 18:21:13  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.1.2.5  2007/08/09 21:31:08  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.1.2.4  2007/06/07 20:01:52  mattl
+ * *** empty log message ***
+ *
+ * Revision 1.1.2.3  2007/06/06 15:58:30  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.1.2.2  2007/04/25 17:27:31  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.1.2.1  2006/12/14 22:24:45  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.29.2.14  2006/05/03 19:14:31  korpela
+ * Updated work estimates.
+ *
+ * Revision 1.29.2.13  2006/04/24 18:41:02  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.29.2.12  2006/01/13 00:37:58  korpela
+ * Moved splitter to using standard BOINC logging mechanisms.  All stderr now
+ * goes to "error.log"
+ *
+ * Added command line parameters "-iterations=" (number of workunit groups to
+ * create before exiting), "-trigger_file_path=" (path to the splitter_stop trigger
+ * file.  Default is /disks/setifiler1/wutape/tapedir/splitter_stop).
+ *
+ * Reduced deadlines by a factor of three.  We now need a 30 MFLOP machine to meet
+ * the deadline.
+ *
+ * Revision 1.29.2.11  2006/01/10 00:39:04  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.29.2.10  2006/01/05 23:55:22  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.29.2.9  2005/12/05 22:11:40  korpela
+ * Fixed bug in flops estimate.
+ *
+ * Revision 1.29.2.8  2005/10/05 16:22:17  jeffc
+ * removed reference to old/new boolean for directory hash.
+ *
+ * Revision 1.29.2.7  2005/09/22 23:05:22  korpela
+ * Fixed threshold calculation.  Was using chisqr rather than reduced chisqr.
+ *
+ * Revision 1.29.2.6  2005/09/21 22:11:23  korpela
+ * Updated Makefile.in for OpenSSL.
+ * Added dynamic threshold generation to wufiles.cpp.
+ *
+ * Revision 1.29.2.5  2005/08/01 17:47:38  korpela
+ * Type fixed.
+ *
+ * Revision 1.29.2.4  2005/08/01 17:43:20  korpela
+ * Refinement of FLOPS estimate for workunits.
+ *
+ * Revision 1.29.2.3  2005/07/26 17:17:01  korpela
+ * Typo fix
+ *
+ * Revision 1.29.2.2  2005/07/19 00:15:19  korpela
+ * Revised delay bound and FLOP estimate for setiathome_enhanced.
+ *
+ * Revision 1.29.2.1  2005/07/06 01:30:17  korpela
+ * Updated estimates of FPOPS per workunit for setiathome enhanced.
+ *
+ * Revision 1.29  2005/03/08 22:36:15  jeffc
+ * jeffc - fixed call to create_work()
+ *
+ * Revision 1.28  2005/02/15 23:06:47  korpela
+ * Fixed missing dir_hier symbol.
+ *
+ * Revision 1.27  2004/12/27 20:48:54  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.26  2004/11/18 22:24:48  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.25  2004/08/25 22:42:11  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.24  2004/08/14 04:44:26  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.23  2004/08/12 15:45:41  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.22  2004/07/15 17:54:20  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.21  2004/07/09 22:35:39  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.20  2004/07/01 17:56:51  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.19  2004/06/25 13:49:33  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.18  2004/06/18 23:23:32  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.17  2004/06/16 20:57:19  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.16  2004/06/02 20:51:32  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.15  2004/01/22 00:57:54  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.14  2004/01/20 22:33:44  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.13  2004/01/06 22:44:05  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.12  2004/01/01 18:42:01  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.11  2003/12/12 01:51:39  korpela
+ * Now using the opaque field in workunit to store SAH wuid.
+ *
+ * Revision 1.10  2003/12/03 23:46:41  korpela
+ * WU count is now only for SAH workunits.
+ *
+ * Revision 1.9  2003/11/25 21:59:53  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.8  2003/11/11 06:20:30  korpela
+ * Increased max fpops_max to prevent timeout on windows clients
+ *
+ * Revision 1.7  2003/10/25 18:19:44  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.6  2003/10/24 16:57:03  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.5  2003/09/26 20:48:52  jeffc
+ * jeffc - merge in branch setiathome-4_all_platforms_beta.
+ *
+ * Revision 1.3.2.2  2003/09/22 19:00:31  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.3.2.1  2003/09/22 17:39:35  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.4  2003/09/22 17:05:38  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.3  2003/09/11 18:53:38  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.2  2003/08/05 17:23:44  korpela
+ * More work on database stuff.
+ * Further tweaks.
+ *
+ * Revision 1.1  2003/07/29 20:36:00  korpela
+ *
+ * renames .C files to .cpp
+ *
+ * Revision 1.3  2003/06/05 15:52:47  korpela
+ *
+ * Fixed coordinate bug that was using the wrong zenith angle from the telescope
+ * strings when handling units from the gregorian.
+ *
+ * Revision 1.2  2003/06/03 01:01:18  korpela
+ *
+ * First working splitter under CVS.
+ *
+ * Revision 1.1  2003/06/03 00:23:44  korpela
+ *
+ * Again
+ *
+ * Revision 3.8  2003/05/19 17:40:59  eheien
+ * *** empty log message ***
+ *
+ * Revision 3.7  2003/04/10 17:32:25  korpela
+ * *** empty log message ***
+ *
+ * Revision 3.6  2002/06/21 01:42:15  eheien
+ * *** empty log message ***
+ *
+ * Revision 3.5  2001/11/07 00:51:47  korpela
+ * Added splitter version to database.
+ * Added max_wus_ondisk option.
+ *
+ * Revision 3.4  2001/08/17 22:20:54  korpela
+ * *** empty log message ***
+ *
+ * Revision 3.3  2001/08/17 01:22:31  korpela
+ * *** empty log message ***
+ *
+ * Revision 3.2  2001/08/17 01:16:53  korpela
+ * *** empty log message ***
+ *
+ * Revision 3.1  2001/08/16 23:42:08  korpela
+ * Mods for splitter to make binary workunits.
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.18  2000/12/01 01:13:29  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.17  1999/06/07 21:00:52  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.16  1999/03/27  16:19:35  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.15  1999/03/05  01:47:18  korpela
+ * Added data_class field.
+ *
+ * Revision 2.14  1999/02/22  22:21:09  korpela
+ * added -nodb option
+ *
+ * Revision 2.13  1999/02/11  16:46:28  korpela
+ * Added db access functions.
+ *
+ * Revision 2.12  1999/01/04  22:27:55  korpela
+ * Updated return codes.
+ *
+ * Revision 2.11  1998/12/14  23:41:44  korpela
+ * Added subband_base to work unit header.
+ * Changed frequency calculation.
+ *
+ * Revision 2.10  1998/12/14  21:55:07  korpela
+ * Added fft_len and ifft_len to work unit header.
+ *
+ * Revision 2.9  1998/11/13  23:58:52  korpela
+ * Modified for move of name field between structures.
+ *
+ * Revision 2.8  1998/11/13  22:18:12  davea
+ * *** empty log message ***
+ *
+ * Revision 2.7  1998/11/10 01:55:26  korpela
+ * Server requires a CR at the end of a WU file
+ * ???
+ *
+ * Revision 2.6  1998/11/10  00:02:44  korpela
+ * Moved remaining wuheader fields into a WU_INFO structure.
+ *
+ * Revision 2.5  1998/11/05  21:33:02  korpela
+ * Fixed angle_range bug.
+ *
+ * Revision 2.4  1998/11/05  21:18:41  korpela
+ * Moved name field from header to seti header.
+ *
+ * Revision 2.3  1998/11/02  21:20:58  korpela
+ * Modified for (internal) integer receiver ID.
+ *
+ * Revision 2.2  1998/11/02  18:45:39  korpela
+ * Changed location of timecvt.h
+ *
+ * Revision 2.1  1998/11/02  16:38:29  korpela
+ * Variable type changes.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.2  1998/10/30  20:26:03  korpela
+ * Bug Fixes.  Now mostly working.
+ *
+ * Revision 1.1  1998/10/27  01:01:16  korpela
+ * Initial revision
+ *
+ *
+ */
diff --git a/gbt_splitter/mb_wufiles.h b/gbt_splitter/mb_wufiles.h
new file mode 100644
index 0000000..5fb95e2
--- /dev/null
+++ b/gbt_splitter/mb_wufiles.h
@@ -0,0 +1,46 @@
+/*
+ *
+ * Functions for managing wufiles and their data
+ *
+ * $Id: mb_wufiles.h,v 1.1.2.2 2007/04/25 17:20:28 korpela Exp $
+ *
+ */
+
+
+extern  std::vector<std::vector<unsigned char> > bin_data;
+
+int make_wu_headers(std::vector<dr2_compact_block_t> &tapebuffer, telescope_id tel, 
+    std::vector<workunit> &wuheader) ;
+void write_wufile_blocks(int nbytes) ;
+void rename_wu_files();
+
+/*
+ * $Log: mb_wufiles.h,v $
+ * Revision 1.1.2.2  2007/04/25 17:20:28  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.1.2.1  2006/12/14 22:24:46  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.2  2003/08/05 17:23:45  korpela
+ * More work on database stuff.
+ * Further tweaks.
+ *
+ * Revision 1.1  2003/06/03 00:23:44  korpela
+ *
+ * Again
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.1  1998/11/02 16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.1  1998/10/27  01:13:16  korpela
+ * Initial revision
+ *
+ *
+ */
diff --git a/gbt_splitter/message.cpp b/gbt_splitter/message.cpp
new file mode 100644
index 0000000..d15181e
--- /dev/null
+++ b/gbt_splitter/message.cpp
@@ -0,0 +1,65 @@
+/*
+ *  Functions for sending messages to stderr and log files.
+ *
+ *  $Id: message.cpp,v 1.2.4.2 2006/12/14 22:24:46 korpela Exp $
+ */
+
+#include "sah_config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "boinc_db.h"
+#include "sched_config.h"
+#include "sched_msgs.h"
+#include "splitter.h"
+
+void message(char *msg) {
+  log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"%s %s",tapeheaders[0].name,msg);
+}
+
+
+
+/*
+ * $Log: message.cpp,v $
+ * Revision 1.2.4.2  2006/12/14 22:24:46  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.2.4.1  2006/01/13 00:37:57  korpela
+ * Moved splitter to using standard BOINC logging mechanisms.  All stderr now
+ * goes to "error.log"
+ *
+ * Added command line parameters "-iterations=" (number of workunit groups to
+ * create before exiting), "-trigger_file_path=" (path to the splitter_stop trigger
+ * file.  Default is /disks/setifiler1/wutape/tapedir/splitter_stop).
+ *
+ * Reduced deadlines by a factor of three.  We now need a 30 MFLOP machine to meet
+ * the deadline.
+ *
+ * Revision 1.2  2003/09/11 18:53:38  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.1  2003/07/29 20:35:43  korpela
+ *
+ * renames .C files to .cpp
+ *
+ * Revision 1.1  2003/06/03 00:16:14  korpela
+ *
+ * Initial splitter under CVS control.
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.2  2000/12/01 01:13:29  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.1  1998/11/02 16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.1  1998/10/27  00:56:16  korpela
+ * Initial revision
+ *
+ */
diff --git a/gbt_splitter/message.h b/gbt_splitter/message.h
new file mode 100644
index 0000000..6c51713
--- /dev/null
+++ b/gbt_splitter/message.h
@@ -0,0 +1,40 @@
+/*
+ *  Functions for sending messages to stderr and log files.
+ *
+ *  $Id: message.h,v 1.1.4.1 2006/01/13 00:37:57 korpela Exp $
+ */
+
+#include "sched_msgs.h"
+
+void message(char *msg);
+
+/*
+ * $Log: message.h,v $
+ * Revision 1.1.4.1  2006/01/13 00:37:57  korpela
+ * Moved splitter to using standard BOINC logging mechanisms.  All stderr now
+ * goes to "error.log"
+ *
+ * Added command line parameters "-iterations=" (number of workunit groups to
+ * create before exiting), "-trigger_file_path=" (path to the splitter_stop trigger
+ * file.  Default is /disks/setifiler1/wutape/tapedir/splitter_stop).
+ *
+ * Reduced deadlines by a factor of three.  We now need a 30 MFLOP machine to meet
+ * the deadline.
+ *
+ * Revision 1.1  2003/06/03 00:16:14  korpela
+ *
+ * Initial splitter under CVS control.
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.1  1998/11/02 16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.1  1998/10/27  01:09:00  korpela
+ * Initial revision
+ *
+ */
diff --git a/gbt_splitter/polyphase.cpp b/gbt_splitter/polyphase.cpp
new file mode 100644
index 0000000..57cbdd8
--- /dev/null
+++ b/gbt_splitter/polyphase.cpp
@@ -0,0 +1,149 @@
+
+#include "sah_config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <unistd.h>
+#include <limits.h>
+#include <assert.h>
+#include <math.h>
+
+#include "splitparms.h"
+#include "splittypes.h"
+#include "splitter.h"
+#include "fftw.h"
+#include "wufiles.h"
+#include "polyphase.h"
+#include "dotransform.h"
+
+/* buffer for fft input/output */
+//float databuf[FFT_LEN*2];
+
+/* buffer for ftt output before data writes, needs to be multiple
+ * of three bytes long for encode to work.
+ */
+#define SAMPLES_PER_OBUF (FFT_LEN*2*3/CHAR_BIT)
+
+extern unsigned char output_buf[NSTRIPS][SAMPLES_PER_OBUF];
+
+double *filter_r, *filter_i;
+float *f_data;
+
+extern int obuf_pos; /* Tracks current postition in the output buffers */
+
+void make_FIR (int n_points, int M, int window, double *output) {
+  /* Create Mth band lowpass FIR filter, n_points long. */
+
+  /* Modify this to give 8-bit quantized filter. */
+  /* Also generate Hilbert transformed filter */
+
+  int n;
+  double q, p;
+
+  for (n=0; n<n_points; n++) {
+    if (n == n_points/2) {
+      output[n] = 1;
+    } else {
+      q = n-(n_points/2);
+      p = n_points/M;
+      output[n] = sin(M_PI*q/p)/(M_PI*q/p);
+    }
+  }
+  if (window == HANNING) {
+    for (n=0; n<n_points; n++) {
+      output[n] = output[n]*.5*(1 - cos(2*M_PI*n/(n_points-1)));
+    }
+  }
+  else if (window == WELCH) {
+    for (n=0; n<n_points; n++) {
+      output[n] = output[n]*(1 - ((n-.5*(n_points-1))/(.5*(n_points+1)))*((n-.5*(n_points-1))/(.5*(n_points+1))));
+    }
+  }
+}
+
+
+void polyphase_seg(float* data) {
+    int i,n;
+    static fftw_plan planfwd;
+    float *p;
+
+    if (!planfwd) {
+      planfwd=fftw_create_plan(P_FFT_LEN, FFTW_FORWARD, 
+		FFTW_MEASURE | FFTW_IN_PLACE | FFTW_USE_WISDOM );
+    }
+
+    for (i=0;i<P_FFT_LEN;i++) {
+        f_data[2*i] = 0;
+        f_data[2*i+1] = 0;
+        for (n=0;n<N_WINDOWS;n++) {
+            f_data[2*i] += data[2*i+2*n*P_FFT_LEN]*filter_r[P_FFT_LEN*n + i];
+            f_data[2*i+1] += data[2*i+2*n*P_FFT_LEN+1]*filter_i[P_FFT_LEN*n + i];
+        }
+    }
+    fftw_one(planfwd, (fftw_complex *)f_data, (fftw_complex *)NULL);
+    /*for (i=0;i<P_FFT_LEN;i++) {
+        fprintf( stderr, "%f %f\n", f_data[2*i], f_data[2*i+1]);
+    }*/
+    //fprintf( stderr, "%f %f ", f_data[2*3], f_data[2*3+1] );
+    p = f_data;
+    for (i=0; i<P_FFT_LEN; i++) {
+        output_samples(p, i, obuf_pos);
+        p += IFFT_LEN*2;
+    }
+    obuf_pos+=IFFT_LEN*2/CHAR_BIT;
+}
+
+#define TBUF_OFFSET(frame,byte) (tapebuffer+(frame)*TAPE_FRAME_SIZE+(byte)+TAPE_HEADER_SIZE)
+
+void do_polyphase(buffer_pos_t *start_of_wu, buffer_pos_t *end_of_wu) {
+   buffer_pos_t end_trans,start_trans=*start_of_wu;
+   int i,nsamp;
+   do {
+     obuf_pos=0;  // reset to the beginning of the output buffer
+     for (i=0;i<768;i++) {
+       end_trans.frame=start_trans.frame;
+       end_trans.byte=start_trans.byte+(FFT_LEN*2/CHAR_BIT);
+       if (end_trans.byte > TAPE_DATA_SIZE) {
+       // End of frame crossed need to trasfer correctly
+          end_trans.frame++;
+          end_trans.byte-=TAPE_DATA_SIZE;
+          nsamp=(TAPE_DATA_SIZE-start_trans.byte)*(CHAR_BIT/2);
+          assert((nsamp+end_trans.byte*(CHAR_BIT/2)) == FFT_LEN);
+          splitter_bits_to_float((unsigned short *)TBUF_OFFSET(start_trans.frame,start_trans.byte),
+                        databuf, nsamp);
+          splitter_bits_to_float((unsigned short *)TBUF_OFFSET(end_trans.frame,0),databuf+nsamp*2,
+                        end_trans.byte*(CHAR_BIT/2));
+       } else {
+          splitter_bits_to_float((unsigned short *)TBUF_OFFSET(start_trans.frame,start_trans.byte),
+                        databuf,FFT_LEN);
+       }
+       polyphase_seg(databuf);
+       // Go on to next transform
+       start_trans=end_trans;
+     }
+     // Check if we're at the end of the wu file. If so we print less bytes
+     if ((end_trans.frame>=end_of_wu->frame) && 
+			 (end_trans.byte>=end_of_wu->byte)) {
+       write_wufile_blocks(NBYTES % SAMPLES_PER_OBUF);
+     } else {
+       write_wufile_blocks(SAMPLES_PER_OBUF);
+     }
+   } while (!((end_trans.frame>=end_of_wu->frame) && (end_trans.byte>=end_of_wu->byte)));
+
+   // Move the data in the buffer so we don't have to reread portions of the
+   // tape.
+   //
+   { 
+     unsigned char *record_offset;
+     int copysize;
+     end_of_wu->frame-=WU_OVERLAP_FRAMES;
+     records_in_buffer=TAPE_RECORDS_IN_BUFFER-
+			 (end_of_wu->frame/TAPE_FRAMES_PER_RECORD);
+     record_offset=tapebuffer+
+             (end_of_wu->frame/TAPE_FRAMES_PER_RECORD)*TAPE_RECORD_SIZE;
+     copysize=records_in_buffer*TAPE_RECORD_SIZE;
+     bcopy(record_offset,tapebuffer,copysize);
+   }
+}
+
+
diff --git a/gbt_splitter/polyphase.h b/gbt_splitter/polyphase.h
new file mode 100644
index 0000000..0393c38
--- /dev/null
+++ b/gbt_splitter/polyphase.h
@@ -0,0 +1,26 @@
+#define NONE    0
+#define WELCH   1
+#define HANNING 2
+
+#define N_WINDOWS 8
+#define P_FFT_LEN 256
+
+/* buffer for fft input/output */
+extern float databuf[FFT_LEN*2];
+
+/* buffer for ftt output before data writes, needs to be multiple
+ * of three bytes long for encode to work.
+ */
+#define SAMPLES_PER_OBUF (FFT_LEN*2*3/CHAR_BIT)
+#define TBUF_OFFSET(frame,byte) (tapebuffer+(frame)*TAPE_FRAME_SIZE+(byte))
+extern unsigned char output_buf[NSTRIPS][SAMPLES_PER_OBUF];  
+
+extern double *filter_r, *filter_i;
+extern float *f_data;
+
+extern int obuf_pos; /* Tracks current postition in the output buffers */
+
+void make_FIR (int n_points, int M, int window, double *output);
+void polyphase_seg(float *data);
+void do_polyphase(buffer_pos_t *start_of_wu, buffer_pos_t *end_of_wu);
+
diff --git a/gbt_splitter/randomdata.cpp b/gbt_splitter/randomdata.cpp
new file mode 100644
index 0000000..094315d
--- /dev/null
+++ b/gbt_splitter/randomdata.cpp
@@ -0,0 +1,77 @@
+#include "sah_config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <math.h>
+#include <string.h>
+#include <unistd.h>
+
+#define NUM_FRAMES 200L
+#define FRAME_DATA_SIZE (1024L*1024)
+#define HEADER_SIZE 1024
+#define FILESIZE (NUM_FRAMES*(FRAME_DATA_SIZE+HEADER_SIZE))
+
+char header[HEADER_SIZE];
+
+int main(void) {
+  int i;
+  int datapos=0;
+  int frameseq=0;
+  long written=0;
+  int on=0;
+  struct tm *tm;
+  unsigned char data;
+
+  char tmpstr[256];
+  char telstr[256];
+  double time0=(double)time(0);
+  time_t clock;
+
+  srandom(time(0));
+
+  for (written=0;written<NUM_FRAMES;written++)  {
+     int headerpos=0;
+     memset(header,0,HEADER_SIZE);
+     strcpy(header,"NAME=randdata");
+     headerpos+=strlen("NAME=randdata")+1;
+     strcpy(header+headerpos,"RCDTYPE=1");
+     headerpos+=strlen("RCDTYPE=1")+1;
+     sprintf(tmpstr,"FRAMESEQ=%d",frameseq);
+     strcpy(header+headerpos,tmpstr);
+     headerpos+=strlen(tmpstr)+1;
+     sprintf(tmpstr,"DATASEQ=%d",frameseq++);
+     strcpy(header+headerpos,tmpstr);
+     headerpos+=strlen(tmpstr)+1;
+     clock=floor(time0);
+     tm=localtime(&clock);
+     sprintf(tmpstr,"AST=%.2d%.3d%.2d%.2d%.2d%.2d",tm->tm_year,tm->tm_yday,tm->tm_hour,tm->tm_min,tm->tm_sec,(int)((time0-floor(time0))*100));
+     strcpy(header+headerpos,tmpstr);
+     headerpos+=strlen(tmpstr)+1;
+     if (!((frameseq-1)%5)) {
+       sprintf(telstr,"TELSTR=%.2d%.3d%.2d%.2d%.2d 0.0 0.0 15.0",tm->tm_year,tm->tm_yday,tm->tm_hour,tm->tm_min,tm->tm_sec);
+     }
+     strcpy(header+headerpos,telstr);
+     headerpos+=strlen(telstr)+1;
+     strcpy(header+headerpos,"RECEIVER=ao1420");
+     headerpos+=strlen("RECEIVER=ao1420")+1;
+     strcpy(header+headerpos,"SAMPLERATE=2.5000");
+     headerpos+=strlen("SAMPLERATE=2.5000")+1;
+     strcpy(header+headerpos,"CENTERFREQ=1420.0");
+     headerpos+=strlen("CENTERFREQ=1420.0")+1;
+     strcpy(header+headerpos,"VER=1.00");
+     headerpos+=strlen("VER=1.00")+1;
+     strcpy(header+headerpos,"NUMRINGBUFS=4");
+     headerpos+=strlen("NUMRINGBUFS=4")+1;
+     strcpy(header+headerpos,"NUMDISKBUFS=2");
+     headerpos+=strlen("NUMDISKBUFS=2")+1;
+     strcpy(header+headerpos,"EOH=");
+     write(stdout->_file, header, HEADER_SIZE);
+     for(i=0;i<FRAME_DATA_SIZE;i++) {
+       if (!((datapos++)%(100/8))) on=!on;
+       data=random()&0xff;
+       write(stdout->_file, &data, 1);
+     }
+     time0+=(1024.0*1024.0*4.0/2.5e6);
+   }
+}  
+
diff --git a/gbt_splitter/readheader.cpp b/gbt_splitter/readheader.cpp
new file mode 100644
index 0000000..6a82fc2
--- /dev/null
+++ b/gbt_splitter/readheader.cpp
@@ -0,0 +1,225 @@
+/*
+ *  Functions for reading tape and work unit headers
+ *
+ *  This file currently assumes that the reciever is at Arecibo.
+ *
+ * $Id: readheader.cpp,v 1.3.4.2 2006/12/14 22:24:47 korpela Exp $
+ *
+ */
+
+#include "sah_config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "splitter.h"
+#include "splitparms.h"
+#include "splittypes.h"
+#include "message.h"
+#include "timecvt.h"
+#include "coordcvt.h"
+
+/* Read a tape header at buffer into a tapeheader_t */
+int read_tape_header(char *buffer, tapeheader_t *header)
+{
+  static char *receivers[]={"","synthetic","ao1420"};
+  int done=0,len;
+  int pos=0,i;
+  char tmpstr[256];
+  double dummy;
+  unsigned int firstdata;
+
+  do {
+    len=strlen(buffer+pos)+1;
+    if (!strncmp(buffer+pos,"EOH=",4)) {
+      done=1;
+    } else if (!strncmp(buffer+pos,"NAME=",5)) {
+       strncpy(tmpstr,buffer+pos+5,36);
+       i=0;
+       while(!isalnum(tmpstr[i])) i++;
+       strncpy(header->name,tmpstr+i,36);
+    } else if (!strncmp(buffer+pos,"RCDTYPE=",8)) {
+       sscanf(buffer+pos+8,"%d",&(header->rcdtype));
+    } else if (!strncmp(buffer+pos,"FRAMESEQ=",9)) {
+       sscanf(buffer+pos+9,"%lu",&(header->frameseq));
+    } else if (!strncmp(buffer+pos,"DATASEQ=",8)) {
+       sscanf(buffer+pos+8,"%lu",&(header->dataseq));
+    } else if (!strncmp(buffer+pos,"NUMRINGBUFS=",12)) {
+       sscanf(buffer+pos+12,"%d",&(header->numringbufs));
+    } else if (!strncmp(buffer+pos,"NUMDISKBUFS=",12)) {
+       sscanf(buffer+pos+12,"%d",&(header->numdiskbufs));
+    } else if (!strncmp(buffer+pos,"MISSED=",7)) {
+       sscanf(buffer+pos+7,"%d",&(header->missed));
+    } else if (!strncmp(buffer+pos,"AST=",4)) {
+       sscanf(buffer+pos+4,"%2d%3d%2d%2d%2d%2d",
+	 &(header->st.y), &(header->st.d), &(header->st.h),
+	 &(header->st.m), &(header->st.s), &(header->st.c));
+	 header->st.tz=AST;
+    } else if (!strncmp(buffer+pos,"TELSTR=",7)) {
+       sscanf(buffer+pos+7,"%2d%3d%2d%2d%2d %lf %lf %lf",
+	 &(header->telstr.st.y), &(header->telstr.st.d), 
+	 &(header->telstr.st.h), &(header->telstr.st.m), 
+	 &(header->telstr.st.s), &(header->telstr.az), 
+	 gregorian?&(header->telstr.alt):&dummy,
+	 gregorian?&dummy:&(header->telstr.alt));
+	 header->telstr.alt=90.0-header->telstr.alt;
+	 header->telstr.st.tz=AST;
+	 header->telstr.st.c=0;
+    } else if (!strncmp(buffer+pos,"RECEIVER=",9)) {
+       i=1;
+       while ((!strstr(buffer+pos+9,receivers[i])) && (++i<NUM_SRCS)) ;
+       if (i==NUM_SRCS) {
+          log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Unknown receiver: %s\n",buffer+pos+9);
+	  header->source=0;
+       } else {
+	  header->source=i;
+       }
+    } else if (!strncmp(buffer+pos,"CENTERFREQ=",11)) {
+       sscanf(buffer+pos+11,"%lf",&(header->centerfreq));
+       header->centerfreq*=1e6;
+    } else if (!strncmp(buffer+pos,"SAMPLERATE=",11)) {
+       sscanf(buffer+pos+11,"%lf",&(header->samplerate));
+       header->samplerate*=1e6;
+    } else if (!strncmp(buffer+pos,"VER=",4)) {
+       strncpy(&(header->version[0]),&(buffer[pos+4]),16);
+    } else if (len>1) {
+       log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Unknown header field: %40s\n",buffer+pos);
+    }
+    pos+=len;
+  } while (!done && (pos<TAPE_HEADER_SIZE));
+/* Right now were only doing this for one observatory. (Arecibo)
+ * May want to change list later to a switch statement on the reciever 
+ */
+
+  st_time_convert(&(header->st));
+  header->st.jd-=(float)RECORDER_BUFFER_SAMPLES/header->samplerate/86400;
+  st_time_convert(&(header->telstr.st));
+  telstr_coord_convert(&(header->telstr),ARECIBO_LAT,ARECIBO_LON);
+
+/*
+ * Fix a bug in recorder versions prior to 1.30
+ */
+
+ if (atof(&(header->version[0]))<1.299) {
+   header->centerfreq-=2.0;
+ }
+
+/*
+ * Check for blank tape
+ */
+  firstdata=*(unsigned int *)(buffer+TAPE_HEADER_SIZE);
+  if (!(firstdata & 0x55555555) || !(firstdata & 0xaaaaaaaa) ||
+       ((firstdata & 0x55555555) == 0x55555555) ||
+       ((firstdata & 0xaaaaaaaa) == 0xaaaaaaaa)) {
+    header->missed++;
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Possible data problem...data[0] = 0x%x\n",firstdata);
+  }
+
+  return(1);
+}
+
+/* Read a work unit header from a FILE into a wuheader_t */
+//int read_wu_header(FILE *file, wuheader_t *header) {
+/* to be implemented. Don't need it yet. */
+//  return(0);
+//}
+
+int parse_tape_headers(unsigned char *tapebuffer, tapeheader_t *tapeheaders) {
+ int i;
+
+ for (i=0;i<TAPE_FRAMES_IN_BUFFER;i++) {
+   read_tape_header((char *)tapebuffer+i*TAPE_FRAME_SIZE, &(tapeheaders[i]));
+ }
+ return(1);
+}
+
+/*
+ * $Log: readheader.cpp,v $
+ * Revision 1.3.4.2  2006/12/14 22:24:47  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.3.4.1  2006/01/13 00:37:57  korpela
+ * Moved splitter to using standard BOINC logging mechanisms.  All stderr now
+ * goes to "error.log"
+ *
+ * Added command line parameters "-iterations=" (number of workunit groups to
+ * create before exiting), "-trigger_file_path=" (path to the splitter_stop trigger
+ * file.  Default is /disks/setifiler1/wutape/tapedir/splitter_stop).
+ *
+ * Reduced deadlines by a factor of three.  We now need a 30 MFLOP machine to meet
+ * the deadline.
+ *
+ * Revision 1.3  2003/09/11 18:53:38  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.2  2003/08/05 17:23:40  korpela
+ * More work on database stuff.
+ * Further tweaks.
+ *
+ * Revision 1.1  2003/07/29 20:35:48  korpela
+ *
+ * renames .C files to .cpp
+ *
+ * Revision 1.3  2003/06/05 15:52:47  korpela
+ *
+ * Fixed coordinate bug that was using the wrong zenith angle from the telescope
+ * strings when handling units from the gregorian.
+ *
+ * Revision 1.2  2003/06/03 01:01:17  korpela
+ *
+ * First working splitter under CVS.
+ *
+ * Revision 1.1  2003/06/03 00:16:16  korpela
+ *
+ * Initial splitter under CVS control.
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.9  1999/06/07 21:00:52  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.8  1999/03/05  01:47:18  korpela
+ * Added data_class field.
+ *
+ * Revision 2.7  1999/02/22  21:49:42  korpela
+ * Fixed bug in bug fix.
+ *
+ * Revision 2.6  1999/02/22  21:48:41  korpela
+ * Fixed frequency bug in recorders prior to v1.3
+ *
+ * Revision 2.5  1998/11/13  23:58:52  korpela
+ * Modified for move of name field between structures.
+ *
+ * Revision 2.4  1998/11/02  21:34:19  korpela
+ * Fixed azimuth error.
+ *
+ * Revision 2.3  1998/11/02  21:20:58  korpela
+ * Modified for (internal) integer receiver ID.
+ *
+ * Revision 2.2  1998/11/02  18:39:38  korpela
+ * Changed location of timecvt.h
+ *
+ * Revision 2.1  1998/11/02  16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.4  1998/10/30  20:26:03  korpela
+ * Bug Fixes.  Now mostly working.
+ *
+ * Revision 1.3  1998/10/27  00:57:14  korpela
+ * Bug fixes.
+ *
+ * Revision 1.2  1998/10/15  19:16:38  korpela
+ * Corrected syntax errors.
+ *
+ * Revision 1.1  1998/10/15  19:05:33  korpela
+ * Initial revision
+ *
+ *
+ */
diff --git a/gbt_splitter/readheader.h b/gbt_splitter/readheader.h
new file mode 100644
index 0000000..67c14da
--- /dev/null
+++ b/gbt_splitter/readheader.h
@@ -0,0 +1,42 @@
+/*
+ *  Functions for reading tape and work unit headers
+ *
+ * $Id: readheader.h,v 1.2 2003/08/05 17:23:41 korpela Exp $
+ *
+ */
+
+/* Read a tape header at buffer into a tapeheader_t */
+int read_tape_header(char *buffer, tapeheader_t *header);
+
+/* Read a work unit header from a FILE into a wuheader_t */
+//int read_wu_header(FILE *file, workunit *header);
+// no longer needed
+
+/* Parse tape headers from binary tape header into a tapeheader_t */
+int parse_tape_headers(unsigned char *tapebuffer, tapeheader_t *tapeheaders);
+/*
+ * $Log: readheader.h,v $
+ * Revision 1.2  2003/08/05 17:23:41  korpela
+ * More work on database stuff.
+ * Further tweaks.
+ *
+ * Revision 1.1  2003/06/03 00:16:16  korpela
+ *
+ * Initial splitter under CVS control.
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.1  1998/11/02 16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.2  1998/10/27  01:09:22  korpela
+ * Added parse_tape_headers()
+ *
+ * Revision 1.1  1998/10/15  17:19:21  korpela
+ * Initial revision
+ *
+ */
diff --git a/gbt_splitter/readtape.cpp b/gbt_splitter/readtape.cpp
new file mode 100644
index 0000000..9c4030a
--- /dev/null
+++ b/gbt_splitter/readtape.cpp
@@ -0,0 +1,333 @@
+/* readtape.c
+ *
+ * Functions for reading tapes.
+ *
+ * $Id: readtape.cpp,v 1.3.4.4 2007/06/07 20:01:52 mattl Exp $
+ *
+ */
+
+#include "sah_config.h"
+#undef USE_MYSQL
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mtio.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <iostream>
+
+#include "util.h"
+#include "splitparms.h"
+#include "splitter.h"
+#include "message.h"
+#include "readheader.h"
+#include "readtape.h"
+#include "sqlrow.h"
+#include "sqlblob.h"
+#include "sqlapi.h"
+#include "db_table.h"
+#include "schema_master.h"
+#include "str_util.h"
+#include "str_replace.h"
+
+int is_tape;
+
+static tape tape_info;
+
+int current_record;
+static int tape_fd;
+struct mtget tape_status;
+
+static void update_checkpoint() {
+  FILE *file=fopen("rcd.chk","w");
+  if (file) {
+    fprintf(file,"%d\n",current_record);
+    fclose(file);
+  }
+}
+
+int read_checkpoint() {
+  FILE *file=fopen("rcd.chk","r");
+  int retval=0;
+  if (file) {
+    fscanf(file,"%d",&retval);
+    fclose(file);
+  }
+  return(retval);
+}
+
+int tape_busy() {
+/* Check if tape is busy.  If so return 1 else return 0 
+ */
+  if (is_tape) {
+    if (ioctl(tape_fd,MTIOCGET,&tape_status) != -1) {
+      return (tape_status.mt_dsreg);
+    } else {
+      log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Unable to get tape status\n");
+      return (1);
+    }
+  } else {
+    return (0);
+  }
+}
+
+int tape_eject() {
+/* Rewind and eject the tape.  Return 1 if sucessful else return 0 
+ */
+  struct mtop op={MTOFFL,1};
+
+  close(tape_fd);
+  if (is_tape) {
+    while (tape_busy()) sleep(1);
+    if (ioctl(tape_fd,MTIOCTOP,&op)==-1) {
+      log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Unable to eject tape\n");
+      return(0);
+    } else {
+      return(1);
+    }
+  } else {
+    return(1);
+  }
+}
+
+
+int tape_rewind() {
+/* Rewind to beginning of tape. Return 1 if sucessful, 0 if failure 
+ */
+  struct mtop op={MTREW, 1};
+  if (is_tape) {
+    while (tape_busy()) sleep(1);
+    if (ioctl(tape_fd,MTIOCTOP,&op)!=-1) {
+      current_record=0;
+      update_checkpoint();
+    } else {
+      current_record=-1;
+      log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Tape rewind failed\n");
+    }
+  } else {
+    if (lseek(tape_fd, 0, SEEK_SET)!=-1) {
+      current_record=0;
+      update_checkpoint();
+    } else {
+      current_record=-1;
+      log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"File rewind failed\n");
+    }
+  }
+  return (!current_record);
+}
+
+
+
+int open_tape_device(char *device) {
+/* opens a device, checks if it is a tape device.  If so, sets is_tape
+ * flag. If not, it resets the flag.  All tape routines check this flag
+ * so routines will work for both tapes and files
+ */
+
+
+  int fd, errcnt=0;
+  struct mtop op={MTNOP,1};
+
+  if ((fd=open(device, O_RDONLY|0x2000, 0777))!=-1) {
+    tape_fd=fd;
+    if (ioctl(tape_fd,MTIOCGET,&tape_status) != -1)  {
+      is_tape = 1;
+    } else {
+      is_tape = 0;
+    }
+    while (!norewind && !tape_rewind() && errcnt<10 ) errcnt++;
+    if (!nodb && resumetape) {
+      tape_rewind();
+      fill_tape_buffer(tapebuffer,TAPE_RECORDS_IN_BUFFER);
+      parse_tape_headers(tapebuffer, &(tapeheaders[0]));
+      if (!tape_info.id) {
+        if (!tape_info.fetch(std::string("where name=\'")+tapeheaders->name+"\'")) {
+          tape_info.start_time=tapeheaders->st.jd;
+          tape_info.last_block_time=tapeheaders->st.jd;
+          tape_info.last_block_done=tapeheaders->frameseq;
+          strlcpy(tape_info.name,tapeheaders->name,sizeof(tape_info.name));
+          tape_info.insert();
+	} 
+      } 
+      startblock=tape_info.last_block_done/TAPE_FRAMES_PER_RECORD;
+    }  
+    if (norewind) {
+      startblock=MAX(read_checkpoint()-TAPE_RECORDS_IN_BUFFER,0);
+      tape_rewind();
+    }
+    if (startblock) {
+      return select_record(startblock);
+    }  
+    return (1);
+  } else {
+      perror( NULL );
+    return (0);
+  }
+}
+
+int select_record(int record_number) {
+/* seeks to a specific record number returns 1 if successful */
+  int diff;
+  struct mtop op;
+  char tmpstr[100];
+  off64_t off,offset;
+
+  if ((current_record<0) && !tape_rewind()) {
+    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Tape error: position lost and unable to rewind!\n");
+    return(0);
+  }
+
+  diff=record_number-current_record;
+
+  if (is_tape) {
+    if (diff==0) return (1);
+    if (diff>0) {
+      op.mt_op=MTFSR;
+      op.mt_count=diff;
+    } else {
+      op.mt_op=MTBSR;
+      op.mt_count=diff;
+    }
+    if (ioctl(tape_fd,MTIOCTOP,&op)==-1) {
+      log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Tape error: unable to position to record %d errno=%d\n",
+	  record_number,errno);
+      current_record=-1;
+      return(0);
+    } else {
+      current_record+=diff;
+      update_checkpoint();
+      return(1);
+    }
+ } else {
+   current_record=record_number;
+   update_checkpoint();
+   offset = record_number;
+   offset *= TAPE_RECORD_SIZE;
+   //fprintf( stderr, "offset: %lld", offset );
+   off=lseek64(tape_fd,offset,SEEK_SET) ;
+   //fprintf( stderr, "off: %lld", offset );
+   return (off != -1);
+ }
+}
+
+int tape_read_record(char *buffer) {
+  int bytesread=0;
+  int i;
+
+  while (tape_busy()) sleep(1);
+  
+  do {
+    i=read(tape_fd,buffer+bytesread,TAPE_RECORD_SIZE);
+    if (i>0) bytesread+=i;
+  } while ((bytesread<TAPE_RECORD_SIZE) && (i>0));
+
+  if (i==0) {
+    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"End of tape.  Please insert new tape\n");
+    current_record=-1;
+    return(0);
+  }
+
+  if (i<0) {
+    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Tape error.\n");
+    current_record=-1;
+    return(0);
+  }
+ 
+  current_record++;
+  update_checkpoint();
+  return(1);
+}
+
+int fill_tape_buffer(unsigned char *buffer, int n_records) {
+   int i;
+   long record;
+   char tmpstr[100];
+
+   for (i=0;i<n_records;i++) {
+     record=current_record;
+     //fprintf( stderr, "Reading record %d\n", i);
+     if (!tape_read_record((char *)buffer+i*TAPE_RECORD_SIZE)) {
+       
+       log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Tape error at record %d\n", current_record);
+       return(0);
+     }
+   }
+   return(1);
+}
+
+/*
+ * $Log: readtape.cpp,v $
+ * Revision 1.3.4.4  2007/06/07 20:01:52  mattl
+ * *** empty log message ***
+ *
+ * Revision 1.3.4.3  2006/12/14 22:24:47  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.3.4.2  2006/01/13 00:37:57  korpela
+ * Moved splitter to using standard BOINC logging mechanisms.  All stderr now
+ * goes to "error.log"
+ *
+ * Added command line parameters "-iterations=" (number of workunit groups to
+ * create before exiting), "-trigger_file_path=" (path to the splitter_stop trigger
+ * file.  Default is /disks/setifiler1/wutape/tapedir/splitter_stop).
+ *
+ * Reduced deadlines by a factor of three.  We now need a 30 MFLOP machine to meet
+ * the deadline.
+ *
+ * Revision 1.3.4.1  2006/01/10 00:39:04  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.3  2003/09/11 18:53:38  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.2  2003/08/05 17:23:41  korpela
+ * More work on database stuff.
+ * Further tweaks.
+ *
+ * Revision 1.1  2003/07/29 20:35:49  korpela
+ *
+ * renames .C files to .cpp
+ *
+ * Revision 1.1  2003/06/03 00:16:16  korpela
+ *
+ * Initial splitter under CVS control.
+ *
+ * Revision 3.3  2003/05/19 17:40:59  eheien
+ * *** empty log message ***
+ *
+ * Revision 3.2  2003/04/23 22:10:29  korpela
+ * *** empty log message ***
+ *
+ * Revision 3.1  2002/06/21 00:06:09  eheien
+ * *** empty log message ***
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.3  1999/02/22 22:21:09  korpela
+ * added -nodb option
+ *
+ * Revision 2.2  1999/02/11  16:46:28  korpela
+ * Added some db access functions.
+ *
+ * Revision 2.1  1998/11/02  16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.3  1998/10/27  00:57:47  korpela
+ * Bug fixes.
+ *
+ * Revision 1.2  1998/10/20  21:33:25  korpela
+ * Added fill_tape_buffer()
+ * Minor bug fixes.
+ *
+ * Revision 1.1  1998/10/15  17:08:07  korpela
+ * Initial revision
+ *
+ */
+
diff --git a/gbt_splitter/readtape.h b/gbt_splitter/readtape.h
new file mode 100644
index 0000000..76987f8
--- /dev/null
+++ b/gbt_splitter/readtape.h
@@ -0,0 +1,85 @@
+/* readtape.h
+ *
+ * Functions for reading tapes.
+ *
+ * $Id: readtape.h,v 1.3.2.1 2006/12/14 22:24:47 korpela Exp $
+ *
+ */
+
+#ifndef READTAPE_H
+#define READTAPE_H
+
+#include "sah_config.h"
+
+/* Status flag to indicate whether open "tape" device is a tape drive */
+extern int is_tape;
+
+/* Check if tape is busy.  If so return 1 else return 0 */
+int tape_busy();
+
+/* Rewind and eject the tape.  Return 1 if sucessful else return 0 */
+int tape_eject();
+
+/* Rewind to beginning of tape. Return 1 if sucessful, 0 if failure */
+int tape_rewind();
+
+/* Open a device, check if it is a tape device.  If so, set is_tape
+ * flag. If not, it resets the flag.  All tape routines check this flag
+ * so routines will work for both tapes and files
+ */
+int open_tape_device(char *device);
+
+/* Seek to a specific record number returns 1 if successful */
+int select_record(int record_number);
+
+/* Read a record of length TAPE_RECORD_SIZE into a buffer 
+ * Returns 1 if successful
+ */
+int tape_read_record(char *buffer);
+
+/* Fill a buffer of length n_records*TAPE_RECORD_SIZE
+ * with data from tape.  Return 1 if sucessful.
+ */
+int fill_tape_buffer(unsigned char *buffer, int n_records);
+
+extern int current_record;
+
+#endif
+/*
+ * $Log: readtape.h,v $
+ * Revision 1.3.2.1  2006/12/14 22:24:47  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.3  2003/09/26 20:48:51  jeffc
+ * jeffc - merge in branch setiathome-4_all_platforms_beta.
+ *
+ * Revision 1.2.2.1  2003/09/23 16:01:45  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.2  2003/08/05 17:23:41  korpela
+ * More work on database stuff.
+ * Further tweaks.
+ *
+ * Revision 1.1  2003/06/03 00:23:39  korpela
+ *
+ * Again
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.2  1999/02/11 16:46:28  korpela
+ * Added db access functions.
+ *
+ * Revision 2.1  1998/11/02  16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.2  1998/10/20  21:35:51  korpela
+ * Added fill_tape_buffer()
+ *
+ * Revision 1.1  1998/10/15  16:49:59  korpela
+ * Initial revision
+ *
+ */
diff --git a/gbt_splitter/splitparms.h b/gbt_splitter/splitparms.h
new file mode 100644
index 0000000..64337a4
--- /dev/null
+++ b/gbt_splitter/splitparms.h
@@ -0,0 +1,145 @@
+/*  splitparms.h
+ *
+ *  Most of the definitions required by the splitter
+ *
+ *  $Id: splitparms.h,v 1.10 2004/11/23 21:26:29 jeffc Exp $
+ *
+ */
+
+#ifndef SPLITPARMS_H
+#define SPLITPARMS_H
+
+#include <limits.h>
+
+#define WU_SUBDIR "/download"
+
+#define SPLITTER_VERSION 0x0012
+#define MAX_WUS_ONDISK 500000
+#define N_SIMULT_SPLITTERS 6
+
+/* Work Unit Parameters */
+#define NBYTES 262144L
+#define NSAMPLES (NBYTES*CHAR_BIT/2)
+#define MAX_POSITION_HISTORY 40
+#define WU_FILESIZE (360L*1024)
+
+/* FFT Parameters */
+#define FFT_LEN 256
+#define IFFT_LEN 1
+#define NSTRIPS (FFT_LEN/IFFT_LEN)
+
+/* Tape format parameters */
+#define TAPE_HEADER_SIZE 1024L
+#define TAPE_DATA_SIZE 1048576L
+#define TAPE_FRAMES_PER_RECORD 8L
+#define TAPE_FRAME_SIZE (TAPE_HEADER_SIZE+TAPE_DATA_SIZE)
+#define TAPE_RECORD_SIZE (TAPE_FRAMES_PER_RECORD*TAPE_FRAME_SIZE)
+#define TAPE_BUFFER_SIZE (((NSTRIPS*NBYTES*7/4)/TAPE_RECORD_SIZE+1)*TAPE_RECORD_SIZE)
+#define TAPE_RECORDS_IN_BUFFER (TAPE_BUFFER_SIZE/TAPE_RECORD_SIZE)
+#define TAPE_FRAMES_IN_BUFFER (TAPE_RECORDS_IN_BUFFER*8)
+#define TAPE_FRAMES_PER_WU (NBYTES*NSTRIPS/TAPE_DATA_SIZE)
+#define WU_OVERLAP_RECORDS 2
+#define WU_OVERLAP_FRAMES (TAPE_FRAMES_PER_RECORD*WU_OVERLAP_RECORDS)
+#define WU_OVERLAP_BYTES (WU_OVERLAP_FRAMES*TAPE_DATA_SIZE)
+#define RECORDER_BUFFER_BYTES (1024L*1024L)
+#define RECORDER_BUFFER_SAMPLES (RECORDER_BUFFER_BYTES*4)
+
+
+/* Time Zone Parameters */
+#define UTC  0.0
+#define AST  (UTC-4.0)
+
+/* Arecibo Observatory Parameters */
+#define ARECIBO_LAT  18.3538056
+#define ARECIBO_LON  (-66.7552222)
+
+#endif
+/*
+ * $Log: splitparms.h,v $
+ * Revision 1.10  2004/11/23 21:26:29  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.9  2004/08/14 04:44:26  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.8  2004/06/16 20:57:19  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.7  2004/05/22 18:12:18  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.6  2003/10/27 17:53:21  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.5  2003/09/26 20:48:51  jeffc
+ * jeffc - merge in branch setiathome-4_all_platforms_beta.
+ *
+ * Revision 1.3.2.1  2003/09/22 17:39:34  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.4  2003/09/22 17:05:38  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.3  2003/09/11 18:53:38  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.2  2003/08/05 17:23:42  korpela
+ * More work on database stuff.
+ * Further tweaks.
+ *
+ * Revision 1.1  2003/06/03 00:23:40  korpela
+ *
+ * Again
+ *
+ * Revision 3.1  2001/11/07 00:51:47  korpela
+ * Added splitter version to database.
+ * Added max_wus_ondisk option.
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.9  2000/12/01 01:13:29  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.8  1999/10/20 19:20:26  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.7  1999/06/07 21:00:52  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.6  1999/03/27  16:19:35  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.5  1999/03/05  01:47:18  korpela
+ * Added data_class field.
+ *
+ * Revision 2.4  1999/02/23  18:57:09  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.3  1999/02/22  22:21:09  korpela
+ * Changed version number.
+ *
+ * Revision 2.2  1999/02/11  16:46:28  korpela
+ * Added WU_FILESIZE, RECORDER_BUFFER_BYTES, RECORDER_BUFFER_SAMPLES.`
+ *
+ * Revision 2.1  1998/11/02  16:38:29  korpela
+ * Variable type changes.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.4  1998/10/27  01:10:04  korpela
+ * Bug fixes.
+ *
+ * Revision 1.3  1998/10/19  23:06:40  korpela
+ * Added UTC and AST definition.
+ * Added ARECIBO_LAT and ARECIBO_LON definitions.
+ *
+ * Revision 1.2  1998/10/16  19:22:14  korpela
+ * Reduced WU file size from 512K to 256K.
+ *
+ * Revision 1.1  1998/10/15  16:39:51  korpela
+ * Initial revision
+ *
+ */
+ 
diff --git a/gbt_splitter/splitter.cpp b/gbt_splitter/splitter.cpp
new file mode 100644
index 0000000..c4cea44
--- /dev/null
+++ b/gbt_splitter/splitter.cpp
@@ -0,0 +1,717 @@
+/*
+ *
+ *  The splitter main program.  
+ *
+ * $Id: splitter.cpp,v 1.22.2.6 2007/06/06 15:58:30 korpela Exp $
+ *
+ */
+
+#include "sah_config.h"
+#undef USE_MYSQL
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <strings.h>
+#include <sys/types.h>
+#include <sys/statvfs.h>
+#include <sys/wait.h>
+
+#include "boinc_db.h"
+#include "crypt.h"
+#include "backend_lib.h"
+#include "sched_config.h"
+#include "splitparms.h"
+#include "splittypes.h"
+#include "splitter.h"
+#include "validrun.h"
+#include "makebufs.h"
+#include "readtape.h"
+#include "readheader.h"
+#include "wufiles.h"
+#include "dotransform.h"
+#include "polyphase.h"
+#include "message.h"
+#include "sqlrow.h"
+#include "sqlapi.h"
+#include "db/db_table.h"
+#include "db/schema_master.h"
+#include "db/app_config.h"
+
+extern "C" {
+  int sqldetach();
+}
+
+char trigger_file_path[1024]="/disks/setifiler1/wutape/tapedir/splitter_stop";
+
+SCHED_CONFIG boinc_config;
+DB_APP app;
+R_RSA_PRIVATE_KEY key;
+
+
+// TEMPLATE DEFS ------------------------------------------------------
+// IMPORTANT: a change to a template should *always* include a change
+// to the template filename.  Only the result template is used now.
+const char *wu_template_filename_id = "wu_0.xml";
+const char *wu_template=
+  "<file_info>\n"
+  "  <number>0</number>\n"
+  "</file_info>\n"
+  "<workunit>\n"
+  "  <file_ref>\n"
+  "    <file_number>0</file_number>\n"
+  "    <open_name>work_unit.sah</open_name>\n"
+  "  </file_ref>\n"
+  "</workunit>\n";
+
+const char *result_template_filename_id = "result_0.xml";
+const char *result_template=
+  "<file_info>\n"
+  "  <name><OUTFILE_0/></name>\n"
+  "  <generated_locally/>\n"
+  "  <upload_when_present/>\n"
+  "  <max_nbytes>65536</max_nbytes>\n"
+  "  <url>http://setiboincdata.ssl.berkeley.edu/sah_cgi/file_upload_handler</url>\n"
+  "</file_info>\n"
+  "<result>\n"
+  "  <file_ref>\n"
+  "    <file_name><OUTFILE_0/></file_name>\n"
+  "    <open_name>result.sah</open_name>\n"
+  "  </file_ref>\n"
+  "</result>\n";
+// END TEMPLATE DEFS --------------------------------------------------
+
+unsigned char *tapebuffer;     /* A buffer for a tape section */
+workunit wuheaders[NSTRIPS];
+tapeheader_t tapeheaders[TAPE_FRAMES_IN_BUFFER];
+int max_wus_ondisk=MAX_WUS_ONDISK;
+int nodb;
+int noencode;
+int resumetape;
+int norewind;
+int startblock;
+int dataclass;
+int atnight;
+int gregorian;
+int output_xml;
+int polyphase;
+int iters=-1;
+int filter_window = 0;
+double start_time;
+double stop_time;
+unsigned long minvfsbuf=-1;
+char wd[1024];
+//char * scidb = NULL;
+char * projectdir = NULL;
+
+APP_CONFIG sah_config;
+
+//const char *result_template_filename="projectdir"/"SAH_APP_NAME"_result.tpl";
+char result_template_filename[1024];
+char result_template_filepath[1024];
+char wu_template_filename[1024];
+
+int check_for_halt();
+int wait_until_night();
+int check_free_disk_space();
+int wait_for_db_wus_ondisk();
+
+void cprint(char *p) {
+  printf("%s\n",p);
+}
+
+/*  wulog: File for logging names of completed wu files */
+/*  errorlog: File for logging errors                   */
+
+FILE *wulog,*errorlog;
+buffer_pos_t start_of_wu,end_of_wu;  /* position of start and end of wu in
+                                      tape buffer */
+int seqno;
+int records_in_buffer;
+
+void cleanup(void) {
+  FILE *tmpfile;
+  if ((tmpfile=fopen("seqno.dat","w"))) {
+    fprintf(tmpfile,"%d\n",seqno);
+    fclose(tmpfile);
+  } else {
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Unable to open seqno.dat for write\n");
+  }
+}
+
+
+int process_command_line(int argc, char *argv[],char **tape_device,
+                         int *norewind, int *startblock, int *resumetape,
+                         int *nodb, int *dataclass, int *atnight,
+                         int *max_wus_ondisk, char **projectdir,
+			 int *iters) {
+  int nargs=0,i;
+  char *ep;
+  for (i=1;i<argc;i++) {
+    if (argv[i][0]=='-') {
+        if (!strncmp(argv[i],"-hanning",MAX(strlen(argv[i]),3))) {
+          filter_window=2;
+        } else
+          if (!strncmp(argv[i],"-welch",MAX(strlen(argv[i]),3))) {
+            filter_window=1;
+          } else
+            if (!strncmp(argv[i],"-xml",MAX(strlen(argv[i]),3))) {
+              output_xml=1;
+            } else
+              if (!strncmp(argv[i],"-atnight",MAX(strlen(argv[i]),7))) {
+                *atnight=1;
+              } else
+                if (!strncmp(argv[i],"-nodb",MAX(strlen(argv[i]),4))) {
+                  if (*resumetape) {
+                    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"-nodb and -resumetape are exclusive\n");
+                    return(1);
+                  }
+                  *nodb=1;
+                } else
+                  if (!strncmp(argv[i],"-gregorian",MAX(strlen(argv[i]),2))) {
+                    gregorian=1;
+                  } else
+                    if (!strncmp(argv[i],"-resumetape",MAX(strlen(argv[i]),2))) {
+                      if (*startblock || *norewind) {
+		        log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"-startblock and -norewind can\'t be used with -resumetape\n");
+                        return(1);
+                      }
+                      if (*nodb) {
+                        log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"-nodb and -resumetape are exclusive\n");
+                        return(1);
+                      }
+                      *resumetape=1;
+                    } else
+                      if (!strncmp(argv[i],"-norewind",MAX(strlen(argv[i]),4))) {
+                        if (*startblock || *resumetape) {
+                          return(1);
+                        }
+                        *norewind=1;
+                      } else
+                        if ((ep=strchr(argv[i],'='))) {
+                          if (!strncmp(argv[i],"-trigger_file_path",MAX(ep-argv[i],2))) {
+			    char *fe=ep+1;
+			    memset(trigger_file_path,0,sizeof(trigger_file_path));
+			    while (isgraph(*(fe++))) trigger_file_path[fe-ep-2]=*fe ;
+                          } else if (!strncmp(argv[i],"-iterations",MAX(ep-argv[i],2))) {
+			    sscanf(ep+1,"%d",iters);
+			  } else if (!strncmp(argv[i],"-startblock",MAX(ep-argv[i],2))) {
+                            if (*norewind || *resumetape) {
+                              return(1);
+                            }
+                            sscanf(ep+1,"%d",startblock);
+                          } else if (!strncmp(argv[i],"-max_wus_ondisk",MAX(ep-argv[i],2))) {
+                              sscanf(ep+1,"%d",max_wus_ondisk);
+                          } else if (!strncmp(argv[i],"-dataclass",MAX(ep-argv[i],2))) {
+                                sscanf(ep+1,"%d",dataclass);
+                          } else if (!strncmp(argv[i],"-projectdir",MAX(ep-argv[i],2))) {
+			          *projectdir=calloc(strlen(ep+1)+5,1)
+    				  strlcpy(*projectdir,ep+1,strlen(ep+1)+5);
+				  strlcat(*projectdir,"/",strlen(ep+1)+5);
+                          } else {
+                            return(1);
+                          }
+                        } else {
+                          return(1);
+                        }
+    } else {
+      *tape_device=argv[i];
+      nargs++;
+    }
+  }
+  //return(nargs!=1);
+
+  // check for required cmd line 
+  //if (! *scidb) return (1);
+  if (! *projectdir) return (1);
+  if (! *tape_device) return (1);
+
+  return 0;
+}
+
+int main(int argc, char *argv[]) {
+  char *tape_device;
+  FILE *tmpfile;
+  int retval;
+  char keyfile[1024];
+  char tmpstr[1024];
+
+
+  /* Process command line arguments */
+  if (process_command_line(argc,argv,&tape_device,&norewind,&startblock,&resumetape,
+                           &nodb,&dataclass,&atnight,&max_wus_ondisk,&projectdir,&iters))  {
+    fprintf(stderr,"Usage: splitter tape_device -projectdir=s [-atnight] [-nodb]\n"
+    "[-xml] [-gregorian] [-resumetape | -norewind | -startblock=n] [-dataclass=n]\n"
+    "[-max_wus_on_disk=n] [-iterations=n] [-trigger_file_path=filename]\n");
+    exit(EXIT_FAILURE);
+  }
+
+  /* Open log files */
+  log_messages.set_debug_level(3);
+  log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"opening log files\n");
+  if (!(wulog=fopen("wu.log","wa")) || !(errorlog=freopen("error.log","wa",stderr))) {
+    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Unable to open log files!\n");
+    exit(EXIT_FAILURE);
+  }
+
+  retval = sah_config.parse_file(projectdir);
+  if (retval) {
+    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Can't parse config file\n");
+    exit(EXIT_FAILURE);
+  } else {
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Using configuration:\n");
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"scidb_name          = %s\n", sah_config.scidb_name);
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"max_wus_ondisk      = %d\n", sah_config.max_wus_ondisk);
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"min_quorum          = %d\n", sah_config.min_quorum);
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"target_nresults     = %d\n", sah_config.target_nresults);
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"max_error_results   = %d\n", sah_config.max_error_results);
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"max_success_results = %d\n", sah_config.max_success_results);
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"max_total_results   = %d\n", sah_config.max_total_results);
+  }
+
+  // Will initially open 
+  if (!db_change(sah_config.scidb_name)) {
+    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Could not open science database %s\n", sah_config.scidb_name);
+    if (!nodb) exit(EXIT_FAILURE);
+  } else {
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Using science database %s\n", sah_config.scidb_name);
+  }
+
+
+  boinc_config.parse_file(projectdir);
+  log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Using boinc config dir  %s\n", projectdir);
+  log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Using boinc database %s\n", boinc_config.db_name);
+
+  // check / commit result template
+  strcpy(result_template_filename, "templates/"SAH_APP_NAME"_");
+  strcat(result_template_filename, result_template_filename_id);
+  strcpy(result_template_filepath, projectdir);
+  strcat(result_template_filepath, result_template_filename);
+  log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"%s %s\n", result_template_filename, result_template_filepath);
+  if (!(tmpfile=fopen(result_template_filepath,"r"))) {
+    if (!(tmpfile=fopen(result_template_filepath,"w"))) {
+      log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Cannot open result file template : %s\n", result_template_filepath);
+      exit(1);
+    }
+    fprintf(tmpfile,result_template);
+  }
+  fclose(tmpfile);
+
+  if (boinc_db.open(boinc_config.db_name,boinc_config.db_host,boinc_config.db_user,boinc_config.db_passwd)) {
+    boinc_db.print_error("boinc_db.open");
+    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"boinc_db.open\n");
+    exit(1);
+  }
+
+  if (app.lookup("where name ='"SAH_APP_NAME"'")) {
+    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Error looking up appname\n");
+    boinc_db.print_error("boinc_app lookup");
+    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"boinc_app lookup\n");
+    exit(1);
+  } else {
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Splitting for application %s (ID = %d)\n", SAH_APP_NAME, app.id);
+  }
+
+  boinc_db.close();
+
+  strcpy(keyfile, projectdir);
+  strcat(keyfile, "/keys/upload_private");
+  if (read_key_file(keyfile,key)) {
+    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Error reading keyfile.\n");
+    exit(1);
+  }
+
+  // if (!getenv("S4_RECEIVER_CONFIG")) putenv(s4cnf_env);
+  check_for_halt();
+
+  /* Process command line arguments */
+  //if (process_command_line(argc,argv,&tape_device,&norewind,&startblock,&resumetape,
+  //                         &nodb,&dataclass,&atnight,&max_wus_ondisk,&scidb,&projectdir))  {
+  //  fprintf(stderr,"Usage: splitter tape_device [-atnight] [-nodb] [-xml] [-gregorian] [-resumetape | -norewind | -startblock=n] [-dataclass=n]\n");
+  //  exit(EXIT_FAILURE);
+  //}
+
+
+  /* Connect to database */
+  //if (!sql_database(SCIENCE_DB)) {
+  //  fprintf(stderr,"Unable to connect to database.\n");
+  //  if (!nodb) exit(EXIT_FAILURE);
+  //}
+
+
+
+
+
+  /*
+   * Allocate temp files for tape buffer.  
+   */
+  makebuffers(&tapebuffer);
+
+  if (!open_tape_device(tape_device)) {
+    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Unable to open tape device\n");
+    exit(EXIT_FAILURE);
+  }
+
+  /*
+   * Get sequence number 
+   */
+
+  if ((tmpfile=fopen("seqno.dat","r"))) {
+    fscanf(tmpfile,"%d",&seqno);
+    fclose(tmpfile);
+  } else {
+    seqno=0;
+  }
+  /* Start of main loop */
+
+  records_in_buffer=0;
+  start_of_wu.frame=0;
+  start_of_wu.byte=0;
+  end_of_wu.frame=0;
+  end_of_wu.byte=0;
+
+  atexit(cleanup);
+
+  getcwd(wd,1024);
+
+  if (polyphase) {
+    int filter_len;
+
+    filter_len = P_FFT_LEN*N_WINDOWS;
+
+    filter_r = (double *)malloc(sizeof(double)*filter_len);
+    filter_i = (double *)malloc(sizeof(double)*filter_len);
+
+    f_data = (float *)malloc(sizeof(float)*P_FFT_LEN*2);
+
+    make_FIR(filter_len, N_WINDOWS, filter_window, filter_r);
+    make_FIR(filter_len, N_WINDOWS, filter_window, filter_i);
+
+    /*
+    int i;
+    float *data;
+    data = (float*)malloc(sizeof(float)*2*2048);
+    for (double n=-20;n<20;n+=.05) {
+    for (i=0;i<2*2048;i+=2) {
+        data[i] = cos(2*(24+n)*3.1415926535*i/(2*2048));
+        data[i+1] = sin(2*(24+n)*3.1415926535*i/(2*2048));
+    }
+    polyphase_seg(data);
+    //fprintf( stderr, "%f\n", 3+n/8);
+    }
+    exit(0);
+    for(i=0;i<filter_len;i++)
+      printf( "%f\n", filter_r[i] );
+    exit(0);*/
+  }
+
+  log_messages.printf(SCHED_MSG_LOG::MSG_DEBUG,"Entering loop\n" );
+  while (iters-- && 
+         fill_tape_buffer(tapebuffer+records_in_buffer*TAPE_RECORD_SIZE,
+           TAPE_RECORDS_IN_BUFFER-records_in_buffer)) {
+    /* check if we should be running now */
+    fflush(stderr);
+    if (atnight) wait_until_night();
+
+    check_for_halt();
+
+    // Make sure we have enough free disk space
+    check_free_disk_space();
+
+    // Wait for ondisk wus in the database to drop below the threshold
+    if (!nodb) wait_for_db_wus_ondisk();
+    //fprintf( stderr, "Read data\n" );
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"less than max wus on disk, continuing\n" );
+    fflush(stderr);
+
+    //printf( "Read tape data, analyzing\n" );
+    parse_tape_headers(tapebuffer, &(tapeheaders[0]));
+    check_for_halt();
+    if (valid_run(tapeheaders,&start_of_wu,&end_of_wu)) {
+      if (make_wu_headers(tapeheaders,wuheaders,&start_of_wu)) {
+        int child_pid=-1;
+        switch (polyphase) {
+          case 1:
+            do_polyphase(&start_of_wu,&end_of_wu);
+            break;
+          default:
+            log_messages.printf(SCHED_MSG_LOG::MSG_DEBUG,"doing transform..." );
+            do_transform(&start_of_wu,&end_of_wu);
+            log_messages.printf(SCHED_MSG_LOG::MSG_DEBUG," done\n" );
+        }
+        wait(0);
+        if (!nodb) sql_finish();
+/*
+        do {
+          sleep(1);
+          child_pid=fork();
+	  if (child_pid<0) log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"splitter cannot fork");
+          //fprintf( stderr, "child pid: %d\n", child_pid);
+        } while (child_pid<0);
+*/
+        child_pid=0;
+        if (!child_pid) {
+          if (!nodb) {
+            sqldetach();
+            while (!sql_database(sah_config.scidb_name)) {
+		//fprintf(stderr,"child sleeping\n");
+		sleep(10);
+	    }
+          }
+          rename_wu_files();
+          if (!nodb) sql_finish();
+//          _exit(0);
+        }
+        if (!nodb) {
+          while (!sql_database(sah_config.scidb_name)) {
+		//fprintf(stderr,"parent sleeping\n");
+		sleep(10);
+	  }
+        }
+      }
+    }
+  }
+return(0);
+
+}
+
+int check_for_halt() {
+  FILE *tf;
+
+  tf = fopen(trigger_file_path, "r");
+  // tf=0;
+  if (tf != NULL) {  // Stop program
+    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Found splitter_stop, exiting.\n" );
+    exit(1);
+  }
+  return(0); // Keep going
+}
+
+int wait_until_night() {
+  time_t t;
+  struct tm *lt;
+  do {
+    t=time(0);
+    lt=localtime(&t);
+    // Don't run M-F 8AM-6PM
+    if ((lt->tm_wday>0) && (lt->tm_wday<6) && (lt->tm_hour>8) && (lt->tm_hour<18)) {
+      sleep(100);
+    }
+  } while ((lt->tm_wday>0) && (lt->tm_wday<6) && (lt->tm_hour>8) && (lt->tm_hour<18));
+  return 0;
+}
+
+int check_free_disk_space() {
+  struct statvfs vfsbuf;
+
+  /* check disk free space */
+  statvfs("wu_inbox/.",&vfsbuf);
+  if (vfsbuf.f_bavail < (100000*1024/vfsbuf.f_frsize)) {
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Not enough free disk space in working directory to continue\n");
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Not enough free disk space in working directory to continue\n");
+    exit(EXIT_FAILURE);
+  }
+  return 0;
+}
+
+int wait_for_db_wus_ondisk() {
+  int wus_ondisk,rv;
+
+  // The boinc db query below takes a long time.  Until we fix this,
+  // we will do it only every 100 times into this routine.  All other
+  // calls here will assume that we need to add WUs.  -- jeffc
+  static int check_count = 100;
+  if (check_count < 100) {
+	check_count++;
+	return 0;
+  } else {
+	check_count = 0;
+  } 
+	
+  if (boinc_db.open(boinc_config.db_name,boinc_config.db_host,boinc_config.db_user,boinc_config.db_passwd)) {
+    boinc_db.print_error("boinc_db.open");
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"boinc_db.open\n");
+    exit(1);
+  }
+  do {
+    DB_RESULT boinc_result;
+    char query[1024];
+    sprintf(query,"where appid=%d and server_state=2",app.id);
+    rv=boinc_result.count(wus_ondisk,query);
+    if (rv) {
+      boinc_db.print_error("boinc_result.count");
+      log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"DB Error, unable to count workunits on disk\n");
+      exit(EXIT_FAILURE);
+    }
+    check_for_halt();
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"%d WUs ondisk\n", wus_ondisk);
+    if (wus_ondisk>sah_config.max_wus_ondisk) sleep(600);
+  } while (wus_ondisk>sah_config.max_wus_ondisk);
+
+  return 0;
+}
+
+/*
+ * $Log: splitter.cpp,v $
+ * Revision 1.22.2.6  2007/06/06 15:58:30  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.22.2.5  2006/12/14 22:24:48  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.22.2.4  2006/11/08 20:16:26  vonkorff
+ * Fixes an error message.
+ *
+ * Revision 1.22.2.3  2006/11/07 19:26:37  vonkorff
+ * Fixed lcgf
+ *
+ * Revision 1.22.2.2  2006/01/13 00:37:58  korpela
+ * Moved splitter to using standard BOINC logging mechanisms.  All stderr now
+ * goes to "error.log"
+ *
+ * Added command line parameters "-iterations=" (number of workunit groups to
+ * create before exiting), "-trigger_file_path=" (path to the splitter_stop trigger
+ * file.  Default is /disks/setifiler1/wutape/tapedir/splitter_stop).
+ *
+ * Reduced deadlines by a factor of three.  We now need a 30 MFLOP machine to meet
+ * the deadline.
+ *
+ * Revision 1.22.2.1  2005/08/01 21:16:25  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.22  2005/01/27 23:03:27  mattl
+ *
+ * commented out tf=0 in check_for_halt
+ *
+ * Revision 1.21  2004/12/27 20:48:54  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.20  2004/08/12 15:45:41  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.19  2004/07/09 22:35:39  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.18  2004/06/27 21:07:04  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.17  2004/06/20 18:56:48  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.16  2004/06/18 23:23:32  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.15  2004/06/16 20:57:19  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.14  2004/04/08 22:25:47  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.13  2004/01/22 00:57:53  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.12  2004/01/01 18:42:01  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.11  2003/12/03 23:46:41  korpela
+ * WU count is now only for SAH workunits.
+ *
+ * Revision 1.10  2003/11/25 21:59:52  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.9  2003/11/01 20:54:02  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.8  2003/10/24 16:57:03  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.7  2003/09/26 20:48:51  jeffc
+ * jeffc - merge in branch setiathome-4_all_platforms_beta.
+ *
+ * Revision 1.5.2.2  2003/09/23 00:49:12  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.5.2.1  2003/09/22 17:39:34  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.6  2003/09/22 17:05:38  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.5  2003/09/13 20:48:38  korpela
+ * directory reorg.  Moved client files to ./client
+ *
+ * Revision 1.4  2003/09/11 18:53:38  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.3  2003/08/13 23:18:47  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.2  2003/08/05 17:23:42  korpela
+ * More work on database stuff.
+ * Further tweaks.
+ *
+ * Revision 1.1  2003/07/29 20:35:50  korpela
+ *
+ * renames .C files to .cpp
+ *
+ * Revision 1.2  2003/06/03 01:01:17  korpela
+ *
+ * First working splitter under CVS.
+ *
+ * Revision 1.1  2003/06/03 00:23:40  korpela
+ *
+ * Again
+ *
+ * Revision 3.6  2003/05/21 00:41:42  korpela
+ * *** empty log message ***
+ *
+ * Revision 3.5  2003/05/19 17:40:59  eheien
+ * *** empty log message ***
+ *
+ * Revision 3.4  2003/04/09 17:46:54  korpela
+ * *** empty log message ***
+ *
+ * Revision 3.3  2002/06/20 22:09:17  eheien
+ * *** empty log message ***
+ *
+ * Revision 3.2  2001/11/07 00:51:47  korpela
+ * Added splitter version to database.
+ * Added max_wus_ondisk option.
+ *
+ * Revision 3.1  2001/08/16 23:42:08  korpela
+ * Mods for splitter to make binary workunits.
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.7  2000/12/01 01:13:29  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.6  1999/06/07 21:00:52  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.5  1999/03/27  16:19:35  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.4  1999/03/05  01:47:18  korpela
+ * Added dataclass paramter.
+ *
+ * Revision 2.3  1999/02/22  22:21:09  korpela
+ * added -nodb option
+ *
+ * Revision 2.2  1999/02/11  16:46:28  korpela
+ * Added some db access functions.
+ *
+ * Revision 2.1  1998/11/02  16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.2  1998/10/30  20:26:03  korpela
+ * Bug Fixes.  Now mostly working.
+ *
+ * Revision 1.1  1998/10/27  00:58:16  korpela
+ * Initial revision
+ *
+ *
+ */
diff --git a/gbt_splitter/splitter.h b/gbt_splitter/splitter.h
new file mode 100644
index 0000000..46b73b3
--- /dev/null
+++ b/gbt_splitter/splitter.h
@@ -0,0 +1,132 @@
+/*
+ *  splitter.h 
+ *
+ *  Global definitions from the splitter main program.  
+ *
+ * $Id: splitter.h,v 1.6.2.1 2006/01/13 00:37:58 korpela Exp $
+ *
+ */
+
+#ifndef SPLITTER_H
+#define SPLITTER_H
+
+#include "splitparms.h"
+#include "splittypes.h"
+
+#define MAX(x,y)  ( ((x)<(y)) ? (y) : (x)  )
+#define MIN(x,y)  ( ((y)<(x)) ? (y) : (x)  )
+
+/*  wulog: File for logging names of completed wu files */
+/*  errorlog: File for logging errors                   */
+#include "boinc_db.h"
+#include "crypt.h"
+#include "backend_lib.h"
+#include "sched_config.h"
+
+extern SCHED_CONFIG boinc_config;
+extern DB_APP app;
+extern R_RSA_PRIVATE_KEY key;
+extern FILE *wulog,*errorlog;
+extern workunit wuheaders[NSTRIPS];
+extern tapeheader_t tapeheaders[TAPE_FRAMES_IN_BUFFER];
+extern int noencode;
+extern int dataclass;
+extern int nodb;
+extern int resumetape;
+extern int startblock;
+extern int norewind;
+extern int output_xml;
+extern int polyphase;
+extern int wu_database_id[NSTRIPS];
+extern int gregorian;
+extern char * projectdir;
+extern char trigger_file_name[1024];
+
+
+/* Buffer that holds tape data */
+extern unsigned char *tapebuffer;
+
+/* Number of records remaining in the buffer after WU creations is complete */
+extern int records_in_buffer;
+
+extern const char *wu_template;
+extern const char *result_template;
+// jeffc
+//extern const char *result_template_filename;
+extern char result_template_filename[];
+extern char result_template_filepath[];
+extern char wu_template_filename[];
+
+/* Persistant sequence number of wu file */
+extern int seqno;
+
+#endif
+
+/* 
+ * $Log: splitter.h,v $
+ * Revision 1.6.2.1  2006/01/13 00:37:58  korpela
+ * Moved splitter to using standard BOINC logging mechanisms.  All stderr now
+ * goes to "error.log"
+ *
+ * Added command line parameters "-iterations=" (number of workunit groups to
+ * create before exiting), "-trigger_file_path=" (path to the splitter_stop trigger
+ * file.  Default is /disks/setifiler1/wutape/tapedir/splitter_stop).
+ *
+ * Reduced deadlines by a factor of three.  We now need a 30 MFLOP machine to meet
+ * the deadline.
+ *
+ * Revision 1.6  2004/07/09 22:35:39  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.5  2004/06/16 20:57:19  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.4  2003/09/26 20:48:52  jeffc
+ * jeffc - merge in branch setiathome-4_all_platforms_beta.
+ *
+ * Revision 1.2.2.1  2003/09/22 17:39:35  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.3  2003/09/22 17:05:38  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.2  2003/08/05 17:23:42  korpela
+ * More work on database stuff.
+ * Further tweaks.
+ *
+ * Revision 1.1  2003/06/03 00:23:40  korpela
+ *
+ * Again
+ *
+ * Revision 3.2  2003/05/19 17:40:59  eheien
+ * *** empty log message ***
+ *
+ * Revision 3.1  2001/08/16 23:42:08  korpela
+ * Mods for splitter to make binary workunits.
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.5  1999/10/20 19:20:26  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.4  1999/03/05 01:47:18  korpela
+ * Added data_class field.
+ *
+ * Revision 2.3  1999/02/22  22:21:09  korpela
+ * Added nodb option
+ *
+ * Revision 2.2  1999/02/11  16:46:28  korpela
+ * Added startblock and norewind support, and wu_database_id.
+ *
+ * Revision 2.1  1998/11/02 16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.1  1998/10/27  01:10:32  korpela
+ * Initial revision
+ *
+ *
+ */
diff --git a/gbt_splitter/splittypes.h b/gbt_splitter/splittypes.h
new file mode 100644
index 0000000..46e4b37
--- /dev/null
+++ b/gbt_splitter/splittypes.h
@@ -0,0 +1,111 @@
+/*  splittypes.h
+ *  
+ *  Type definitions specific to the splitter. 
+ *
+ *
+ *  $Id: splittypes.h,v 1.4 2003/08/05 17:23:43 korpela Exp $
+ *
+ */
+#ifndef SPLITTYPES_H
+#define SPLITTYPES_H
+
+#include <stdio.h>
+
+#include "splitparms.h"
+#include "s_util.h"
+#include "seti_header.h"
+
+//typedef struct wuheader {
+  //WU_INFO wuhead;
+  //SETI_WU_INFO wuinfo;
+//} wuheader_t;
+
+typedef struct tapeheader {
+  char name[36];
+  int rcdtype;
+  int numringbufs;
+  int numdiskbufs;
+  unsigned long frameseq;
+  unsigned long dataseq;
+  int missed;
+  TIME st;
+  SCOPE_STRING telstr;
+  int source;
+  double centerfreq,samplerate;
+  char version[16];
+} tapeheader_t;
+
+typedef struct buffer_pos {
+  int frame;
+  long byte;
+} buffer_pos_t;
+
+#endif
+/*
+ * $Log: splittypes.h,v $
+ * Revision 1.4  2003/08/05 17:23:43  korpela
+ * More work on database stuff.
+ * Further tweaks.
+ *
+ * Revision 1.3  2003/07/29 20:35:51  korpela
+ *
+ * renames .C files to .cpp
+ *
+ * Revision 1.2  2003/06/03 01:01:17  korpela
+ *
+ * First working splitter under CVS.
+ *
+ * Revision 1.1  2003/06/03 00:23:41  korpela
+ *
+ * Again
+ *
+ * Revision 3.1  2003/05/19 17:40:59  eheien
+ * *** empty log message ***
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.5  1999/02/11 16:46:28  korpela
+ * Added startblock and norewind support, and wu_database_id.
+ *
+ * Revision 2.4  1998/11/10 00:02:44  korpela
+ * Moved remaining wuheader fields into a WU_INFO structure.
+ *
+ * Revision 2.3  1998/11/05  21:18:41  korpela
+ * Moved name field from header to seti header.
+ *
+ * Revision 2.2  1998/11/02  21:20:58  korpela
+ * Moved tape_version and encoding_type into SETI_WU_INFO.
+ *
+ * Revision 2.1  1998/11/02  16:38:29  korpela
+ * Variable type changes.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.7  1998/10/30  21:01:13  davea
+ * *** empty log message ***
+ *
+ * Revision 1.6  1998/10/27 01:10:58  korpela
+ * Modified tapeheader_t to match new tape header fields.
+ *
+ * Revision 1.5  1998/10/19  23:04:32  korpela
+ * Moved times in telstr_t into an st_t.
+ * Changed name of ast_t to st_t.
+ * Added time zone (tz) field to ast_t.
+ *
+ * Revision 1.4  1998/10/15  19:13:30  korpela
+ * Renamed "unix" fields to "unix_time" because of GCC #define.
+ * Added position_history field to wuheader_t.
+ *
+ * Revision 1.3  1998/10/15  18:58:50  korpela
+ * Added time_t unix to ast_t and telstr_t types.
+ * Changed times in wuheader_t to time_t types.
+ *
+ * Revision 1.2  1998/10/15  18:01:19  korpela
+ * Removed month field from ast_t and telstr_t.
+ *
+ * Revision 1.1  1998/10/15  16:20:24  korpela
+ * Initial revision
+ *
+ */
diff --git a/gbt_splitter/squarewave.cpp b/gbt_splitter/squarewave.cpp
new file mode 100644
index 0000000..7ac379d
--- /dev/null
+++ b/gbt_splitter/squarewave.cpp
@@ -0,0 +1,75 @@
+#include "sah_config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <math.h>
+#include <string.h>
+#include <unistd.h>
+
+#define NUM_FRAMES 200L
+#define FRAME_DATA_SIZE (1024L*1024)
+#define HEADER_SIZE 1024
+#define FILESIZE (NUM_FRAMES*(FRAME_DATA_SIZE+HEADER_SIZE))
+
+char header[HEADER_SIZE];
+
+int main(void) {
+  int i;
+  int datapos=0;
+  int frameseq=0;
+  long written=0;
+  int on=0;
+  struct tm *tm;
+  char data;
+
+  char tmpstr[256];
+  char telstr[256];
+  double time0=(double)time(0);
+  time_t clock;
+
+  for (written=0;written<NUM_FRAMES;written++)  {
+     int headerpos=0;
+     memset(header,0,HEADER_SIZE);
+     strcpy(header,"NAME=sqrwave");
+     headerpos+=strlen("NAME=sqrwave")+1;
+     strcpy(header+headerpos,"RCDTYPE=1");
+     headerpos+=strlen("RCDTYPE=1")+1;
+     sprintf(tmpstr,"FRAMESEQ=%d",frameseq);
+     strcpy(header+headerpos,tmpstr);
+     headerpos+=strlen(tmpstr)+1;
+     sprintf(tmpstr,"DATASEQ=%d",frameseq++);
+     strcpy(header+headerpos,tmpstr);
+     headerpos+=strlen(tmpstr)+1;
+     clock=floor(time0);
+     tm=localtime(&clock);
+     sprintf(tmpstr,"AST=%.2d%.3d%.2d%.2d%.2d%.2d",tm->tm_year,tm->tm_yday,tm->tm_hour,tm->tm_min,tm->tm_sec,(int)((time0-floor(time0))*100));
+     strcpy(header+headerpos,tmpstr);
+     headerpos+=strlen(tmpstr)+1;
+     if (!((frameseq-1)%5)) {
+       sprintf(telstr,"TELSTR=%.2d%.3d%.2d%.2d%.2d 0.0 0.0 15.0",tm->tm_year,tm->tm_yday,tm->tm_hour,tm->tm_min+(tm->tm_sec>57),(tm->tm_sec+2)%60);
+     }
+     strcpy(header+headerpos,telstr);
+     headerpos+=strlen(telstr)+1;
+     strcpy(header+headerpos,"RECEIVER=ao1420");
+     headerpos+=strlen("RECEIVER=ao1420")+1;
+     strcpy(header+headerpos,"SAMPLERATE=2.5000");
+     headerpos+=strlen("SAMPLERATE=2.5000")+1;
+     strcpy(header+headerpos,"VER=1.00");
+     headerpos+=strlen("VER=1.00")+1;
+     strcpy(header+headerpos,"CENTERFREQ=1420.0");
+     headerpos+=strlen("CENTERFREQ=1420.0")+1;
+     strcpy(header+headerpos,"NUMRINGBUFS=4");
+     headerpos+=strlen("NUMRINGBUFS=4")+1;
+     strcpy(header+headerpos,"NUMDISKBUFS=2");
+     headerpos+=strlen("NUMDISKBUFS=2")+1;
+     strcpy(header+headerpos,"EOH=");
+     write(stdout->_file, header, HEADER_SIZE);
+     for(i=0;i<FRAME_DATA_SIZE;i++) {
+       if (!((datapos++)%(100/8))) on=!on;
+       data=0xaa*on;
+       write(stdout->_file, &data, 1);
+     }
+     time0+=(1024.0*1024.0*4.0/2.5e6);
+   }
+}  
+
diff --git a/gbt_splitter/tags b/gbt_splitter/tags
new file mode 100644
index 0000000..36fa81d
--- /dev/null
+++ b/gbt_splitter/tags
@@ -0,0 +1,463 @@
+!_TAG_FILE_FORMAT	2	/extended format; --format=1 will not append ;" to lines/
+!_TAG_FILE_SORTED	1	/0=unsorted, 1=sorted, 2=foldcase/
+!_TAG_PROGRAM_AUTHOR	Darren Hiebert	/dhiebert at users.sourceforge.net/
+!_TAG_PROGRAM_NAME	Exuberant Ctags	//
+!_TAG_PROGRAM_URL	http://ctags.sourceforge.net	/official site/
+!_TAG_PROGRAM_VERSION	5.8	//
+ARECIBO_LAT	splitparms.h	53;"	d
+ARECIBO_LON	splitparms.h	54;"	d
+AST	splitparms.h	50;"	d
+AltAzCorrection	coordcvt.cpp	/^void AltAzCorrection(double *alt, double *az) {$/;"	f	namespace:SPLITTER
+COMPLEX	fftw.h	74;"	d
+COORDCVT_H	coordcvt.h	11;"	d
+D2R	coordcvt.cpp	109;"	d	file:
+DB_FNS_H	db_fns.h	8;"	d
+DL_IMPORT	fftw.h	141;"	d
+DL_IMPORT	fftw.h	143;"	d
+DL_IMPORT	fftw.h	145;"	d
+DL_IMPORT	fftw.h	148;"	d
+DTOR	angdist.cpp	16;"	d	file:
+DTOR	mb_angdist.cpp	24;"	d	file:
+EXIT_NORMAL_EOF	mb_splitter.h	/^const int EXIT_NORMAL_EOF       = 0;$/;"	v
+EXIT_NORMAL_NOT_EOF	mb_splitter.h	/^const int EXIT_NORMAL_NOT_EOF   = 2;$/;"	v
+FFTWND_FORCE_BUFFERED	fftw.h	289;"	d
+FFTWND_HAS_PRINT_PLAN	fftw.h	401;"	d
+FFTW_1_0_COMPATIBILITY	fftw.h	68;"	d
+FFTW_BACKWARD	fftw.h	/^     FFTW_FORWARD = -1, FFTW_BACKWARD = 1$/;"	e	enum:__anon2
+FFTW_COMPLEX	fftw.h	/^typedef fftw_complex FFTW_COMPLEX;$/;"	t
+FFTW_ENABLE_FLOAT	fftw.h	40;"	d
+FFTW_ESTIMATE	fftw.h	278;"	d
+FFTW_FAILURE	fftw.h	/^     FFTW_SUCCESS = 0, FFTW_FAILURE = -1$/;"	e	enum:__anon3
+FFTW_FORWARD	fftw.h	/^     FFTW_FORWARD = -1, FFTW_BACKWARD = 1$/;"	e	enum:__anon2
+FFTW_GENERIC	fftw.h	/^     FFTW_NOTW, FFTW_TWIDDLE, FFTW_GENERIC, FFTW_RADER,$/;"	e	enum:fftw_node_type
+FFTW_H	fftw.h	26;"	d
+FFTW_HAS_FPRINT_PLAN	fftw.h	335;"	d
+FFTW_HAS_PLAN_SPECIFIC	fftw.h	295;"	d
+FFTW_HAS_WISDOM	fftw.h	322;"	d
+FFTW_HC2HC	fftw.h	/^     FFTW_REAL2HC, FFTW_HC2REAL, FFTW_HC2HC, FFTW_RGENERIC$/;"	e	enum:fftw_node_type
+FFTW_HC2REAL	fftw.h	/^     FFTW_REAL2HC, FFTW_HC2REAL, FFTW_HC2HC, FFTW_RGENERIC$/;"	e	enum:fftw_node_type
+FFTW_IN_PLACE	fftw.h	282;"	d
+FFTW_MEASURE	fftw.h	279;"	d
+FFTW_NOTW	fftw.h	/^     FFTW_NOTW, FFTW_TWIDDLE, FFTW_GENERIC, FFTW_RADER,$/;"	e	enum:fftw_node_type
+FFTW_OUT_OF_PLACE	fftw.h	281;"	d
+FFTW_RADER	fftw.h	/^     FFTW_NOTW, FFTW_TWIDDLE, FFTW_GENERIC, FFTW_RADER,$/;"	e	enum:fftw_node_type
+FFTW_REAL	fftw.h	/^typedef fftw_real FFTW_REAL;$/;"	t
+FFTW_REAL2HC	fftw.h	/^     FFTW_REAL2HC, FFTW_HC2REAL, FFTW_HC2HC, FFTW_RGENERIC$/;"	e	enum:fftw_node_type
+FFTW_RGENERIC	fftw.h	/^     FFTW_REAL2HC, FFTW_HC2REAL, FFTW_HC2HC, FFTW_RGENERIC$/;"	e	enum:fftw_node_type
+FFTW_SUCCESS	fftw.h	/^     FFTW_SUCCESS = 0, FFTW_FAILURE = -1$/;"	e	enum:__anon3
+FFTW_THREADSAFE	fftw.h	285;"	d
+FFTW_TWIDDLE	fftw.h	/^     FFTW_NOTW, FFTW_TWIDDLE, FFTW_GENERIC, FFTW_RADER,$/;"	e	enum:fftw_node_type
+FFTW_USE_WISDOM	fftw.h	283;"	d
+FFT_LEN	splitparms.h	27;"	d
+FILESIZE	randomdata.cpp	12;"	d	file:
+FILESIZE	squarewave.cpp	12;"	d	file:
+FRAME_DATA_SIZE	randomdata.cpp	10;"	d	file:
+FRAME_DATA_SIZE	squarewave.cpp	10;"	d	file:
+HANNING	polyphase.h	3;"	d
+HEADER_SIZE	randomdata.cpp	11;"	d	file:
+HEADER_SIZE	squarewave.cpp	11;"	d	file:
+IFFT_LEN	splitparms.h	28;"	d
+MAKEBUFS_H	makebufs.h	11;"	d
+MAX	mb_splitter.h	16;"	d
+MAX	splitter.h	16;"	d
+MAX_POSITION_HISTORY	splitparms.h	23;"	d
+MAX_WUS_ONDISK	splitparms.h	17;"	d
+MIN	mb_splitter.h	17;"	d
+MIN	splitter.h	17;"	d
+NBYTES	splitparms.h	21;"	d
+NONE	polyphase.h	1;"	d
+NSAMPLES	splitparms.h	22;"	d
+NSTRIPS	splitparms.h	29;"	d
+NUM_FRAMES	randomdata.cpp	9;"	d	file:
+NUM_FRAMES	squarewave.cpp	9;"	d	file:
+N_SIMULT_SPLITTERS	splitparms.h	18;"	d
+N_WINDOWS	polyphase.h	5;"	d
+P_FFT_LEN	polyphase.h	6;"	d
+READTAPE_H	readtape.h	10;"	d
+REAL	fftw.h	73;"	d
+RECORDER_BUFFER_BYTES	splitparms.h	44;"	d
+RECORDER_BUFFER_SAMPLES	splitparms.h	45;"	d
+SAMPLES_PER_OBUF	dotransform.cpp	32;"	d	file:
+SAMPLES_PER_OBUF	dotransform.h	17;"	d
+SAMPLES_PER_OBUF	mb_dotransform.cpp	30;"	d	file:
+SAMPLES_PER_OBUF	mb_dotransform.h	15;"	d
+SAMPLES_PER_OBUF	mb_polyphase.cpp	26;"	d	file:
+SAMPLES_PER_OBUF	polyphase.cpp	25;"	d	file:
+SAMPLES_PER_OBUF	polyphase.h	14;"	d
+SPLITPARMS_H	splitparms.h	10;"	d
+SPLITTER	coordcvt.cpp	/^namespace SPLITTER {$/;"	n	file:
+SPLITTER_H	mb_splitter.h	11;"	d
+SPLITTER_H	splitter.h	11;"	d
+SPLITTER_VERSION	splitparms.h	16;"	d
+SPLITTYPES_H	mb_splittypes.h	10;"	d
+SPLITTYPES_H	splittypes.h	10;"	d
+SWAP	four1.cpp	11;"	d	file:
+SWAP	four1.cpp	57;"	d	file:
+TAPE_BUFFER_SIZE	splitparms.h	37;"	d
+TAPE_DATA_SIZE	splitparms.h	33;"	d
+TAPE_FRAMES_IN_BUFFER	splitparms.h	39;"	d
+TAPE_FRAMES_PER_RECORD	splitparms.h	34;"	d
+TAPE_FRAMES_PER_WU	splitparms.h	40;"	d
+TAPE_FRAME_SIZE	splitparms.h	35;"	d
+TAPE_HEADER_SIZE	splitparms.h	32;"	d
+TAPE_RECORDS_IN_BUFFER	splitparms.h	38;"	d
+TAPE_RECORD_SIZE	splitparms.h	36;"	d
+TBUF_OFFSET	dotransform.cpp	108;"	d	file:
+TBUF_OFFSET	dotransform.h	18;"	d
+TBUF_OFFSET	mb_dotransform.h	16;"	d
+TBUF_OFFSET	mb_polyphase.cpp	97;"	d	file:
+TBUF_OFFSET	polyphase.cpp	96;"	d	file:
+TBUF_OFFSET	polyphase.h	15;"	d
+USE_MYSQL	mb_splitter.cpp	10;"	d	file:
+USE_MYSQL	mb_wufiles.cpp	10;"	d	file:
+USE_MYSQL	readtape.cpp	10;"	d	file:
+USE_MYSQL	splitter.cpp	10;"	d	file:
+USE_MYSQL	wufiles.cpp	10;"	d	file:
+UTC	splitparms.h	49;"	d
+WELCH	polyphase.h	2;"	d
+WU_FILESIZE	splitparms.h	24;"	d
+WU_OVERLAP_BYTES	splitparms.h	43;"	d
+WU_OVERLAP_FRAMES	splitparms.h	42;"	d
+WU_OVERLAP_RECORDS	splitparms.h	41;"	d
+WU_SUBDIR	splitparms.h	14;"	d
+alfa	mb_splitter.cpp	/^int alfa;$/;"	v
+angdist	angdist.cpp	/^double angdist(const SCOPE_STRING &a, const SCOPE_STRING &b) {$/;"	f
+angdist	angdist.cpp	/^double angdist(double r1, double d1, double r2, double d2) {$/;"	f
+angdist	mb_angdist.cpp	/^double angdist(const coordinate_t &a, const coordinate_t &b) {$/;"	f
+angdist	mb_angdist.cpp	/^double angdist(double r1, double d1, double r2, double d2) {$/;"	f
+app	mb_splitter.cpp	/^DB_APP app;$/;"	v
+app	splitter.cpp	/^DB_APP app;$/;"	v
+atnight	mb_splitter.cpp	/^int atnight;$/;"	v
+atnight	splitter.cpp	/^int atnight;$/;"	v
+beam	mb_splitter.cpp	/^int beam;$/;"	v
+bin_data	mb_wufiles.cpp	/^std::vector<std::vector<unsigned char> > bin_data;$/;"	v
+bin_data	wufiles.cpp	/^static std::vector<unsigned char> bin_data[NSTRIPS];$/;"	v	file:
+boinc_config	mb_splitter.cpp	/^SCHED_CONFIG boinc_config;$/;"	v
+boinc_config	splitter.cpp	/^SCHED_CONFIG boinc_config;$/;"	v
+buffer_pos	mb_splittypes.h	/^typedef struct buffer_pos {$/;"	s
+buffer_pos	splittypes.h	/^typedef struct buffer_pos {$/;"	s
+buffer_pos_t	mb_splittypes.h	/^} buffer_pos_t;$/;"	t	typeref:struct:buffer_pos
+buffer_pos_t	splittypes.h	/^} buffer_pos_t;$/;"	t	typeref:struct:buffer_pos
+byte	splittypes.h	/^  long byte;$/;"	m	struct:buffer_pos
+c_im	fftw.h	57;"	d
+c_re	fftw.h	56;"	d
+cdesc	fftw.h	/^     const fftw_codelet_desc *cdesc;$/;"	m	struct:fftw_twiddle_struct
+cdesc	fftw.h	/^     fftw_codelet_desc *cdesc;$/;"	m	struct:fftw_rader_data_struct
+centerfreq	mb_splittypes.h	/^  double centerfreq,samplerate;$/;"	m	struct:tapeheader
+centerfreq	splittypes.h	/^  double centerfreq,samplerate;$/;"	m	struct:tapeheader
+check_for_halt	mb_splitter.cpp	/^int check_for_halt() {$/;"	f
+check_for_halt	splitter.cpp	/^int check_for_halt() {$/;"	f
+check_free_disk_space	mb_splitter.cpp	/^int check_free_disk_space() {$/;"	f
+check_free_disk_space	splitter.cpp	/^int check_free_disk_space() {$/;"	f
+cleanup	mb_splitter.cpp	/^void cleanup(void) {$/;"	f
+cleanup	splitter.cpp	/^void cleanup(void) {$/;"	f
+cmap_interp	cmap_interp.cpp	/^coordinate_t cmap_interp(std::map<seti_time,coordinate_t> &map, seti_time &t) {$/;"	f
+codelet	fftw.h	/^	       fftw_generic_codelet *codelet;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon8
+codelet	fftw.h	/^	       fftw_hc2hc_codelet *codelet;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon12
+codelet	fftw.h	/^	       fftw_hc2real_codelet *codelet;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon11
+codelet	fftw.h	/^	       fftw_notw_codelet *codelet;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon6
+codelet	fftw.h	/^	       fftw_rader_codelet *codelet;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon9
+codelet	fftw.h	/^	       fftw_real2hc_codelet *codelet;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon10
+codelet	fftw.h	/^	       fftw_rgeneric_codelet *codelet;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon13
+codelet	fftw.h	/^	       fftw_twiddle_codelet *codelet;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon7
+codelet	fftw.h	/^     void (*codelet) ();	\/* pointer to the codelet itself *\/$/;"	m	struct:__anon4
+codelet_desc	fftw.h	/^	       const fftw_codelet_desc *codelet_desc;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon10
+codelet_desc	fftw.h	/^	       const fftw_codelet_desc *codelet_desc;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon11
+codelet_desc	fftw.h	/^	       const fftw_codelet_desc *codelet_desc;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon12
+codelet_desc	fftw.h	/^	       const fftw_codelet_desc *codelet_desc;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon6
+codelet_desc	fftw.h	/^	       const fftw_codelet_desc *codelet_desc;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon7
+coord_history	mb_splitter.cpp	/^std::map<seti_time,coordinate_t> coord_history;$/;"	v
+cost	fftw.h	/^     double cost;$/;"	m	struct:fftw_plan_struct
+cprint	mb_splitter.cpp	/^void cprint(char *p) {$/;"	f
+cprint	splitter.cpp	/^void cprint(char *p) {$/;"	f
+current_record	readtape.cpp	/^int current_record;$/;"	v
+databuf	dotransform.cpp	/^float databuf[FFT_LEN*2];$/;"	v
+dataclass	mb_splitter.cpp	/^int dataclass;$/;"	v
+dataclass	splitter.cpp	/^int dataclass;$/;"	v
+dataseq	mb_splittypes.h	/^  unsigned long dataseq;$/;"	m	struct:tapeheader
+dataseq	splittypes.h	/^  unsigned long dataseq;$/;"	m	struct:tapeheader
+daynames	writeheader.cpp	/^char *daynames[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};$/;"	v
+delbuffer	makebufs.cpp	/^void delbuffer(void) {$/;"	f
+delbuffer_sig	makebufs.cpp	/^void delbuffer_sig(int i) {$/;"	f
+dir	fftw.h	/^	       fftw_direction dir;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon12
+dir	fftw.h	/^	       fftw_direction dir;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon13
+dir	fftw.h	/^     fftw_direction dir;	\/* direction *\/$/;"	m	struct:__anon4
+dir	fftw.h	/^     fftw_direction dir;$/;"	m	struct:__anon14
+dir	fftw.h	/^     fftw_direction dir;$/;"	m	struct:fftw_plan_struct
+do_polyphase	mb_polyphase.cpp	/^void do_polyphase(buffer_pos_t *start_of_wu, buffer_pos_t *end_of_wu) {$/;"	f
+do_polyphase	polyphase.cpp	/^void do_polyphase(buffer_pos_t *start_of_wu, buffer_pos_t *end_of_wu) {$/;"	f
+do_transform	dotransform.cpp	/^void do_transform(buffer_pos_t *start_of_wu, buffer_pos_t *end_of_wu) {$/;"	f
+do_transform	mb_dotransform.cpp	/^void do_transform(std::vector<dr2_compact_block_t> &tapebuffer) {$/;"	f
+end_of_wu	mb_splitter.cpp	/^buffer_pos_t start_of_wu,end_of_wu;  \/* position of start and end of wu in$/;"	v
+end_of_wu	splitter.cpp	/^buffer_pos_t start_of_wu,end_of_wu;  \/* position of start and end of wu in$/;"	v
+errorlog	mb_splitter.cpp	/^FILE *wulog,*errorlog;$/;"	v
+errorlog	splitter.cpp	/^FILE *wulog,*errorlog;$/;"	v
+f_data	mb_polyphase.cpp	/^float *f_data;$/;"	v
+f_data	polyphase.cpp	/^float *f_data;$/;"	v
+fftw_codelet_desc	fftw.h	/^} fftw_codelet_desc;$/;"	t	typeref:struct:__anon4
+fftw_complex	fftw.h	/^} fftw_complex;$/;"	t	typeref:struct:__anon1
+fftw_die_type_function	fftw.h	/^typedef void  (*fftw_die_type_function) (const char *errString);$/;"	t
+fftw_direction	fftw.h	/^} fftw_direction;$/;"	t	typeref:enum:__anon2
+fftw_free_type_function	fftw.h	/^typedef void  (*fftw_free_type_function) (void *p);$/;"	t
+fftw_generic_codelet	fftw.h	/^typedef void (fftw_generic_codelet) $/;"	t
+fftw_hc2hc_codelet	fftw.h	/^typedef void (fftw_hc2hc_codelet)$/;"	t
+fftw_hc2real_codelet	fftw.h	/^typedef void (fftw_hc2real_codelet)$/;"	t
+fftw_malloc_type_function	fftw.h	/^typedef void *(*fftw_malloc_type_function) (size_t n);$/;"	t
+fftw_node_type	fftw.h	/^enum fftw_node_type {$/;"	g
+fftw_notw_codelet	fftw.h	/^typedef void (fftw_notw_codelet) $/;"	t
+fftw_plan	fftw.h	/^typedef struct fftw_plan_struct *fftw_plan;$/;"	t	typeref:struct:fftw_plan_struct
+fftw_plan_node	fftw.h	/^} fftw_plan_node;$/;"	t	typeref:struct:fftw_plan_node_struct
+fftw_plan_node_struct	fftw.h	/^typedef struct fftw_plan_node_struct {$/;"	s
+fftw_plan_struct	fftw.h	/^struct fftw_plan_struct {$/;"	s
+fftw_rader_codelet	fftw.h	/^typedef void (fftw_rader_codelet) $/;"	t
+fftw_rader_data	fftw.h	/^} fftw_rader_data;$/;"	t	typeref:struct:fftw_rader_data_struct
+fftw_rader_data_struct	fftw.h	/^typedef struct fftw_rader_data_struct {$/;"	s
+fftw_real	fftw.h	/^typedef double fftw_real;$/;"	t
+fftw_real	fftw.h	/^typedef float fftw_real;$/;"	t
+fftw_real2hc_codelet	fftw.h	/^typedef void (fftw_real2hc_codelet)$/;"	t
+fftw_rgeneric_codelet	fftw.h	/^typedef void (fftw_rgeneric_codelet)$/;"	t
+fftw_status	fftw.h	/^} fftw_status;$/;"	t	typeref:enum:__anon3
+fftw_twiddle	fftw.h	/^} fftw_twiddle;$/;"	t	typeref:struct:fftw_twiddle_struct
+fftw_twiddle_codelet	fftw.h	/^typedef void (fftw_twiddle_codelet)$/;"	t
+fftw_twiddle_struct	fftw.h	/^typedef struct fftw_twiddle_struct {$/;"	s
+fftwnd_data	fftw.h	/^} fftwnd_data;$/;"	t	typeref:struct:__anon14
+fftwnd_plan	fftw.h	/^typedef fftwnd_data *fftwnd_plan;$/;"	t
+filecopy	mb_wufiles.cpp	/^int filecopy(char *oldname,char *newname) {$/;"	f
+filecopy	wufiles.cpp	/^int filecopy(char *oldname,char *newname) {$/;"	f
+fill_tape_buffer	readtape.cpp	/^int fill_tape_buffer(unsigned char *buffer, int n_records) {$/;"	f
+filter_i	mb_polyphase.cpp	/^double *filter_r, *filter_i;$/;"	v
+filter_i	polyphase.cpp	/^double *filter_r, *filter_i;$/;"	v
+filter_r	mb_polyphase.cpp	/^double *filter_r, *filter_i;$/;"	v
+filter_r	polyphase.cpp	/^double *filter_r, *filter_i;$/;"	v
+filter_window	mb_splitter.cpp	/^int filter_window = 0;$/;"	v
+filter_window	splitter.cpp	/^int filter_window = 0;$/;"	v
+flags	fftw.h	/^     int flags;$/;"	m	struct:fftw_plan_struct
+flags	fftw.h	/^     int p, flags, refcount;$/;"	m	struct:fftw_rader_data_struct
+four1	four1.cpp	/^void four1(float data[], unsigned long nn, int isign) {$/;"	f
+frame	mb_splittypes.h	/^  int frame;$/;"	m	struct:buffer_pos
+frame	splittypes.h	/^  int frame;$/;"	m	struct:buffer_pos
+frameseq	mb_splittypes.h	/^  unsigned long frameseq;$/;"	m	struct:tapeheader
+frameseq	splittypes.h	/^  unsigned long frameseq;$/;"	m	struct:tapeheader
+g	fftw.h	/^     int g, ginv;$/;"	m	struct:fftw_rader_data_struct
+generic	fftw.h	/^	  } generic;$/;"	m	union:fftw_plan_node_struct::__anon5	typeref:struct:fftw_plan_node_struct::__anon5::__anon8
+get_last_block	db_fns.cpp	/^int get_last_block(tapeheader_t *tapeheader) {$/;"	f
+ginv	fftw.h	/^     int g, ginv;$/;"	m	struct:fftw_rader_data_struct
+gregorian	mb_splitter.cpp	/^int gregorian;$/;"	v
+gregorian	splitter.cpp	/^int gregorian;$/;"	v
+hc2hc	fftw.h	/^	  } hc2hc;$/;"	m	union:fftw_plan_node_struct::__anon5	typeref:struct:fftw_plan_node_struct::__anon5::__anon12
+hc2real	fftw.h	/^	  } hc2real;$/;"	m	union:fftw_plan_node_struct::__anon5	typeref:struct:fftw_plan_node_struct::__anon5::__anon11
+header	randomdata.cpp	/^char header[HEADER_SIZE];$/;"	v
+header	squarewave.cpp	/^char header[HEADER_SIZE];$/;"	v
+horz_to_equatorial	coordcvt.cpp	/^void horz_to_equatorial(double alt, double azimuth, double lsthour,$/;"	f	namespace:SPLITTER
+hr_min_sec	hr_min_sec.cpp	/^char* hr_min_sec (double x) {$/;"	f
+im	fftw.h	/^     fftw_real re, im;$/;"	m	struct:__anon1
+is_in_place	fftw.h	/^     int is_in_place;		\/* 1 if for in-place FFTs, 0 otherwise *\/$/;"	m	struct:__anon14
+is_tape	readtape.cpp	/^int is_tape;$/;"	v
+iters	mb_splitter.cpp	/^int iters=-1;$/;"	v
+iters	splitter.cpp	/^int iters=-1;$/;"	v
+jd_to_lmst	coordcvt.cpp	/^double jd_to_lmst(double jd, double longitude) {$/;"	f	namespace:SPLITTER
+key	mb_splitter.cpp	/^R_RSA_PRIVATE_KEY key;$/;"	v
+key	splitter.cpp	/^R_RSA_PRIVATE_KEY key;$/;"	v
+main	mb_splitter.cpp	/^int main(int argc, char *argv[]) {$/;"	f
+main	randomdata.cpp	/^int main(void) {$/;"	f
+main	splitter.cpp	/^int main(int argc, char *argv[]) {$/;"	f
+main	squarewave.cpp	/^int main(void) {$/;"	f
+make_FIR	mb_polyphase.cpp	/^void make_FIR (int n_points, int M, int window, double *output) {$/;"	f
+make_FIR	polyphase.cpp	/^void make_FIR (int n_points, int M, int window, double *output) {$/;"	f
+make_wu_headers	mb_wufiles.cpp	/^int make_wu_headers(std::vector<dr2_compact_block_t> &tapebuffer, telescope_id$/;"	f
+make_wu_headers	wufiles.cpp	/^int make_wu_headers(tapeheader_t tapeheader[],workunit wuheader[],$/;"	f
+makebuffers	makebufs.cpp	/^void makebuffers(unsigned char **tapebuffer) {$/;"	f
+max_wus_ondisk	mb_splitter.cpp	/^int max_wus_ondisk=MAX_WUS_ONDISK;$/;"	v
+max_wus_ondisk	splitter.cpp	/^int max_wus_ondisk=MAX_WUS_ONDISK;$/;"	v
+message	mb_message.cpp	/^void message(char *msg) {$/;"	f
+message	message.cpp	/^void message(char *msg) {$/;"	f
+minvfsbuf	mb_splitter.cpp	/^unsigned long minvfsbuf=-1;$/;"	v
+minvfsbuf	splitter.cpp	/^unsigned long minvfsbuf=-1;$/;"	v
+missed	mb_splittypes.h	/^  int missed;$/;"	m	struct:tapeheader
+missed	splittypes.h	/^  int missed;$/;"	m	struct:tapeheader
+monthnames	writeheader.cpp	/^char *monthnames[]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep"$/;"	v
+n	fftw.h	/^     int *n;			\/*$/;"	m	struct:__anon14
+n	fftw.h	/^     int n;$/;"	m	struct:fftw_plan_struct
+n	fftw.h	/^     int n;$/;"	m	struct:fftw_twiddle_struct
+n_after	fftw.h	/^     int *n_after;		\/* n_after[i] = product of n[j] for j > i *\/$/;"	m	struct:__anon14
+n_before	fftw.h	/^     int *n_before;		\/*$/;"	m	struct:__anon14
+name	fftw.h	/^     const char *name;		\/* name of the codelet *\/$/;"	m	struct:__anon4
+name	mb_splittypes.h	/^  char name[36];$/;"	m	struct:tapeheader
+name	splittypes.h	/^  char name[36];$/;"	m	struct:tapeheader
+nbuffers	fftw.h	/^     int nbuffers, nwork;$/;"	m	struct:__anon14
+next	fftw.h	/^     struct fftw_plan_struct *next;$/;"	m	struct:fftw_plan_struct	typeref:struct:fftw_plan_struct::fftw_plan_struct
+next	fftw.h	/^     struct fftw_rader_data_struct *next;$/;"	m	struct:fftw_rader_data_struct	typeref:struct:fftw_rader_data_struct::fftw_rader_data_struct
+next	fftw.h	/^     struct fftw_twiddle_struct *next;$/;"	m	struct:fftw_twiddle_struct	typeref:struct:fftw_twiddle_struct::fftw_twiddle_struct
+nodb	mb_splitter.cpp	/^int nodb;$/;"	v
+nodb	splitter.cpp	/^int nodb;$/;"	v
+nodeu	fftw.h	/^     } nodeu;$/;"	m	struct:fftw_plan_node_struct	typeref:union:fftw_plan_node_struct::__anon5
+noencode	mb_splitter.cpp	/^int noencode;$/;"	v
+noencode	splitter.cpp	/^int noencode;$/;"	v
+norewind	mb_splitter.cpp	/^int norewind;$/;"	v
+norewind	splitter.cpp	/^int norewind;$/;"	v
+notw	fftw.h	/^	  } notw;$/;"	m	union:fftw_plan_node_struct::__anon5	typeref:struct:fftw_plan_node_struct::__anon5::__anon6
+ntwiddle	fftw.h	/^     int ntwiddle;		\/* number of twiddle factors *\/$/;"	m	struct:__anon4
+numdiskbufs	mb_splittypes.h	/^  int numdiskbufs;$/;"	m	struct:tapeheader
+numdiskbufs	splittypes.h	/^  int numdiskbufs;$/;"	m	struct:tapeheader
+numringbufs	mb_splittypes.h	/^  int numringbufs;$/;"	m	struct:tapeheader
+numringbufs	splittypes.h	/^  int numringbufs;$/;"	m	struct:tapeheader
+nwork	fftw.h	/^     int nbuffers, nwork;$/;"	m	struct:__anon14
+obuf_pos	dotransform.cpp	/^int obuf_pos; \/* Tracks current postition in the output buffers *\/$/;"	v
+obuf_pos	mb_dotransform.cpp	/^int obuf_pos; \/* Tracks current postition in the output buffers *\/$/;"	v
+offset	mb_splittypes.h	/^  long offset;$/;"	m	struct:buffer_pos
+omega	fftw.h	/^     fftw_complex *omega;$/;"	m	struct:fftw_rader_data_struct
+open_tape_device	readtape.cpp	/^int open_tape_device(char *device) {$/;"	f
+output_buf	dotransform.cpp	/^unsigned char output_buf[NSTRIPS][SAMPLES_PER_OBUF];  $/;"	v
+output_samples	dotransform.cpp	/^void output_samples(float *data, int i, int buf_pos) {$/;"	f
+output_samples	mb_dotransform.cpp	/^void output_samples(float *data, int i, int buf_pos) {$/;"	f
+output_xml	mb_splitter.cpp	/^int output_xml;$/;"	v
+output_xml	splitter.cpp	/^int output_xml;$/;"	v
+p	fftw.h	/^     int p, flags, refcount;$/;"	m	struct:fftw_rader_data_struct
+parse_tape_headers	readheader.cpp	/^int parse_tape_headers(unsigned char *tapebuffer, tapeheader_t *tapeheaders) {$/;"	f
+plan	fftw.h	/^     struct fftw_plan_struct *plan;$/;"	m	struct:fftw_rader_data_struct	typeref:struct:fftw_rader_data_struct::fftw_plan_struct
+plans	fftw.h	/^     fftw_plan *plans;		\/* 1d fftw plans for each dimension *\/$/;"	m	struct:__anon14
+pol	mb_splitter.cpp	/^int pol;$/;"	v
+polyphase	mb_splitter.cpp	/^int polyphase;$/;"	v
+polyphase	splitter.cpp	/^int polyphase;$/;"	v
+polyphase_seg	mb_polyphase.cpp	/^void polyphase_seg(float* data) {$/;"	f
+polyphase_seg	polyphase.cpp	/^void polyphase_seg(float* data) {$/;"	f
+process_command_line	mb_splitter.cpp	/^int process_command_line(int argc, char *argv[],char **tape_device,$/;"	f
+process_command_line	splitter.cpp	/^int process_command_line(int argc, char *argv[],char **tape_device,$/;"	f
+process_seg	dotransform.cpp	/^void process_seg(float* data) {$/;"	f
+process_seg	mb_dotransform.cpp	/^void process_seg(std::vector<complex<signed char> > &data,int offset) {$/;"	f
+projectdir	mb_splitter.cpp	/^char * projectdir = NULL;$/;"	v
+projectdir	splitter.cpp	/^char * projectdir = NULL;$/;"	v
+rader	fftw.h	/^	  } rader;$/;"	m	union:fftw_plan_node_struct::__anon5	typeref:struct:fftw_plan_node_struct::__anon5::__anon9
+rader_data	fftw.h	/^	       fftw_rader_data *rader_data;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon9
+randn	mb_dotransform.cpp	/^float randn() {$/;"	f
+randu	mb_dotransform.cpp	/^float randu() {$/;"	f
+rank	fftw.h	/^     int rank;			\/* $/;"	m	struct:__anon14
+rcdtype	mb_splittypes.h	/^  int rcdtype;$/;"	m	struct:tapeheader
+rcdtype	splittypes.h	/^  int rcdtype;$/;"	m	struct:tapeheader
+rcvr	mb_splitter.cpp	/^receiver_config rcvr;$/;"	v
+re	fftw.h	/^     fftw_real re, im;$/;"	m	struct:__anon1
+read_checkpoint	readtape.cpp	/^int read_checkpoint() {$/;"	f
+read_tape_header	readheader.cpp	/^int read_tape_header(char *buffer, tapeheader_t *header)$/;"	f
+real2hc	fftw.h	/^	  } real2hc;$/;"	m	union:fftw_plan_node_struct::__anon5	typeref:struct:fftw_plan_node_struct::__anon5::__anon10
+records_in_buffer	splitter.cpp	/^int records_in_buffer;$/;"	v
+recurse	fftw.h	/^	       struct fftw_plan_node_struct *recurse;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon12	typeref:struct:fftw_plan_node_struct::__anon5::__anon12::fftw_plan_node_struct
+recurse	fftw.h	/^	       struct fftw_plan_node_struct *recurse;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon13	typeref:struct:fftw_plan_node_struct::__anon5::__anon13::fftw_plan_node_struct
+recurse	fftw.h	/^	       struct fftw_plan_node_struct *recurse;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon7	typeref:struct:fftw_plan_node_struct::__anon5::__anon7::fftw_plan_node_struct
+recurse	fftw.h	/^	       struct fftw_plan_node_struct *recurse;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon8	typeref:struct:fftw_plan_node_struct::__anon5::__anon8::fftw_plan_node_struct
+recurse	fftw.h	/^	       struct fftw_plan_node_struct *recurse;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon9	typeref:struct:fftw_plan_node_struct::__anon5::__anon9::fftw_plan_node_struct
+refcnt	fftw.h	/^     int refcnt;$/;"	m	struct:fftw_plan_node_struct
+refcnt	fftw.h	/^     int refcnt;$/;"	m	struct:fftw_plan_struct
+refcnt	fftw.h	/^     int refcnt;$/;"	m	struct:fftw_twiddle_struct
+refcount	fftw.h	/^     int p, flags, refcount;$/;"	m	struct:fftw_rader_data_struct
+rename_wu_files	mb_wufiles.cpp	/^void rename_wu_files() {$/;"	f
+rename_wu_files	wufiles.cpp	/^void rename_wu_files() {$/;"	f
+result_template	mb_splitter.cpp	/^const char *result_template=$/;"	v
+result_template	splitter.cpp	/^const char *result_template=$/;"	v
+result_template_filename	mb_splitter.cpp	/^char result_template_filename[1024];$/;"	v
+result_template_filename	splitter.cpp	/^char result_template_filename[1024];$/;"	v
+result_template_filename_id	mb_splitter.cpp	/^const char *result_template_filename_id = "result_0.xml";$/;"	v
+result_template_filename_id	splitter.cpp	/^const char *result_template_filename_id = "result_0.xml";$/;"	v
+result_template_filepath	mb_splitter.cpp	/^char result_template_filepath[1024];$/;"	v
+result_template_filepath	splitter.cpp	/^char result_template_filepath[1024];$/;"	v
+resumetape	mb_splitter.cpp	/^int resumetape;$/;"	v
+resumetape	splitter.cpp	/^int resumetape;$/;"	v
+rgeneric	fftw.h	/^	  } rgeneric;$/;"	m	union:fftw_plan_node_struct::__anon5	typeref:struct:fftw_plan_node_struct::__anon5::__anon13
+root	fftw.h	/^     fftw_plan_node *root;$/;"	m	struct:fftw_plan_struct
+sah_config	mb_splitter.cpp	/^APP_CONFIG sah_config;$/;"	v
+sah_config	splitter.cpp	/^APP_CONFIG sah_config;$/;"	v
+samplerate	mb_splittypes.h	/^  double centerfreq,samplerate;$/;"	m	struct:tapeheader
+samplerate	splittypes.h	/^  double centerfreq,samplerate;$/;"	m	struct:tapeheader
+select_record	readtape.cpp	/^int select_record(int record_number) {$/;"	f
+seqno	mb_splitter.cpp	/^int seqno;$/;"	v
+seqno	splitter.cpp	/^int seqno;$/;"	v
+signature	fftw.h	/^     int signature;		\/* unique id *\/$/;"	m	struct:__anon4
+size	fftw.h	/^	       int size;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon10
+size	fftw.h	/^	       int size;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon11
+size	fftw.h	/^	       int size;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon12
+size	fftw.h	/^	       int size;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon13
+size	fftw.h	/^	       int size;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon6
+size	fftw.h	/^	       int size;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon7
+size	fftw.h	/^	       int size;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon8
+size	fftw.h	/^	       int size;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon9
+size	fftw.h	/^     int size;			\/* size of the codelet *\/$/;"	m	struct:__anon4
+source	mb_splittypes.h	/^  int source;$/;"	m	struct:tapeheader
+source	splittypes.h	/^  int source;$/;"	m	struct:tapeheader
+splitter_bits_to_float	dotransform.cpp	/^void splitter_bits_to_float(unsigned short *raw, float *data, int nsamples) {$/;"	f
+splitter_bits_to_float	mb_dotransform.cpp	/^void splitter_bits_to_float(unsigned short *raw, float *data, int nsamples) {$/;"	f
+splitter_encode	encode.cpp	/^void splitter_encode(unsigned char *bin, int nbytes, FILE *f) {$/;"	f
+splitter_settings	mb_splitter.cpp	/^settings splitter_settings;$/;"	v
+st	mb_splittypes.h	/^  TIME st;$/;"	m	struct:tapeheader
+st	splittypes.h	/^  TIME st;$/;"	m	struct:tapeheader
+start_of_wu	mb_splitter.cpp	/^buffer_pos_t start_of_wu,end_of_wu;  \/* position of start and end of wu in$/;"	v
+start_of_wu	splitter.cpp	/^buffer_pos_t start_of_wu,end_of_wu;  \/* position of start and end of wu in$/;"	v
+start_time	mb_splitter.cpp	/^double start_time;$/;"	v
+start_time	splitter.cpp	/^double start_time;$/;"	v
+startblock	mb_splitter.cpp	/^int startblock;$/;"	v
+startblock	splitter.cpp	/^int startblock;$/;"	v
+stop_time	mb_splitter.cpp	/^double stop_time;$/;"	v
+stop_time	splitter.cpp	/^double stop_time;$/;"	v
+tape_busy	readtape.cpp	/^int tape_busy() {$/;"	f
+tape_eject	readtape.cpp	/^int tape_eject() {$/;"	f
+tape_fd	readtape.cpp	/^static int tape_fd;$/;"	v	file:
+tape_info	readtape.cpp	/^static tape tape_info;$/;"	v	file:
+tape_read_record	readtape.cpp	/^int tape_read_record(char *buffer) {$/;"	f
+tape_rewind	readtape.cpp	/^int tape_rewind() {$/;"	f
+tape_status	readtape.cpp	/^struct mtget tape_status;$/;"	v	typeref:struct:mtget
+tape_struct	db_fns.cpp	/^static tape tape_struct;$/;"	v	file:
+tapebuffd	makebufs.cpp	/^int tapebuffd;$/;"	v
+tapebuffer	mb_splitter.cpp	/^std::vector<dr2_compact_block_t> tapebuffer;$/;"	v
+tapebuffer	splitter.cpp	/^unsigned char *tapebuffer;     \/* A buffer for a tape section *\/$/;"	v
+tapebufname	makebufs.cpp	/^char tapebufname[30];$/;"	v
+tapeheader	mb_splittypes.h	/^typedef struct tapeheader {$/;"	s
+tapeheader	splittypes.h	/^typedef struct tapeheader {$/;"	s
+tapeheader_t	mb_splittypes.h	/^} tapeheader_t;$/;"	t	typeref:struct:tapeheader
+tapeheader_t	splittypes.h	/^} tapeheader_t;$/;"	t	typeref:struct:tapeheader
+tapeheaders	splitter.cpp	/^tapeheader_t tapeheaders[TAPE_FRAMES_IN_BUFFER];$/;"	v
+telstr	mb_splittypes.h	/^  SCOPE_STRING telstr;$/;"	m	struct:tapeheader
+telstr	splittypes.h	/^  SCOPE_STRING telstr;$/;"	m	struct:tapeheader
+telstr_coord_convert	coordcvt.cpp	/^void telstr_coord_convert(SCOPE_STRING *telstr, double lat, double lon) {$/;"	f
+trigger_file_path	mb_splitter.cpp	/^char trigger_file_path[1024]="\/disks\/setifiler1\/wutape\/tapedir\/splitter_stop";$/;"	v
+trigger_file_path	splitter.cpp	/^char trigger_file_path[1024]="\/disks\/setifiler1\/wutape\/tapedir\/splitter_stop";$/;"	v
+tw	fftw.h	/^	       fftw_twiddle *tw;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon12
+tw	fftw.h	/^	       fftw_twiddle *tw;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon13
+tw	fftw.h	/^	       fftw_twiddle *tw;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon7
+tw	fftw.h	/^	       fftw_twiddle *tw;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon8
+tw	fftw.h	/^	       fftw_twiddle *tw;$/;"	m	struct:fftw_plan_node_struct::__anon5::__anon9
+twarray	fftw.h	/^     fftw_complex *twarray;$/;"	m	struct:fftw_twiddle_struct
+twiddle	fftw.h	/^	  } twiddle;$/;"	m	union:fftw_plan_node_struct::__anon5	typeref:struct:fftw_plan_node_struct::__anon5::__anon7
+twiddle_order	fftw.h	/^     const int *twiddle_order;	\/* $/;"	m	struct:__anon4
+type	fftw.h	/^     enum fftw_node_type type;	\/* TWIDDLE or NO_TWIDDLE *\/$/;"	m	struct:__anon4	typeref:enum:__anon4::fftw_node_type
+type	fftw.h	/^     enum fftw_node_type type;$/;"	m	struct:fftw_plan_node_struct	typeref:enum:fftw_plan_node_struct::fftw_node_type
+update_checkpoint	readtape.cpp	/^static void update_checkpoint() {$/;"	f	file:
+useanalysiscfgid	mb_splitter.cpp	/^int useanalysiscfgid = 0;$/;"	v
+usereceivercfgid	mb_splitter.cpp	/^int usereceivercfgid = 0;$/;"	v
+userecordercfgid	mb_splitter.cpp	/^int userecordercfgid = 0;$/;"	v
+usesplittercfgid	mb_splitter.cpp	/^int usesplittercfgid = 0;$/;"	v
+valid_run	mb_validrun.cpp	/^bool valid_run(std::vector<dr2_compact_block_t> &tapebuffer) {$/;"	f
+valid_run	validrun.cpp	/^int valid_run(tapeheader_t tapeheader[],buffer_pos_t *start_of_wu, $/;"	f
+version	mb_splittypes.h	/^  char version[16];$/;"	m	struct:tapeheader
+version	splittypes.h	/^  char version[16];$/;"	m	struct:tapeheader
+wait_for_db_wus_ondisk	mb_splitter.cpp	/^int wait_for_db_wus_ondisk() {$/;"	f
+wait_for_db_wus_ondisk	splitter.cpp	/^int wait_for_db_wus_ondisk() {$/;"	f
+wait_until_night	mb_splitter.cpp	/^int wait_until_night() {$/;"	f
+wait_until_night	splitter.cpp	/^int wait_until_night() {$/;"	f
+wd	mb_splitter.cpp	/^char wd[1024];$/;"	v
+wd	splitter.cpp	/^char wd[1024];$/;"	v
+wisdom_signature	fftw.h	/^     int wisdom_signature;$/;"	m	struct:fftw_plan_struct
+wisdom_type	fftw.h	/^     enum fftw_node_type wisdom_type;$/;"	m	struct:fftw_plan_struct	typeref:enum:fftw_plan_struct::fftw_node_type
+work	fftw.h	/^     fftw_complex *work;	\/* $/;"	m	struct:__anon14
+write_tape_header	writeheader.cpp	/^int write_tape_header(char *buffer, tapeheader_t *header) {$/;"	f
+write_wufile_blocks	mb_wufiles.cpp	/^void write_wufile_blocks(int nbytes) {$/;"	f
+write_wufile_blocks	wufiles.cpp	/^void write_wufile_blocks(int nbytes) {$/;"	f
+wu_database_id	mb_wufiles.cpp	/^std::vector<long long> wu_database_id;$/;"	v
+wu_database_id	wufiles.cpp	/^int wu_database_id[NSTRIPS];$/;"	v
+wu_template	mb_splitter.cpp	/^const char *wu_template=$/;"	v
+wu_template	splitter.cpp	/^const char *wu_template=$/;"	v
+wu_template_filename	mb_splitter.cpp	/^char wu_template_filename[1024];$/;"	v
+wu_template_filename	splitter.cpp	/^char wu_template_filename[1024];$/;"	v
+wu_template_filename_id	mb_splitter.cpp	/^const char *wu_template_filename_id = "wu_0.xml";$/;"	v
+wu_template_filename_id	splitter.cpp	/^const char *wu_template_filename_id = "wu_0.xml";$/;"	v
+wuheaders	mb_splitter.cpp	/^std::vector<workunit> wuheaders;$/;"	v
+wuheaders	splitter.cpp	/^workunit wuheaders[NSTRIPS];$/;"	v
+wulog	mb_splitter.cpp	/^FILE *wulog,*errorlog;$/;"	v
+wulog	splitter.cpp	/^FILE *wulog,*errorlog;$/;"	v
diff --git a/gbt_splitter/tools/disksplitter b/gbt_splitter/tools/disksplitter
new file mode 100755
index 0000000..a4bc323
--- /dev/null
+++ b/gbt_splitter/tools/disksplitter
@@ -0,0 +1,121 @@
+#! /bin/tcsh -x
+
+set PATH=/opt/misc:/opt/misc/bin:/usr/ccs/bin:/usr/openwin/bin:/usr/openwin/bin/xview:/usr/lang:/usr/ucb:/bin:/usr/bin:/usr/local/bin:/usr/hosts:/usr/bin/X11:/usr/casual/sparc:/usr/etc:/usr/local/lib/tex/bin:/usr/local/lib/frame/bin:/disks/asimov/a/apps/informix/bin:.:/disks/albert/d/office/bin:/usr/ucb:/disks/albert/e/users/eurd/data_analysis/bin:/usr/local/lib/g++-include.bak:/disks/siren/a/users/seti/s4/siren/bin:/disks/albert/d/orfeus:/disks/albert/d/chips:/disks/asimov/a/apps/inform [...]
+# export PATH
+set LD_LIBRARY_PATH=/usr/lib/X11:/usr/openwin/lib:/usr/lib:/lib:/disks/islay/a/users/korpela/bin/lib:/disks/asimov/a/apps/informix/lib:/disks/asimov/a/apps/informix/lib/esql
+# export LD_LIBRARY_PATH
+set INFORMIXDIR=/disks/asimov/a/apps/informix
+# export INFORMIXDIR
+set INFORMIXSERVER=ejk_tcp
+# export INFORMIXSERVER
+
+set SPLIT_PROG_LOC=/disks/milkyway/a/users/anderson/seti/splitter/bin/
+set SPLIT_PROG_NAME=splitter
+set SPLIT_LOG_LOC=/disks/milkyway/a/users/anderson/seti/sethi/hi_tape_logs/
+# set HI_TAPE_DIR=/disks/philmor/a/users/eheien/hitest/
+set SPLIT_TAPE_DIR=/disks/setifiler1/wutape/tapedir/
+set SPLIT_SUFFIX=.split
+set HIDONE_SUFFIX=.hidone
+set SPLITDONE_SUFFIX=.splitdone
+set EMAIL_LIST="jeffc at ssl.berkeley.edu mattl at ssl.berkeley.edu"
+set FOUND_FILE=0
+set HOST=`hostname`
+set SPLIT_HALT_MSG=splitter_stop
+
+# Check to see if this machine is already running the splitter program
+set PROG_RUNNING=`/usr/ucb/ps -auxww | grep "$SPLIT_PROG_NAME" | grep -v "disksplitter" | wc | awk '{print $1}'`
+echo "$PROG_RUNNING"
+if( $PROG_RUNNING > 1 ) then
+  echo "Splitter is already running on this machine.  Quitting."
+  exit
+endif
+
+# Get rid of all .split files here with HOSTNAME in them(?)
+
+while ( ! -f $SPLIT_TAPE_DIR$SPLIT_HALT_MSG )
+
+set FOUND_FILE=0
+cd $SPLIT_TAPE_DIR
+
+set FILE_LIST=`ls . | grep ".tape" | grep -v "done" | grep -v "reading" | grep -v "hi" | grep -v "msg" | grep -v "split"`
+
+if( -z "$FILE_LIST" ) then
+    exit
+endif
+
+foreach file ($FILE_LIST)
+  if ( $FOUND_FILE == 0 && ! -f $file$SPLITDONE_SUFFIX ) then
+      if( -f $file$SPLIT_SUFFIX ) then
+        set FOUND_FILE=0
+      else
+        echo $HOST > $file$SPLIT_SUFFIX
+        set TAPE_FILE=$file
+        set SPLIT_FILE=$SPLIT_TAPE_DIR$file
+        set SPLIT_MARK_FILE=$SPLIT_TAPE_DIR$file$SPLIT_SUFFIX
+        set HI_DONE_FILE=$SPLIT_TAPE_DIR$file$HIDONE_SUFFIX
+        set SPLIT_DONE_FILE=$SPLIT_TAPE_DIR$file$SPLITDONE_SUFFIX
+        set FOUND_FILE=1
+      endif
+  endif
+end
+
+cd /mydisks/a/servers/splitter/
+/bin/rm -f error.log rcd.chk
+touch error.log
+touch rcd.chk
+
+if ( $FOUND_FILE == 0 ) then
+# echo "" | /usr/ucb/mail -s"no more splitter tape files" $EMAIL_LIST
+  exit
+else
+  if( -f /disks/milkyway/a/users/anderson/seti/watchdogs/go_spliiter ) then
+    /bin/rm -f wu_inbox/.*
+#set START_MSG=`echo "Splitter is starting on tape" $SPLIT_FILE "on" $HOST`
+    cat error.log rcd.chk | /usr/ucb/mail -s""$HOST" splitter starting" $EMAIL_LIST
+    /bin/nice $SPLIT_PROG_LOC$SPLIT_PROG_NAME $SPLIT_FILE $1 -resume >>& splitterlog
+    set TEMP=`grep -i "end" error.log`
+    if( "$TEMP" != "" ) then
+        sleep 60 # wait for it to finish moving the files from wu_inbox
+        cat error.log rcd.chk | /usr/ucb/mail -s""$HOST" splitter finished" $EMAIL_LIST
+       /bin/rm -f error.log rcd.chk
+       /bin/rm -f wu_inbox/.*
+       /bin/rm -f $SPLIT_MARK_FILE
+       if( -f $HI_DONE_FILE ) then
+           /bin/rm -f $HI_DONE_FILE
+           /bin/rm -f `cd $SPLIT_TAPE_DIR; ls -l | grep $TAPE_FILE | awk '{print $NF}'`
+           /bin/rm -f $SPLIT_FILE
+       else
+           touch -f $SPLIT_DONE_FILE
+       endif
+    endif
+    /bin/rm -f $SPLIT_MARK_FILE
+    exit
+  else
+    /bin/rm -f $SPLIT_MARK_FILE
+    exit
+  endif
+endif
+
+#if ( 0 == 1 ) then
+# if ( grep -i done hi_log ) then
+#  cat error.log rcd.chk | /usr/ucb/mail -s"end of tape on $HOST" $EMAIL_LIST
+#  touch $HI_FILE$HIDONE_SUFFIX
+#  if ( -f $HI_FILE$HIDONE_SUFFIX ) then
+# unlink $SPLITFILE
+#  fi
+# unlink .$SPLITFILE
+#  /bin/rm error.log rcd.chk
+#  /bin/rm wu_inbox/.*
+# nice -10 $SPLITTER_PROG_LOC $SPLITFILE -resume 2>> splitterlog &
+#else
+#  if [ -f $MARKER$HOST ]
+#  then
+#    /bin/rm wu_inbox/.*
+#    cat error.log rcd.chk | /usr/ucb/mail -s"restarting HI analysis on $HOST" $EMAIL_LIST
+# nice -10 $SPLITTER_PROG_LOC $SPLITFILE -resume 2>> splitterlog &
+#  else
+#    cat error.log rcd.chk | /usr/ucb/mail -s"hi analysis disabled on $HOST" $EMAIL_LIST
+#  fi
+#endif
+end
+
diff --git a/gbt_splitter/tools/sah_splitter.sh b/gbt_splitter/tools/sah_splitter.sh
new file mode 100755
index 0000000..2ff1d34
--- /dev/null
+++ b/gbt_splitter/tools/sah_splitter.sh
@@ -0,0 +1,150 @@
+#! /bin/sh 
+PATH=/opt/misc:/opt/misc/bin:/usr/ccs/bin:/usr/openwin/bin:/usr/openwin/bin/xview:/usr/lang:/usr/ucb:/bin:/usr/bin:/usr/local/bin:/usr/hosts:/usr/bin/X11:/usr/casual/sparc:/usr/etc:/usr/local/lib/tex/bin:/usr/local/lib/frame/bin:/disks/asimov/a/apps/informix/bin:.:/disks/albert/d/office/bin:/usr/ucb:/disks/albert/e/users/eurd/data_analysis/bin:/usr/local/lib/g++-include.bak:/disks/siren/a/users/seti/s4/siren/bin:/disks/albert/d/orfeus:/disks/albert/d/chips:/disks/asimov/a/apps/informix/b [...]
+export PATH
+LD_LIBRARY_PATH=/lib:/disks/asimov/a/apps/informix/lib:/disks/asimov/a/apps/informix/lib/esql::/usr/ucblib:/lib:/usr/lib:/usr/openwin/lib:/usr/ccs/lib:/usr/local/gcc/lib:/disks/asimov/a/lang/gnu/H-sparc-sun-solaris2/lib:/opt/misc/lib:/usr/local/lib:/disks/ellie/a/users/korpela/lib:/usr/dt/lib
+export LD_LIBRARY_PATH
+INFORMIXDIR=/disks/asimov/a/apps/informix/
+export INFORMIXDIR
+INFORMIXSERVER=ejk_tcp
+export INFORMIXSERVER
+S4_RECEIVER_CONFIG=/usr/local/warez/projects/s4/siren/db/ReceiverConfig.tab
+export S4_RECEIVER_CONFIG
+
+PROJECTDIR=/disks/koloth/a/inet_services/boinc_www/share/projects/sah
+SPLIT_PROG_LOC=${PROJECTDIR}/bin/
+SPLIT_PROG_NAME=sah_splitter
+SPLIT_TAPE_DIR=/disks/setifiler1/wutape/tapedir/seti_boinc_public/
+SPLIT_SUFFIX=.split
+#HIDONE_SUFFIX=.hidone
+SPLITDONE_SUFFIX=.splitdone
+EMAIL_LIST="korpela at ssl.berkeley.edu jeffc at ssl.berkeley.edu mattl at ssl.berkeley.edu davea at ssl.berkeley.edu"
+FOUND_FILE=0
+HOST=`hostname`
+SPLIT_HALT_MSG=splitter_stop
+
+# Check to see if this machine is already running the splitter program
+PROG_RUNNING=`/usr/ucb/ps -auxww | grep "$SPLIT_PROG_NAME " | grep -v grep` 
+if [ ! -z  "$PROG_RUNNING" ] 
+then
+  echo "Splitter is already running on this machine.  Quitting."
+  exit 1
+fi
+
+# Get rid of all .split files here with HOSTNAME in them(?)
+
+TAPE_FILE=
+
+# get list of all tapes in the sah classic tape directory
+cd $SPLIT_TAPE_DIR/..
+FILE_LIST=`ls *.tape`
+
+cd $SPLIT_TAPE_DIR
+
+# if no sah classic tapes then bail
+if [ -z "$FILE_LIST" ] 
+then
+    exit 2
+fi
+
+# for each sah classic tape...
+for file in $FILE_LIST
+do
+  # if we have already split it...
+  if [ -f $file$SPLITDONE_SUFFIX ]
+  then
+    #  ... then remove it ("it" being a hard link upward into the sah classic dir)
+    if [ -f $file ]
+    then
+      /bin/rm $file
+    fi
+  else
+    # if we are in the process of splitting it...
+    if [ -f $file$SPLIT_SUFFIX ] 
+    then
+      # and are splitting it from this host...  (this logic prevents one host from repeating another host's tape)
+      if grep $HOST $file$SPLIT_SUFFIX 
+      then
+        # trigger to restart the split
+        /bin/rm $file$SPLIT_SUFFIX
+      fi
+    fi
+    # if a restart or a brand new tape...
+    if [ ! -f $file$SPLIT_SUFFIX ] 
+    then
+      # claim it for this host (there is certainly a race condition here)
+      echo $HOST > $file$SPLIT_SUFFIX
+      ln ../$file
+      TAPE_FILE=$file
+      SPLIT_FILE=$SPLIT_TAPE_DIR$file
+      SPLIT_MARK_FILE=$SPLIT_TAPE_DIR$file$SPLIT_SUFFIX
+#     HI_DONE_FILE=$SPLIT_TAPE_DIR$file$HIDONE_SUFFIX
+      SPLIT_DONE_FILE=$SPLIT_TAPE_DIR$file$SPLITDONE_SUFFIX
+      break
+    fi
+  fi
+done
+
+cd /tmp/splitter/sah
+if [ ! -d splitter ]
+then
+  mkdir splitter
+fi
+cd splitter
+if [ ! -d wu_inbox ]
+then
+  mkdir wu_inbox
+fi
+/bin/rm -f error.log rcd.chk
+touch error.log
+touch rcd.chk
+
+if [ -z "$TAPE_FILE" ]
+then
+  exit 3
+else
+  /bin/rm -f wu_inbox/.*
+  cat error.log rcd.chk | /usr/ucb/mail -s""$HOST" boinc_splitter starting" $EMAIL_LIST
+  /bin/nice $SPLIT_PROG_LOC$SPLIT_PROG_NAME $SPLIT_FILE $* -resume -projectdir=$PROJECTDIR 
+  if grep -i "end" error.log >/dev/null 2>&1
+  then 
+    /bin/nice $SPLIT_PROG_LOC$SPLIT_PROG_NAME $SPLIT_FILE $* -resume -projectdir=$PROJECTDIR
+  fi
+  if grep -i "end" error.log >/dev/null 2>&1
+  then
+    cat error.log rcd.chk | /usr/ucb/mail -s""$HOST" boinc_splitter finished" $EMAIL_LIST
+    /bin/rm -f error.log rcd.chk
+    /bin/rm -f wu_inbox/.*
+    /bin/rm -f $SPLIT_MARK_FILE
+    /bin/rm -f `cd $SPLIT_TAPE_DIR; ls -l | grep $TAPE_FILE | awk '{print $NF}'`
+    /bin/rm -f $SPLIT_FILE
+    touch -f $SPLIT_DONE_FILE
+    exit
+  else 
+    /bin/rm -f $SPLIT_MARK_FILE
+    exit 4
+  fi
+fi
+
+#if ( 0 == 1 ) then
+# if ( grep -i done hi_log ) then
+#  cat error.log rcd.chk | /usr/ucb/mail -s"end of tape on $HOST" $EMAIL_LIST
+#  touch $HI_FILE$HIDONE_SUFFIX
+#  if ( -f $HI_FILE$HIDONE_SUFFIX ) then
+# unlink $SPLITFILE
+#  fi
+# unlink .$SPLITFILE
+#  /bin/rm error.log rcd.chk
+#  /bin/rm wu_inbox/.*
+# nice -10 $SPLITTER_PROG_LOC $SPLITFILE -resume 2>> splitterlog &
+#else
+#  if [ -f $MARKER$HOST ]
+#  then
+#    /bin/rm wu_inbox/.*
+#    cat error.log rcd.chk | /usr/ucb/mail -s"restarting HI analysis on $HOST" $EMAIL_LIST
+# nice -10 $SPLITTER_PROG_LOC $SPLITFILE -resume 2>> splitterlog &
+#  else
+#    cat error.log rcd.chk | /usr/ucb/mail -s"hi analysis disabled on $HOST" $EMAIL_LIST
+#  fi
+#endif
+end
+
diff --git a/gbt_splitter/uttolst.h b/gbt_splitter/uttolst.h
new file mode 100644
index 0000000..8f29efb
--- /dev/null
+++ b/gbt_splitter/uttolst.h
@@ -0,0 +1,2 @@
+double tm_UtToLst(double ddtime, double longitude,
+                  long mon, long day, long year);
diff --git a/gbt_splitter/validrun.cpp b/gbt_splitter/validrun.cpp
new file mode 100644
index 0000000..45d3854
--- /dev/null
+++ b/gbt_splitter/validrun.cpp
@@ -0,0 +1,181 @@
+/*
+ * validrun.c
+ *
+ * Functions for determining if a section of the tape buffer can be
+ * turned into a valid work unit
+ *
+ * $Id: validrun.cpp,v 1.2.4.2 2006/12/14 22:24:48 korpela Exp $
+ *
+ */
+
+#include "sah_config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <assert.h>
+#include "splitparms.h"
+#include "splittypes.h"
+#include "splitter.h"
+#include "message.h"
+
+
+int valid_run(tapeheader_t tapeheader[],buffer_pos_t *start_of_wu, 
+               buffer_pos_t *end_of_wu) {
+
+  int i=0,valid=1;
+  SCOPE_STRING *first_telstr;
+  double first_telstr_time=0;
+  double first_jd=tapeheader[0].st.jd;
+  char tmpstr[256];
+
+  /* find the first telstr that refers to valid data */
+
+  do {
+    first_telstr=&(tapeheader[++i].telstr);
+    first_telstr_time=first_telstr->st.jd;
+  } while ((first_telstr_time<=first_jd) && (i<TAPE_FRAMES_IN_BUFFER) && 
+	   ((first_jd-first_telstr_time)<60.0/86400.0));
+	   
+
+  if (i==TAPE_FRAMES_IN_BUFFER) {
+     log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"No valid telstr with time later than %14.5f\n",first_jd);
+     end_of_wu->frame=1+WU_OVERLAP_FRAMES;
+     end_of_wu->byte=0;
+     return(0);
+  }
+    
+  /* find the correct byte offset for the start of the work unit */
+
+  start_of_wu->frame=i;
+  start_of_wu->byte=(long)((tapeheader[i].telstr.st.jd-tapeheader[i].st.jd)*86400.0*tapeheader[i].samplerate*2/CHAR_BIT);
+  start_of_wu->byte &= 0xfffffffe;
+
+
+  while (start_of_wu->byte<0) {
+    start_of_wu->frame--;
+    start_of_wu->byte+=TAPE_DATA_SIZE;
+  }
+
+  while (start_of_wu->byte>TAPE_DATA_SIZE) {
+    start_of_wu->frame++;
+    start_of_wu->byte-=TAPE_DATA_SIZE;
+  }
+
+  if (start_of_wu->frame<0) {
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Missing telescope strings near %lu\n",
+	      tapeheader[0].frameseq);
+    end_of_wu->frame=0;
+    end_of_wu->byte=0;
+    records_in_buffer=0;
+    return(0);
+  }   
+
+  if ((start_of_wu->frame+TAPE_FRAMES_PER_WU)>TAPE_FRAMES_IN_BUFFER) {
+    log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Missing telescope strings near %lu\n",
+	       tapeheader[0].frameseq);
+    end_of_wu->frame=0;
+    end_of_wu->byte=0;
+    records_in_buffer=0;
+    return(0);
+  }   
+
+  /* check for frames in error */
+  for (i=0; i<TAPE_FRAMES_PER_WU; i++) {
+    int j=start_of_wu->frame+i;
+    // missed frames
+    if (tapeheader[j].missed) {
+      log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Missing frames between %lu and %lu\n",
+	      tapeheader[j-1].frameseq,tapeheader[j].frameseq);
+      valid=0;
+    }
+    // failed blanking signal acquisition
+    if (tapeheader[j].blanking_failed) {
+      log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,"Failed blanking between frames %lu and %lu\n",
+	      tapeheader[j-1].frameseq,tapeheader[j].frameseq);
+      valid=0;
+    }
+    if(!valid) {
+      end_of_wu->frame=j+WU_OVERLAP_FRAMES+1;
+      end_of_wu->byte=0;
+      assert((j+WU_OVERLAP_FRAMES)<=TAPE_FRAMES_IN_BUFFER);
+    }
+  }   
+
+  if (!valid) {
+     end_of_wu->frame=0;
+     records_in_buffer=0;
+     return(valid);
+  }
+
+  end_of_wu->frame=start_of_wu->frame+TAPE_FRAMES_PER_WU;
+  end_of_wu->byte=start_of_wu->byte;
+
+  return(valid);
+}
+
+
+/*
+ * $Log: validrun.cpp,v $
+ * Revision 1.2.4.2  2006/12/14 22:24:48  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.2.4.1  2006/01/13 00:37:58  korpela
+ * Moved splitter to using standard BOINC logging mechanisms.  All stderr now
+ * goes to "error.log"
+ *
+ * Added command line parameters "-iterations=" (number of workunit groups to
+ * create before exiting), "-trigger_file_path=" (path to the splitter_stop trigger
+ * file.  Default is /disks/setifiler1/wutape/tapedir/splitter_stop).
+ *
+ * Reduced deadlines by a factor of three.  We now need a 30 MFLOP machine to meet
+ * the deadline.
+ *
+ * Revision 1.2  2003/09/11 18:53:38  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.1  2003/07/29 20:35:57  korpela
+ *
+ * renames .C files to .cpp
+ *
+ * Revision 1.1  2003/06/03 00:23:43  korpela
+ *
+ * Again
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.7  2000/12/01 01:13:29  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.6  1999/06/07 21:00:52  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.5  1999/03/27  16:19:35  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.4  1999/02/22  22:21:09  korpela
+ * added -nodb option
+ *
+ * Revision 2.3  1999/02/11  16:46:28  korpela
+ * Added checkpointing.
+ *
+ * Revision 2.2  1998/11/04  23:08:25  korpela
+ * Byte and bit order change.
+ *
+ * Revision 2.1  1998/11/02  16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.3  1998/10/30  20:26:03  korpela
+ * Bug Fixes.  Now mostly working.
+ *
+ * Revision 1.2  1998/10/27  00:59:22  korpela
+ * Bug fixes.
+ *
+ * Revision 1.1  1998/10/22  17:48:20  korpela
+ * Initial revision
+ *
+ *
+ */
diff --git a/gbt_splitter/validrun.h b/gbt_splitter/validrun.h
new file mode 100644
index 0000000..89f7c6d
--- /dev/null
+++ b/gbt_splitter/validrun.h
@@ -0,0 +1,33 @@
+/*
+ * validrun.h
+ *
+ * Functions for determining if a section of the tape buffer can be
+ * turned into a valid work unit
+ *
+ * $Id: validrun.h,v 1.1 2003/06/03 00:23:43 korpela Exp $
+ *
+ */
+
+int valid_run(tapeheader_t tapeheader[],buffer_pos_t *start_of_wu, 
+               buffer_pos_t *end_of_wu);
+
+/*
+ * $Log: validrun.h,v $
+ * Revision 1.1  2003/06/03 00:23:43  korpela
+ *
+ * Again
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.1  1998/11/02 16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.1  1998/10/22  17:49:15  korpela
+ * Initial revision
+ *
+ *
+ */
diff --git a/gbt_splitter/writeheader.cpp b/gbt_splitter/writeheader.cpp
new file mode 100644
index 0000000..89296c3
--- /dev/null
+++ b/gbt_splitter/writeheader.cpp
@@ -0,0 +1,105 @@
+/*
+ *  Functions for writing tape and work unit headers
+ *
+ * $Id: writeheader.cpp,v 1.3.4.1 2006/12/14 22:24:49 korpela Exp $
+ *
+ */
+
+#include "sah_config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/types.h>
+
+#include "splitparms.h"
+#include "splittypes.h"
+#include "timecvt.h"
+#include "seti_header.h"
+
+extern int output_xml;
+
+/* Write a tape header into a buffer */
+int write_tape_header(char *buffer, tapeheader_t *header) {
+/* Unimplemented as yet  */
+return(0);
+}
+
+char *monthnames[]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep"
+                    "Oct","Nov","Dec"};
+char *daynames[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
+
+/* Write a work unit header into a FILE */
+/*int splitter_write_wu_header(FILE *file, wuheader_t *header) {
+    if (!output_xml)
+      write_wu_header(file, header->wuhead);
+  return (seti_write_wu_header(file,header->wuinfo,output_xml));
+
+}
+*/
+
+/*
+ * $Log: writeheader.cpp,v $
+ * Revision 1.3.4.1  2006/12/14 22:24:49  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.3  2003/09/11 18:53:38  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.2  2003/08/05 17:23:44  korpela
+ * More work on database stuff.
+ * Further tweaks.
+ *
+ * Revision 1.1  2003/07/29 20:35:59  korpela
+ *
+ * renames .C files to .cpp
+ *
+ * Revision 1.2  2003/06/03 01:01:18  korpela
+ *
+ * First working splitter under CVS.
+ *
+ * Revision 1.1  2003/06/03 00:23:43  korpela
+ *
+ * Again
+ *
+ * Revision 3.1  2003/05/19 17:40:59  eheien
+ * *** empty log message ***
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.6  1999/01/04 22:27:55  korpela
+ * Updated return codes.
+ *
+ * Revision 2.5  1998/11/10  00:02:44  korpela
+ * Moved remaining wuheader fields into a WU_INFO structure.
+ *
+ * Revision 2.4  1998/11/09  23:26:27  korpela
+ * Added generic version= to default header.
+ *
+ * Revision 2.3  1998/11/05  21:18:41  korpela
+ * Moved name field from header to seti header.
+ *
+ * Revision 2.2  1998/11/02  18:42:03  korpela
+ * Changed write_wu_header to call seti_write_wu_header
+ *
+ * Revision 2.1  1998/11/02  16:38:29  korpela
+ * Will be transfered to client.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.4  1998/10/30  20:26:03  korpela
+ * Bug Fixes.  Now mostly working.
+ *
+ * Revision 1.3  1998/10/27  00:59:43  korpela
+ * Bug fixes.
+ * /
+ *
+ * Revision 1.2  1998/10/20  16:32:03  korpela
+ * Fixed syntax error.
+ *
+ * Revision 1.1  1998/10/20  16:27:41  korpela
+ * Initial revision
+ *
+ *
+ */
diff --git a/gbt_splitter/writeheader.h b/gbt_splitter/writeheader.h
new file mode 100644
index 0000000..c3d6d4a
--- /dev/null
+++ b/gbt_splitter/writeheader.h
@@ -0,0 +1,39 @@
+/*
+ *  Functions for writing tape and work unit headers
+ *
+ * $Id: writeheader.h,v 1.2 2003/08/05 17:23:44 korpela Exp $
+ *
+ */
+
+/* Write a tape header into a buffer */
+int write_tape_header(char *buffer, tapeheader_t *header);
+
+/* Write a work unit header into a FILE */
+//  int splitter_write_wu_header(FILE *file, wuheader_t *header);
+
+/*
+ * $Log: writeheader.h,v $
+ * Revision 1.2  2003/08/05 17:23:44  korpela
+ * More work on database stuff.
+ * Further tweaks.
+ *
+ * Revision 1.1  2003/06/03 00:23:44  korpela
+ *
+ * Again
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.2  1999/01/04 22:27:55  korpela
+ * Updated return codes.
+ *
+ * Revision 2.1  1998/11/02  16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.1  1998/10/15  17:20:01  korpela
+ * Initial revision
+ *
+ */
diff --git a/gbt_splitter/wufiles.cpp b/gbt_splitter/wufiles.cpp
new file mode 100644
index 0000000..d8663ce
--- /dev/null
+++ b/gbt_splitter/wufiles.cpp
@@ -0,0 +1,679 @@
+/*
+ *
+ * Functions for managing wufiles and their data
+ *
+ * $Id: wufiles.cpp,v 1.29.2.18 2007/08/10 18:21:13 korpela Exp $
+ *
+ */
+
+#include "sah_config.h"
+#undef USE_MYSQL
+#include <cstdio>
+#include <cstdlib>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <iostream>
+#include <string>
+#include <algorithm>
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "boinc_db.h"
+#include "sched_util.h"
+#include "splitparms.h"
+#include "splittypes.h"
+#include "timecvt.h"
+#include "s_util.h"
+#include "util.h"
+#include "str_util.h"
+#include "str_replace.h"
+#include "splitter.h"
+#include "writeheader.h"
+#include "message.h"
+#include "encode.h"
+#include "dotransform.h"
+#include "angdist.h"
+#include "lcgamm.h"
+#include "readtape.h"
+#include "sqlrow.h"
+#include "sqlblob.h"
+#include "sqlapi.h"
+#include "db_table.h"
+#include "schema_master.h"
+#include "seti_tel.h"
+#include "seti_cfg.h"
+#include "xml_util.h"
+#include "db/app_config.h"
+#include "str_util.h"
+#include <errno.h>
+
+int wu_database_id[NSTRIPS];
+static std::vector<unsigned char> bin_data[NSTRIPS];
+
+extern APP_CONFIG sah_config;
+
+int make_wu_headers(tapeheader_t tapeheader[],workunit wuheader[],
+                    buffer_pos_t *start_of_wu) {
+  int procid=getpid();
+  int i,j,startframe=start_of_wu->frame;
+  double receiver_freq;
+  int bandno;
+  SCOPE_STRING *lastpos;
+  FILE *tmpfile;
+  char tmpstr[256];
+  char buf[64];
+  static int HaveConfigTable=0;
+  static ReceiverConfig_t ReceiverConfig;   
+  static receiver_config r;
+  static settings s;
+
+  if(!HaveConfigTable) {
+    sprintf(buf,"where s4_id=%d",gregorian?AOGREG_1420:AO_1420);
+    r.fetch(std::string(buf));
+    ReceiverConfig.ReceiverID=r.s4_id;
+    strlcpy(ReceiverConfig.ReceiverName,r.name,
+           sizeof(ReceiverConfig.ReceiverName));
+    ReceiverConfig.Latitude=r.latitude;
+    ReceiverConfig.Longitude=r.longitude;
+    ReceiverConfig.WLongitude=-r.longitude;
+    ReceiverConfig.Elevation=r.elevation;
+    ReceiverConfig.Diameter=r.diameter;
+    ReceiverConfig.BeamWidth=r.beam_width;
+    ReceiverConfig.CenterFreq=r.center_freq;
+    ReceiverConfig.AzOrientation=r.az_orientation;
+    for (i=0;i<(sizeof(ReceiverConfig.ZenCorrCoeff)/sizeof(ReceiverConfig.ZenCorrCoeff[0]));i++) {
+      ReceiverConfig.ZenCorrCoeff[i]=r.zen_corr_coeff[i];
+      ReceiverConfig.AzCorrCoeff[i]=r.az_corr_coeff[i];
+    }
+    HaveConfigTable=1;
+  }
+  sprintf(buf,"where active=%d",app.id);
+  if (!s.fetch(std::string(buf))) {
+    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Unable to find active settings for app.id=%d\n",app.id);
+    exit(1);
+  }
+  if (s.receiver_cfg->id != r.id) {
+    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Receiver config does not match settings (%d != %d)\n",s.receiver_cfg->id, r.id);
+    exit(1);
+  }
+  s.recorder_cfg->fetch();
+  s.splitter_cfg->fetch();
+  s.analysis_cfg->fetch();
+  if (!strncmp(s.splitter_cfg->data_type,"encoded",
+     std::min(static_cast<size_t>(7),sizeof(s.splitter_cfg->data_type)))) {
+    noencode=0;
+  } else {
+      noencode=1;
+  }
+
+  workunit_grp wugrp;
+  sprintf(wugrp.name,"%s.%ld.%d.%ld.%d",tapeheader[startframe].name,
+    procid, 
+    (current_record-TAPE_RECORDS_IN_BUFFER)*8+startframe,
+    start_of_wu->byte,s.id);
+  wugrp.receiver_cfg=r;
+  wugrp.recorder_cfg=s.recorder_cfg;
+  wugrp.splitter_cfg=s.splitter_cfg;
+  wugrp.analysis_cfg=s.analysis_cfg;
+
+  wugrp.data_desc.start_ra=tapeheader[startframe+1].telstr.ra;
+  wugrp.data_desc.start_dec=tapeheader[startframe+1].telstr.dec;
+  wugrp.data_desc.end_ra=tapeheader[startframe+TAPE_FRAMES_PER_WU].telstr.ra;
+  wugrp.data_desc.end_dec=tapeheader[startframe+TAPE_FRAMES_PER_WU].telstr.dec;
+  wugrp.data_desc.nsamples=NSAMPLES;
+  wugrp.data_desc.true_angle_range=0;
+  {
+    double sample_rate=tapeheader[startframe].samplerate/NSTRIPS;
+    /* startframe+1 contains the first valid RA and Dec */
+    TIME st=tapeheader[startframe+1].telstr.st;
+    TIME et=tapeheader[startframe+TAPE_FRAMES_PER_WU].telstr.st;
+    double diff=(et-st).jd*86400.0;
+    for (j=2;j<TAPE_FRAMES_PER_WU;j++) {
+      wugrp.data_desc.true_angle_range+=angdist(tapeheader[startframe+j-1].telstr,tapeheader[startframe+j].telstr);
+    }
+    wugrp.data_desc.true_angle_range*=(double)wugrp.data_desc.nsamples/(double)sample_rate/diff;
+    if (wugrp.data_desc.true_angle_range==0) wugrp.data_desc.true_angle_range=1e-10;
+  }
+  // Calculate the number of unique signals that could be found in a workunit.
+  // We will use these numbers to calculate thresholds.
+  double numgauss=2.36368e+08/wugrp.data_desc.true_angle_range;
+  double numpulse=std::min(4.52067e+10/wugrp.data_desc.true_angle_range,2.00382e+11);
+  double numtrip=std::min(3.25215e+12/wugrp.data_desc.true_angle_range,1.44774e+13);
+
+  
+
+  // Calculate a unique key to describe this analysis config.
+  long keyuniq=floor(std::min(wugrp.data_desc.true_angle_range*100,1000.0)+0.5)+
+    s.analysis_cfg.id*1024.0;
+  if ((keyuniq>(13*1024)) ||(keyuniq<12*1024)) {
+     log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Invalid keyuniq value!\n");
+     log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"%d %d %f\n",keyuniq,s.analysis_cfg.id,wugrp.data_desc.true_angle_range);
+     exit(1);
+  }
+
+  keyuniq*=-1;
+  long save_keyuniq=keyuniq;
+  s.analysis_cfg=wugrp.analysis_cfg;
+  sprintf(tmpstr,"where keyuniq=%d",keyuniq); 
+  // Check if we've already done this analysis_config...
+  s.analysis_cfg.id=0;
+  s.analysis_cfg->fetch(tmpstr);
+
+  if (s.analysis_cfg->id==0) {
+    if (keyuniq != save_keyuniq) {
+      log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"keyuniq value changed!\n");
+      exit(1);
+    }
+
+    // If not calculate the thresholds based upon the input analysis_config
+    // Triplets are distributed exponentially...
+    wugrp.analysis_cfg->triplet_thresh+=(log(numtrip)-29.0652);
+
+    // Gaussians are based upon chisqr...
+    double p_gauss=lcgf(32.0,wugrp.analysis_cfg->gauss_null_chi_sq_thresh*32.0);
+    p_gauss-=(log(numgauss)-19.5358);
+    wugrp.analysis_cfg->gauss_null_chi_sq_thresh=invert_lcgf(p_gauss,32,1e-4)*0.03125;
+
+    // Pulses thresholds are log of the probability
+    wugrp.analysis_cfg->pulse_thresh+=(log(numpulse)-24.7894);
+
+    wugrp.analysis_cfg->keyuniq=keyuniq;
+    wugrp.analysis_cfg->insert();
+  } else {
+    wugrp.analysis_cfg=s.analysis_cfg;
+  }
+
+  strlcpy(wugrp.data_desc.time_recorded,
+      short_jd_string(tapeheader[startframe+1].telstr.st.jd),
+      sizeof(wugrp.data_desc.time_recorded));
+  wugrp.data_desc.time_recorded_jd=tapeheader[startframe+1].telstr.st.jd;
+
+  lastpos=&(tapeheader[startframe].telstr);
+  coordinate_t tmpcoord;
+  tmpcoord.time=tapeheader[startframe].telstr.st.jd;
+  tmpcoord.ra=tapeheader[startframe].telstr.ra;
+  tmpcoord.dec=tapeheader[startframe].telstr.dec;
+  wugrp.data_desc.coords.push_back(tmpcoord);  
+
+  for (j=1;j<TAPE_FRAMES_PER_WU;j++) {
+    if ((tapeheader[startframe+j].telstr.st.jd-lastpos->st.jd) > (1.0/86400.0)) 
+    {
+      lastpos=&(tapeheader[startframe+j].telstr);
+      tmpcoord.time=tapeheader[startframe+j].telstr.st.jd;
+      tmpcoord.ra=tapeheader[startframe+j].telstr.ra;
+      tmpcoord.dec=tapeheader[startframe+j].telstr.dec;
+      wugrp.data_desc.coords.push_back(tmpcoord);  
+    }
+  }
+
+  wugrp.tape_info->id=0;
+  wugrp.tape_info->fetch(std::string("where name=\'")+tapeheader[startframe].name+"\'");
+  wugrp.tape_info->start_time=tapeheader[startframe].st.jd;
+  wugrp.tape_info->last_block_time=tapeheader[startframe].st.jd;
+  wugrp.tape_info->last_block_done=tapeheader[startframe].frameseq;
+
+  if (!nodb) {
+    if (wugrp.tape_info.id) {
+      if (!(wugrp.tape_info->update())) {
+        char buf[1024];
+        log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"%s",sql_error_message());
+	exit(1);
+      }
+    } else {
+      strlcpy(wugrp.tape_info->name,tapeheader[startframe].name,sizeof(wugrp.tape_info->name));
+      wugrp.tape_info->insert();
+    }
+  }
+
+  if (!nodb) wugrp.insert();
+  
+  for (i=0;i<NSTRIPS;i++) {
+    bin_data[i].clear();
+    wuheader[i].group_info=wugrp;
+    sprintf(wuheader[i].name,"%s.%ld.%d.%ld.%d.%d",tapeheader[startframe].name,
+       procid, (current_record-TAPE_RECORDS_IN_BUFFER)*8+startframe,
+       start_of_wu->byte,s.id,i);
+    wuheader[i].subband_desc.sample_rate=tapeheader[startframe].samplerate/NSTRIPS;
+ 
+    receiver_freq=tapeheader[startframe].centerfreq;
+
+    bandno=((i+NSTRIPS/2)%NSTRIPS)-NSTRIPS/2;
+
+    wuheader[i].subband_desc.base=receiver_freq+
+	       (double)(bandno)*wuheader[i].subband_desc.sample_rate;
+    wuheader[i].subband_desc.center=receiver_freq+wuheader[i].subband_desc.sample_rate*NSTRIPS*((double)IFFT_LEN*bandno/FFT_LEN+(double)IFFT_LEN/(2*FFT_LEN)-1.0/(2*FFT_LEN));
+    wuheader[i].subband_desc.number=i;
+
+    if (!nodb ) {
+      if (!(wu_database_id[i]=wuheader[i].insert())) {
+        log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Database error in make_wu_headers()\n");
+        exit(EXIT_FAILURE);
+      }
+    }
+	
+    sprintf(tmpstr,"./wu_inbox/%s",wuheader[i].name);
+    if ((tmpfile=fopen(tmpstr,"w"))) {
+      fprintf(tmpfile,"<workunit>\n");
+      fprintf(tmpfile,wuheader[i].print_xml().c_str());
+      fclose(tmpfile);
+    } else {
+      log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Unable to open file ./wu_inbox/%s, errno=%d\n",wuheader[i].name,errno);
+      exit(1);
+    }
+    bin_data[i].reserve(wuheaders[i].group_info->recorder_cfg->bits_per_sample*
+       wuheaders[i].group_info->data_desc.nsamples/8);
+  }
+  return(1);
+}
+
+
+void write_wufile_blocks(int nbytes) {
+  static bool first_call=true;
+  int i,j;
+
+
+  for (i=0;i<NSTRIPS;i++) {
+    for  (j=0;j<nbytes;j++) {
+      bin_data[i].push_back(output_buf[i][j]);
+    }
+  }
+}
+
+int filecopy(char *oldname,char *newname) {
+  FILE *oldfile,*newfile;
+  char buffer[16384];
+  int nread;
+  if ((oldfile=fopen(oldname,"rb")) && (newfile=fopen(newname,"wb"))) {
+      do {
+	nread=fread(buffer,1,16384,oldfile);
+	fwrite(buffer,1,nread,newfile);
+      } while (nread>0);
+      fclose(oldfile);
+      fclose(newfile);
+      return 0;
+  } else {
+    return 1;
+  }
+}
+      
+
+
+void rename_wu_files() {
+  int i, retval;
+  char oldname[256],newname[1024];
+  unsigned long sz;
+  DB_WORKUNIT db_wu;
+  const char *name[1];
+  char *wudir="./wu_inbox";
+  xml_encoding encoding=(noencode?_binary:_x_setiathome);
+  FILE *tmpfile;
+
+  if (boinc_db.open(boinc_config.db_name,boinc_config.db_host,boinc_config.db_user,boinc_config.db_passwd)) {
+    boinc_db.print_error("boinc_db.open");
+    log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Fatal error in boinc_db.open\n");
+    exit(1);
+  }
+
+  for (i=0;i<NSTRIPS;i++) {
+    name[0]=wuheaders[i].name;
+    sprintf(oldname,"%s/%s",wudir,name[0]);
+
+    //sprintf(newname,"%s%s/%s",projectdir,WU_SUBDIR,name[0]);
+    retval = dir_hier_path(name[0],
+                           boinc_config.download_dir,
+                           boinc_config.uldl_dir_fanout,
+                           newname,
+			   true
+    );
+    if (retval) {
+        char buf[1024];
+        log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"[%s] dir_hier_path() failed: %d\n", name[0], retval);
+	exit(1);
+    } 
+
+    struct stat sbuf;
+    if (!stat(oldname,&sbuf) && (tmpfile=fopen(oldname,"a"))) {
+       std::string tmpstr=xml_encode_string(bin_data[i],encoding);
+       fprintf(tmpfile,"<data length=%ld encoding=\"%s\">",tmpstr.size(),
+            xml_encoding_names[encoding]);
+       fwrite(tmpstr.c_str(),tmpstr.size(),1,tmpfile);
+       fprintf(tmpfile,"</data>\n");
+       fprintf(tmpfile,"</workunit>\n");
+       sz=bin_data[i].size();
+
+       fclose(tmpfile);
+    } else {
+        log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"Header file no longer exists! splitter start script may be failing\n ");
+	exit(1);
+    }  
+    if (!nodb) {
+      if (!filecopy(oldname,newname)) {
+        db_wu.clear();
+        db_wu.opaque=wuheaders[i].id;
+        strncpy(db_wu.name,name[0],sizeof(db_wu.name)-2);
+        db_wu.appid=app.id;
+        //db_wu.rsc_fpops_est=2.79248e+13*6;
+        //db_wu.rsc_fpops_bound=4.46797e+14*6;
+        double ar=wuheaders[i].group_info->data_desc.true_angle_range;
+        double dur=(double)(wuheaders[i].group_info->data_desc.nsamples)/wuheaders[i].subband_desc.sample_rate;
+        double min_slew=wuheaders[i].group_info->analysis_cfg->pot_min_slew;
+        double max_slew=wuheaders[i].group_info->analysis_cfg->pot_max_slew;
+        if ( ar < ( dur*min_slew )/2 ) {
+          db_wu.rsc_fpops_est=4.95e+13;
+        } else {
+          if ( ar < ( dur*min_slew ) ) {
+            db_wu.rsc_fpops_est=(2.85e+13+2.0e+14*ar);
+          } else {
+	    if ( ar <= (dur*max_slew) ) {
+              db_wu.rsc_fpops_est=(2.22e+13/pow(ar,1.25));
+            } else {
+              db_wu.rsc_fpops_est=1.125e+13;
+            }
+	  }
+        }
+        db_wu.rsc_fpops_bound=db_wu.rsc_fpops_est*10;
+        db_wu.rsc_memory_bound=32505856;
+        db_wu.rsc_disk_bound=500000;
+        // Our minimum is 10% of a 100 MFLOP machine
+        db_wu.delay_bound=db_wu.rsc_fpops_est/3e+7;
+        db_wu.min_quorum=sah_config.min_quorum;
+        db_wu.target_nresults=sah_config.target_nresults;
+        db_wu.max_error_results=sah_config.max_error_results;
+        db_wu.max_total_results=sah_config.max_total_results;
+        db_wu.max_success_results=sah_config.max_success_results;
+        strncpy(db_wu.app_name,SAH_APP_NAME,sizeof(db_wu.app_name)-2);
+        if (create_work(db_wu,
+                        wu_template,
+                        result_template_filename,
+                        result_template_filepath,
+                        name,
+                        1,
+		        boinc_config,
+		        NULL
+                       )
+           ) {
+          log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"create work failed\n");
+          exit(1);
+        }
+        //unlink(oldname);   // we now *always* unlink
+      } else {
+	  log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,"file copy failed\n");
+          exit(1);
+      }
+      unlink(oldname);
+    }
+  }
+  boinc_db.close();
+}
+
+/*
+ * $Log: wufiles.cpp,v $
+ * Revision 1.29.2.18  2007/08/10 18:21:13  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.29.2.17  2007/06/07 20:01:52  mattl
+ * *** empty log message ***
+ *
+ * Revision 1.29.2.16  2007/06/06 15:58:30  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.29.2.15  2006/12/14 22:24:49  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.29.2.14  2006/05/03 19:14:31  korpela
+ * Updated work estimates.
+ *
+ * Revision 1.29.2.13  2006/04/24 18:41:02  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.29.2.12  2006/01/13 00:37:58  korpela
+ * Moved splitter to using standard BOINC logging mechanisms.  All stderr now
+ * goes to "error.log"
+ *
+ * Added command line parameters "-iterations=" (number of workunit groups to
+ * create before exiting), "-trigger_file_path=" (path to the splitter_stop trigger
+ * file.  Default is /disks/setifiler1/wutape/tapedir/splitter_stop).
+ *
+ * Reduced deadlines by a factor of three.  We now need a 30 MFLOP machine to meet
+ * the deadline.
+ *
+ * Revision 1.29.2.11  2006/01/10 00:39:04  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.29.2.10  2006/01/05 23:55:22  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.29.2.9  2005/12/05 22:11:40  korpela
+ * Fixed bug in flops estimate.
+ *
+ * Revision 1.29.2.8  2005/10/05 16:22:17  jeffc
+ * removed reference to old/new boolean for directory hash.
+ *
+ * Revision 1.29.2.7  2005/09/22 23:05:22  korpela
+ * Fixed threshold calculation.  Was using chisqr rather than reduced chisqr.
+ *
+ * Revision 1.29.2.6  2005/09/21 22:11:23  korpela
+ * Updated Makefile.in for OpenSSL.
+ * Added dynamic threshold generation to wufiles.cpp.
+ *
+ * Revision 1.29.2.5  2005/08/01 17:47:38  korpela
+ * Type fixed.
+ *
+ * Revision 1.29.2.4  2005/08/01 17:43:20  korpela
+ * Refinement of FLOPS estimate for workunits.
+ *
+ * Revision 1.29.2.3  2005/07/26 17:17:01  korpela
+ * Typo fix
+ *
+ * Revision 1.29.2.2  2005/07/19 00:15:19  korpela
+ * Revised delay bound and FLOP estimate for setiathome_enhanced.
+ *
+ * Revision 1.29.2.1  2005/07/06 01:30:17  korpela
+ * Updated estimates of FPOPS per workunit for setiathome enhanced.
+ *
+ * Revision 1.29  2005/03/08 22:36:15  jeffc
+ * jeffc - fixed call to create_work()
+ *
+ * Revision 1.28  2005/02/15 23:06:47  korpela
+ * Fixed missing dir_hier symbol.
+ *
+ * Revision 1.27  2004/12/27 20:48:54  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.26  2004/11/18 22:24:48  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.25  2004/08/25 22:42:11  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.24  2004/08/14 04:44:26  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.23  2004/08/12 15:45:41  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.22  2004/07/15 17:54:20  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.21  2004/07/09 22:35:39  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.20  2004/07/01 17:56:51  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.19  2004/06/25 13:49:33  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.18  2004/06/18 23:23:32  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.17  2004/06/16 20:57:19  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.16  2004/06/02 20:51:32  jeffc
+ * *** empty log message ***
+ *
+ * Revision 1.15  2004/01/22 00:57:54  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.14  2004/01/20 22:33:44  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.13  2004/01/06 22:44:05  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.12  2004/01/01 18:42:01  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.11  2003/12/12 01:51:39  korpela
+ * Now using the opaque field in workunit to store SAH wuid.
+ *
+ * Revision 1.10  2003/12/03 23:46:41  korpela
+ * WU count is now only for SAH workunits.
+ *
+ * Revision 1.9  2003/11/25 21:59:53  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.8  2003/11/11 06:20:30  korpela
+ * Increased max fpops_max to prevent timeout on windows clients
+ *
+ * Revision 1.7  2003/10/25 18:19:44  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.6  2003/10/24 16:57:03  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.5  2003/09/26 20:48:52  jeffc
+ * jeffc - merge in branch setiathome-4_all_platforms_beta.
+ *
+ * Revision 1.3.2.2  2003/09/22 19:00:31  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.3.2.1  2003/09/22 17:39:35  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.4  2003/09/22 17:05:38  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.3  2003/09/11 18:53:38  korpela
+ * *** empty log message ***
+ *
+ * Revision 1.2  2003/08/05 17:23:44  korpela
+ * More work on database stuff.
+ * Further tweaks.
+ *
+ * Revision 1.1  2003/07/29 20:36:00  korpela
+ *
+ * renames .C files to .cpp
+ *
+ * Revision 1.3  2003/06/05 15:52:47  korpela
+ *
+ * Fixed coordinate bug that was using the wrong zenith angle from the telescope
+ * strings when handling units from the gregorian.
+ *
+ * Revision 1.2  2003/06/03 01:01:18  korpela
+ *
+ * First working splitter under CVS.
+ *
+ * Revision 1.1  2003/06/03 00:23:44  korpela
+ *
+ * Again
+ *
+ * Revision 3.8  2003/05/19 17:40:59  eheien
+ * *** empty log message ***
+ *
+ * Revision 3.7  2003/04/10 17:32:25  korpela
+ * *** empty log message ***
+ *
+ * Revision 3.6  2002/06/21 01:42:15  eheien
+ * *** empty log message ***
+ *
+ * Revision 3.5  2001/11/07 00:51:47  korpela
+ * Added splitter version to database.
+ * Added max_wus_ondisk option.
+ *
+ * Revision 3.4  2001/08/17 22:20:54  korpela
+ * *** empty log message ***
+ *
+ * Revision 3.3  2001/08/17 01:22:31  korpela
+ * *** empty log message ***
+ *
+ * Revision 3.2  2001/08/17 01:16:53  korpela
+ * *** empty log message ***
+ *
+ * Revision 3.1  2001/08/16 23:42:08  korpela
+ * Mods for splitter to make binary workunits.
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.18  2000/12/01 01:13:29  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.17  1999/06/07 21:00:52  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.16  1999/03/27  16:19:35  korpela
+ * *** empty log message ***
+ *
+ * Revision 2.15  1999/03/05  01:47:18  korpela
+ * Added data_class field.
+ *
+ * Revision 2.14  1999/02/22  22:21:09  korpela
+ * added -nodb option
+ *
+ * Revision 2.13  1999/02/11  16:46:28  korpela
+ * Added db access functions.
+ *
+ * Revision 2.12  1999/01/04  22:27:55  korpela
+ * Updated return codes.
+ *
+ * Revision 2.11  1998/12/14  23:41:44  korpela
+ * Added subband_base to work unit header.
+ * Changed frequency calculation.
+ *
+ * Revision 2.10  1998/12/14  21:55:07  korpela
+ * Added fft_len and ifft_len to work unit header.
+ *
+ * Revision 2.9  1998/11/13  23:58:52  korpela
+ * Modified for move of name field between structures.
+ *
+ * Revision 2.8  1998/11/13  22:18:12  davea
+ * *** empty log message ***
+ *
+ * Revision 2.7  1998/11/10 01:55:26  korpela
+ * Server requires a CR at the end of a WU file
+ * ???
+ *
+ * Revision 2.6  1998/11/10  00:02:44  korpela
+ * Moved remaining wuheader fields into a WU_INFO structure.
+ *
+ * Revision 2.5  1998/11/05  21:33:02  korpela
+ * Fixed angle_range bug.
+ *
+ * Revision 2.4  1998/11/05  21:18:41  korpela
+ * Moved name field from header to seti header.
+ *
+ * Revision 2.3  1998/11/02  21:20:58  korpela
+ * Modified for (internal) integer receiver ID.
+ *
+ * Revision 2.2  1998/11/02  18:45:39  korpela
+ * Changed location of timecvt.h
+ *
+ * Revision 2.1  1998/11/02  16:38:29  korpela
+ * Variable type changes.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.2  1998/10/30  20:26:03  korpela
+ * Bug Fixes.  Now mostly working.
+ *
+ * Revision 1.1  1998/10/27  01:01:16  korpela
+ * Initial revision
+ *
+ *
+ */
diff --git a/gbt_splitter/wufiles.h b/gbt_splitter/wufiles.h
new file mode 100644
index 0000000..046c378
--- /dev/null
+++ b/gbt_splitter/wufiles.h
@@ -0,0 +1,39 @@
+/*
+ *
+ * Functions for managing wufiles and their data
+ *
+ * $Id: wufiles.h,v 1.2 2003/08/05 17:23:45 korpela Exp $
+ *
+ */
+
+
+
+int make_wu_headers(tapeheader_t tapeheader[],workunit wuheaders[],
+                    buffer_pos_t *start_of_wu) ;
+void write_wufile_blocks(int nbytes) ;
+void rename_wu_files();
+
+/*
+ * $Log: wufiles.h,v $
+ * Revision 1.2  2003/08/05 17:23:45  korpela
+ * More work on database stuff.
+ * Further tweaks.
+ *
+ * Revision 1.1  2003/06/03 00:23:44  korpela
+ *
+ * Again
+ *
+ * Revision 3.0  2001/08/01 19:04:57  korpela
+ * Check this in before Paul screws it up.
+ *
+ * Revision 2.1  1998/11/02 16:41:21  korpela
+ * Minor Change.
+ *
+ * Revision 2.0  1998/10/30  22:00:04  korpela
+ * Conversion to C++ and merger with client source tree.
+ *
+ * Revision 1.1  1998/10/27  01:13:16  korpela
+ * Initial revision
+ *
+ *
+ */

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-boinc/boinc-app-seti.git



More information about the pkg-boinc-commits mailing list