📄 dedicated.c
字号:
/* * Walk the list of outages, looking for overlaps and resolving them. * Once an overlap has been resolved, return 1 to indicate that there * was an overlap found. In this case, this function should be called * again. If no overlaps are found, return 0 to indicate that fact. * Return -1 on error. * * Note that system outages should take priority over per-host outages. * * The outages list *must* be sorted into ascending order of start-time * for the outages. * * The five possible overlap scenarios are ('*' indicates system outage * time, '-' indicates host outages, blank space is non-outage time) : * * Time *** *** ----- ----- ----- * | -***- *** ----- *** * | -***- ----- *** *** *** * | *** ----- *** ----- *** * | * V Case: 1 2 3 4 5 (no overlap) */ /* * Discarded outages go on this list, so they can be easily reclaimed * if another outage needs to be allocated. */ discard = NULL; /* * Start with the original list head pointer. This will be replaced * with the new head at the end of the for loop. */ new = *outlistp; for (this = new; this->next != NULL; this = next) { next = this->next; /* * If this outage ends before the next one starts, then there is no * overlap between these two elements. */ if (this->end_time < next->beg_time) continue; /* Found an overlap. */ found = 1; /* * Check the types of the two outages. If they are the same, extend * the first entry to stretch through the whole time, note the fact. * Otherwise, figure out which is the host outage, and which is the * system outage, and assign pointers respectively. */ if ((this->flags & OUTAGE_FLAGS_SYSTEM) == (next->flags & OUTAGE_FLAGS_SYSTEM)) { DBPRT(("%s: Two outages of same type (%s) overlap.\n", id, (this->flags & OUTAGE_FLAGS_SYSTEM) ? "system" : "host")); DBPRT(("%s: Outages are (%s)\n", id, print_outage(this))); DBPRT(("%s: (%s)\n", id, print_outage(next))); /* * Expand both outages to cover the same time. This will * cause it to be dealt with by case 1 below. */ this->beg_time = MIN(this->beg_time, next->beg_time); this->end_time = MAX(this->end_time, next->end_time); next->beg_time = this->beg_time; next->end_time = this->end_time; /* Create new time/date strings for the different time_t's. */ make_time_strs(this); make_time_strs(next); DBPRT(("%s: Overlap extended to (%s)\n", id, print_outage(this))); /* And assign them "relative priorities". */ sys = this; host = next; } else { /* Figure out which is the system and which is the host outage. */ if (this->flags & OUTAGE_FLAGS_SYSTEM) { sys = this; host = next; } else { host = this; sys = next; } } DBPRT(("%s: system outage (%s) overlaps\n", id, print_outage(sys))); DBPRT(("%s: host outage (%s)\n", id, print_outage(host))); sys_beg = sys->beg_time; sys_end = sys->end_time; host_beg = host->beg_time; host_end = host->end_time; /* * Quick sanity check for reasonable outage times. */ if ((sys_end - sys_beg) < 1) { (void)sprintf(log_buffer, "system outage (%s) less than 1 second!\n", print_outage(sys)); log_record(PBSEVENT_SYSTEM, PBS_EVENTCLASS_SERVER, id, log_buffer); DBPRT(("%s: %s\n", id, log_buffer)); /* Note the problem and return an error. */ found = -1; break; } if ((host_end - host_beg) < 1) { (void)sprintf(log_buffer, "host outage (%s) less than 1 second!\n", print_outage(host)); log_record(PBSEVENT_SYSTEM, PBS_EVENTCLASS_SERVER, id, log_buffer); DBPRT(("%s: %s\n", id, log_buffer)); /* Note the problem and return an error. */ found = -1; break; } /* Case 1: 'sys' starts before, and ends after, 'host'. * This is a complete overlap (the easy case). This is either a * duplicated host outage, or a system outage overlaps the host * outage. In either case, choose one to discard and it's done. */ if ((sys_beg <= host_beg) && (sys_end >= host_end)) { DBPRT(("%s: case 1: sys outage overlaps all of host outage.\n", id)); DBPRT(("%s: Discarding host outage (%s)\n", id, print_outage(host))); /* * Discard the per-host outage onto the discard pile. It * may be re-used if a new element is required. If not, it * will be freed at the end of the function. If the host * outage is the first in the list, bump the new list pointer * forward, otherwise find the previous element and point over * the host element to the next one. */ if (host != new) { for (outp = new; outp != NULL; outp = outp->next) /* Walk list looking for previous pointer. */ if (outp->next == host) break; if (outp == NULL) { DBPRT(("%s: host outage not found!\n", id)); found = -1; break; } DBPRT(("%s: host outage not head of list. Skipping from %s\n", id, print_outage(outp))); outp->next = host->next; } else { new = host->next; DBPRT(("%s: host outage is head of list. new head %s\n", id, print_outage(new))); } host->next = discard; discard = host; DBPRT(("%s: Place host on discard pile %s\n", id, print_outage(discard))); /* This conflict is now resolved. Break out of loop. */ break; } /* Case 2: 'system' starts before, and ends before, 'host' outage. * Adjust the host outage to start just after the system outage ends. * The conflict is then resolved. */ if ((sys_beg <= host_beg) && (sys_end < host_end)) { DBPRT(("%s: case 2: sys outage overlaps start of host outage.\n", id)); host->beg_time = sys_end + 1; /* Sanity check. "This can't happen." */ if (host->end_time <= host->beg_time) { DBPRT(("%s: host outage %s < 1 second long!", id, print_outage(host))); found = -1; break; } /* Create new time/date strings for the changed time_t's. */ make_time_strs(host); DBPRT(("%s: host outage bumped to (%s)\n", id, print_outage(host))); /* That's all that's required to resolve the conflict. */ break; } /* Case 3: 'system' outage starts after, and ends after, 'host' outage. * Adjust the host outage to end just before the system outage starts. * The conflict is then resolved. */ if ((sys_beg > host_beg) && (sys_end >= host_end)) { DBPRT(("%s: case 3: sys outage overlaps end of host outage.\n", id)); host->end_time = sys_beg - 1; /* Sanity check. "This can't happen." */ if (host->end_time <= host->beg_time) { DBPRT(("%s: host outage %s < 1 second long!", id, print_outage(host))); found = -1; break; } /* Create new time/date strings for the changed time_t's. */ make_time_strs(host); DBPRT(("%s: host outage bumped to (%s)\n", id, print_outage(host))); /* That's all that's required to resolve the conflict. */ break; } /* Case 4: 'system' outage starts after, and ends before 'host' outage. * System outage splits the host outage into two pieces. Shorten the * first piece like case #3 above, and create a new Outage for the * remaining chunk. */ if ((sys_beg > host_beg) && (sys_end < host_end)) { DBPRT(("%s: case 4: sys outage overlaps middle of host outage.\n", id)); /* Shorten the original host entry to first chunk of the outage. */ host->end_time = sys_beg - 1; /* Create a new host chunk to follow the system one on the list. */ if (discard) { outp = discard; discard = discard->next; } else { if ((outp = (Outage *)malloc(sizeof (Outage))) == NULL) { (void)sprintf(log_buffer, "malloc(%d) failed!", (int)sizeof (Outage)); log_record(PBSEVENT_SYSTEM, PBS_EVENTCLASS_SERVER, id, log_buffer); DBPRT(("%s: %s\n", id, log_buffer)); found = -1; break; } } /* Initialize the new element. */ memset((void *)outp, 0, sizeof (Outage)); /* Point to the host's exechost, and fill in the time fields. */ outp->exechost = host->exechost; outp->beg_time = sys_end + 1; outp->end_time = host_end; /* Now recompute the date and time strings for each outage. */ make_time_strs(host); /* The original "first" chunk */ make_time_strs(outp); /* The newly-created 2nd chunk */ DBPRT(("%s: Split host outage into :\n", id)); DBPRT(("%s: host outage (%s)\n", id, print_outage(host))); DBPRT(("%s: sys outage (%s)\n", id, print_outage(sys))); DBPRT(("%s: new host outage (%s)\n", id, print_outage(outp))); /* And link the new host outage in after the system outage. */ outp->next = sys->next; sys->next = outp; /* And this case is resolved. */ break; } /* Unexpected case! Return an error! */ (void)sprintf(log_buffer, "unexpected outage overlap!"); log_record(PBSEVENT_SYSTEM, PBS_EVENTCLASS_SERVER, id, log_buffer); DBPRT(("%s: %s\n", id, log_buffer)); found = -1; break; } /* * Replace the pointer to the head of the list with the head of the new * outage list. The new list may not have the same head as the old one * (if the original head was discarded). */ *outlistp = new; /* Clean up the discard list, if necessary. */ if (discard) free_outages(discard); discard = NULL; return (found);}/* * Return a pointer to a static buffer containing a string describing the * times of the outage. */static char *print_outage(Outage *outp){ static char buffer[64]; sprintf(buffer, "%s %s:%02.2d - %s %s:%02.2d [%s]", outp->beg_datestr, outp->beg_timestr, (int)(outp->beg_time % 60), outp->end_datestr, outp->end_timestr, (int)(outp->end_time % 60), outp->exechost); return (buffer);}static intcompare_outages_time(const void *e1, const void *e2){ Outage *outage1 = *(Outage **)e1; Outage *outage2 = *(Outage **)e2; time_t diff; /* Sort first based on starting time, from soonest to latest. */ diff = outage1->beg_time - outage2->beg_time; if (diff) return (diff); /* Break ties by sorting by end time. */ diff = outage1->end_time - outage2->end_time; return (diff);}static int make_time_strs (Outage *outp){ struct tm *tm_ptr; if ((tm_ptr = localtime(&(outp->beg_time))) == NULL) return (1); sprintf(outp->beg_datestr, "%2.2d/%2.2d/%4.4d", tm_ptr->tm_mon + 1, tm_ptr->tm_mday, tm_ptr->tm_year + 1900); sprintf(outp->beg_timestr, "%2.2d:%2.2d", tm_ptr->tm_hour, tm_ptr->tm_min); if ((tm_ptr = localtime(&(outp->end_time))) == NULL) return (1); sprintf(outp->end_datestr, "%2.2d/%2.2d/%4.4d", tm_ptr->tm_mon + 1, tm_ptr->tm_mday, tm_ptr->tm_year + 1900); sprintf(outp->end_timestr, "%2.2d:%2.2d", tm_ptr->tm_hour, tm_ptr->tm_min); return (0);}/* * Free each element of a list of outages. Note that the 'exechost' field * for the outage points back to the OutageList->host, and isn't allocated * storage. */static int free_outages(Outage *outages){ int n; Outage *ptr, *next; for (n = 0, ptr = outages; ptr != NULL; ptr = next) { next = ptr->next; free(ptr); n++; } return (n);}/* Parse "MM/DD/YYYY HH:MM" style dates into seconds since the Epoch. */static int MMDDYYYY_HHMM(char *MMDDYYYY, char *HHMM){ /* char *id = "MMDDYYYY_HHMM"; */ struct tm junk; char copy[MAX_TXT + 1]; strcpy(copy, MMDDYYYY); /* Copy it so we can modify the string. */ copy[2] = copy[5] = '\0'; /* 'MM/DD/YYYY\0' ==> 'MM\0DD\0YYYY\0' */ junk.tm_mon = atoi(copy); junk.tm_mday = atoi(copy + 3); junk.tm_year = atoi(copy + 6); junk.tm_mon -= 1; /* mktime() counts from 0, not 1 like us */ junk.tm_year -= 1900; /* mktime() counts from 1900 */ strcpy(copy, HHMM); /* Copy it so we can modify the string. */ copy[2] = '\0'; /* 'HH:MM\0' ==> 'HH\0MM\0' */ junk.tm_hour = atoi(copy); junk.tm_min = atoi(copy + 3); junk.tm_sec = 0; junk.tm_isdst = -1; /* Choose correct DST value from timezone */ return (int)mktime(&junk);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -