IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 37595


Ignore:
Timestamp:
Nov 13, 2014, 4:32:59 PM (12 years ago)
Author:
eugene
Message:

update relphot to launch only remote host groups (at least for updating the objects)

Location:
branches/eam_branches/ipp-20140904/Ohana/src
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/ipp-20140904/Ohana/src/libdvo/include/dvo.h

    r37546 r37595  
    273273  short *index;
    274274} HostTable;
     275
     276typedef struct {
     277  int Nhosts;
     278  HostInfo **hosts;
     279} HostTableGroup;
    275280
    276281// A RegionHost processes data for some region in parallel with other regions
  • branches/eam_branches/ipp-20140904/Ohana/src/libdvo/src/HostTable.c

    r35848 r37595  
    4040}
    4141
     42// a HostTableGroup is a pointer set to one or more HostTable entries
     43void FreeTableGroup (HostTableGroup *table) {
     44
     45  if (!table) return;
     46  if (table->hosts) {
     47    free (table->hosts);
     48  }
     49  if (table->index) free (table->index);
     50  free (table);
     51  return;
     52}
     53
    4254HostTable *HostTableLoad (char *catdir, char *rootname) {
    4355
     
    136148  fclose (f);
    137149  return table;
     150}
     151
     152// split a host table into Ngroups, each with a unique set of hosts
     153HostTableGroup *HostTableGroups (HostTable *table, int *ngroups) {
     154
     155  // identify the unique host names and the number of times they each exist
     156  // (Host tables are not very large; I can afford to do this in an inefficient way)
     157
     158  int Nunique = 0;
     159  char **unique_hosts = NULL; // an array of pointers to a set of the names
     160  int  *Nunique_hosts = NULL; // an array of pointers to the count of each
     161  ALLOCATE ( unique_hosts, char *, table->Nhosts);
     162  ALLOCATE (Nunique_hosts, int, table->Nhosts);
     163  for (i = 0; i < table->Nhosts; i++) Nunique_hosts[i] = 0;
     164
     165  for (i = 0; i < table->Nhosts; i++) {
     166    found = FALSE;
     167    for (j = 0; !found && (j < Nunique); j++) {
     168      if (!strcmp(table->hosts[i].hostname, unique_hosts[j])) {
     169        Nunique_hosts[j] ++;
     170        found = TRUE;
     171      }
     172    }
     173    if (!found) {
     174      unique_hosts[Nunique] = table->hosts[i].hostname;
     175      Nunique_hosts[Nunique] = 1;
     176      Nunique ++;
     177    }
     178  }
     179
     180  int Ngroups = 0;
     181  for (i = 0; i < Nunique; i++) {
     182    Ngroups = MAX (Nunique_hosts[i], Ngroups);
     183  }
     184
     185  HostTableGroup *groups = NULL;
     186  int *foundHost = NULL;
     187 
     188  ALLOCATE (foundHost, int, table->Nhosts);
     189  ALLOCATE (groups, HostTableGroup, Ngroups);
     190
     191  for (i = 0; i < table->Nhosts; i++) foundHost[i] = FALSE;
     192
     193  // in each group, attempt to add one of each unique host
     194  for (i = 0; i < Ngroups; i++) {
     195    groups[i].Nhosts = 0;
     196    ALLOCATE (groups[i].hosts, HostTable *, Nunique);
     197    for (j = 0; j < Nunique; j++) {
     198      found = FALSE;
     199      for (k = 0; !found && (k < table->Nhosts); k++) {
     200        if (foundHost[k]) continue;
     201        if (strcmp(unique_hosts[j], table->hosts[k].hostname));
     202        groups[i].hosts[groups[i].Nhosts] = &table->hosts[k];
     203        groups[i].Nhosts ++;
     204        found = TRUE;
     205        foundHost[k] = TRUE;
     206      }
     207    }
     208  }
     209  *ngroups = Ngroups;
     210  return groups;
    138211}
    139212
     
    389462}
    390463
     464// wait for all children to complete, report output to stdout
     465int HostTableGroupWaitJobsGetIO (HostTableGroup *table, char *file, int lineno, int VERBOSE) {
     466
     467  // we have launched table->Nhosts jobs; wait for all of them to complete...
     468  // if one (N) failed to launch, we will get an ECHILD error from the last (N) calls
     469
     470  // we need to read any data waiting on stderr or stdout from these jobs, or the overfull
     471  // buffers can cause a problem.  we alternate between 'select' and 'waitpid' calls with
     472  // timeouts for both
     473
     474  // add all hosts' sockets to the fd_sets
     475  fd_set rdSet, wtSet;
     476  FD_ZERO (&rdSet);
     477  FD_ZERO (&wtSet);
     478
     479  // XXX can I set the fd_sets once, since I am not actually closing the fd's?
     480
     481  int globalStatus = TRUE;
     482
     483  int i;
     484  int Nmax = 0;
     485  for (i = 0; i < table->Nhosts; i++) {
     486    if (!table->hosts[i][0].pid) continue; // any unconnected hosts should be skipped
     487    FD_SET (table->hosts[i][0].stdio[HOST_STDIN], &wtSet);
     488    Nmax = MAX (Nmax, table->hosts[i][0].stdio[HOST_STDIN]);
     489    FD_SET (table->hosts[i][0].stdio[HOST_STDOUT], &rdSet);
     490    Nmax = MAX (Nmax, table->hosts[i][0].stdio[HOST_STDOUT]);
     491    FD_SET (table->hosts[i][0].stdio[HOST_STDERR], &rdSet);
     492    Nmax = MAX (Nmax, table->hosts[i][0].stdio[HOST_STDERR]);
     493  }   
     494  Nmax ++;
     495
     496  // need the list of connected hosts for exit test below
     497  int Nrunning = 0;
     498  for (i = 0; i < table->Nhosts; i++) {
     499    if (!table->hosts[i][0].pid) continue; // any unconnected hosts should be skipped
     500    Nrunning ++;
     501  }
     502
     503  int Nfound = 0;
     504
     505  // this loop has 2 chunks: (a) check for I/O + (b) check for jobs done
     506  while (1) {
     507
     508    // Wait up to 0.5 second for host to provide I/O
     509    // timeout gets mucked: need to reset before each select
     510    struct timeval timeout;
     511    timeout.tv_sec = 10;
     512    timeout.tv_usec = 500000;
     513
     514    int status = select (Nmax, NULL, &wtSet, NULL, &timeout);
     515    if (status == -1) {
     516      perror("select()");
     517      exit (2);
     518    }
     519
     520    // we have some sockets to check, check sockets for all hosts
     521    for (i = 0; (status > 0) && (i < table->Nhosts); i++) {
     522      if (!table->hosts[i][0].pid) continue; // any unconnected hosts should be skipped
     523
     524      if (FALSE && FD_ISSET (table->hosts[i][0].stdio[HOST_STDIN], &wtSet)) {
     525        // this host is waiting for input : this is an error, so exit
     526        fprintf (stderr, "host %s is waiting for input\n", table->hosts[i][0].hostname);
     527        abort();
     528      }
     529     
     530      if ((table->hosts[i][0].stdio[HOST_STDOUT] > 0) && FD_ISSET (table->hosts[i][0].stdio[HOST_STDOUT], &rdSet)) {
     531        // this host has waiting output : read to buffer, and dump if necessary
     532        ReadtoIOBuffer (&table->hosts[i][0].stdout, table->hosts[i][0].stdio[HOST_STDOUT]);
     533        // if (table->hosts[i][0].stdout.Nbuffer > 0x10000) {
     534        if (table->hosts[i][0].stdout.Nbuffer > 0x1000) {
     535          int printHead = VERBOSE || (table->hosts[i][0].stdout.Nbuffer > 0);
     536          if (printHead) fprintf (stdout, "--- stdout from %s --- (%d bytes, v1)\n", table->hosts[i][0].hostname, table->hosts[i][0].stdout.Nbuffer);
     537          int Nout = write (STDOUT_FILENO, table->hosts[i][0].stdout.buffer, table->hosts[i][0].stdout.Nbuffer);
     538          if (Nout != table->hosts[i][0].stdout.Nbuffer) { fprintf (stderr, "(error writing log?)\n"); }
     539          FlushIOBuffer (&table->hosts[i][0].stdout);
     540          if (printHead) fprintf (stdout, "\n");
     541        }
     542      }
     543
     544      if ((table->hosts[i][0].stdio[HOST_STDERR] > 0) && FD_ISSET (table->hosts[i][0].stdio[HOST_STDERR], &rdSet)) {
     545        // this host has waiting output : read to buffer, and dump if necessary
     546        ReadtoIOBuffer (&table->hosts[i][0].stderr, table->hosts[i][0].stdio[HOST_STDERR]);
     547        // if (table->hosts[i][0].stderr.Nbuffer > 0x10000) {
     548        if (table->hosts[i][0].stderr.Nbuffer > 0x1000) {
     549          int printHead = VERBOSE || (table->hosts[i][0].stderr.Nbuffer > 0);
     550          if (printHead) fprintf (stdout, "--- stderr from %s --- (%d bytes, v1)\n", table->hosts[i][0].hostname, table->hosts[i][0].stderr.Nbuffer);
     551          int Nout = write (STDOUT_FILENO, table->hosts[i][0].stderr.buffer, table->hosts[i][0].stderr.Nbuffer);
     552          if (Nout != table->hosts[i][0].stderr.Nbuffer) { fprintf (stderr, "(error writing log?)\n"); }
     553          FlushIOBuffer (&table->hosts[i][0].stderr);
     554          if (printHead) fprintf (stdout, "\n");
     555        }
     556      }
     557    }
     558
     559    // now check if any children have finished...
     560    while (TRUE) {
     561      int status = 0;
     562      int pid = waitpid (-1, &status, WNOHANG);
     563      if (!pid) {
     564        // fprintf (stderr, "no hosts to harvest\n");
     565        usleep (500000);
     566        break; // no outstanding jobs have finished
     567      }
     568      if ((pid == -1) && (errno == ECHILD)) goto escape; // no more jobs on which to wait
     569      if ((pid == -1) && (errno != ECHILD)) {
     570        fprintf (stderr, "programming error (2)? %s %d", file, lineno);
     571        exit (2);
     572      }
     573
     574      // find the host which has finished
     575      int found = FALSE;
     576      for (i = 0; (i < table->Nhosts) && !found; i++) {
     577        if (table->hosts[i][0].pid != pid) continue;
     578        found = TRUE;
     579
     580        HostInfo *host = table->hosts[i];
     581
     582        // check on the status of this and report any output?
     583        if (VERBOSE) fprintf (stdout, "job finished for %s (%d)\n", host->hostname, pid);
     584
     585        // read stdout
     586        int printHead;
     587        printHead = VERBOSE || (host->stdout.Nbuffer > 0);
     588        EmptyIOBuffer (&host->stdout, 100, host->stdio[HOST_STDOUT]);
     589        if (printHead) fprintf (stdout, "--- stdout from %s --- (%d bytes, v2)\n", host->hostname, host->stdout.Nbuffer);
     590        int Nout = write (STDOUT_FILENO, host->stdout.buffer, host->stdout.Nbuffer);
     591        if (Nout != host->stdout.Nbuffer) { fprintf (stderr, "(error writing log?)\n"); }
     592        FlushIOBuffer (&host->stdout);
     593        if (printHead) fprintf (stdout, "\n");
     594           
     595        // read stderr
     596        printHead = VERBOSE || (host->stderr.Nbuffer > 0);
     597        EmptyIOBuffer (&host->stderr, 100, host->stdio[HOST_STDERR]);
     598        if (printHead) fprintf (stdout, "--- stderr from %s --- (%d bytes, v2)\n", host->hostname, host->stderr.Nbuffer);
     599        Nout = write (STDOUT_FILENO, host->stderr.buffer, host->stderr.Nbuffer);
     600        if (Nout != host->stderr.Nbuffer) { fprintf (stderr, "(error writing log?)\n"); }
     601        FlushIOBuffer (&host->stderr);
     602        if (printHead) fprintf (stdout, "\n");
     603
     604        if (WIFEXITED(status)) {
     605          if (VERBOSE) fprintf (stdout, "normal completion, exit status is %d\n", WEXITSTATUS(status));
     606          host->status = WEXITSTATUS(status);
     607          if (host->status) {
     608            fprintf (stdout, "job failed on %s\n", host->hostname);
     609            globalStatus = FALSE;
     610          }
     611        } else {
     612          host->status = -1;
     613          fprintf (stdout, "job exited abnormally on %s\n", host->hostname);
     614          globalStatus = FALSE;
     615          continue;
     616        }
     617      }
     618      if (!found) {
     619        fprintf (stderr, "Programming error: failed to matched finished job to known host!\n");
     620        exit (2);
     621      }
     622      Nfound ++;
     623      if (Nfound == Nrunning) goto escape; // we've harvested all jobs
     624    }
     625  }
     626
     627escape:
     628
     629  // close all opened connections
     630  for (i = 0; i < table->Nhosts; i++) {
     631    if (!table->hosts[i][0].pid) continue; // any unconnected hosts should be skipped
     632    close (table->hosts[i][0].stdio[HOST_STDIN]);
     633    close (table->hosts[i][0].stdio[HOST_STDOUT]);
     634    close (table->hosts[i][0].stdio[HOST_STDERR]);
     635  }
     636
     637  return globalStatus;
     638}
     639
    391640int HostTableTestHost (SkyRegion *region, int hostID) {
    392641
  • branches/eam_branches/ipp-20140904/Ohana/src/relphot/src/reload_catalogs.c

    r37593 r37595  
    167167  }
    168168
     169  int Ngroups;
     170  HostTable *groups = HostTableGroups (table, &Ngroups);
     171  // split the table into Ngroups, each with a unique set of machines (this avoids overloading the remote host machines)
     172
     173  for (i = 0; i < Ngroups; i++) {
     174    // update only a group of unique machines at a time
     175    reload_catalog_parallel_group (&groups[i], sky, imageFile);
     176  }
     177  return TRUE;
     178}
     179
     180int reload_catalog_parallel_group (HostTableGroup *group, SkyList *sky, char *imageFile) {
     181
    169182  int i, j;
    170   for (i = 0; i < table->Nhosts; i++) {
    171 
    172     if (sky->Nregions < table->Nhosts) {
     183  for (i = 0; i < group->Nhosts; i++) {
     184
     185    if (sky->Nregions < group->Nhosts) {
    173186      // do any of the regions want this host?
    174187      int wantThisHost = FALSE;
    175188      for (j = 0; j < sky->Nregions; j++) {
    176         if (HostTableTestHost (sky->regions[j], table->hosts[i].hostID)) {
     189        if (HostTableTestHost (sky->regions[j], group->hosts[i][0].hostID)) {
    177190          wantThisHost = TRUE;
    178191          break;
     
    180193      }
    181194      if (!wantThisHost) {
    182         // fprintf (stderr, "skip host %s\n", table->hosts[i].hostname);
     195        // fprintf (stderr, "skip host %s\n", group->hosts[i][0].hostname);
    183196        continue;
    184197      }
     
    186199
    187200    // ensure that the paths are absolute path names
    188     char *tmppath = abspath (table->hosts[i].pathname, DVO_MAX_PATH);
    189     free (table->hosts[i].pathname);
    190     table->hosts[i].pathname = tmppath;
     201    char *tmppath = abspath (group->hosts[i][0].pathname, DVO_MAX_PATH);
     202    free (group->hosts[i][0].pathname);
     203    group->hosts[i][0].pathname = tmppath;
    191204
    192205    char command[1024];
    193206    snprintf (command, 1024, "relphot_client %s -update-catalogs %s -hostID %d -D CATDIR %s -hostdir %s -region %f %f %f %f -statmode %s -D CAMERA %s -D STAR_TOOFEW %d -minerror %f",
    194               PhotcodeList, imageFile, table->hosts[i].hostID, CATDIR, table->hosts[i].pathname, UserPatch.Rmin, UserPatch.Rmax, UserPatch.Dmin, UserPatch.Dmax, STATMODE, CAMERA, STAR_TOOFEW, MIN_ERROR);
     207              PhotcodeList, imageFile, group->hosts[i][0].hostID, CATDIR, group->hosts[i][0].pathname, UserPatch.Rmin, UserPatch.Rmax, UserPatch.Dmin, UserPatch.Dmax, STATMODE, CAMERA, STAR_TOOFEW, MIN_ERROR);
    195208
    196209    // options & configs which affect relphot_client -update-catalogs
     
    237250      // launch the job on the remote machine (no handshake)
    238251      int errorInfo = 0;
    239       int pid = rconnect ("ssh", table->hosts[i].hostname, command, table->hosts[i].stdio, &errorInfo, FALSE);
     252      int pid = rconnect ("ssh", group->hosts[i][0].hostname, command, group->hosts[i][0].stdio, &errorInfo, FALSE);
    240253      if (!pid) {
    241         if (DEBUG) fprintf (stderr, "failure to start %s (error %d)\n", table->hosts[i].hostname, errorInfo);
     254        if (DEBUG) fprintf (stderr, "failure to start %s (error %d)\n", group->hosts[i][0].hostname, errorInfo);
    242255        exit (1);
    243256      }
    244       table->hosts[i].pid = pid; // save for future reference
     257      group->hosts[i][0].pid = pid; // save for future reference
    245258    }
    246259  }
     
    251264  }
    252265  if (!PARALLEL_MANUAL && !PARALLEL_SERIAL) {
    253     int status = HostTableWaitJobsGetIO (table, __FILE__, __LINE__, VERBOSE);
     266    int status = HostTableGroupWaitJobsGetIO (group, __FILE__, __LINE__, VERBOSE);
    254267    if (!status) {
    255268      fprintf (stderr, "at least one remote client job failed to load data, exiting\n");
Note: See TracChangeset for help on using the changeset viewer.