📄 dedicated.c
字号:
/** OpenPBS (Portable Batch System) v2.3 Software License* * Copyright (c) 1999-2000 Veridian Information Solutions, Inc.* All rights reserved.* * ---------------------------------------------------------------------------* For a license to use or redistribute the OpenPBS software under conditions* other than those described below, or to purchase support for this software,* please contact Veridian Systems, PBS Products Department ("Licensor") at:* * www.OpenPBS.org +1 650 967-4675 sales@OpenPBS.org* 877 902-4PBS (US toll-free)* ---------------------------------------------------------------------------* * This license covers use of the OpenPBS v2.3 software (the "Software") at* your site or location, and, for certain users, redistribution of the* Software to other sites and locations. Use and redistribution of* OpenPBS v2.3 in source and binary forms, with or without modification,* are permitted provided that all of the following conditions are met.* After December 31, 2001, only conditions 3-6 must be met:* * 1. Commercial and/or non-commercial use of the Software is permitted* provided a current software registration is on file at www.OpenPBS.org.* If use of this software contributes to a publication, product, or* service, proper attribution must be given; see www.OpenPBS.org/credit.html* * 2. Redistribution in any form is only permitted for non-commercial,* non-profit purposes. There can be no charge for the Software or any* software incorporating the Software. Further, there can be no* expectation of revenue generated as a consequence of redistributing* the Software.* * 3. Any Redistribution of source code must retain the above copyright notice* and the acknowledgment contained in paragraph 6, this list of conditions* and the disclaimer contained in paragraph 7.* * 4. Any Redistribution in binary form must reproduce the above copyright* notice and the acknowledgment contained in paragraph 6, this list of* conditions and the disclaimer contained in paragraph 7 in the* documentation and/or other materials provided with the distribution.* * 5. Redistributions in any form must be accompanied by information on how to* obtain complete source code for the OpenPBS software and any* modifications and/or additions to the OpenPBS software. The source code* must either be included in the distribution or be available for no more* than the cost of distribution plus a nominal fee, and all modifications* and additions to the Software must be freely redistributable by any party* (including Licensor) without restriction.* * 6. All advertising materials mentioning features or use of the Software must* display the following acknowledgment:* * "This product includes software developed by NASA Ames Research Center,* Lawrence Livermore National Laboratory, and Veridian Information * Solutions, Inc.* Visit www.OpenPBS.org for OpenPBS software support,* products, and information."* * 7. DISCLAIMER OF WARRANTY* * THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. ANY EXPRESS* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT* ARE EXPRESSLY DISCLAIMED.* * IN NO EVENT SHALL VERIDIAN CORPORATION, ITS AFFILIATED COMPANIES, OR THE* U.S. GOVERNMENT OR ANY OF ITS AGENCIES BE LIABLE FOR ANY DIRECT OR INDIRECT,* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.* * This license will be governed by the laws of the Commonwealth of Virginia,* without reference to its choice of law rules.*//* $Id: dedicated.c,v 1.1.6.2 2000/08/09 00:18:38 hender Exp $ *//* * *********************************** * *** STANDARDS COMPLIANCE NOTICE *** * *********************************** * * This file makes use of the AT&T UNIX-based popen() and pclose() calls * to read the output of a user-supplied command (schd_DEDTIME_COMMAND). * This file will not build in a strict ANSI-only environment. Neither * ANSI-C (ISO/IEC 9899-1990), nor the POSIX 1003.1 specification (ISO/IEC * 9945-1) specify the popen()/pclose() library functions. * * If the target machine does not have an implementation of popen() and * pclose(), a working implementation of the library routines should be * available from one of the free UN*X/BSD clones (i.e. NetBSD, FreeBSD, * OpenBSD, etc). * * most real machines do provide an implementation of the popen() and * pclose() library routines. It may be necessary to turn off strict * ANSI-compliance modes to build this file. It may also be necessary * to link with a compatibility library in order to use popen()/pclose(). * * Note: popen()/pclose() are only necessary if dedicated time information * can only be retrieved from the output of a command. Another strategy * might be to exec() the command, redirecting its output into a file, and * then use open()/read()/close() to parse the resultant flat file. */#include <sys/stat.h>#include <ctype.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <errno.h>#include <pbs_error.h>#include <pbs_ifl.h>#include <log.h>#ifdef DBPRT#undef DBPRT#define DBPRT(X)#endif /* DBPRT */#include "toolkit.h"#include "gblxvars.h"struct outagelist { struct outagelist *next; /* next pointer */ char *exechost; /* pointer to name of host for this element */ Outage *outages; /* list of outages for host */ time_t cached_at; /* time the list was fetched or 0 if invalid */};typedef struct outagelist OutageList;OutageList *host_outage_list = NULL;static int get_outages(char *exechost, Outage **outlistp);static Outage *merge_outages (Outage *system_outages, Outage *host_outages);static int MMDDYYYY_HHMM (char *MMDDYYYY, char *HHMM);static int make_time_strs (Outage *outp);static int free_outages(Outage *outages);static int compare_outages_time (const void *e1, const void *e2);static int resolve_outage_overlap (Outage **outlistp);static char *print_outage (Outage *outp);/* * The outage resolution algorithm uses an iterative approach to resolve * one outage at a time. To prevent it looping indefinitely, set this * to some ludicrously large number (say, 250) of times that the list * should be passed through without resolving all the conflicts. If this * happens, it is almost certainly a bug in the implementation. */#define MAX_OUTAGE_RESOLVE_ITERS 250/* * Invalidate any existing entries on the outage caches, and free the lists. */voidschd_clear_outage_cache(void){ OutageList *outlp; for (outlp = host_outage_list; outlp != NULL; outlp = outlp->next) { free_outages(outlp->outages); outlp->cached_at = 0; outlp->outages = NULL; }}Outage *schd_host_outage(char *exechost, time_t when){ char *id = "schd_host_outage"; OutageList *outlp, *newoutl; Outage *outages, *sys_out, *outp; if (when == 0) when = schd_TimeNow; else if (when < schd_TimeNow) { (void)sprintf(log_buffer, "Asked for outages for time in the past - results may be inaccurate!"); log_record(PBSEVENT_SYSTEM, PBS_EVENTCLASS_SERVER, id, log_buffer); DBPRT(("%s: %s\n", id, log_buffer)); } /* * Scan the list of host outage lists for an entry that matches * the requested hostname. If not found, then there is no data * cached. If the data is old, purge it and ask for a new list * of outages for this host. */ for (outlp = host_outage_list; outlp != NULL; outlp = outlp->next) { if (strcmp(exechost, outlp->exechost) == 0) { break; } } /* If no entry was found on the list, one must be created. */ if (outlp == NULL) { newoutl = (OutageList *)malloc(sizeof(OutageList)); if ((newoutl == NULL) || ((newoutl->exechost = schd_strdup(exechost)) == NULL)) { (void)sprintf(log_buffer, "Warning! Couldn't allocate space to track dedicated times!"); log_record(PBSEVENT_SYSTEM, PBS_EVENTCLASS_SERVER, id, log_buffer); DBPRT(("%s: %s\n", id, log_buffer)); return (NULL); } /* newoutl->exechost is set, now fill in the rest of the fields. */ newoutl->next = NULL; newoutl->outages = NULL; /* * Indicate that the list pointed to by newoutl->outages is bogus and * needs to be re-fetched. */ newoutl->cached_at = 0; /* * If the list is empty, make this the first element. Otherwise, * place the new element at the tail of the existing list. */ if (host_outage_list == NULL) { host_outage_list = newoutl; } else { for (outlp = host_outage_list; outlp->next; outlp = outlp->next) /* Just walk to last element in list. */ ; outlp->next = newoutl; } outlp = newoutl; } /* * outlp now points to a valid host OutageList. See if the list of * outages hanging off the host name is still valid. */ if ((outlp->cached_at == 0) || (schd_TimeNow - outlp->cached_at) > schd_DEDTIME_CACHE_SECS) { DBPRT(("%s: dedicated time list for host %s ", id, outlp->exechost)); if (outlp->cached_at) { DBPRT(("expired %s ago\n", schd_sec2val(schd_TimeNow - (outlp->cached_at + schd_DEDTIME_CACHE_SECS)))); } else { DBPRT(("uninitialized\n")); } /* * Try to get a new list of outages. Don't blow away the old one yet, * though. If there's some problem getting the new list, the values * from the old list are more likely to be valid than a NULL list. */ if (get_outages(exechost, &outages)) { (void)sprintf(log_buffer, "WARNING! Could not update dedtime cache for %s!", exechost); log_record(PBSEVENT_SYSTEM, PBS_EVENTCLASS_SERVER, id, log_buffer); DBPRT(("%s: %s\n", id, log_buffer)); if (outlp->cached_at) (void)sprintf(log_buffer, "WARNING! Cached data is %s old!", schd_sec2val(schd_TimeNow - outlp->cached_at)); else (void)sprintf(log_buffer, "WARNING! Cache is uninitialized!"); log_record(PBSEVENT_SYSTEM, PBS_EVENTCLASS_SERVER, id, log_buffer); DBPRT(("%s: %s\n", id, log_buffer)); } else { DBPRT(("%s: got valid list for %s - update cache\n", id, exechost)); (void)sprintf(log_buffer, "updating dedtime cache for %s (valid for %s)", exechost, schd_sec2val(schd_DEDTIME_CACHE_SECS)); log_record(PBSEVENT_SYSTEM, PBS_EVENTCLASS_SERVER, id, log_buffer); DBPRT(("%s: %s\n", id, log_buffer)); /* Set up back pointers to the OutageList's exechost string. */ for (outp = outages; outp != NULL; outp = outp->next) outp->exechost = outlp->exechost;#ifdef DEBUG_DEDTIME DBPRT(("%s: EXECHOST OUTAGES FOR %s:\n", id, exechost)); for (outp = outages; outp != NULL; outp = outp->next) DBPRT(("%s: %s\n", id, print_outage(outp)));#endif /* DEBUG_DEDTIME */ /* * Now that the valid per-host data has been received, check for * any system outage, if schd_SYSTEM_NAME is not NULL. Mix these * into the list, handling overlaps. Note that system dedtimes * take precedence over the per-host dedtimes. */ if (schd_SYSTEM_NAME) { DBPRT(("%s: SYSTEM_NAME is '%s' - look for outages.\n", id, schd_SYSTEM_NAME)); if (get_outages(schd_SYSTEM_NAME, &sys_out) == 0) { if (sys_out != NULL) { /* Mark these outages as system outages. */ for (outp = sys_out; outp != NULL; outp = outp->next) { outp->exechost = schd_SYSTEM_NAME; outp->flags |= OUTAGE_FLAGS_SYSTEM; }#ifdef DEBUG_DEDTIME DBPRT(("%s: SYSTEM OUTAGES FOR %s:\n", id, exechost)); for (outp = sys_out; outp != NULL; outp = outp->next) DBPRT(("%s: %s\n", id, print_outage(outp)));#endif /* DEBUG_DEDTIME */ (void)sprintf(log_buffer, "merging system %s outages with host %s outages", schd_SYSTEM_NAME, exechost); log_record(PBSEVENT_SYSTEM, PBS_EVENTCLASS_SERVER, id, log_buffer); DBPRT(("%s: %s\n", id, log_buffer)); /* Merge the sys_out outages on top of any outages. */ outages = merge_outages(sys_out, outages); if (outages == NULL) DBPRT(("%s: dedtime merge failed\n", id)); sys_out = NULL; /* list was merged into outages list. */ } } else { (void)sprintf(log_buffer, "WARNING! Could not get " "outages for system '%s'!", schd_SYSTEM_NAME); log_record(PBSEVENT_SYSTEM, PBS_EVENTCLASS_SERVER, id, log_buffer); DBPRT(("%s: %s\n", id, log_buffer)); } } /* Throw out the old list. */ free_outages(outlp->outages); /* And point to the new list of outages. */ outlp->outages = outages; outlp->cached_at = schd_TimeNow; } } /* * There is now (at least somewhat) valid data in the host cache. Find * the first entry on the list that we might be within. One could clean * up this list if a dedtime had come and gone, but the benefits would * be quite minimal, given the ratio of cache time to length of the * scheduled outages (usually secs vs. hours). * * A NULL list means that there is no scheduled outage - return the NULL * and be done with it. */#ifdef DEBUG_DEDTIME DBPRT(("%s: FINAL OUTAGES FOR %s:\n", id, exechost)); for (outp = outlp->outages; outp != NULL; outp = outp->next) DBPRT(("%s: %s\n", id, print_outage(outp)));#endif /* DEBUG_DEDTIME */ for (outp = outlp->outages; outp != NULL; outp = outp->next) { /* Ignore any outage that has already come and gone. */ if (outp->end_time > when) break; DBPRT(("%s: Outage from %s:%s to %s:%s ignored\n", id, outp->beg_datestr, outp->beg_timestr, outp->end_datestr, outp->end_timestr)); } return (outp);}/* * Dedicated time is scheduled to begin soon. Determine if the given job * will complete before dedicated time starts. */int schd_dedicated_can_run(Job *job, Queue *queue, time_t when, char *reason){#ifdef DEBUG_DEDTIME char *id = "schd_dedicated_can_run";#endif /* DEBUG_DEDTIME */ Outage *host_out; char *shorthost; time_t job_ends; /* * If no dedicated queues are defined, or dedicated time is not being * enforced, then there's no dedtime to worry about. */ if (!(schd_ENFORCE_DEDTIME && schd_TimeNow >= schd_ENFORCE_DEDTIME)) return(1); if (schd_DedQueues == NULL) return(1); /* If no time is given, assume that the caller means "now". */ if (when == 0) when = schd_TimeNow; /* Get the (possibly cached) dedicated time for the queue's exechost. */ host_out = schd_host_outage(queue->exechost, when); /* No dedicated time for this host. */ if (host_out == NULL) return (1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -