/* * 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. */ /* * * xpbs_datadump - (PBS) show stats of batch jobs, queues, or servers. * - basically, this code borrows heavily from "qstat". * * Authors: * Terry Heidelberg * Livermore Computing * * Bruce Kelly * National Energy Research Supercomputer Center * * Lawrence Livermore National Laboratory * University of California * * Albeaus Bayucan * Sterling Software * NASA Ames Research Center */ #include /* the master config generated by configure */ #include "cmds.h" #include "../lib/Libifl/lib_ifl.h" #include #include #include #include #include static int myconnection; static sigjmp_buf env_alrm; static void no_hang(int sig) { fprintf(stderr, "xpbs_datadump: alarm timed-out\n"); myconnection = 0; /* connection to server has failed */ siglongjmp(env_alrm, 1); } static char *mystrdup( char *str) { char *dup; dup = (char *)malloc((size_t)strlen(str) * sizeof(str)); if (dup == NULL) { fprintf(stderr, "xpbs_datadump: out of memory\n"); exit(2); } strcpy(dup, str); return(dup); } void set_attrop( struct attropl **list, const char *a_name, const char *r_name, const char *v_name, enum batch_op op) { struct attropl *attr; attr = (struct attropl *) malloc(sizeof(struct attropl)); if (attr == NULL) { fprintf(stderr, "xpbs_datadump: out of memory\n"); exit(2); } if (a_name == NULL) { attr->name = NULL; } else { attr->name = (char *) malloc(strlen(a_name) + 1); if (attr->name == NULL) { fprintf(stderr, "xpbs_datadump: out of memory\n"); exit(2); } strcpy(attr->name, a_name); } if (r_name == NULL) { attr->resource = (char *)NULL; } else { attr->resource = (char *) malloc(strlen(r_name) + 1); if (attr->resource == NULL) { fprintf(stderr, "xpbs_datadump: out of memory\n"); exit(2); } strcpy(attr->resource, r_name); } if (v_name == NULL) { attr->value = NULL; } else { attr->value = (char *) malloc(strlen(v_name) + 1); if (attr->value == NULL) { fprintf(stderr, "xpbs_datadump: out of memory\n"); exit(2); } strcpy(attr->value, v_name); } attr->op = op; attr->next = *list; *list = attr; return; } #define OPSTRING_LEN 4 #define OP_LEN 2 #define OP_ENUM_LEN 6 static const char *opstring_vals[] = { "eq", "ne", "ge", "gt", "le", "lt" }; static enum batch_op opstring_enums[] = { EQ, NE, GE, GT, LE, LT }; void check_op(char *optarg, enum batch_op *op, char *optargout) { char opstring[OP_LEN+1]; int i; int cp_pos; *op = EQ; /* default */ cp_pos = 0; if (optarg[0] == '.') { strncpy(opstring, &optarg[1], OP_LEN); opstring[OP_LEN] = '\0'; cp_pos = OPSTRING_LEN; for (i = 0; i < OP_ENUM_LEN; i++) { if (strncmp(opstring, opstring_vals[i], OP_LEN) == 0) { *op = opstring_enums[i]; break; } } } strcpy(optargout, &optarg[cp_pos]); return; } int check_res_op(char *optarg, char *resource_name, enum batch_op *op, char *resource_value, char **res_pos) { char opstring[OPSTRING_LEN]; int i; int hit; char *p; p = strchr(optarg, '.'); if (p == NULL || *p == '\0') { fprintf(stderr, "xpbs_datadump: illegal -l value\n"); fprintf(stderr, "resource_list: %s\n", optarg); return (1); } else { strncpy(resource_name, optarg, p - optarg); resource_name[p-optarg] = '\0'; *res_pos = p + OPSTRING_LEN; } if (p[0] == '.') { strncpy(opstring, &p[1] , OP_LEN); opstring[OP_LEN] = '\0'; hit = 0; for (i = 0; i < OP_ENUM_LEN; i++) { if (strncmp(opstring, opstring_vals[i], OP_LEN) == 0) { *op = opstring_enums[i]; hit = 1; break; } } if (! hit) { fprintf(stderr, "xpbs_datadump: illegal -l value\n"); fprintf(stderr, "resource_list: %s\n", optarg); return (1); } } p = strchr(*res_pos, ','); if (p == NULL) { p = strchr(*res_pos, '\0'); } strncpy(resource_value, *res_pos, p - (*res_pos)); resource_value[p-(*res_pos)] = '\0'; if (strlen(resource_value) == 0) { fprintf(stderr, "xpbs_datadump: illegal -l value\n"); fprintf(stderr, "resource_list: %s\n", optarg); return (1); } *res_pos = (*p == '\0') ? p : (p += 1) ; if (**res_pos == '\0' && *(p - 1) == ',') { fprintf(stderr, "xpbs_datadump: illegal -l value\n"); fprintf(stderr, "resource_list: %s\n", optarg); return (1); } return(0); /* ok */ } int istrue(char *string) { if (strcmp(string, "TRUE") == 0) return TRUE; if (strcmp(string, "True") == 0) return TRUE; if (strcmp(string, "true") == 0) return TRUE; if (strcmp(string, "1") == 0) return TRUE; return FALSE; } void states(char *string, char *q, char *r, char *h, char *w, char *t, char *e, char *comp, int len) { char *c, *d, *f, *s, l; c = string; while (isspace(*c) && *c != '\0') c++; while (*c != '\0') { s = c; while (*c != ':') c++; *c = '\0'; d = NULL; if (strcmp(s, "Queued") == 0) d = q; else if (strcmp(s, "Running") == 0) d = r; else if (strcmp(s, "Held") == 0) d = h; else if (strcmp(s, "Waiting") == 0) d = w; else if (strcmp(s, "Transit") == 0) d = t; else if (strcmp(s, "Exiting") == 0) d = e; else if (strcmp(s, "Complete") == 0) d = comp; c++; if (d != NULL) { s = c; while (*c != ' ' && *c != '\0') c++; l = *c; *c = '\0'; if (strlen(s) > (size_t)len) { f = s + len; *f = '\0'; } strcpy(d, s); if (l != '\0') c++; } } } /* * print a attribute value string, formating to break a comma if possible */ void prt_attr(char *n, char *r, char *v) { char *c; const char *comma = ","; int first = 1; int l; int start; start = strlen(n) + 7; /* 4 spaces + ' = ' is 7 */ printf(" %s", n); if (r) { start += strlen(r) + 1; printf(".%s", r); } printf(" = "); c = strtok(v, comma); while (c) { if ((l = strlen(c)) + start < 78) { printf("%s", c); start += l; } else { if (! first) { printf("\n\t"); start = 9; } while (*c) { putchar(*c++); if (++start > 78) { start = 8; printf("\n\t"); } } } if ((c = strtok((char *)0, comma))) { first = 0; putchar(','); } } } #define NAMEL 12 /* printf of jobs, queues, and servers */ #define NODEL 5 #define OWNERL 8 /* printf of jobs */ #define TIMEUL 8 /* printf of jobs */ #define STATEL 1 /* printf of jobs */ #define LOCL 12 /* printf of jobs */ void display_statjob(struct batch_status *status, int prtheader, int full, char *server_name) { struct batch_status *p; struct attrl *a; int l; char *c, *e = NULL; char jid[PBS_MAXSEQNUM+14+1]; char name[NAMEL+1]; char owner[OWNERL+1]; char nodes[NODEL+1]; char cputimeu[TIMEUL+1]; char walltimeu[TIMEUL+1]; char state[STATEL+1]; char location[LOCL+1]; char format[80]; char format2[80]; char long_name[17]; time_t epoch; sprintf(format, "%%-%ds %%-%ds %%-%ds %%%ds %%%ds %%%ds %%%ds %%s@%%s %%s %%s\n", PBS_MAXSEQNUM + 14, NAMEL, OWNERL, NODEL, TIMEUL, TIMEUL, STATEL); sprintf(format2, "%%-%ds %%-%ds %%-%ds %%%ds %%%ds %%%ds %%%ds %%s\n", PBS_MAXSEQNUM + 14, NAMEL, OWNERL, NODEL, TIMEUL, TIMEUL, STATEL); if (! full && prtheader) { printf(":"); printf(format2, "Job id", "Name", "User", "PEs", "CputUse", "WalltUse", "S", "Queue"); } p = status; while (p != NULL) { jid[0] = '\0'; name[0] = '\0'; owner[0] = '\0'; cputimeu[0] = '\0'; walltimeu[0] = '\0'; state[0] = '\0'; location[0] = '\0'; nodes[0] = '\0'; if (full) { printf("Job Id: %s@%s\n", p->name, server_name); a = p->attribs; while (a != NULL) { if (a->name != NULL) { if (strcmp(a->name, ATTR_ctime) == 0 || strcmp(a->name, ATTR_mtime) == 0 || strcmp(a->name, ATTR_qtime) == 0 || strcmp(a->name, ATTR_a) == 0) { epoch = (time_t) atoi(a->value); prt_attr(a->name, a->resource, ctime(&epoch)); } else { prt_attr(a->name, a->resource, a->value); printf("\n"); } } a = a->next; } } else { if (p->name != NULL) { if ((e = mystrdup(p->name)) == NULL) { fprintf(stderr, "Error getting more space to malloc\n"); exit(2); } c = e; /* we need e as the starting address for */ /* future free */ while (*c != '.' && *c != '\0') c++; c++; /* List the first part of the server name, too. */ while (*c != '.' && *c != '\0') c++; c++; /* List also the 2nd part of the server name, too. */ while (*c != '.' && *c != '\0') c++; *c = '\0'; l = strlen(e); if (l > (PBS_MAXSEQNUM + 14)) { c = e + PBS_MAXSEQNUM + 14; *c = '\0'; } strcpy(jid, e); free(e); } a = p->attribs; while (a != NULL) { if (a->name != NULL) { if ((e = mystrdup(a->value)) == NULL) { fprintf(stderr, "Error getting more space to malloc\n"); exit(2); } c = e; /* we need e as the starting address for */ /* future free */ if (strcmp(a->name, ATTR_name) == 0) { l = strlen(e); if (l > NAMEL) { l = l - NAMEL + 3; c = e + l; while (*c != '/' && *c != '\0') c++; if (*c == '\0') c = e + l; strcpy(long_name, "..."); strcat(long_name, c); c = long_name; } else c = e; strcpy(name, c); } else if (strcmp(a->name, ATTR_owner) == 0) { c = e; while (*c != '@' && *c != '\0') c++; *c = '\0'; l = strlen(e); if (l > OWNERL) { c = e + OWNERL; *c = '\0'; } strcpy(owner, e); } else if (strcmp(a->name, ATTR_used) == 0) { if (strcmp(a->resource, "cput") == 0) { l = strlen(e); if (l > TIMEUL) { c = e + TIMEUL; *c = '\0'; } strcpy(cputimeu, e); } else if (strcmp(a->resource, "walltime") == 0) { l = strlen(e); if (l > TIMEUL) { c = e + TIMEUL; *c = '\0'; } strcpy(walltimeu, e); } } else if (strcmp(a->name, ATTR_state) == 0) { l = strlen(e); if (l > STATEL) { c = e + STATEL; *c = '\0'; } strcpy(state, e); } else if (strcmp(a->name, ATTR_queue) == 0) { c = e; while (*c != '@' && *c != '\0') c++; *c = '\0'; l = strlen(e); if (l > LOCL) { c = e + LOCL; *c = '\0'; } strcpy(location, e); } else if (strcmp(a->name, ATTR_l) == 0) { if (strcmp(a->resource, "nodect") == 0 || \ strcmp(a->resource, "ncpus") == 0) { l = strlen(e); if (l > NODEL) { c = e + NODEL; *c = '\0'; } strcpy(nodes, e); } } } a = a->next; free(e); } if (cputimeu[0] == '\0') strcpy(cputimeu, "0"); if (walltimeu[0] == '\0') strcpy(walltimeu, "0"); if (nodes[0] == '\0') strcpy(nodes, "-"); printf(format, jid, name, owner, nodes, cputimeu, walltimeu, state, location, server_name, server_name, p->name); } if (full) printf("\n"); p = p->next; } return; } void display_trackstatjob(struct batch_status *status, char *server_name) { struct batch_status *p; struct attrl *a; char owner[OWNERL+1]; char output_path[MAXPATHLEN]; char error_path[MAXPATHLEN]; int l; char *c, *e = NULL; p = status; while (p != NULL) { printf("%s@%s ", p->name, server_name); a = p->attribs; while (a != NULL) { if (a->name != NULL) { if ((e = mystrdup(a->value)) == NULL) { fprintf(stderr, "Error getting more space to malloc\n"); exit(2); } c = e; /* we need e as the starting address for */ /* future free */ if (strcmp(a->name, ATTR_owner) == 0) { c = e; while (*c != '@' && *c != '\0') c++; *c = '\0'; l = strlen(e); if (l > OWNERL) { c = e + OWNERL; *c = '\0'; } strcpy(owner, e); } else if (strcmp(a->name, ATTR_o) == 0) { strcpy(output_path, a->value); } else if (strcmp(a->name, ATTR_e) == 0) { strcpy(error_path, a->value); } } free(e); a = a->next; } printf("%s %s %s\n", owner, output_path, error_path); p = p->next; } return; } #define QNAMEL 16 #define NUML 5 #define TYPEL 10 void display_statque(struct batch_status *status, int prtheader, int full, char *server_name) { struct batch_status *p; struct attrl *a; int l; char *c, *e; char name[QNAMEL+1]; char max[NUML+1]; char tot[NUML+1]; char ena[NUML+1]; char str[NUML+1]; char que[NUML+1]; char run[NUML+1]; char hld[NUML+1]; char wat[NUML+1]; char trn[NUML+1]; char ext[NUML+1]; char comp[NUML+1]; char type[TYPEL+1]; char format[80]; sprintf(format, "%%-%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%-%ds %%s\n", QNAMEL, NUML, NUML, NUML, NUML, NUML, NUML, NUML, NUML, NUML, NUML, TYPEL); if (! full && prtheader) { printf(":"); printf(format, "Queue", "Max", "Tot", "Ena", "Str", "Que", "Run", "Hld", "Wat", "Trn", "Ext", "Type", "Server"); } p = status; while (p != NULL) { name[0] = '\0'; strcpy(max, "0"); strcpy(tot, "0"); strcpy(ena, "no"); strcpy(str, "no"); strcpy(que, "0"); strcpy(run, "0"); strcpy(hld, "0"); strcpy(wat, "0"); strcpy(trn, "0"); strcpy(ext, "0"); strcpy(comp, "0"); type[0] = '\0'; if (full) { printf("Queue: %s@%s\n", p->name, server_name); a = p->attribs; while (a != NULL) { if (a->name != NULL) { prt_attr(a->name, a->resource, a->value); printf("\n"); } a = a->next; } } else { if (p->name != NULL) { if ((e = mystrdup(p->name)) == NULL) { fprintf(stderr, "Error getting more space to malloc\n"); exit(2); } c = e; /* we need e as the starting address for */ /* future free */ l = strlen(e); if (l > NAMEL) { c = e + NAMEL; *c = '\0'; } strcpy(name, e); free(e); } a = p->attribs; while (a != NULL) { if ((e = mystrdup(a->value)) == NULL) { fprintf(stderr, "Error getting more space to malloc\n"); exit(2); } c = e; /* we need e as the starting address for */ /* future free */ if (a->name != NULL) { if (strcmp(a->name, ATTR_maxrun) == 0) { l = strlen(e); if (l > NUML) { c = e + NUML; *c = '\0'; } strcpy(max, e); } else if (strcmp(a->name, ATTR_total) == 0) { l = strlen(e); if (l > NUML) { c = e + NUML; *c = '\0'; } strcpy(tot, e); } else if (strcmp(a->name, ATTR_enable) == 0) { if (istrue(e)) strcpy(ena, "yes"); else strcpy(ena, "no"); } else if (strcmp(a->name, ATTR_start) == 0) { if (istrue(e)) strcpy(str, "yes"); else strcpy(str, "no"); } else if (strcmp(a->name, ATTR_count) == 0) { states(e, que, run, hld, wat, trn, ext, comp, NUML); } else if (strcmp(a->name, ATTR_qtype) == 0) { l = strlen(e); if (l > TYPEL) { c = e + TYPEL; *c = '\0'; } strcpy(type, e); } } a = a->next; free(e); } printf(format, name, max, tot, ena, str, que, run, hld, wat, trn, ext, type, server_name); } if (full) printf("\n"); p = p->next; } return; } #define SERVERL 23 #define STATUSL 10 #define NODESL 9 void display_statserver(struct batch_status *status, int prtheader, int full, int nodesInUse) { struct batch_status *p; struct attrl *a; int l; char *c, *e; char name[SERVERL+1]; char max[NUML+1]; char tot[NUML+1]; char que[NUML+1]; char run[NUML+1]; char hld[NUML+1]; char wat[NUML+1]; char trn[NUML+1]; char ext[NUML+1]; char comp[NUML+1]; char nod[NODESL+1]; char stats[STATUSL+1]; char format[80]; sprintf(format, "%%-%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%-%ds %%%ds %%s\n", SERVERL, NUML, NUML, NUML, NUML, NUML, NUML, NUML, NUML, STATUSL, NODESL); if (! full && prtheader) { printf(":"); printf(format, "Server", "Max", "Tot", "Que", "Run", "Hld", "Wat", "Trn", "Ext", "Status", "PEsInUse", ""); } p = status; while (p != NULL) { name[0] = '\0'; strcpy(max, "0"); strcpy(tot, "0"); strcpy(que, "0"); strcpy(run, "0"); strcpy(hld, "0"); strcpy(wat, "0"); strcpy(trn, "0"); strcpy(ext, "0"); strcpy(comp, "0"); strcpy(nod, "-/-"); stats[0] = '\0'; if (full) { printf("Server: %s\n", p->name); a = p->attribs; while (a != NULL) { if (a->name != NULL) { prt_attr(a->name, a->resource, a->value); printf("\n"); } a = a->next; } } else { if (p->name != NULL) { if ((e = mystrdup(p->name)) == NULL) { fprintf(stderr, "Error getting more space to malloc\n"); exit(2); } c = e; /* we need e as the starting address for */ /* future free */ l = strlen(e); if (l > SERVERL) { c = e + SERVERL; *c = '\0'; } strcpy(name, e); free(e); } a = p->attribs; while (a != NULL) { if ((e = mystrdup(a->value)) == NULL) { fprintf(stderr, "Error getting more space to malloc\n"); exit(2); } c = e; /* we need e as the starting address for */ /* future free */ if (a->name != NULL) { if (strcmp(a->name, ATTR_maxrun) == 0) { l = strlen(e); if (l > NUML) { c = e + NUML; *c = '\0'; } strcpy(max, e); } else if (strcmp(a->name, ATTR_total) == 0) { l = strlen(e); if (l > NUML) { c = e + NUML; *c = '\0'; } strcpy(tot, e); } else if (strcmp(a->name, ATTR_count) == 0) { states(e, que, run, hld, wat, trn, ext, comp, NUML); } else if (strcmp(a->name, ATTR_status) == 0) { l = strlen(e); if (l > STATUSL) { c = e + STATUSL; *c = '\0'; } strcpy(stats, e); } else if (strcmp(a->name, ATTR_rescmax) == 0) { if (strcmp(a->resource, "nodect") == 0 || \ strcmp(a->resource, "ncpus") == 0) { l = strlen(e); if (l > NODESL) { c = e + NODESL; *c = '\0'; } sprintf(nod, "%d/%s", nodesInUse, e); } } } a = a->next; free(e); } printf(format, name, max, tot, que, run, hld, wat, trn, ext, stats, nod, p->name ? p->name : (char *)""); } if (full) printf("\n"); p = p->next; } return; } static int getNumNodesInUse( int myconnection) { struct batch_status *j_status; struct batch_status *temp; struct attrl *attr; struct attropl *run_list = 0; int nodesInUse = 0; char *errmsg; int nodect; int cpuct; int nodes; int local_errno = 0; set_attrop(&run_list, ATTR_state, (char *)NULL, "R", EQ); j_status = pbs_selstat_err(myconnection, run_list, NULL, &local_errno); if (j_status == NULL) { if (local_errno != PBSE_NONE) { errmsg = pbs_geterrmsg(myconnection); if (errmsg != NULL) { fprintf(stderr, "xpbs_datadump: %s\n", errmsg); } else { fprintf(stderr, "xpbs_datadump: Error (%d) selecting running jobs to obtain nodes in use value\n", local_errno); } return(-1); } } else /* got some output */ { for (temp = j_status; temp; temp = temp->next) { nodect = 0; /* start with a nodect of 0 */ cpuct = 0; /* start with a cpuct of 0 */ nodes = 0; /* nodes is not set */ for (attr = temp->attribs; attr; attr = attr->next) { if (strcmp(attr->name, ATTR_l) == 0) { if (strcmp(attr->resource, "nodect") == 0) { nodect = atoi(attr->value); } else if (strcmp(attr->resource, "nodes") == 0) { nodes = 1; /* nodes is set */ } else if (strcmp(attr->resource, "ncpus") == 0) { cpuct = atoi(attr->value); } } } if (nodes) { nodesInUse += nodect; } else { nodesInUse += cpuct; } } pbs_statfree(j_status); } return(nodesInUse); } int main( /* qstat */ int argc, char **argv) { int c; int errflg = 0; int any_failed = 0; char server_out[MAXSERVERNAME]; char full_server_name[MAXSERVERNAME]; char *queue_name_out = NULL; struct batch_status *p_status; char *errmsg; #define MAX_OPTARG_LEN 256 #define MAX_RESOURCE_NAME_LEN 256 char optargout[MAX_OPTARG_LEN+1]; char resource_name[MAX_RESOURCE_NAME_LEN+1]; enum batch_op op; enum batch_op *pop = &op; struct attropl *select_list = 0; static char destination[PBS_MAXQUEUENAME+1]; char *server_name_out; char *res_pos; char *pc; int u_cnt, o_cnt, s_cnt, n_cnt; time_t after; char a_value[80]; volatile int do_job_only = FALSE; volatile int do_trackjob_only = FALSE; volatile int timeout_secs = 30; /* # of seconds before timing out waiting */ /* for a connection to the server */ struct sigaction act; destination[0] = '\0'; #define GETOPT_ARGS "a:A:c:h:l:N:p:q:r:s:u:JTt:" while ((c = getopt(argc, argv, GETOPT_ARGS)) != EOF) switch (c) { case 't': timeout_secs = atoi(optarg); break; case 'T': do_trackjob_only = TRUE; break; case 'J': do_job_only = TRUE; break; case 'a': check_op(optarg, pop, optargout); if ((after = cvtdate(optargout)) < 0) { fprintf(stderr, "xpbs_datadump: illegal -a value\n"); errflg++; break; } sprintf(a_value, "%ld", (long)after); set_attrop(&select_list, ATTR_a, (char *)NULL, a_value, op); break; case 'c': check_op(optarg, pop, optargout); pc = optargout; while (isspace((int)*pc)) pc++; if (strlen(pc) == 0) { fprintf(stderr, "xpbs_datadump: illegal -c value\n"); errflg++; break; } if (strcmp(pc, "u") == 0) { if ((op != EQ) && (op != NE)) { fprintf(stderr, "xpbs_datadump: illegal -c value\n"); errflg++; break; } } else if ((strcmp(pc, "n") != 0) && (strcmp(pc, "s") != 0) && (strcmp(pc, "c") != 0)) { if (strncmp(pc, "c=", 2) != 0) { fprintf(stderr, "xpbs_datadump: illegal -c value\n"); errflg++; break; } pc += 2; if (strlen(pc) == 0) { fprintf(stderr, "xpbs_datadump: illegal -c value\n"); errflg++; break; } while (*pc != '\0') { if (!isdigit((int)*pc)) { fprintf(stderr, "xpbs_datadump: illegal -c value\n"); errflg++; break; } pc++; } } set_attrop(&select_list, ATTR_c, (char *)NULL, optargout, op); break; case 'h': check_op(optarg, pop, optargout); pc = optargout; while (isspace((int)*pc)) pc++; if (strlen(pc) == 0) { fprintf(stderr, "xpbs_datadump: illegal -h value\n"); errflg++; break; } u_cnt = o_cnt = s_cnt = n_cnt = 0; while (*pc) { if (*pc == 'u') u_cnt++; else if (*pc == 'o') o_cnt++; else if (*pc == 's') s_cnt++; else if (*pc == 'n') n_cnt++; else { fprintf(stderr, "xpbs_datadump: illegal -h value\n"); errflg++; break; } pc++; } if (n_cnt && (u_cnt + o_cnt + s_cnt)) { fprintf(stderr, "xpbs_datadump: illegal -h value\n"); errflg++; break; } set_attrop(&select_list, ATTR_h, (char *)NULL, optargout, op); break; case 'l': res_pos = optarg; while (*res_pos != '\0') { if (check_res_op(res_pos, resource_name, pop, optargout, &res_pos) != 0) { errflg++; break; } set_attrop(&select_list, ATTR_l, resource_name, optargout, op); } break; case 'p': check_op(optarg, pop, optargout); set_attrop(&select_list, ATTR_p, (char *)NULL, optargout, op); break; case 'q': strcpy(destination, optarg); check_op(optarg, pop, optargout); set_attrop(&select_list, ATTR_q, (char *)NULL, optargout, op); break; case 'r': op = EQ; pc = optarg; while (isspace((int)(*pc))) pc++; if (strlen(pc) != 1) { fprintf(stderr, "xpbs_datadump: illegal -r value\n"); errflg++; break; } if (*pc != 'y' && *pc != 'n') { fprintf(stderr, "xpbs_datadump: illegal -r value\n"); errflg++; break; } set_attrop(&select_list, ATTR_r, (char *)NULL, pc, op); break; case 's': check_op(optarg, pop, optargout); pc = optargout; while (isspace((int)(*pc))) pc++; if (strlen(optarg) == 0) { fprintf(stderr, "xpbs_datadump: illegal -s value\n"); errflg++; break; } while (*pc) { if (*pc != 'E' && *pc != 'H' && *pc != 'Q' && *pc != 'R' && *pc != 'T' && *pc != 'W') { fprintf(stderr, "xpbs_datadump: illegal -s value\n"); errflg++; break; } pc++; } set_attrop(&select_list, ATTR_state, (char *)NULL, optargout, op); break; case 'u': op = EQ; if (parse_at_list(optarg, FALSE, FALSE)) { fprintf(stderr, "xpbs_datadump: illegal -u value\n"); errflg++; break; } set_attrop(&select_list, ATTR_u, (char *)NULL, optarg, op); break; case 'A': op = EQ; set_attrop(&select_list, ATTR_A, (char *)NULL, optarg, op); break; case 'N': op = EQ; set_attrop(&select_list, ATTR_N, (char *)NULL, optarg, op); break; default : errflg++; } if (errflg || (optind == argc)) { static char usage[] = "usage: xpbs_datadump \ [-a [op]date_time] [-A account_string] [-c [op]interval] \n\ [-h hold_list] [-l resource_list] [-N name] [-p [op]priority] \n\ [-q destination] [-r y|n] [-s states] [-u user_name] [-J] [-T] \n\ [-t timeout_secs] server_name..\n"; fprintf(stderr, "%s", usage); exit(2); } if (notNULL(destination)) { if (parse_destination_id(destination, &queue_name_out, &server_name_out)) { fprintf(stderr, "xpbs_datadump: illegally formed destination: %s\n", destination); exit(2); } else { if (notNULL(server_name_out)) { strcpy(server_out, server_name_out); } } } act.sa_handler = no_hang; sigemptyset(&act.sa_mask); #ifdef SA_INTERRUPT act.sa_flags = SA_INTERRUPT; #else act.sa_flags = 0; #endif /* SA_INTERRUPT */ (void)sigaction(SIGALRM, &act, (struct sigaction *)0); for (; optind < argc; optind++) { strcpy(server_out, argv[optind]); if (sigsetjmp(env_alrm, 1) == 0) { alarm(timeout_secs); myconnection = cnt2server(server_out); } alarm(0); if (myconnection <= 0) { fprintf(stderr, "xpbs_datadump: Can not connect to server %s \n", server_out); any_failed = myconnection; continue; } /* Get server information */ p_status = pbs_statserver_err(myconnection, NULL, NULL, &any_failed); if (p_status == NULL) { if (any_failed) { errmsg = pbs_geterrmsg(myconnection); if (errmsg != NULL) { fprintf(stderr, "qstat: %s ", errmsg); } else fprintf(stderr, "xpbs_datadump: Error (%d) getting status of server ", any_failed); fprintf(stderr, "%s\n", server_out); } } else { strcpy(full_server_name, p_status->name); if (!do_job_only && !do_trackjob_only) { display_statserver(p_status, TRUE, FALSE, getNumNodesInUse(myconnection)); } pbs_statfree(p_status); } /* Get the queue information */ p_status = pbs_statque_err(myconnection, queue_name_out, NULL, NULL, &any_failed); if (p_status == NULL) { if (any_failed) { errmsg = pbs_geterrmsg(myconnection); if (errmsg != NULL) { fprintf(stderr, "qstat: %s ", errmsg); } else fprintf(stderr, "xpbs_datadump: Error (%d) getting status of queue ", any_failed); fprintf(stderr, "%s\n", queue_name_out); } } else { if (!do_job_only && !do_trackjob_only) { display_statque(p_status, TRUE, FALSE, full_server_name); } pbs_statfree(p_status); } /* ### Get Jobs summary info information for each of the servers */ p_status = pbs_selstat_err(myconnection, select_list, NULL, &any_failed); if (p_status == NULL) { if (any_failed != PBSE_NONE) { errmsg = pbs_geterrmsg(myconnection); if (errmsg != NULL) { fprintf(stderr, "xpbs_datadump: %s\n", errmsg); } else { fprintf(stderr, "xpbs_datadump: Error (%d) selecting jobs\n", any_failed); } } } else /* got some output */ { if (!do_trackjob_only) { display_statjob(p_status, TRUE, FALSE, full_server_name); } else { display_trackstatjob(p_status, full_server_name); } pbs_statfree(p_status); } pbs_disconnect(myconnection); } exit(any_failed); }