/* * 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. */ /* * svr_func.c - miscellaneous server functions */ #include /* the master config generated by configure */ #include "portability.h" #include #include #include #include #include #include #include "server_limits.h" #include "list_link.h" #include "attribute.h" #include "resource.h" #include "pbs_job.h" #include "queue.h" #include "server.h" #include "pbs_error.h" #include "svrfunc.h" #include "sched_cmds.h" #include "csv.h" #include "log.h" #include "../lib/Liblog/pbs_log.h" #include "mutex_mgr.hpp" extern int LOGLEVEL; extern int scheduler_sock; extern pthread_mutex_t *scheduler_sock_jobct_mutex; extern int svr_do_schedule; extern pthread_mutex_t *svr_do_schedule_mutex; extern pthread_mutex_t *listener_command_mutex; extern int listener_command; /* * the following array of strings is used in decoding/encoding the server state */ static const char *svr_idle = "Idle"; static const char *svr_sched = "Scheduling"; static const char *svr_state_names[] = { "", /* SV_STATE_DOWN */ "", /* SV_STATE_INIT */ "Hot_Start", /* SV_STATE_HOT */ "Active", /* SV_STATE_RUN */ "Terminating_Delay", /* SV_STATE_SHUTDEL */ "Terminating", /* SV_STATE_SHUTIMM */ "Terminating" /* SV_STATE_SHUTSIG */ }; /* * encode_svrstate - encode the current server state from the internal * integer to a state name string. */ int encode_svrstate( pbs_attribute *pattr, /* ptr to pbs_attribute */ tlist_head *phead, /* head of attrlist list */ const char *atname, /* pbs_attribute name */ const char *rsname, /* null */ int mode, /* encode mode */ int perm) /* only used for resources */ { svrattrl *pal; const char *psname; if (pattr == NULL) { /* FAILURE */ return(-1); } if ((mode == ATR_ENCODE_SAVE) || (pattr->at_val.at_long <= SV_STATE_DOWN) || (pattr->at_val.at_long > SV_STATE_SHUTSIG)) { /* SUCCESS */ return(0); /* don't bother to encode it */ } psname = svr_state_names[pattr->at_val.at_long]; if (pattr->at_val.at_long == SV_STATE_RUN) { pthread_mutex_lock(server.sv_attr_mutex); if (server.sv_attr[SRV_ATR_scheduling].at_val.at_long == 0) psname = svr_idle; else { pthread_mutex_lock(scheduler_sock_jobct_mutex); if (scheduler_sock != -1) psname = svr_sched; pthread_mutex_unlock(scheduler_sock_jobct_mutex); } pthread_mutex_unlock(server.sv_attr_mutex); } pal = attrlist_create(atname, rsname, strlen(psname) + 1); if (pal == NULL) { /* FAILURE */ return(-1); } strcpy(pal->al_value, psname); pal->al_flags = pattr->at_flags; append_link(phead, &pal->al_link, pal); /* SUCCESS */ return(1); } /* END encode_svrstate() */ /* * set_resc_assigned - set the resources used by a job in the server and * queue resources_used pbs_attribute */ void set_resc_assigned( job *pjob, /* I */ enum batch_op op) /* INCR or DECR */ { resource *jobrsc; resource *pr; pbs_attribute *queru; resource_def *rscdef; pbs_attribute *sysru; pbs_queue *pque; char log_buf[LOCAL_LOG_BUF_SIZE]; if ((pjob == NULL)) return; if ((pque = get_jobs_queue(&pjob)) != NULL) { mutex_mgr pque_mutex = mutex_mgr(pque->qu_mutex, true); if (pque->qu_qs.qu_type == QTYPE_Execution) { if (op == DECR) { /* if freeing completed job resources, ignore constraint (???) */ /* NO-OP */ } } else { snprintf(log_buf,sizeof(log_buf), "job %s isn't in an execution queue, can't modify resources\njob is in queue %s", pjob->ji_qs.ji_jobid, pque->qu_qs.qu_name); log_err(-1, __func__, log_buf); return; } if (op == INCR) { if (pjob->ji_qs.ji_svrflags & JOB_SVFLG_RescAssn) { return; /* already added in */ } pjob->ji_qs.ji_svrflags |= JOB_SVFLG_RescAssn; } else if (op == DECR) { if ((pjob->ji_qs.ji_svrflags & JOB_SVFLG_RescAssn) == 0) { return; /* not currently included */ } pjob->ji_qs.ji_svrflags &= ~JOB_SVFLG_RescAssn; } else { return; /* invalid op */ } sysru = &server.sv_attr[SRV_ATR_resource_assn]; queru = &pque->qu_attr[QE_ATR_ResourceAssn]; jobrsc = (resource *)GET_NEXT(pjob->ji_wattr[JOB_ATR_resource].at_val.at_list); while (jobrsc != NULL) { rscdef = jobrsc->rs_defin; /* if resource usage is to be tracked */ if ((rscdef->rs_flags & ATR_DFLAG_RASSN) && (jobrsc->rs_value.at_flags & ATR_VFLAG_SET)) { /* update system pbs_attribute of resources assigned */ pr = find_resc_entry(sysru, rscdef); if (pr == NULL) { pr = add_resource_entry(sysru, rscdef); if (pr == NULL) { return; } } rscdef->rs_set(&pr->rs_value, &jobrsc->rs_value, op); /* update queue pbs_attribute of resources assigned */ pr = find_resc_entry(queru, rscdef); if (pr == NULL) { pr = add_resource_entry(queru, rscdef); if (pr == NULL) { return; } } rscdef->rs_set(&pr->rs_value, &jobrsc->rs_value, op); } jobrsc = (resource *)GET_NEXT(jobrsc->rs_link); } /* END while (jobrsc != NULL) */ } else if (pjob == NULL) { log_err(PBSE_JOBNOTFOUND, __func__, "Job lost while acquiring queue 9"); } return; } /* END set_resc_assigned() */ /* * ck_checkpoint - check validity of job checkpoint pbs_attribute value * * This routine is not directly called. * Rather it is referenced by an at_action field. * This is invoked inside of a loop over attributes in req_quejob. */ int ck_checkpoint( pbs_attribute *pattr, void *pobject, /* not used */ int mode) /* not used */ { char *val; int field_count; int i; int len; char *str; val = pattr->at_val.at_str; if (val == NULL) { /* SUCCESS */ return(0); } field_count = csv_length(val); for (i = 0; i < field_count; i++) { str = csv_nth(val, i); if (str) { if ((len = strlen(str)) > 0) { if (len == 1 && !((str[0] == 'n') || (str[0] == 's') || (str[0] == 'u'))) { return(PBSE_BADATVAL); } else if (!strncmp(str, "c=", 2)) { if (atoi(&str[2]) <= 0) { return(PBSE_BADATVAL); } continue; } else if (!strcmp(str, "none")) {} else if (!strcmp(str, "periodic")) {} else if (!strcmp(str, "shutdown")) {} else if (!strcmp(str, "enabled")) {} else if (!strncmp(str, "interval=", 9)) {} else if (!strncmp(str, "depth=", 6)) {} else if (!strncmp(str, "dir=", 4)) {} else { return(PBSE_BADATVAL); } } } } /* SUCCESS */ return(0); } /* * decode_null - Null pbs_attribute decode routine for Read Only (server * and queue ) attributes. It just returns 0. */ int decode_null(pbs_attribute *patr, const char *name, const char *rn, const char *val, int perm) { return 0; } /* * set_null - Null set routine for Read Only attributes. */ int set_null( pbs_attribute *pattr, pbs_attribute *new_attr, enum batch_op op) { return(0); } int is_svr_attr_set( int attr_index) { int is_set = FALSE; if (SRV_ATR_LAST <= attr_index) return(is_set); pthread_mutex_lock(server.sv_attr_mutex); if (server.sv_attr[attr_index].at_flags & ATR_VFLAG_SET) is_set = TRUE; pthread_mutex_unlock(server.sv_attr_mutex); return(is_set); } /* END is_svr_attr_set() */ int set_svr_attr( int attr_index, /* I */ void *val) /* I */ { char *str; long *l; char *c; struct array_strings *arst; if (attr_index >= SRV_ATR_LAST) return(-1); pthread_mutex_lock(server.sv_attr_mutex); server.sv_attr[attr_index].at_flags = ATR_VFLAG_SET; switch (svr_attr_def[attr_index].at_type) { case ATR_TYPE_LONG: l = (long *)val; server.sv_attr[attr_index].at_val.at_long = *l; break; case ATR_TYPE_CHAR: c = (char *)val; server.sv_attr[attr_index].at_val.at_char = *c; break; case ATR_TYPE_STR: str = (char *)val; server.sv_attr[attr_index].at_val.at_str = str; break; case ATR_TYPE_ARST: case ATR_TYPE_ACL: arst = (struct array_strings *)val; server.sv_attr[attr_index].at_val.at_arst = arst; break; default: server.sv_attr[attr_index].at_flags &= ~ATR_VFLAG_SET; break; } pthread_mutex_unlock(server.sv_attr_mutex); return(PBSE_NONE); } /* END set_svr_attr() */ int get_svr_attr_l( int attr_index, long *l) { int rc = PBSE_NONE; pthread_mutex_lock(server.sv_attr_mutex); if ((attr_index >= SRV_ATR_LAST) || ((server.sv_attr[attr_index].at_flags & ATR_VFLAG_SET) == FALSE)) { rc = -1; } else if (svr_attr_def[attr_index].at_type == ATR_TYPE_LONG) { *l = server.sv_attr[attr_index].at_val.at_long; } else { rc = -2; } pthread_mutex_unlock(server.sv_attr_mutex); return rc; } int get_svr_attr_c( int attr_index, char *c) { int rc = PBSE_NONE; pthread_mutex_lock(server.sv_attr_mutex); if ((attr_index >= SRV_ATR_LAST) || ((server.sv_attr[attr_index].at_flags & ATR_VFLAG_SET) == FALSE)) { rc = -1; } else if (svr_attr_def[attr_index].at_type == ATR_TYPE_CHAR) { *c = server.sv_attr[attr_index].at_val.at_char; } else { rc = -2; } pthread_mutex_unlock(server.sv_attr_mutex); return rc; } int get_svr_attr_str( int attr_index, char **str) { int rc = PBSE_NONE; pthread_mutex_lock(server.sv_attr_mutex); if ((attr_index >= SRV_ATR_LAST) || ((server.sv_attr[attr_index].at_flags & ATR_VFLAG_SET) == FALSE)) { rc = -1; } else if (svr_attr_def[attr_index].at_type == ATR_TYPE_STR) { *str = server.sv_attr[attr_index].at_val.at_str; } else { rc = -2; } pthread_mutex_unlock(server.sv_attr_mutex); return rc; } int get_svr_attr_arst( int attr_index, struct array_strings **arst) { int rc = PBSE_NONE; pthread_mutex_lock(server.sv_attr_mutex); if ((attr_index >= SRV_ATR_LAST) || ((server.sv_attr[attr_index].at_flags & ATR_VFLAG_SET) == FALSE)) { rc = -1; } else if ((svr_attr_def[attr_index].at_type == ATR_TYPE_ARST) || (svr_attr_def[attr_index].at_type == ATR_TYPE_ACL)) { *arst = server.sv_attr[attr_index].at_val.at_arst; } else { rc = -2; } pthread_mutex_unlock(server.sv_attr_mutex); return rc; } /* * poke_scheduler - action routine for the server's "scheduling" pbs_attribute. * Call the scheduler whenever the pbs_attribute is set (or reset) to true. */ int poke_scheduler( pbs_attribute *pattr, void *pobj, int actmode) { if (actmode == ATR_ACTION_ALTER) { if (pattr->at_val.at_long) { pthread_mutex_lock(svr_do_schedule_mutex); svr_do_schedule = SCH_SCHEDULE_CMD; pthread_mutex_unlock(svr_do_schedule_mutex); pthread_mutex_lock(listener_command_mutex); listener_command = SCH_SCHEDULE_CMD; pthread_mutex_unlock(listener_command_mutex); } } return(0); } /* END poke_scheduler() */