Changeset 37595
- Timestamp:
- Nov 13, 2014, 4:32:59 PM (12 years ago)
- Location:
- branches/eam_branches/ipp-20140904/Ohana/src
- Files:
-
- 3 edited
-
libdvo/include/dvo.h (modified) (1 diff)
-
libdvo/src/HostTable.c (modified) (3 diffs)
-
relphot/src/reload_catalogs.c (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/eam_branches/ipp-20140904/Ohana/src/libdvo/include/dvo.h
r37546 r37595 273 273 short *index; 274 274 } HostTable; 275 276 typedef struct { 277 int Nhosts; 278 HostInfo **hosts; 279 } HostTableGroup; 275 280 276 281 // 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 40 40 } 41 41 42 // a HostTableGroup is a pointer set to one or more HostTable entries 43 void 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 42 54 HostTable *HostTableLoad (char *catdir, char *rootname) { 43 55 … … 136 148 fclose (f); 137 149 return table; 150 } 151 152 // split a host table into Ngroups, each with a unique set of hosts 153 HostTableGroup *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; 138 211 } 139 212 … … 389 462 } 390 463 464 // wait for all children to complete, report output to stdout 465 int 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 627 escape: 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 391 640 int HostTableTestHost (SkyRegion *region, int hostID) { 392 641 -
branches/eam_branches/ipp-20140904/Ohana/src/relphot/src/reload_catalogs.c
r37593 r37595 167 167 } 168 168 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 180 int reload_catalog_parallel_group (HostTableGroup *group, SkyList *sky, char *imageFile) { 181 169 182 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) { 173 186 // do any of the regions want this host? 174 187 int wantThisHost = FALSE; 175 188 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)) { 177 190 wantThisHost = TRUE; 178 191 break; … … 180 193 } 181 194 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); 183 196 continue; 184 197 } … … 186 199 187 200 // 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; 191 204 192 205 char command[1024]; 193 206 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); 195 208 196 209 // options & configs which affect relphot_client -update-catalogs … … 237 250 // launch the job on the remote machine (no handshake) 238 251 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); 240 253 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); 242 255 exit (1); 243 256 } 244 table->hosts[i].pid = pid; // save for future reference257 group->hosts[i][0].pid = pid; // save for future reference 245 258 } 246 259 } … … 251 264 } 252 265 if (!PARALLEL_MANUAL && !PARALLEL_SERIAL) { 253 int status = HostTable WaitJobsGetIO (table, __FILE__, __LINE__, VERBOSE);266 int status = HostTableGroupWaitJobsGetIO (group, __FILE__, __LINE__, VERBOSE); 254 267 if (!status) { 255 268 fprintf (stderr, "at least one remote client job failed to load data, exiting\n");
Note:
See TracChangeset
for help on using the changeset viewer.
