📄 dedicated.c
字号:
/* Is the time currently between the start and end of the dedicated time? */ if ((host_out->beg_time <= when) && (when <= host_out->end_time)) { /* * If the job was not queued on the dedicated queue, it cannot be * run during dedicated time. Note that and return "not okay." */ if (job->flags & JFLAGS_DEDICATED) { /* * The job is on the dedicated queue. It may not be runnable * if it runs over past the end of dedicated time. Check that. */ if (job_ends >= host_out->end_time) { if (reason) (void)sprintf(reason, "Can't complete within this dedicated time (%s %s %s)", shorthost ? shorthost : host_out->exechost, host_out->end_datestr, host_out->end_timestr); return 0; } } else { /* Job is a regular job. It cannot run during dedicated time. */ if (reason) sprintf(reason, "Waiting for end of dedicated time (%s %s %s)", shorthost ? shorthost : host_out->exechost, host_out->end_datestr, host_out->end_timestr); return 0; } } else { /* * It is not currently dedicated time. However, the job may spill * over into dedtime. Check this by calculating when the job will * finish execution and seeing if that falls within dedicated time. */ if (job_ends >= host_out->beg_time) { if (reason) (void)sprintf(reason, "Can't complete before next dedicated time (%s %s %s)", shorthost ? shorthost : host_out->exechost, host_out->beg_datestr, host_out->beg_timestr); return 0; } }#ifdef DEBUG_DEDTIME DBPRT(("%s: job %s is okay.\n", id, job->jobid));#endif /* DEBUG_DEDTIME */ return 1; /* Job will not interfere with dedicated time if run now. */}/* * Get a linked list of outages for host exechost. The caller is expected * to point the 'exechost' pointer for each element in this list to a piece * of storage containing the exechost's name. This is crufty, but minimizes * the amount of extra allocation being done. */static intget_outages(char *exechost, Outage **outlistp){ char *id = "get_outages"; char buffer[BUFSIZ]; char ded_ck_cmd[BUFSIZ]; char *p, *shortexec; char Start_Date[DATE_LENGTH + 1]; /* + 1 for '\0' */ char Start_Time[TIME_LENGTH + 1]; /* + 1 for '\0' */ char End_Date[DATE_LENGTH + 1]; /* + 1 for '\0' */ char End_Time[TIME_LENGTH + 1]; /* + 1 for '\0' */ char *ded_system; FILE *schedule_pipe; Outage *outs, *tail, *newout; int info_valid, ded_cancelled; size_t length; outs = tail = NULL; /* * Assume we will not get valid dedtime information from the piped command. */ info_valid = 0; Start_Date[0] = '\0'; Start_Time[0] = '\0'; End_Date[0] = '\0'; End_Time[0] = '\0'; /* Get the "short" version of the exechost. */ shortexec = schd_shorthost(exechost); if (shortexec == NULL) return (-1); sprintf(ded_ck_cmd, "%s %s", schd_DEDTIME_COMMAND, shortexec); DBPRT(("%s: Consult '%s'\n", id, ded_ck_cmd)); if ((schedule_pipe = popen(ded_ck_cmd, "r")) == NULL) { (void)sprintf(log_buffer, "ERROR: \"%s\": %s", ded_ck_cmd, strerror(errno)); log_record(PBSEVENT_SYSTEM, PBS_EVENTCLASS_SERVER, id, log_buffer); DBPRT(("%s: %s\n", id, log_buffer)); free(shortexec); return (1); } /* Read each entry from the schedule output. */ while (fgets(buffer, sizeof buffer, schedule_pipe) != NULL) { ded_cancelled = 0; /* Skip totally blank lines. */ if ((length = strlen(buffer)) == 0) continue; /* Flag an error if this line was too long. */ if (length >= (sizeof (buffer) - 1)) { (void)sprintf(log_buffer, "%s: Input line from '%s' too long.", id, ded_ck_cmd); log_record(PBSEVENT_SYSTEM, PBS_EVENTCLASS_SERVER, id, log_buffer); DBPRT(("%s: %s\n", id, log_buffer)); info_valid = 0; break; } /* Remove trailing carriage return. */ if (buffer[length - 1] == '\n') buffer[length - 1] = '\0'; /* Check for error conditions returned by the program. */ if (!strncmp(buffer, "ERROR", 5)) { info_valid = 0; log_record(PBSEVENT_SYSTEM, PBS_EVENTCLASS_SERVER, id, buffer); DBPRT(("%s: %s\n", id, buffer)); break; } if (!strcmp(buffer, "No scheduled downtime for the specified period.")) { info_valid ++; break; /* None scheduled */ } /* * Output of 'schedule' "linewraps" with more than 8 spaces before * the text. I.e. more than 8 spaces means that this is a continued * line. We are only interested in the "header" lines. */ if (!strncmp(buffer, " ", 8)) { continue; } if (strstr(buffer, "CANCELLED")) ded_cancelled ++; /* format: "SYSTEM MM/DD/YYYY HH:MM-HH:MM MM/DD/YYYY" */ p = strtok(buffer, " \t"); /* p -> '<system>' */ if (p == NULL) continue; /* Keep track of which system this line references. */ ded_system = p; p = strtok(NULL, " \t"); /* p -> '<startdate>' */ if (p == NULL) continue; strncpy(Start_Date, p, DATE_LENGTH); p = strtok(NULL, "-"); /* p -> '<starttime>' */ if (p == NULL) continue; strncpy(Start_Time, p, TIME_LENGTH); p = strtok(NULL, " \t"); /* p -> '<endtime>' */ if (p == NULL) continue; strncpy(End_Time, p, TIME_LENGTH); p = strtok(NULL, " \t"); /* p -> '<enddate>' */ if (p == NULL) continue; strncpy(End_Date, p, DATE_LENGTH); /* * We have discovered a line that "looks okay". Consider the output * being sent from the schedule command to be "acceptable". */ info_valid++; /* * It may be a valid line, and still not be information about this * machine. Convert the string to all lowercase before comparing * it against the lowercase system name. */ schd_lowercase(ded_system); if (strcmp(ded_system, shortexec) != 0) {#if 0 DBPRT(("%s: wrong host '%s' != '%s'\n", id, ded_system, shortexec));#endif /* 0 */ continue; } if (MMDDYYYY_HHMM(Start_Date, Start_Time) >= MMDDYYYY_HHMM(End_Date, End_Time)) { DBPRT(("%s: found dedtime shorter than 1 minute!\n", id)); DBPRT(("%s: bad dedtime: (%s %s %s - %s %s)\n", id, shortexec, Start_Date, Start_Time, End_Date, End_Time)); continue; } if (ded_cancelled) { /* * A cancellation is a valid entry. It also means we need to * update our cache, since it may be cancelling the cached * value. However, we also need to see if there is any time * really scheduled later. */ DBPRT(("%s: found cancelled dedtime for %s from %s:%s to %s:%s\n", id, shortexec, Start_Date, Start_Time, End_Date, End_Time)); info_valid ++; continue; } /* * Dedicated time is scheduled for this machine. Will it end at * some _future_ time ?? If so, make a new entry in the list of * Outages for the shortexec. */ if (MMDDYYYY_HHMM(End_Date, End_Time) > schd_TimeNow) { info_valid ++; if ((newout = (Outage *)malloc(sizeof(Outage))) == NULL) { (void)sprintf(log_buffer, "malloc(Outage) failed\n"); log_record(PBSEVENT_SYSTEM, PBS_EVENTCLASS_SERVER, id, log_buffer); DBPRT(("%s: %s\n", id, log_buffer)); info_valid = 0; break; } memset((void *)newout, 0, sizeof(Outage)); /* Hook the new element on the end of the list. */ if (tail) tail->next = newout; else outs = newout; tail = newout; newout->next = NULL; /* Load the outage information into the new struct. */ newout->exechost = NULL; /* Caller must set. */ strncpy(newout->beg_datestr, Start_Date, DATE_LENGTH); strncpy(newout->beg_timestr, Start_Time, TIME_LENGTH); strncpy(newout->end_datestr, End_Date, DATE_LENGTH); strncpy(newout->end_timestr, End_Time, TIME_LENGTH); newout->beg_time = MMDDYYYY_HHMM(Start_Date, Start_Time); newout->end_time = MMDDYYYY_HHMM(End_Date, End_Time);#if 0 DBPRT(("Got Outage for %s %s:%s %s:%s\n", shortexec, newout->beg_datestr, newout->beg_timestr, newout->end_datestr, newout->end_datestr));#endif /* 0 */ } } pclose(schedule_pipe); free(shortexec); if (info_valid) { *outlistp = outs; return 0; } else { DBPRT(("%s: no valid dedtime info found (%s)\n", id, ded_ck_cmd)); if (outs) free_outages(outs); *outlistp = NULL; return 1; }}static Outage *merge_outages(Outage *system_outages, Outage *host_outages){ char *id = "merge_outages"; Outage **outp_array, *outp, *newlist; int num_outages, i, found; /* If there are no system outages, just return the host list. */ if (system_outages == NULL) return (host_outages); /* If there are no host outages, just return the system list. */ if (host_outages == NULL) return (system_outages); /* Count the total number of outages in both lists. */ num_outages = 0; for (outp = system_outages; outp != NULL; outp = outp->next) ++ num_outages; for (outp = host_outages; outp != NULL; outp = outp->next) ++ num_outages; /* Now allocate space for a bunch of pointers to the outages. */ outp_array = (Outage **)calloc(num_outages, sizeof(Outage *)); if (outp_array == NULL) { (void)sprintf(log_buffer, "calloc() failed (%d * %d)\n", num_outages, (int)sizeof(Outage *)); log_record(PBSEVENT_SYSTEM, PBS_EVENTCLASS_SERVER, id, log_buffer); DBPRT(("%s: %s\n", id, log_buffer)); /* Free the passed-in lists. */ free_outages(system_outages); free_outages(host_outages); /* And return an error condition. */ return (NULL); } /* * Walk the outage lists again, assigning each element in the array to * point to one outage. Sort the resultant array in ascending order * of the start time of the outage pointed to by each element in the * array. */ i = 0; for (outp = system_outages; outp != NULL; outp = outp->next) outp_array[i++] = outp; for (outp = host_outages; outp != NULL; outp = outp->next) outp_array[i++] = outp; qsort(outp_array, num_outages, sizeof (Outage *), compare_outages_time); /* * The array is now a set of pointers to outages. Re-link the outages in * the order given in the array. */ newlist = outp = outp_array[0]; for (i = 1; i < num_outages; i++) { outp->next = outp_array[i]; outp = outp->next; } outp->next = NULL; /* Free the array of pointers since it is no longer needed. */ free(outp_array); /* * Now the 'newlist' list contains the members of both lists, arranged in * time from earliest to latest. All that remains is to resolve any * overlapping cases. Do this one at a time, until no more can be found. * This should significantly simplify the code, and since there should * only be a handful of outages at any time, it won't be prohibitively * expensive. */ DBPRT(("%s: MERGED/SORTED OUTAGES LIST:\n", id)); for (outp = newlist; outp != NULL; outp = outp->next) DBPRT(("%s: %s\n", id, print_outage(outp))); for (i = 0; i < MAX_OUTAGE_RESOLVE_ITERS; i++) { found = resolve_outage_overlap(&newlist); if (found < 0) { (void)sprintf(log_buffer, "couldn't resolve overlaps!"); log_record(PBSEVENT_SYSTEM, PBS_EVENTCLASS_SERVER, id, log_buffer); DBPRT(("%s: %s\n", id, log_buffer)); /* Free the merged contents of the two lists. */ free_outages(newlist); return (NULL); } if (found == 0) { /* No overlaps were found and resolved, so nothing left to do. */ break; } /* At least one overlap was found and fixed. Try to find more. */ continue; } if (i == MAX_OUTAGE_RESOLVE_ITERS) { (void)sprintf(log_buffer, "WARNING!!! Couldn't resolve all overlaps in %d passes!", i); log_record(PBSEVENT_SYSTEM, PBS_EVENTCLASS_SERVER, id, log_buffer); DBPRT(("%s: %s\n", id, log_buffer)); } /* * 'newlist' should now contain a list of outages, either for the system * or for this individual host, ordered in time, and with no overlaps. */ return (newlist);}static intresolve_outage_overlap(Outage **outlistp){ char *id = "resolve_outage_overlap"; Outage *new, *discard;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -