Index: branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/Makefile
===================================================================
--- branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/Makefile	(revision 34916)
+++ branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/Makefile	(revision 34916)
@@ -0,0 +1,42 @@
+default: dvopsps dvopsps_client
+help:
+@echo "make options: dvopsps default help install (dvopsps)"
+
+include ../../Makefile.System
+HOME    =       $(ROOT)/src/dvopsps
+BIN	=	$(HOME)/bin
+LIB	=	$(HOME)/lib
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+INC	= 	$(HOME)/include
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = -ldvo -lFITS -lohana $(BASE_LDFLAGS)
+
+dvopsps: $(BIN)/dvopsps.$(ARCH)
+dvopsps_client: $(BIN)/dvopsps_client.$(ARCH)
+
+install: $(DESTBIN)/dvopsps $(DESTBIN)/dvopsps_client
+
+DVOPSPS = \
+$(SRC)/dvopsps.$(ARCH).o	    \
+$(SRC)/initialize_dvopsps.$(ARCH).o \
+$(SRC)/mysql_dvopsps.$(ARCH).o \
+$(SRC)/insert_detections_dvopsps.$(ARCH).o \
+$(SRC)/insert_detections_dvopsps_catalog.$(ARCH).o
+
+$(DVOPSPS): $(INC)/dvopsps.h
+$(BIN)/dvopsps.$(ARCH): $(DVOPSPS)
+
+DVOPSPS_CLIENT = \
+$(SRC)/dvopsps_client.$(ARCH).o	    \
+$(SRC)/initialize_dvopsps.$(ARCH).o \
+$(SRC)/mysql_dvopsps.$(ARCH).o \
+$(SRC)/insert_detections_dvopsps.$(ARCH).o \
+$(SRC)/insert_detections_dvopsps_catalog.$(ARCH).o
+
+$(DVOPSPS_CLIENT): $(INC)/dvopsps.h
+$(BIN)/dvopsps_client.$(ARCH): $(DVOPSPS_CLIENT)
Index: branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/include/dvopsps.h
===================================================================
--- branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/include/dvopsps.h	(revision 34916)
+++ branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/include/dvopsps.h	(revision 34916)
@@ -0,0 +1,48 @@
+# include <ohana.h>
+# include <dvo.h>
+# include <signal.h>
+# include "mysql.h"
+
+# define DVO_MAX_PATH 1024
+
+/* global variables set in parameter file */
+char         ImageCat[DVO_MAX_PATH];
+
+char        *CATDIR;
+int          HOST_ID;
+char        *HOSTDIR;
+int          VERBOSE;
+
+int          PARALLEL;
+int          PARALLEL_MANUAL;
+int          PARALLEL_SERIAL;
+
+char        *SINGLE_CPT;
+
+char        *DATABASE_HOST;
+char        *DATABASE_USER;
+char        *DATABASE_PASS;
+char        *DATABASE_NAME;
+
+SkyRegion    UserPatch;
+
+/***** prototypes ****/
+int    main                          	  PROTO((int argc, char **argv));
+       
+void   GetConfig                     	  PROTO((char *config, char *field, char *format, int N, void *ptr));
+void   ConfigInit                    	  PROTO((int *argc, char **argv));
+       
+void   usage_dvopsps                 	  PROTO(());
+void   initialize_dvopsps            	  PROTO((int argc, char **argv));
+int    args_dvopsps                  	  PROTO((int argc, char **argv));
+       
+void   usage_dvopsps_client          	  PROTO(());
+void   initialize_dvopsps_client     	  PROTO((int argc, char **argv));
+int    args_dvopsps_client           	  PROTO((int argc, char **argv));
+       
+int    insert_detections_dvopsps          PROTO(());
+int    insert_detections_dvopsps_parallel PROTO((SkyTable *sky));
+int    insert_detections_mysql             PROTO((Average *average, Measure *measure, MYSQL *mysql));
+int    insert_detections_dvopsps_catalog   PROTO((Catalog *catalog, MYSQL *mysql));
+      
+MYSQL *mysql_dvopsps_connect              PROTO((MYSQL *mysqlBase));
Index: branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/src/dvopsps.c
===================================================================
--- branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/src/dvopsps.c	(revision 34916)
+++ branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/src/dvopsps.c	(revision 34916)
@@ -0,0 +1,18 @@
+# include "dvopsps.h"
+
+int main (int argc, char **argv) {
+
+  int status;
+
+  /* get configuration info, args, lockfile */
+  initialize_dvopsps (argc, argv);
+
+  status = insert_detections_dvopsps ();
+
+  if (!status) exit (1);
+  exit (0);
+}
+  
+
+/* dvopsps : extract the ids and other needed fields from dvo and insert in the mysql db
+ */
Index: branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/src/dvopsps_client.c
===================================================================
--- branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/src/dvopsps_client.c	(revision 34916)
+++ branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/src/dvopsps_client.c	(revision 34916)
@@ -0,0 +1,22 @@
+# include "dvopsps.h"
+
+// dvopsps_client is run on a remote host and is responsible for updating the catalogs
+// owned by that host.  
+
+// dvopsps_client -hostname (hostname) -catdir (catdir) -hostdir (hostdir) -images (images)
+// load the SkyTable and HostTable from (catdir) [contains the host responsibilities]
+// loop over tables from SkyTable with my host ID
+// the calling program tells the client which host they are (or host ID?); we do not actually have to run this on the real host
+
+int main (int argc, char **argv) {
+
+  int status;
+
+  // get configuration info, args, lockfile (set CATDIR, HOST_ID, HOSTDIR, IMAGES)
+  initialize_dvopsps_client (argc, argv);
+
+  status = insert_detections_dvopsps ();
+
+  if (!status) exit (1);
+  exit (0);
+}
Index: branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/src/initialize_dvopsps.c
===================================================================
--- branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/src/initialize_dvopsps.c	(revision 34916)
+++ branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/src/initialize_dvopsps.c	(revision 34916)
@@ -0,0 +1,315 @@
+# include "dvopsps.h"
+
+void usage_dvopsps () {
+  fprintf (stderr, "USAGE: dvopsps [dbinfo] [options]\n");
+  fprintf (stderr, "    mysql database info is supplied with these:\n");
+  fprintf (stderr, "    -dbhost : database host machine\n");
+  fprintf (stderr, "    -dbuser : database username\n");
+  fprintf (stderr, "    -dbpass : database password\n");
+  fprintf (stderr, "    -dbname : database name\n\n");
+  fprintf (stderr, "  options:\n");
+  fprintf (stderr, "    -v : verbose mode\n");
+  fprintf (stderr, "    -region Rmin Rmax Dmin Dmax\n");
+  fprintf (stderr, "    -parallel : run in parallel mode\n");
+  fprintf (stderr, "    -h     : this help list\n");
+  fprintf (stderr, "    -help  : this help list\n");
+  fprintf (stderr, "    --h    : this help list\n");
+  fprintf (stderr, "    --help : this help list\n");
+  fprintf (stderr, "    Note that the dvo db can be specified by -D CATDIR (directory)\n");
+  exit (2);
+}
+
+void initialize_dvopsps (int argc, char **argv) {
+
+  int N;
+  struct stat statbuffer;
+  char CatdirPhotcodeFile[256];
+
+  if ((N = get_argument (argc, argv, "-h"))) usage_dvopsps();
+  if ((N = get_argument (argc, argv, "-help"))) usage_dvopsps();
+  if ((N = get_argument (argc, argv, "--h"))) usage_dvopsps();
+  if ((N = get_argument (argc, argv, "--help"))) usage_dvopsps();
+
+  /* are these set correctly? */
+  ConfigInit (&argc, argv);
+  args_dvopsps (argc, argv);
+
+  if (stat (CATDIR, &statbuffer)) {
+    fprintf (stderr, "error accessing dvo database directory '%s'\n", CATDIR);
+    exit (1);
+  }
+
+  // load the photcode table
+  sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", CATDIR);
+  if (!LoadPhotcodes (CatdirPhotcodeFile, NULL, FALSE)) {
+    fprintf (stderr, "error loading photcode table %s\n", CatdirPhotcodeFile);
+    exit (1);
+  }
+}
+
+int args_dvopsps (int argc, char **argv) {
+
+  int N;
+
+  if ((N = get_argument (argc, argv, "-dbhost"))) {
+    remove_argument (N, &argc, argv);
+    DATABASE_HOST = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  } else usage_dvopsps();
+
+  if ((N = get_argument (argc, argv, "-dbuser"))) {
+    remove_argument (N, &argc, argv);
+    DATABASE_USER = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  } else usage_dvopsps();
+
+  if ((N = get_argument (argc, argv, "-dbpass"))) {
+    remove_argument (N, &argc, argv);
+    DATABASE_PASS = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  } else usage_dvopsps();
+
+  if ((N = get_argument (argc, argv, "-dbname"))) {
+    remove_argument (N, &argc, argv);
+    DATABASE_NAME = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  } else usage_dvopsps();
+
+  SINGLE_CPT = NULL;
+  if ((N = get_argument (argc, argv, "-cpt"))) {
+    remove_argument (N, &argc, argv);
+    SINGLE_CPT = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* specify portion of the sky : allow default of all sky? */
+  UserPatch.Rmin = 0;
+  UserPatch.Rmax = 360;
+  UserPatch.Dmin = -90;
+  UserPatch.Dmax = +90;
+  if ((N = get_argument (argc, argv, "-region"))) {
+    remove_argument (N, &argc, argv);
+    UserPatch.Rmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Rmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Dmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Dmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  } 
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  PARALLEL = FALSE;
+  if ((N = get_argument (argc, argv, "-parallel"))) {
+    PARALLEL = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  // this is a test mode : rather than launching the remote jobs and waiting for completion,
+  // dvopsps will simply list the remote command and wait for the user to signal completion
+  PARALLEL_MANUAL = FALSE;
+  if ((N = get_argument (argc, argv, "-parallel-manual"))) {
+    PARALLEL = TRUE; // -parallel-manual implies -parallel
+    PARALLEL_MANUAL = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  // this is a test mode : rather than launching the dvopsps_client jobs remotely, they are 
+  // run in serial via 'system'
+  PARALLEL_SERIAL = FALSE;
+  if ((N = get_argument (argc, argv, "-parallel-serial"))) {
+    if (PARALLEL_MANUAL) {
+      fprintf (stderr, "ERROR: cannot mix -parallel-manual and -parallel-serial\n");
+      exit (1);
+    }
+    PARALLEL = TRUE; // -parallel-serial implies -parallel
+    PARALLEL_SERIAL = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 2) usage_dvopsps();
+
+  return (TRUE);
+}
+
+void usage_dvopsps_client () {
+  fprintf (stderr, "USAGE: dvopsps_client [dbinfo] [hostinfo] [options]\n");
+  fprintf (stderr, "    dvo host info:\n");
+  fprintf (stderr, "    -hostID (ID)   : dvo host ID\n");
+  fprintf (stderr, "    -hostdir (dir) : local dvo catdir\n");
+  fprintf (stderr, "    -catdir  (dir) : master dvo catdir\n\n");
+  fprintf (stderr, "    mysql database info is supplied with these:\n");
+  fprintf (stderr, "    -dbhost : database host machine\n");
+  fprintf (stderr, "    -dbuser : database username\n");
+  fprintf (stderr, "    -dbpass : database password\n");
+  fprintf (stderr, "    -dbname : database name\n\n");
+  fprintf (stderr, "  options:\n");
+  fprintf (stderr, "    -v : verbose mode\n");
+  fprintf (stderr, "    -region Rmin Rmax Dmin Dmax\n");
+  fprintf (stderr, "    -parallel : run in parallel mode\n");
+  fprintf (stderr, "    -h     : this help list\n");
+  fprintf (stderr, "    -help  : this help list\n");
+  fprintf (stderr, "    --h    : this help list\n");
+  fprintf (stderr, "    --help : this help list\n");
+  fprintf (stderr, "    Note that the dvo db can be specified by -D CATDIR (directory)\n");
+  exit (2);
+}
+
+void initialize_dvopsps_client (int argc, char **argv) {
+
+  int N;
+  struct stat statbuffer;
+  char CatdirPhotcodeFile[256];
+
+  if ((N = get_argument (argc, argv, "-h"))) usage_dvopsps_client();
+  if ((N = get_argument (argc, argv, "-help"))) usage_dvopsps_client();
+  if ((N = get_argument (argc, argv, "--h"))) usage_dvopsps_client();
+  if ((N = get_argument (argc, argv, "--help"))) usage_dvopsps_client();
+
+  SetZeroPoint (25.0); // XXX is this needed?
+  args_dvopsps_client (argc, argv);
+
+  if (stat (CATDIR, &statbuffer)) {
+    fprintf (stderr, "error accessing dvo database directory '%s'\n", CATDIR);
+    exit (1);
+  }
+
+  // load the photcode table : XXX needed?
+  sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", CATDIR);
+  if (!LoadPhotcodes (CatdirPhotcodeFile, NULL, FALSE)) {
+    fprintf (stderr, "error loading photcode table %s\n", CatdirPhotcodeFile);
+    exit (1);
+  }
+}
+
+int args_dvopsps_client (int argc, char **argv) {
+
+  int N;
+
+  if ((N = get_argument (argc, argv, "-dbhost"))) {
+    remove_argument (N, &argc, argv);
+    DATABASE_HOST = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  } else usage_dvopsps_client();
+
+  if ((N = get_argument (argc, argv, "-dbuser"))) {
+    remove_argument (N, &argc, argv);
+    DATABASE_USER = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  } else usage_dvopsps_client();
+
+  if ((N = get_argument (argc, argv, "-dbpass"))) {
+    remove_argument (N, &argc, argv);
+    DATABASE_PASS = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  } else usage_dvopsps_client();
+
+  if ((N = get_argument (argc, argv, "-dbname"))) {
+    remove_argument (N, &argc, argv);
+    DATABASE_NAME = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  } else usage_dvopsps_client();
+
+  SINGLE_CPT = NULL;
+  if ((N = get_argument (argc, argv, "-cpt"))) {
+    remove_argument (N, &argc, argv);
+    SINGLE_CPT = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* specify portion of the sky : allow default of all sky? */
+  UserPatch.Rmin = 0;
+  UserPatch.Rmax = 360;
+  UserPatch.Dmin = -90;
+  UserPatch.Dmax = +90;
+  if ((N = get_argument (argc, argv, "-region"))) {
+    remove_argument (N, &argc, argv);
+    UserPatch.Rmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Rmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Dmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Dmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  } 
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  HOST_ID = 0;
+  if ((N = get_argument (argc, argv, "-hostID"))) {
+    remove_argument (N, &argc, argv);
+    HOST_ID = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!HOST_ID) usage_dvopsps_client();
+
+  HOSTDIR = NULL;
+  if ((N = get_argument (argc, argv, "-hostdir"))) {
+    remove_argument (N, &argc, argv);
+    HOSTDIR = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!HOSTDIR) usage_dvopsps_client();
+
+  if ((N = get_argument (argc, argv, "-catdir"))) {
+    remove_argument (N, &argc, argv);
+    CATDIR = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!CATDIR) usage_dvopsps_client();
+
+  if (argc != 2) usage_dvopsps_client();
+  return (TRUE);
+}
+
+void ConfigInit (int *argc, char **argv) {
+
+  double ZERO_POINT;
+  char  *config, *file;
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  config = LoadConfigFile (file);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find configuration file %s\n", file);
+    if (file != (char *) NULL) free (file);
+    exit (0);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  // force CATDIR to be absolute (so parallel mode will work)
+  char *tmpcatdir = NULL;
+  ALLOCATE (tmpcatdir, char, DVO_MAX_PATH);
+  GetConfig (config, "CATDIR",                 "%s",  0, tmpcatdir);
+  CATDIR = abspath (tmpcatdir, DVO_MAX_PATH);
+  free (tmpcatdir);
+
+  sprintf (ImageCat, "%s/Images.dat", CATDIR);
+
+  ScanConfig (config, "ZERO_PT",                "%lf", 0, &ZERO_POINT);
+  SetZeroPoint (ZERO_POINT);
+
+  free (config);
+  free (file);
+}
+
+void GetConfig (char *config, char *field, char *format, int N, void *ptr) {
+
+  char *status;
+
+  status = ScanConfig (config, field, format, N, ptr);
+  if (status == NULL) {
+    fprintf (stderr, "error in config, cannot find %s\n", field);
+    exit (1);
+  }
+  return;
+}
Index: branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/src/insert_detections_dvopsps.c
===================================================================
--- branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/src/insert_detections_dvopsps.c	(revision 34916)
+++ branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/src/insert_detections_dvopsps.c	(revision 34916)
@@ -0,0 +1,136 @@
+# include "dvopsps.h"
+
+// determine the relevant catalogs, launch parallel clients if desired
+int insert_detections_dvopsps () {
+
+  SkyTable *sky = NULL;
+  SkyList *skylist = NULL;
+  Catalog catalog;
+  off_t i;
+
+  // load the current sky table (layout of all SkyRegions) 
+  sky = SkyTableLoadOptimal (CATDIR, NULL, NULL, FALSE, -1, VERBOSE);
+  SkyTableSetFilenames (sky, CATDIR, "cpt");
+  
+  if (PARALLEL && !HOST_ID) {
+    int status = insert_detections_dvopsps_parallel (sky);
+    return status;
+  }
+
+  // determine the populated SkyRegions overlapping the requested area (default depth)
+  if (SINGLE_CPT) {
+      skylist = SkyRegionByCPT (sky, SINGLE_CPT);
+  } else {
+      skylist = SkyListByPatch (sky, -1, &UserPatch);
+  }
+  myAssert (skylist, "ooops!");
+
+  // NOTE: mysql connection happens here since each dvopsps_client makes its own connection
+  MYSQL  mysqlBase;
+  MYSQL *mysqlReal = mysql_dvopsps_connect (&mysqlBase);
+  if (!mysqlReal) {
+    fprintf (stderr, "failed to connect to mysql\n");
+    exit (1);
+  }
+
+  // select measurements for each populated catalog
+  for (i = 0; i < skylist[0].Nregions; i++) {
+
+    // does this host ID match the desired location for the table?
+    if (!HostTableTestHost(skylist[0].regions[i], HOST_ID)) continue;
+
+    char localFilename[1024];
+    snprintf (localFilename, 1024, "%s/%s.cpt", HOSTDIR, skylist->regions[i]->name);
+
+    // set up the basic catalog info
+    catalog.filename  = HOST_ID ? localFilename : skylist[0].filename[i];
+    catalog.catformat = DVO_FORMAT_UNDEF; // not needed since we skip empty catalogs
+    catalog.catmode   = DVO_MODE_UNDEF;	  // not needed since we skip empty catalogs
+    catalog.catflags  = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+    catalog.Nsecfilt  = GetPhotcodeNsecfilt ();
+
+    if (!dvo_catalog_open (&catalog, skylist[0].regions[i], VERBOSE, "w")) {
+      fprintf (stderr, "ERROR: failure reading catalog %s\n", catalog.filename);
+      exit (1);
+    }
+    if (!catalog.Naves_disk) {
+      if (VERBOSE) fprintf (stderr, "no data in %s, skipping\n", catalog.filename);
+      dvo_catalog_unlock (&catalog);
+      dvo_catalog_free (&catalog);
+      continue;
+    }
+
+    // NOTE: this is where the real action happens
+    insert_detections_dvopsps_catalog (&catalog, mysqlReal);
+
+    // NOTE : unlike setastrom or relphot, this program is read-only wrt dvo
+    dvo_catalog_unlock (&catalog);
+    dvo_catalog_free (&catalog);
+  }
+  return (TRUE);
+}      
+
+# define DEBUG 1
+
+int insert_detections_dvopsps_parallel (SkyTable *sky) {
+
+  // launch the dvopsps_client jobs to the parallel hosts
+
+  // load the list of hosts
+  HostTable *table = HostTableLoad (CATDIR, sky->hosts);
+
+  int i;
+  for (i = 0; i < table->Nhosts; i++) {
+
+    // ensure that the paths are absolute path names
+    char *tmppath = abspath (table->hosts[i].pathname, DVO_MAX_PATH);
+    free (table->hosts[i].pathname);
+    table->hosts[i].pathname = tmppath;
+
+    char command[1024];
+    snprintf (command, 1024, "dvopsps_client -hostID %d -catdir %s -hostdir %s -region %f %f %f %f", 
+	      table->hosts[i].hostID, CATDIR, table->hosts[i].pathname, 
+	      UserPatch.Rmin, UserPatch.Rmax, UserPatch.Dmin, UserPatch.Dmax);
+
+    fprintf (stderr, "command: %s\n", command);
+
+    char tmpline[1024];
+    snprintf (tmpline, 1024, "%s -dbhost %s", command, DATABASE_HOST); strcpy (command, tmpline);
+    snprintf (tmpline, 1024, "%s -dbuser %s", command, DATABASE_USER); strcpy (command, tmpline);
+    snprintf (tmpline, 1024, "%s -dbpass %s", command, DATABASE_PASS); strcpy (command, tmpline);
+    snprintf (tmpline, 1024, "%s -dbname %s", command, DATABASE_NAME); strcpy (command, tmpline);
+
+    if (VERBOSE) { snprintf (tmpline, 1024, "%s -v", command); strcpy (command, tmpline); }
+
+    if (PARALLEL_MANUAL) continue;
+
+    if (PARALLEL_SERIAL) {
+      int status = system (command);
+      if (status) {
+	fprintf (stderr, "ERROR running dvopsps_client\n");
+	exit (2);
+      }
+    } else {
+      // launch the job on the remote machine (no handshake)
+      int errorInfo = 0;
+      int pid = rconnect ("ssh", table->hosts[i].hostname, command, table->hosts[i].stdio, &errorInfo, FALSE);
+      if (!pid) {
+	if (DEBUG) fprintf (stderr, "failure to start %s (error %d)\n", table->hosts[i].hostname, errorInfo);
+	exit (1);
+      }
+      table->hosts[i].pid = pid; // save for future reference
+    }
+  }
+
+  // wait for the remote jobs to be completed
+  if (PARALLEL_MANUAL) {
+    fprintf (stderr, "run the dvopsps_client commands above.  when these are done, hit return\n");
+    getchar();
+  }
+  if (!PARALLEL_MANUAL && !PARALLEL_SERIAL) {
+    int status = HostTableWaitJobsGetIO (table, __FILE__, __LINE__, VERBOSE);
+    if (!status) return FALSE;
+  }
+
+  return (TRUE);
+}      
Index: branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/src/insert_detections_dvopsps_catalog.c
===================================================================
--- branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/src/insert_detections_dvopsps_catalog.c	(revision 34916)
+++ branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/src/insert_detections_dvopsps_catalog.c	(revision 34916)
@@ -0,0 +1,61 @@
+# include "dvopsps.h"
+
+int insert_detections_dvopsps_catalog (Catalog *catalog, MYSQL *mysql) {
+
+  off_t i, j;
+  int missingID = 0;
+
+  Average *average = catalog->average;
+  Measure *measure = catalog->measure;
+
+  off_t found = 0;
+
+  for (i = 0; i < catalog[0].Naverage; i++) {
+
+    if (average[i].extID == 0) {
+      missingID ++;
+    }
+
+    off_t m = average[i].measureOffset;
+    for (j = 0; j < average[i].Nmeasure; j++) {
+
+      // XXX check return status
+      insert_detections_mysql (&average[i], &measure[m+j], mysql);
+
+      found ++;
+    }
+  }
+
+  fprintf (stderr, "inserted "OFF_T_FMT" rows, skipped %d without IDs\n", found, missingID);
+  return (TRUE);
+}
+
+int insert_detections_mysql (Average *average, Measure *measure, MYSQL *mysql) {
+
+  // XXX length OK?
+  char sql[1024];
+
+  PhotCode *code = GetPhotcodebyCode(measure->photcode);
+  sprintf(sql, 
+	  "INSERT INTO dvoDetection (imageID, ippDetectID, detectID, ippObjID, objID, flags, zp, zpErr, airMass, expTime, ra, dec_, raErr, decErr) VALUES (%d, %u, %lu, %lu, %lu, %u, %f, %f, %f, %f, %lf, %lf, %f, %f)",
+	  measure->imageID,    // imageID
+	  measure->detID,   // ippDetectID
+	  measure->extID,   // detectID
+	  (uint64_t)average->catID*1000000000 + (uint64_t)average->objID, // ippObjID
+	  average->extID,   // objID
+	  measure->dbFlags,  // flags
+	  code->C * 0.001 + code->K * (measure->airmass - 1) - measure->Mcal,   // zp
+	  measure->dMcal,    // zpErr
+	  measure->airmass,
+	  pow(10.0, 0.4 * measure->dt),    // expTime
+	  average->R - measure->dR / 3600.,    // ra
+	  average->D - measure->dR / 3600.,    // dec
+	  measure->dXccd * 0.01 * fabs(measure->pltscale), // estimate of raErr
+	  measure->dYccd * 0.01 * fabs(measure->pltscale) // estimate of decErr
+    );
+  
+  // XXX check return status
+  mysql_query(mysql, sql); 
+
+  return TRUE;
+}
Index: branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/src/mysql_dvopsps.c
===================================================================
--- branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/src/mysql_dvopsps.c	(revision 34916)
+++ branches/eam_branches/ipp-20121219/Ohana/src/dvopsps/src/mysql_dvopsps.c	(revision 34916)
@@ -0,0 +1,38 @@
+# include "dvopsps.h"
+
+// DATABASE_* are supplied on the command line and are global variables in dvopsps.h
+MYSQL *mysql_dvopsps_connect (MYSQL *mysqlBase) {
+
+  char query[256];
+  MYSQL_RES *result;
+
+  mysql_init (mysqlBase);
+  MYSQL *connection = mysql_real_connect (mysqlBase, DATABASE_HOST, DATABASE_USER, DATABASE_PASS, DATABASE_NAME, 0, 0, 0);
+
+  if (connection == NULL) {
+    fprintf (stderr, "failed to connect to database\n");
+    fprintf (stderr, "%s\n", mysql_error (mysqlBase));
+    return NULL;
+  }
+    
+  sprintf (query, "set @@interactive_timeout = 30000");
+  if (mysql_query (connection, query)) {
+    fprintf (stderr, "failed to set interactive timout\n");
+    fprintf (stderr, "%s\n", mysql_error (connection));
+    return NULL;
+  }
+  result = mysql_store_result (connection);
+  mysql_free_result (result);
+    
+  sprintf (query, "set @@wait_timeout = 30000");
+  if (mysql_query (connection, query)) {
+    fprintf (stderr, "failed to set wait timout\n");
+    fprintf (stderr, "%s\n", mysql_error (connection));
+    return NULL;
+  }
+  result = mysql_store_result (connection);
+  mysql_free_result (result);
+    
+  return connection;
+}
+
