Index: /branches/eam_branches/ipp-20130307/Ohana/src/dvomerge/Makefile
===================================================================
--- /branches/eam_branches/ipp-20130307/Ohana/src/dvomerge/Makefile	(revision 35332)
+++ /branches/eam_branches/ipp-20130307/Ohana/src/dvomerge/Makefile	(revision 35333)
@@ -23,5 +23,5 @@
 dvoverify_client : $(BIN)/dvoverify_client.$(ARCH)
 
-all: dvomerge dvomerge_client dvoconvert dvosecfilt dvoverify dvoverify_client
+all: dvomerge dvomerge_client dvoconvert dvosecfilt dvosecfilt_client dvoverify dvoverify_client
 
 #  $(SRC)/dvomergeContinue.$(ARCH).o
@@ -93,4 +93,5 @@
 DVOSECFILT = \
 $(SRC)/dvosecfilt.$(ARCH).o \
+$(SRC)/dvosecfilt_catalogs.$(ARCH).o \
 $(SRC)/SetSignals.$(ARCH).o \
 $(SRC)/ConfigInit.$(ARCH).o \
@@ -101,4 +102,16 @@
 $(DVOSECFILT)  : $(INC)/dvomerge.h
 $(BIN)/dvosecfilt.$(ARCH) : $(DVOSECFILT)
+
+DVOSECFILT_CLIENT = \
+$(SRC)/dvosecfilt_client.$(ARCH).o \
+$(SRC)/dvosecfilt_catalogs.$(ARCH).o \
+$(SRC)/SetSignals.$(ARCH).o \
+$(SRC)/ConfigInit.$(ARCH).o \
+$(SRC)/Shutdown.$(ARCH).o \
+$(SRC)/help.$(ARCH).o \
+$(SRC)/args.$(ARCH).o
+
+$(DVOSECFILT_CLIENT)  : $(INC)/dvomerge.h
+$(BIN)/dvosecfilt_client.$(ARCH) : $(DVOSECFILT_CLIENT)
 
 DVOREPAIR = \
@@ -136,5 +149,5 @@
 $(BIN)/dvoverify_client.$(ARCH) : $(DVOVERIFY_CLIENT)
 
-INSTALL = dvomerge dvomerge_client dvoconvert dvosecfilt dvorepair dvoverify dvoverify_client
+INSTALL = dvomerge dvomerge_client dvoconvert dvosecfilt dvosecfilt_client dvorepair dvoverify dvoverify_client
 
 # dependancy rules for binary code #########################
Index: /branches/eam_branches/ipp-20130307/Ohana/src/dvomerge/include/dvomerge.h
===================================================================
--- /branches/eam_branches/ipp-20130307/Ohana/src/dvomerge/include/dvomerge.h	(revision 35332)
+++ /branches/eam_branches/ipp-20130307/Ohana/src/dvomerge/include/dvomerge.h	(revision 35333)
@@ -104,4 +104,11 @@
 int  	   dvosecfilt_args	  PROTO((int *argc, char **argv));
 
+void       dvosecfilt_client_usage PROTO((void));
+void 	   dvosecfilt_client_help  PROTO((int argc, char **argv));
+int  	   dvosecfilt_client_args  PROTO((int *argc, char **argv));
+
+int        dvosecfilt_catalogs     PROTO((SkyTable *insky, int Nsecfilt));
+int        dvosecfilt_parallel     PROTO((SkyTable *insky, int Nsecfilt));
+
 int        SkyTablePopulatedRange PROTO((off_t *ns, off_t *ne, SkyTable *sky, off_t Nstart));
 int        SkyListPopulatedRange  PROTO((off_t *ns, off_t *ne, SkyList *sky, off_t Nstart));
Index: /branches/eam_branches/ipp-20130307/Ohana/src/dvomerge/src/args.c
===================================================================
--- /branches/eam_branches/ipp-20130307/Ohana/src/dvomerge/src/args.c	(revision 35332)
+++ /branches/eam_branches/ipp-20130307/Ohana/src/dvomerge/src/args.c	(revision 35333)
@@ -170,8 +170,36 @@
   int N;
 
-  /* extra error messages */
-  VERBOSE = FALSE;
-  if ((N = get_argument (*argc, argv, "-v"))) {
-    VERBOSE = TRUE;
+  HOST_ID = 0;
+
+  /* extra error messages */
+  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,
+  // relphot 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 relphot_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);
   }
@@ -180,2 +208,39 @@
   return TRUE;
 }
