📄 getqueues.c
字号:
} else { (void)sprintf(log_buffer, "Can't get resources for %s@%s - marking unavailable.", queue->qname, queue->exechost); log_record(PBSEVENT_SYSTEM, PBS_EVENTCLASS_SERVER, id, log_buffer); DBPRT(("%s: %s\n", id, log_buffer)); queue->flags |= QFLAGS_DISABLED; } }#ifdef DEBUG schd_dump_queue(queue, QUEUE_DUMP_JOBS);#endif /* DEBUG */ /* * It would probably be better to wait for the world to stabilize * than to try to impose some artificial order upon it. Do not do * the sanity check if the queue is stopped. */ if ((queue->flags & QFLAGS_STOPPED) == 0) { if (!queue_sanity(queue)) { sprintf(log_buffer, "WARNING! Queue '%s' failed sanity checks.", queue->qname); log_record(PBSEVENT_ERROR, PBS_EVENTCLASS_SERVER, id, log_buffer); DBPRT(("%s: %s\n", id, log_buffer)); return (1); } } return (0);}#ifdef DEBUGvoid schd_dump_queue(Queue *queue, int dumpjobs){ Job *job; UserAcl *aclent; char num[32]; char *ptr; int columns;#ifdef NODEMASK Bitfield all_ones;#endif /* NODEMASK */ DBPRT(("\nQueue '%s@%s': %sabled/%sed", queue->qname, queue->exechost, (queue->flags & QFLAGS_DISABLED) ? "Dis" : "En", (queue->flags & QFLAGS_STOPPED) ? "Stopp" : "Start")); DBPRT(("%s%s%s%s ", (queue->flags & QFLAGS_FULL) ? "/Full" : "", (queue->flags & QFLAGS_MAXRUN) ? "/MaxRun" : "", (queue->flags & QFLAGS_DRAINING) ? "/Drain" : "", (queue->flags & QFLAGS_USER_ACL) ? "/ACL" : "")); if (schd_ENFORCE_PRIME_TIME && schd_TimeNow >= schd_ENFORCE_PRIME_TIME) DBPRT(("obsv_pt:%s", queue->observe_pt ? "Yes" : "No")); DBPRT(("\n"));#ifdef NODEMASK if (queue->flags & QFLAGS_NODEMASK) { BITFIELD_SETALL(&all_ones); DBPRT((" Nodes: %s\n", schd_format_nodemask(&queue->queuemask, &all_ones))); DBPRT((" Avail: %s\n", schd_format_nodemask(&queue->queuemask, &queue->availmask))); }#endif /* NODEMASK */ sprintf(num, "%d", queue->running); DBPRT((" Job counts: %s running, ", queue->running != UNSPECIFIED ? num : "???")); sprintf(num, "%d", queue->maxrun); DBPRT(("%s max ", queue->maxrun != UNSPECIFIED ? num : "???")); sprintf(num, "%d", queue->userrun); DBPRT(("(%s/user), ", queue->userrun != UNSPECIFIED ? num : "???")); sprintf(num, "%d", queue->queued); DBPRT(("%s queued\n", queue->queued != UNSPECIFIED ? num : "???")); sprintf(num, "%d", queue->nodes_assn); DBPRT((" Nodes:%s/", queue->nodes_assn != UNSPECIFIED ? num : "???")); sprintf(num, "%d", queue->nodes_max); DBPRT(("%s", queue->nodes_max != UNSPECIFIED ? num : "???")); sprintf(num, "%d", queue->nodes_default); DBPRT((" [def %s, ", queue->nodes_default != UNSPECIFIED ? num : "???")); sprintf(num, "%d", queue->nodes_min); DBPRT(("min %s], ", queue->nodes_min != UNSPECIFIED ? num : "???")); DBPRT(("wallt max %s ", (queue->wallt_max != UNSPECIFIED) ? schd_sec2val(queue->wallt_max) : "???")); DBPRT(("[def %s ", queue->wallt_default!=UNSPECIFIED ? schd_sec2val(queue->wallt_default) : "???")); DBPRT(("min %s]\n", (queue->wallt_min != UNSPECIFIED) ? schd_sec2val(queue->wallt_min) : "???")); if (queue->empty_by) /* ctime(2) returns a '\n'-terminated string, so no additional '\n' */ DBPRT((" Queue will empty by: %s", ctime(&queue->empty_by))); if (queue->idle_since) /* ctime(2) returns a '\n'-terminated string, so no additional '\n' */ DBPRT((" Queue idle since: %s", ctime(&queue->idle_since))); if (queue->useracl && (queue->flags & QFLAGS_USER_ACL)) { DBPRT((" User ACL: ")); columns = 9; /* Start with 9 columns for 'User ACL: ' */ for (aclent = queue->useracl; aclent != NULL; aclent = aclent->next) { columns += strlen(aclent->user) + 1; if (columns >= 72) { DBPRT(("\n ")); columns = 0; } DBPRT(("%s%s", ((columns == 0) || (aclent == queue->useracl)) ? "" : "/", aclent->user)); } DBPRT(("\n")); } if (dumpjobs && queue->jobs) { DBPRT((" Jobs: ")); columns = 5; /* Start with 5 columns for 'Jobs: ' */ for (job = queue->jobs; job != NULL; job = job->next) { /* Just the job numbers -- but be sure to put the '.' back! */ if ((ptr = strchr(job->jobid, '.')) != NULL) *ptr = '\0'; columns += strlen(job->jobid) + 3; /* 3 == job->state + '/' + ' ' */ if (columns >= 72) { DBPRT(("\n ")); columns = 0; } DBPRT((" %s/", job->jobid)); DBPRT(("%c", (job->flags & JFLAGS_PRIORITY) ? '!' : (job->flags & JFLAGS_WAITING) ? 'W' : job->state)); if (ptr != NULL) *ptr = '.'; } DBPRT(("\n")); }}#endif /* DEBUG */static int queue_claim_jobs(Queue *queue, Job **joblist_ptr){ Job *job, *prev, *next, *qtail, *longest; int moved; int running, queued, held, other; /* * The time at which this queue should be empty (i.e. when all jobs * currently running on it are completed). Keep track of the longest * running job and compute the empties_at value from that. */ longest = NULL; /* * Keep track of some statistics about what jobs have been found in the * list. These aren't really used (yet), but are easy to compute. */ running = 0; queued = 0; held = 0; other = 0; /* * The number of jobs that have been moved from the global list to the * per-queue list. */ moved = 0; /* * Find the last element of the list of jobs on this queue. This is * probably unnecessary (since this should always be called with * 'queue->jobs' pointing to NULL. Still, it doesn't hurt to try. */ qtail = NULL; if (queue->jobs) { for (qtail = queue->jobs; qtail->next != NULL; qtail = qtail->next) /* Do nothing - just walk to next-to-last element of list */ ; } prev = NULL; for (job = *joblist_ptr; job != NULL; job = next) { next = job->next; /* Wrong queue -- ignore this job. */ if (strcmp(job->qname, queue->qname)) { prev = job; continue; } /* * This job belongs to this queue. Remove it from the job list and * place it at the tail of the queue's job list. This is somewhat * complicated since we have to remove it from the joblist first. * If there is no "previous" job element, then the current job is * the head of the list. */ if (job == *joblist_ptr) { /* * This is the head of the list -- just point the list head to * the job's next pointer and now the job is "orphaned". */ *joblist_ptr = next; prev = *joblist_ptr; } else { /* * This job lies in the middle of the list somewhere. Jump over * it in the previous element, and we're done. Note that since * we skipped this job, the previous job pointer does not change. */ prev->next = job->next; } /* * Now 'job' is the only active handle on the job. Place it at the * tail of the queue's list. If 'qtail' is NULL, this is the first * job -- place it at the head of the list. Otherwise, place it after * the element pointed to by the 'qtail'. Either way, this is the * last element in the list, so point the qtail at it and clear its * next pointer. */ if (qtail == NULL) queue->jobs = job; else qtail->next = job; qtail = job; job->next = NULL; if (job->flags & JFLAGS_QNAME_LOCAL) { /* * The job has some memory that was allocated when it was created, * that is used to store the name of the queue on which it resides. * Since we know exactly what queue it lives on (the one pointed to * by 'queue', to be exact), we can free the storage and point the * 'job->qname' at 'queue->qname'. Also store a reference to the * owner queue in the job itself. */ free (job->qname); job->qname = queue->qname; job->queue = queue; /* * Turn off the flag -- job->qname is now a reference to a queue. */ job->flags &= ~JFLAGS_QNAME_LOCAL; } /* Now, count the job and increment the correct statistic. */ moved ++; switch (job->state) { case 'R': running ++; /* * Adjust the time of any job that has run over its expected * time to the JOB_OVERTIME_SLOP. */ if (job->time_left < 0) { job->time_left = JOB_OVERTIME_SLOP; } /* If this job will be running the longest, note that. */ if ((longest == NULL) || (job->time_left > longest->time_left)) { longest = job; } break; case 'Q': queued ++; break; case 'H': held ++; break; default: other ++; break; } } /* * If any jobs were running, then set the empty_by time to the absolute * time (in seconds) when all jobs should be completed. If none are * running, then set empty_by time to 0. */ if (longest) queue->empty_by = schd_TimeNow + longest->time_left; else queue->empty_by = 0; return (moved);}/* * PBS has been known to provide some bizarre information about the state * of the queue (i.e. no jobs are running in it, but some of its resources * are consumed). Perform some consistency checks on the queue information * before agreeing that it is correct. Generate a laundry list of everything * that appears wrong with it. */static intqueue_sanity(Queue *queue){ char *id = "queue_sanity"; Job *job; int queued, running; int is_sane;#ifdef NODEMASK int nodes_used;#endif /* NODEMASK */ is_sane = 1; /* Assume the queue is sane for now. */#ifdef NODEMASK if (queue->flags & QFLAGS_NODEMASK) { if (queue->nodes_max != BITFIELD_NUM_ONES(&(queue->queuemask))) { sprintf(log_buffer, "Queue '%s' nodemask does not contain " "expected %d nodes (has %d)", queue->qname, queue->nodes_max, BITFIELD_NUM_ONES(&(queue->queuemask))); log_record(PBSEVENT_ERROR, PBS_EVENTCLASS_SERVER, id, log_buffer); DBPRT(("%s: %s\n", id, log_buffer)); } nodes_used = 0; for (job = queue->jobs; job != NULL; job = job->next) if (job->state == 'R') nodes_used += job->nodes; if (queue->nodes_assn != nodes_used) { if (queue->nodes_assn > nodes_used) { sprintf(log_buffer, "Queue '%s' has %d nodes assigned, only %d in running jobs", queue->qname, queue->nodes_assn, nodes_used); is_sane = 0; } else { sprintf(log_buffer, "Queue '%s' has %d nodes assigned, " "%d in running jobs - using %d", queue->qname, queue->nodes_assn, nodes_used, nodes_used); queue->nodes_assn = nodes_used; } log_record(PBSEVENT_ERROR, PBS_EVENTCLASS_SERVER, id, log_buffer); DBPRT(("%s: %s\n", id, log_buffer)); } }#endif /* NODEMASK */ /* * Count running and queued jobs and make sure the numbers match up. */ queued = running = 0; for (job = queue->jobs; job != NULL; job = job->next) { switch (job->state) { case 'R': running ++; break; case 'Q': queued ++; break; default: /* Empty */ break; } } if (queue->running != running) { sprintf(log_buffer, "Queue '%s' expected %d running jobs, but found %d", queue->qname, queue->running, running); log_record(PBSEVENT_ERROR, PBS_EVENTCLASS_SERVER, id, log_buffer); DBPRT(("%s: %s\n", id, log_buffer)); is_sane = 0; } if (queue->queued != queued) { sprintf(log_buffer, "Queue '%s' expected %d queued jobs, but found %d", queue->qname, queue->queued, queued); log_record(PBSEVENT_ERROR, PBS_EVENTCLASS_SERVER, id, log_buffer); DBPRT(("%s: %s\n", id, log_buffer)); is_sane = 0; } if (queue->running && (queue->empty_by < schd_TimeNow)) { sprintf(log_buffer, "Queue '%s' was expected to be empty %d seconds ago", queue->qname, (schd_TimeNow - queue->empty_by)); log_record(PBSEVENT_ERROR, PBS_EVENTCLASS_SERVER, id, log_buffer); DBPRT(("%s: %s\n", id, log_buffer)); is_sane = 0; } return (is_sane);}#ifdef NODEMASKstatic intfind_nodemasks(Queue *queue, Resources *rsrcs){ Job *job; Bitfield jobs_using; BITFIELD_CLRALL(&jobs_using); /* * Compute the set of nodes that are both physically available and also * assigned to this queue. */ BITFIELD_CPY(&queue->availmask, &(queue->queuemask)); BITFIELD_ANDM(&queue->availmask, &(queue->rsrcs->availmask)); /* * Compute the set of nodes in use by jobs running on the queue (if * there are any) and remove those nodes from the available node mask. */ if (queue->running) { for (job = queue->jobs; job != NULL; job = job->next) { if (job->state == 'R') BITFIELD_SETM(&jobs_using, &(job->nodemask)); } } /* * Remove the used node bits from the queue's availmask, and add them to * the resources' nodes used bits. */ BITFIELD_CLRM(&queue->availmask, &jobs_using); BITFIELD_SETM(&rsrcs->nodes_used, &jobs_using); return (0);}#endif /* NODEMASK */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -