Index: branches/eam_branches/ipp-20140206/Ohana/src/libdvo/include/dvo.h
===================================================================
--- branches/eam_branches/ipp-20140206/Ohana/src/libdvo/include/dvo.h	(revision 36558)
+++ branches/eam_branches/ipp-20140206/Ohana/src/libdvo/include/dvo.h	(revision 36562)
@@ -303,4 +303,6 @@
   int pid;		      // remote process ID
   int status;
+  IOBuffer stdout;
+  IOBuffer stderr;
 
   off_t Nimage;
@@ -899,4 +901,5 @@
 RegionHostTable *RegionHostTableLoad (char *catdir, char *rootname);
 int RegionHostTableWaitJobs (RegionHostTable *regionHosts, char *file, int lineno);
+int RegionHostTableWaitJobsGetIO (RegionHostTable *regionHosts, char *file, int lineno, int VERBOSE);
 
 # endif // DVO_H
Index: branches/eam_branches/ipp-20140206/Ohana/src/libdvo/src/RegionHostTable.c
===================================================================
--- branches/eam_branches/ipp-20140206/Ohana/src/libdvo/src/RegionHostTable.c	(revision 36558)
+++ branches/eam_branches/ipp-20140206/Ohana/src/libdvo/src/RegionHostTable.c	(revision 36562)
@@ -122,4 +122,7 @@
     hosts[Nhosts].hostID = ID;
     hosts[Nhosts].hostname = strcreate(tmphost);
+
+    InitIOBuffer (&hosts[Nhosts].stdout, 1000);
+    InitIOBuffer (&hosts[Nhosts].stderr, 1000);
 
     hosts[Nhosts].Rmin = Rmin;
@@ -169,12 +172,12 @@
 
 // wait for all children to complete, report output to stdout
-int RegionHostTableWaitJobs (RegionHostTable *regionHosts, char *file, int lineno) {
+int RegionHostTableWaitJobs (RegionHostTable *table, char *file, int lineno) {
 
   int i;
 
-  // we have launched regionHosts->Nhosts jobs; wait for all of them to complete...
+  // we have launched table->Nhosts jobs; wait for all of them to complete...
   // if one (N) failed to launch, we will get an ECHILD error from the last (N) calls
   int done = FALSE;
-  for (i = 0; !done  && (i < regionHosts->Nhosts); i++) {
+  for (i = 0; !done  && (i < table->Nhosts); i++) {
     int status = 0;
 
@@ -202,14 +205,14 @@
     int Nout, j;
     int found = FALSE;
-    for (j = 0; j < regionHosts->Nhosts; j++) {
-      if (regionHosts->hosts[j].pid != pid) continue;
+    for (j = 0; j < table->Nhosts; j++) {
+      if (table->hosts[j].pid != pid) continue;
       found = TRUE;
       // check on the status of this and report any output?
-      fprintf (stderr, "job finished for %s (%d)\n", regionHosts->hosts[j].hostname, pid);
+      fprintf (stderr, "job finished for %s (%d)\n", table->hosts[j].hostname, pid);
       // read the stderr and stdout
       IOBuffer buffer;
       InitIOBuffer (&buffer, 100);
-      EmptyIOBuffer (&buffer, 100, regionHosts->hosts[j].stdio[HOST_STDOUT]);
-      fprintf (stderr, "--- stdout from %s ---\n", regionHosts->hosts[j].hostname);
+      EmptyIOBuffer (&buffer, 100, table->hosts[j].stdio[HOST_STDOUT]);
+      fprintf (stderr, "--- stdout from %s ---\n", table->hosts[j].hostname);
       Nout = write (STDOUT_FILENO, buffer.buffer, buffer.Nbuffer);
       if (Nout != buffer.Nbuffer) { fprintf (stderr, "(error writing log?)\n"); }
@@ -217,6 +220,6 @@
 	  
       InitIOBuffer (&buffer, 100);
-      EmptyIOBuffer (&buffer, 100, regionHosts->hosts[j].stdio[HOST_STDERR]);
-      fprintf (stderr, "--- stderr from %s ---\n", regionHosts->hosts[j].hostname);
+      EmptyIOBuffer (&buffer, 100, table->hosts[j].stdio[HOST_STDERR]);
+      fprintf (stderr, "--- stderr from %s ---\n", table->hosts[j].hostname);
       Nout = write (STDOUT_FILENO, buffer.buffer, buffer.Nbuffer);
       if (Nout != buffer.Nbuffer) { fprintf (stderr, "(error writing log?)\n"); }
@@ -224,12 +227,12 @@
       if (WIFEXITED(status)) {
 	fprintf (stderr, "normal completion, exit status is %d\n", WEXITSTATUS(status));
-	regionHosts->hosts[j].status = WEXITSTATUS(status);
-	if (regionHosts->hosts[j].status) {
-	  fprintf (stderr, "job failed on %s\n", regionHosts->hosts[j].hostname);
+	table->hosts[j].status = WEXITSTATUS(status);
+	if (table->hosts[j].status) {
+	  fprintf (stderr, "job failed on %s\n", table->hosts[j].hostname);
 	  continue;
 	}
       } else {
-	regionHosts->hosts[j].status = -1;
-	fprintf (stderr, "job exited abnormally on %s\n", regionHosts->hosts[j].hostname);
+	table->hosts[j].status = -1;
+	fprintf (stderr, "job exited abnormally on %s\n", table->hosts[j].hostname);
 	continue;
       }
@@ -243,2 +246,178 @@
 }
 
+
+// wait for all children to complete, report output to stdout
+int RegionHostTableWaitJobsGetIO (RegionHostTable *table, char *file, int lineno, int VERBOSE) {
+
+  // we have launched table->Nhosts jobs; wait for all of them to complete...
+  // if one (N) failed to launch, we will get an ECHILD error from the last (N) calls
+
+  // we need to read any data waiting on stderr or stdout from these jobs, or the overfull
+  // buffers can cause a problem.  we alternate between 'select' and 'waitpid' calls with
+  // timeouts for both
+
+  // add all hosts' sockets to the fd_sets
+  fd_set rdSet, wtSet;
+  FD_ZERO (&rdSet);
+  FD_ZERO (&wtSet);
+
+  // XXX can I set the fd_sets once, since I am not actually closing the fd's?
+
+  int globalStatus = TRUE;
+
+  int i;
+  int Nmax = 0;
+  for (i = 0; i < table->Nhosts; i++) {
+    if (!table->hosts[i].pid) continue; // any unconnected hosts should be skipped
+    FD_SET (table->hosts[i].stdio[HOST_STDIN], &wtSet);
+    Nmax = MAX (Nmax, table->hosts[i].stdio[HOST_STDIN]);
+    FD_SET (table->hosts[i].stdio[HOST_STDOUT], &rdSet);
+    Nmax = MAX (Nmax, table->hosts[i].stdio[HOST_STDOUT]);
+    FD_SET (table->hosts[i].stdio[HOST_STDERR], &rdSet);
+    Nmax = MAX (Nmax, table->hosts[i].stdio[HOST_STDERR]);
+  }    
+  Nmax ++;
+
+  // need the list of connected hosts for exit test below
+  int Nrunning = 0;
+  for (i = 0; i < table->Nhosts; i++) {
+    if (!table->hosts[i].pid) continue; // any unconnected hosts should be skipped
+    Nrunning ++;
+  }
+
+  int Nfound = 0;
+
+  // this loop has 2 chunks: (a) check for I/O + (b) check for jobs done
+  while (1) {
+
+    // Wait up to 0.5 second for host to provide I/O
+    // timeout gets mucked: need to reset before each select
+    struct timeval timeout;
+    timeout.tv_sec = 10;
+    timeout.tv_usec = 500000;
+
+    int status = select (Nmax, NULL, &wtSet, NULL, &timeout);
+    if (status == -1) {
+      perror("select()");
+      exit (2);
+    }
+
+    // we have some sockets to check, check sockets for all hosts
+    for (i = 0; (status > 0) && (i < table->Nhosts); i++) {
+      if (!table->hosts[i].pid) continue; // any unconnected hosts should be skipped
+
+      if (FALSE && FD_ISSET (table->hosts[i].stdio[HOST_STDIN], &wtSet)) {
+	// this host is waiting for input : this is an error, so exit
+	fprintf (stderr, "host %s is waiting for input\n", table->hosts[i].hostname);
+	abort();
+      }
+      
+      if ((table->hosts[i].stdio[HOST_STDOUT] > 0) && FD_ISSET (table->hosts[i].stdio[HOST_STDOUT], &rdSet)) {
+	// this host has waiting output : read to buffer, and dump if necessary
+	ReadtoIOBuffer (&table->hosts[i].stdout, table->hosts[i].stdio[HOST_STDOUT]);
+	// if (table->hosts[i].stdout.Nbuffer > 0x10000) {
+	if (table->hosts[i].stdout.Nbuffer > 0x1000) {
+	  int printHead = VERBOSE || (table->hosts[i].stdout.Nbuffer > 0);
+	  if (printHead) fprintf (stdout, "--- stdout from %s --- (%d bytes, v1)\n", table->hosts[i].hostname, table->hosts[i].stdout.Nbuffer);
+	  int Nout = write (STDOUT_FILENO, table->hosts[i].stdout.buffer, table->hosts[i].stdout.Nbuffer);
+	  if (Nout != table->hosts[i].stdout.Nbuffer) { fprintf (stderr, "(error writing log?)\n"); }
+	  FlushIOBuffer (&table->hosts[i].stdout);
+	  if (printHead) fprintf (stdout, "\n");
+	}
+      }
+
+      if ((table->hosts[i].stdio[HOST_STDERR] > 0) && FD_ISSET (table->hosts[i].stdio[HOST_STDERR], &rdSet)) {
+	// this host has waiting output : read to buffer, and dump if necessary
+	ReadtoIOBuffer (&table->hosts[i].stderr, table->hosts[i].stdio[HOST_STDERR]);
+	// if (table->hosts[i].stderr.Nbuffer > 0x10000) {
+	if (table->hosts[i].stderr.Nbuffer > 0x1000) {
+	  int printHead = VERBOSE || (table->hosts[i].stderr.Nbuffer > 0);
+	  if (printHead) fprintf (stdout, "--- stderr from %s --- (%d bytes, v1)\n", table->hosts[i].hostname, table->hosts[i].stderr.Nbuffer);
+	  int Nout = write (STDOUT_FILENO, table->hosts[i].stderr.buffer, table->hosts[i].stderr.Nbuffer);
+	  if (Nout != table->hosts[i].stderr.Nbuffer) { fprintf (stderr, "(error writing log?)\n"); }
+	  FlushIOBuffer (&table->hosts[i].stderr);
+	  if (printHead) fprintf (stdout, "\n");
+	}
+      }
+    }
+
+    // now check if any children have finished...
+    while (TRUE) {
+      int status = 0;
+      int pid = waitpid (-1, &status, WNOHANG);
+      if (!pid) {
+	// fprintf (stderr, "no hosts to harvest\n");
+	usleep (500000);
+	break; // no outstanding jobs have finished 
+      }
+      if ((pid == -1) && (errno == ECHILD)) goto escape; // no more jobs on which to wait
+      if ((pid == -1) && (errno != ECHILD)) {
+	fprintf (stderr, "programming error (2)? %s %d", file, lineno);
+	exit (2);
+      }
+
+      // find the host which has finished
+      int found = FALSE;
+      for (i = 0; (i < table->Nhosts) && !found; i++) {
+	if (table->hosts[i].pid != pid) continue;
+	found = TRUE;
+
+	RegionHostInfo *host = &table->hosts[i];
+
+	// check on the status of this and report any output?
+	if (VERBOSE) fprintf (stdout, "job finished for %s (%d)\n", host->hostname, pid);
+
+	// read stdout
+	int printHead;
+	printHead = VERBOSE || (host->stdout.Nbuffer > 0);
+	EmptyIOBuffer (&host->stdout, 100, host->stdio[HOST_STDOUT]);
+	if (printHead) fprintf (stdout, "--- stdout from %s --- (%d bytes, v2)\n", host->hostname, host->stdout.Nbuffer);
+	int Nout = write (STDOUT_FILENO, host->stdout.buffer, host->stdout.Nbuffer);
+	if (Nout != host->stdout.Nbuffer) { fprintf (stderr, "(error writing log?)\n"); }
+	FlushIOBuffer (&host->stdout);
+	if (printHead) fprintf (stdout, "\n");
+	    
+	// read stderr
+	printHead = VERBOSE || (host->stderr.Nbuffer > 0);
+	EmptyIOBuffer (&host->stderr, 100, host->stdio[HOST_STDERR]);
+	if (printHead) fprintf (stdout, "--- stderr from %s --- (%d bytes, v2)\n", host->hostname, host->stderr.Nbuffer);
+	Nout = write (STDOUT_FILENO, host->stderr.buffer, host->stderr.Nbuffer);
+	if (Nout != host->stderr.Nbuffer) { fprintf (stderr, "(error writing log?)\n"); }
+	FlushIOBuffer (&host->stderr);
+	if (printHead) fprintf (stdout, "\n");
+
+	if (WIFEXITED(status)) {
+	  if (VERBOSE) fprintf (stdout, "normal completion, exit status is %d\n", WEXITSTATUS(status));
+	  host->status = WEXITSTATUS(status);
+	  if (host->status) {
+	    fprintf (stdout, "job failed on %s\n", host->hostname);
+	    globalStatus = FALSE;
+	  }
+	} else {
+	  host->status = -1;
+	  fprintf (stdout, "job exited abnormally on %s\n", host->hostname);
+	  globalStatus = FALSE;
+	  continue;
+	}
+      }
+      if (!found) {
+	fprintf (stderr, "Programming error: failed to matched finished job to known host!\n");
+	exit (2);
+      }
+      Nfound ++;
+      if (Nfound == Nrunning) goto escape; // we've harvested all jobs
+    }
+  }
+
+escape:
+
+  // close all opened connections
+  for (i = 0; i < table->Nhosts; i++) {
+    if (!table->hosts[i].pid) continue; // any unconnected hosts should be skipped
+    close (table->hosts[i].stdio[HOST_STDIN]);
+    close (table->hosts[i].stdio[HOST_STDOUT]);
+    close (table->hosts[i].stdio[HOST_STDERR]);
+  }
+
+  return globalStatus;
+}
Index: branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/BrightCatalog.c
===================================================================
--- branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/BrightCatalog.c	(revision 36558)
+++ branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/BrightCatalog.c	(revision 36562)
@@ -101,4 +101,5 @@
       measure[i].catID     = catID[i];
       measure[i].photcode  = photcode[i];
+      measure[i].myDet     = FALSE;
     }
     fprintf (stderr, "loaded data for %lld measure\n", (long long) Nrow);
@@ -141,4 +142,5 @@
     GET_COLUMN(flags,         "FLAGS",       int);
     GET_COLUMN(catID,         "CAT_ID",      int);
+    GET_COLUMN(objID,         "OBJ_ID",      int);
     gfits_free_header (&theader);
     gfits_free_table  (&ftable);
@@ -153,4 +155,6 @@
       average[i].flags          = flags[i];
       average[i].catID          = catID[i];
+      average[i].objID          = objID[i];
+      average[i].nOwn           = 0;
     }
     fprintf (stderr, "loaded data for %lld average\n", (long long) Nrow);
@@ -162,4 +166,5 @@
     free (flags         );
     free (catID         );
+    free (objID         );
 
     catalog->average = average;
@@ -370,4 +375,5 @@
     gfits_define_bintable_column (&theader, "J", "FLAGS",       "flags",                  NULL,    1.0, 0.0);
     gfits_define_bintable_column (&theader, "J", "CAT_ID",      "catalog ref",            NULL,    1.0, 0.0);
+    gfits_define_bintable_column (&theader, "J", "OBJ_ID",      "object ref",             NULL,    1.0, 0.0);
 
     // generate the output array that carries the data
@@ -381,4 +387,5 @@
     int   *flags          ; ALLOCATE (flags,         int,    catalog->Naverage);
     int   *catID          ; ALLOCATE (catID,         int,    catalog->Naverage);
+    int   *objID          ; ALLOCATE (objID,         int,    catalog->Naverage);
 
     // assign the storage arrays
@@ -391,4 +398,5 @@
       flags[i]          = average[i].flags;
       catID[i]          = average[i].catID;
+      objID[i]          = average[i].objID;
     }
 
@@ -400,4 +408,5 @@
     gfits_set_bintable_column (&theader, &ftable, "FLAGS",       flags,         catalog->Naverage);
     gfits_set_bintable_column (&theader, &ftable, "CAT_ID",      catID,         catalog->Naverage);
+    gfits_set_bintable_column (&theader, &ftable, "OBJ_ID",      objID,         catalog->Naverage);
 
     free (R             );
@@ -407,4 +416,5 @@
     free (flags         );
     free (catID         );
+    free (objID         );
 
     gfits_fwrite_Theader (f, &theader);
Index: branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/args.c
===================================================================
--- branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/args.c	(revision 36558)
+++ branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/args.c	(revision 36562)
@@ -387,5 +387,5 @@
     if ((N = get_argument (argc, argv, "-parallel-regions-manual"))) {
       remove_argument (N, &argc, argv);
-      PARALLEL_REGIONS_MANUAL = FALSE;
+      PARALLEL_REGIONS_MANUAL = TRUE;
     }
   }
Index: branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/client_logger.c
===================================================================
--- branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/client_logger.c	(revision 36558)
+++ branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/client_logger.c	(revision 36562)
@@ -13,5 +13,5 @@
   int fd = mkstemp (filename);
   if (fd == -1) {
-    fprintf (stderr, "failed to open client logger, exiting\n");
+    fprintf (stderr, "failed to open client logger %s, exiting\n", filename);
     exit (50);
   }
Index: branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/launch_region_hosts.c
===================================================================
--- branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/launch_region_hosts.c	(revision 36558)
+++ branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/launch_region_hosts.c	(revision 36562)
@@ -92,7 +92,12 @@
     getchar();
   } else {
-    RegionHostTableWaitJobs (regionHosts, __FILE__, __LINE__);
+    RegionHostTableWaitJobsGetIO (regionHosts, __FILE__, __LINE__, VERBOSE);
   }
  
-  return TRUE;
+  int status = TRUE;
+  for (i = 0; i < regionHosts->Nhosts; i++) {
+    status = status && (regionHosts->hosts[i].status == 0);
+  }
+
+  return status;
 }
Index: branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/relphot_parallel_regions.c
===================================================================
--- branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/relphot_parallel_regions.c	(revision 36558)
+++ branches/eam_branches/ipp-20140206/Ohana/src/relphot/src/relphot_parallel_regions.c	(revision 36562)
@@ -21,8 +21,4 @@
   sprintf (flatcorrfile, "%s/flatcorr.fits", CATDIR);
   FlatCorrectionTable *flatcorr = FlatCorrectionLoad (flatcorrfile, VERBOSE);
-
-  SkyTable *sky = SkyTableLoadOptimal (CATDIR, SKY_TABLE, GSCFILE, TRUE, SKY_DEPTH, VERBOSE);
-  SkyTableSetFilenames (sky, CATDIR, "cpt");
-  SkyList *skylist = SkyListByBounds (sky, -1, regionHosts->Rmin, regionHosts->Rmax, regionHosts->Dmin, regionHosts->Dmax);
 
   /* register database handle with shutdown procedure */
@@ -54,8 +50,8 @@
 
   /* launch processing on the parallel region hosts */
-  launch_region_hosts (regionHosts);
+  if (!launch_region_hosts (regionHosts)) Shutdown ("error launching region hosts");
 
   // retrieve updated image parameters from the remote hosts (also set Image.mcal)
-  slurp_image_mags (regionHosts, -1);
+  if (!slurp_image_mags (regionHosts, -1)) Shutdown ("error loading image updates");
 
   if (!UPDATE) { 
@@ -65,4 +61,8 @@
     exit (0);
   }
+
+  SkyTable *sky = SkyTableLoadOptimal (CATDIR, SKY_TABLE, GSCFILE, TRUE, SKY_DEPTH, VERBOSE);
+  SkyTableSetFilenames (sky, CATDIR, "cpt");
+  SkyList *skylist = SkyListByBounds (sky, -1, regionHosts->Rmin, regionHosts->Rmax, regionHosts->Dmin, regionHosts->Dmax);
 
   /* update catalogs (in parallel) */