+
+/*** check for command line options ***/
+int dvosecfilt_client_args (int *argc, char **argv) {
+  
+  int N;
+
+  // by definition, the client is not parallel 
+  PARALLEL = FALSE;
+  PARALLEL_MANUAL = FALSE;
+  PARALLEL_SERIAL = FALSE;
+
+  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) dvosecfilt_client_usage();
+
+  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) dvosecfilt_client_usage();
+
+  /* extra error messages */
+  VERBOSE = FALSE;
+  if ((N = get_argument (*argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  if (*argc != 3) dvosecfilt_client_usage();
+  return TRUE;
+}
Index: /branches/eam_branches/ipp-20130307/Ohana/src/dvomerge/src/dvosecfilt.c
===================================================================
--- /branches/eam_branches/ipp-20130307/Ohana/src/dvomerge/src/dvosecfilt.c	(revision 35332)
+++ /branches/eam_branches/ipp-20130307/Ohana/src/dvomerge/src/dvosecfilt.c	(revision 35333)
@@ -3,10 +3,4 @@
 // modify the number of average photcodes : change only secfilt tables in place
 int main (int argc, char **argv) {
-
-  char filename[256], *input;
-  off_t i, j, k, Nsecfilt, NsecInput, Nstart;
-  SkyTable *insky;
-  Catalog catalog;
-  SecFilt *insec, *outsec;
 
   SetSignals ();
@@ -15,75 +9,12 @@
   dvosecfilt_args (&argc, argv);
 
-  input = argv[1];
-  Nsecfilt = atoi(argv[2]);
+  strcpy (CATDIR, argv[1]);
+  int Nsecfilt = atoi(argv[2]);
 
   // load the sky table for the existing database
-  insky = SkyTableLoadOptimal (input, NULL, NULL, FALSE, SKY_DEPTH_HST, VERBOSE);
-  SkyTableSetFilenames (insky, input, "cpt");
+  SkyTable *insky = SkyTableLoadOptimal (CATDIR, NULL, NULL, FALSE, SKY_DEPTH_HST, VERBOSE);
+  SkyTableSetFilenames (insky, CATDIR, "cpt");
 
-  // loop over all input catalogs
-  for (i = 0; i < insky[0].Nregions; i++) {
-    if (!insky[0].regions[i].table) continue;
-    if (VERBOSE) fprintf (stderr, "table: %s\n", insky[0].regions[i].name);
-
-    // set the parameters which guide catalog open/load/create
-    catalog.filename  = insky[0].filename[i];
-    catalog.Nsecfilt  = 0;
-
-    // always load all of the data (if any exists)
-    catalog.catflags  = LOAD_SECF;
-    catalog.catformat = dvo_catalog_catformat (CATFORMAT);  // set the default catformat from config data
-    catalog.catmode   = dvo_catalog_catmode (CATMODE);      // set the default catmode from config data
-
-    if (!dvo_catalog_open (&catalog, &insky[0].regions[i], VERBOSE, "w")) {
-	fprintf (stderr, "ERROR: failure to open catalog file %s\n", filename);
-	exit (2);
-    }
-
-    if (catalog.Naves_disk == 0) {
-      dvo_catalog_unlock (&catalog);
-      dvo_catalog_free (&catalog);
-      continue;
-    }
-
-    if (Nsecfilt == catalog.Nsecfilt) {
-      dvo_catalog_unlock (&catalog);
-      dvo_catalog_free (&catalog);
-      continue;
-    }
-
-    NsecInput = catalog.Nsecfilt;
-    Nstart = MIN(Nsecfilt, NsecInput);
-
-    insec = catalog.secfilt;
-    ALLOCATE (outsec, SecFilt, catalog.Naves_disk * Nsecfilt);
-
-    for (k = 0; k < catalog.Naves_disk; k++) {
-      for (j = 0; (j < catalog.Nsecfilt) && (j < Nsecfilt); j++) {
-	outsec[k*Nsecfilt + j].M  = insec[k*NsecInput + j].M;
-	outsec[k*Nsecfilt + j].dM = insec[k*NsecInput + j].dM;
-	outsec[k*Nsecfilt + j].Xm = insec[k*NsecInput + j].Xm;
-	outsec[k*Nsecfilt + j].flags  = insec[k*NsecInput + j].flags;
-	outsec[k*Nsecfilt + j].Ncode  = insec[k*NsecInput + j].Ncode;
-	outsec[k*Nsecfilt + j].Nused  = insec[k*NsecInput + j].Nused;
-	outsec[k*Nsecfilt + j].M_20   = insec[k*NsecInput + j].M_20;
-	outsec[k*Nsecfilt + j].M_80   = insec[k*NsecInput + j].M_80;
-      }
-      for (j = Nstart; j < Nsecfilt; j++) {
-	outsec[k*Nsecfilt + j].M  = NAN;
-	outsec[k*Nsecfilt + j].dM = NAN;
-	outsec[k*Nsecfilt + j].Xm = NAN_S_SHORT;
-      }
-    }
-    free (catalog.secfilt);
-    catalog.secfilt = outsec;
-    catalog.Nsecfilt = Nsecfilt;
-    catalog.Nsecf_mem = Nsecfilt * catalog.Naves_disk;
-    catalog.Nsecf_disk = Nsecfilt * catalog.Naves_disk;
-
-    dvo_catalog_save (&catalog, VERBOSE);
-    dvo_catalog_unlock (&catalog);
-    dvo_catalog_free (&catalog);
-  }
+  dvosecfilt_catalogs (insky, Nsecfilt);
 
   exit (0);
Index: /branches/eam_branches/ipp-20130307/Ohana/src/dvomerge/src/dvosecfilt_catalogs.c
===================================================================
--- /branches/eam_branches/ipp-20130307/Ohana/src/dvomerge/src/dvosecfilt_catalogs.c	(revision 35333)
+++ /branches/eam_branches/ipp-20130307/Ohana/src/dvomerge/src/dvosecfilt_catalogs.c	(revision 35333)
@@ -0,0 +1,139 @@
+# include "dvomerge.h"
+
+int dvosecfilt_catalogs (SkyTable *insky, int Nsecfilt) {
+
+  off_t i, j, k, NsecInput, Nstart;
+  Catalog catalog;
+  SecFilt *insec, *outsec;
+  char filename[DVO_MAX_PATH];
+
+  if (PARALLEL && !HOST_ID) {
+    int status = dvosecfilt_parallel (insky, Nsecfilt);
+    return status;
+  }
+
+  // loop over all input catalogs
+  for (i = 0; i < insky[0].Nregions; i++) {
+    if (!insky[0].regions[i].table) continue;
+    if (VERBOSE) fprintf (stderr, "table: %s\n", insky[0].regions[i].name);
+
+    // does this host ID match the desired location for the table?
+    if (!HostTableTestHost(&insky[0].regions[i], HOST_ID)) continue;
+
+    char hostfile[1024];
+    snprintf (hostfile, 1024, "%s/%s.cpt", HOSTDIR, insky[0].regions[i].name);
+    catalog.filename  = HOST_ID ? hostfile : insky[0].filename[i];
+
+    // always load all of the data (if any exists)
+    catalog.Nsecfilt  = 0;
+    catalog.catflags  = LOAD_SECF;  // XXX this will fail for MEF version
+    catalog.catformat = dvo_catalog_catformat (CATFORMAT);  // set the default catformat from config data
+    catalog.catmode   = dvo_catalog_catmode (CATMODE);      // set the default catmode from config data
+
+    if (!dvo_catalog_open (&catalog, &insky[0].regions[i], VERBOSE, "w")) {
+	fprintf (stderr, "ERROR: failure to open catalog file %s\n", filename);
+	exit (2);
+    }
+
+    if (catalog.Naves_disk == 0) {
+      dvo_catalog_unlock (&catalog);
+      dvo_catalog_free (&catalog);
+      continue;
+    }
+
+    if (Nsecfilt == catalog.Nsecfilt) {
+      dvo_catalog_unlock (&catalog);
+      dvo_catalog_free (&catalog);
+      continue;
+    }
+
+    NsecInput = catalog.Nsecfilt;
+    Nstart = MIN(Nsecfilt, NsecInput);
+
+    insec = catalog.secfilt;
+    ALLOCATE (outsec, SecFilt, catalog.Naves_disk * Nsecfilt);
+
+    for (k = 0; k < catalog.Naves_disk; k++) {
+      for (j = 0; (j < catalog.Nsecfilt) && (j < Nsecfilt); j++) {
+	outsec[k*Nsecfilt + j] = insec[k*NsecInput + j];
+      }
+      for (j = Nstart; j < Nsecfilt; j++) {
+	dvo_secfilt_init (&outsec[k*Nsecfilt + j]);
+      }
+    }
+    free (catalog.secfilt);
+    catalog.secfilt = outsec;
+    catalog.Nsecfilt = Nsecfilt;
+    catalog.Nsecf_mem = Nsecfilt * catalog.Naves_disk;
+    catalog.Nsecf_disk = Nsecfilt * catalog.Naves_disk;
+
+    dvo_catalog_save (&catalog, VERBOSE);
+    dvo_catalog_unlock (&catalog);
+    dvo_catalog_free (&catalog);
+  }
+
+  return TRUE;
+}
+
+// launch the dvosecfilt_client jobs to the parallel hosts
+int dvosecfilt_parallel (SkyTable *insky, int Nsecfilt) {
+
+  // ensure that the paths are absolute path names
+  char *abscatdir = abspath (CATDIR, DVO_MAX_PATH);
+
+  // load the list of hosts
+  HostTable *table = HostTableLoad (CATDIR, insky->hosts);
+  if (!table) {
+    fprintf (stderr, "ERROR: failure reading Host Table %s for database %s\n", insky->hosts, CATDIR);
+    exit (1);
+  }    
+
+  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;
+
+    // options / arguments that can affect relastro_client -update-objects:
+    char command[DVO_MAX_PATH];
+    snprintf (command, DVO_MAX_PATH, "dvosecfilt_client %s %d -hostID %d -hostdir %s", 
+	      abscatdir, Nsecfilt, table->hosts[i].hostID, table->hosts[i].pathname
+      );
+
+    char tmpline[DVO_MAX_PATH];
+    if (VERBOSE)         { snprintf (tmpline, DVO_MAX_PATH, "%s -v", command); strcpy (command, tmpline); }
+
+    fprintf (stderr, "command: %s\n", command);
+
+    if (PARALLEL_MANUAL) continue;
+
+    if (PARALLEL_SERIAL) {
+      int status = system (command);
+      if (status) {
+	fprintf (stderr, "ERROR running photdbc_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) {
+	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
+    }
+  }
+
+  if (PARALLEL_MANUAL) {
+    fprintf (stderr, "run the photdbc_client commands above.  when these are done, hit return\n");
+    getchar();
+  }
+  if (!PARALLEL_MANUAL && !PARALLEL_SERIAL) {
+    HostTableWaitJobsGetIO (table, __FILE__, __LINE__, VERBOSE);
+  }
+
+  return TRUE;
+}      
Index: /branches/eam_branches/ipp-20130307/Ohana/src/dvomerge/src/dvosecfilt_client.c
===================================================================
--- /branches/eam_branches/ipp-20130307/Ohana/src/dvomerge/src/dvosecfilt_client.c	(revision 35333)
+++ /branches/eam_branches/ipp-20130307/Ohana/src/dvomerge/src/dvosecfilt_client.c	(revision 35333)
@@ -0,0 +1,21 @@
+# include "dvomerge.h"
+
+// modify the number of average photcodes : change only secfilt tables in place
+int main (int argc, char **argv) {
+
+  SetSignals ();
+  dvosecfilt_client_help (argc, argv);
+  ConfigInit (&argc, argv);
+  dvosecfilt_client_args (&argc, argv);
+
+  strcpy (CATDIR, argv[1]);
+  int Nsecfilt = atoi(argv[2]);
+
+  // load the sky table for the existing database
+  SkyTable *insky = SkyTableLoadOptimal (CATDIR, NULL, NULL, FALSE, SKY_DEPTH_HST, VERBOSE);
+  SkyTableSetFilenames (insky, CATDIR, "cpt");
+
+  dvosecfilt_catalogs (insky, Nsecfilt);
+
+  exit (0);
+}
Index: /branches/eam_branches/ipp-20130307/Ohana/src/dvomerge/src/help.c
===================================================================
--- /branches/eam_branches/ipp-20130307/Ohana/src/dvomerge/src/help.c	(revision 35332)
+++ /branches/eam_branches/ipp-20130307/Ohana/src/dvomerge/src/help.c	(revision 35333)
@@ -25,5 +25,16 @@
 void dvosecfilt_usage(void) {
 
-  fprintf (stderr, "USAGE: dvosecfilt (catdir) (Nsecfilt)\n");
+  fprintf (stderr, "USAGE: dvosecfilt (catdir) (Nsecfilt)\n\n");
+  fprintf (stderr, "  optional flags:\n");
+  fprintf (stderr, "  -v                    	  : verbose mode\n");
+
+  exit (2);
+}
+
+void dvosecfilt_client_usage(void) {
+
+  fprintf (stderr, "USAGE: dvosecfilt_client (catdir) (Nsecfilt)\n\n");
+  fprintf (stderr, "  optional flags:\n");
+  fprintf (stderr, "  -v                    	  : verbose mode\n");
 
   exit (2);
@@ -123,4 +134,26 @@
 }
 
+void dvosecfilt_client_help (int argc, char **argv) {
+
+  /* check for help request */
+  if (get_argument (argc, argv, "-help")) goto show_help;
+  if (get_argument (argc, argv, "-h"))    goto show_help;
+  return;
+
+show_help:
+
+  fprintf (stderr, "USAGE\n");
+  fprintf (stderr, "  dvosecfilt_client (catdir) (Nsecfilt)\n\n");
+
+  fprintf (stderr, "  change number of secfilt entries in photcode table (updates secfilt tables (cps), NSECFILT in cpt files)\n");
+  fprintf (stderr, "  NOTE: the user must change the photcode table to reflect the change (use photcode-table -export / -import)\n");
+ 
+  fprintf (stderr, "  optional flags:\n");
+  fprintf (stderr, "  -v                    	  : verbose mode\n");
+  fprintf (stderr, "  -help                 	  : this list\n");
+  fprintf (stderr, "  -h                    	  : this list\n\n");
+  exit (2);
+}
+
 void dvorepair_help (int argc, char **argv) {
 
