/* * 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. */ #include /* the master config generated by configure */ #ifndef _POSIX_SOURCE #define _POSIX_SOURCE 1 #endif /* _POSIX_SOURCE */ /* System headers */ #include #include #include #include #include /* local headers */ #include "portability.h" #include "af_que.h" /* Macros */ /* File Scope Variables */ static char ident[] = "@(#) $RCSfile$ $Revision$"; struct QueSortArgs { Que **array; SetQue *set; union { int (*ifunc)(); double(*ffunc)(); char *(*sfunc)(); DateTime(*dfunc)(); Size(*szfunc)(); } key; enum { INTKEY, FLOATKEY, STRINGKEY, DATETIMEKEY, SIZEKEY } keytype; int order; /* ASC or DESC */ }; /* External Variables */ /* External Functions */ /* Structures and Unions */ /* Signal catching functions */ /* External Functions */ /* Functions */ char *QueNameGet(que) Que *que; { if (que == NOQUE) return(NULLSTR); return que->name; } int QueTypeGet(que) Que *que; { if (que == NOQUE) return(-1); /* unknown type */ return que->type; } int QueNumJobsGet(que) Que *que; { if (que == NOQUE) return(0); return que->numJobs; } int QuePriorityGet(que) Que *que; { if (que == NOQUE) return(-1); /* unknown priority */ return que->priority; } int QueMaxRunJobsGet(que) Que *que; { if (que == NOQUE) return(0); return que->maxRunJobs; } int QueMaxRunJobsPerUserGet(que) Que *que; { if (que == NOQUE) return(0); return que->maxRunJobsPerUser; } int QueMaxRunJobsPerGroupGet(que) Que *que; { if (que == NOQUE) return(0); return que->maxRunJobsPerGroup; } int QueStateGet(que) Que *que; { if (que == NOQUE) return(SCHED_DISABLED); /* unknown state */ return que->state; } int QueIntResAvailGet(que, name) Que *que; char *name; { if (que == NOQUE) return(-1); return(IntResValueGet(que->intResAvail, name)); } int QueIntResAssignGet(que, name) Que *que; char *name; { if (que == NOQUE) return(-1); return(IntResValueGet(que->intResAssign, name)); } Size QueSizeResAvailGet(que, name) Que *que; char *name; { if (que == NOQUE) return(strToSize("-1b")); return(SizeResValueGet(que->sizeResAvail, name)); } Size QueSizeResAssignGet(que, name) Que *que; char *name; { if (que == NOQUE) return(strToSize("-1b")); return(SizeResValueGet(que->sizeResAssign, name)); } char *QueStringResAvailGet(que, name) Que *que; char *name; { if (que == NOQUE) return(NULLSTR); return(StringResValueGet(que->stringResAvail, name)); } char *QueStringResAssignGet(que, name) Que *que; char *name; { if (que == NOQUE) return(NULLSTR); return(StringResValueGet(que->stringResAssign, name)); } struct SetJobElement *QueJobsGet(que) Que *que; { if (que == NOQUE) return(EMPTYSETJOB); return(que->jobs.head); } /* Put functions */ void QueNamePut(que, queue_name) Que *que; char *queue_name; { assert(que != NOQUE); dynamic_strcpy(&que->name, queue_name); varstrModPptr(que->name, que); } void QueTypePut(que, type) Que *que; int type; { assert(que != NOQUE); que->type = type; } void QueNumJobsPut(que, numJobs) Que *que; int numJobs; { assert(que != NOQUE); que->numJobs = numJobs; } void QueMaxRunJobsPut(que, maxRunJobs) Que *que; int maxRunJobs; { assert(que != NOQUE); que->maxRunJobs = maxRunJobs; } void QueMaxRunJobsPerUserPut(que, maxRunJobsPerUser) Que *que; int maxRunJobsPerUser; { assert(que != NOQUE); que->maxRunJobsPerUser = maxRunJobsPerUser; } void QueMaxRunJobsPerGroupPut(que, maxRunJobsPerGroup) Que *que; int maxRunJobsPerGroup; { assert(que != NOQUE); que->maxRunJobsPerGroup = maxRunJobsPerGroup; } void QuePriorityPut(que, priority) Que *que; int priority; { que->priority = priority; } void QueStatePut(que, state) Que *que; int state; { que->state = state; } void QueIntResAvailPut(que, name, value) Que *que; char *name; int value; { struct IntRes * m; assert(que != NOQUE && name != NULLSTR); m = IntResValuePut(que->intResAvail, name, value, que); if (m != NULL) que->intResAvail = m; } void QueIntResAssignPut(que, name, value) Que *que; char *name; int value; { struct IntRes *m; assert(que != NOQUE && name != NULLSTR); m = IntResValuePut(que->intResAssign, name, value, que); if (m != NULL) que->intResAssign = m; } void QueSizeResAvailPut(que, name, value) Que *que; char *name; Size value; { struct SizeRes *m; assert(que != NOQUE && name != NULLSTR); m = SizeResValuePut(que->sizeResAvail, name, value, que); if (m != NULL) que->sizeResAvail = m; } void QueSizeResAssignPut(que, name, value) Que *que; char *name; Size value; { struct SizeRes *m; assert(que != NOQUE && name != NULLSTR); m = SizeResValuePut(que->sizeResAssign, name, value, que); if (m != NULL) que->sizeResAssign = m; } void QueStringResAvailPut(que, name, value) Que *que; char *name; char *value; { struct StringRes *m; assert(que != NOQUE && name != NULLSTR); m = StringResValuePut(que->stringResAvail, name, value, que); if (m != NULL) que->stringResAvail = m; } void QueStringResAssignPut(que, name, value) Que *que; char *name; char *value; { struct StringRes *m; assert(que != NOQUE && name != NULLSTR); m = StringResValuePut(que->stringResAssign, name, value, que); if (m != NULL) que->stringResAssign = m; } void QueInit(que) Que *que; { assert(que != NOQUE); que->name = NULLSTR; QueTypePut(que, QTYPE_U); QueNumJobsPut(que, 0); QuePriorityPut(que, 0); QueMaxRunJobsPut(que, 0); QueMaxRunJobsPerUserPut(que, 0); QueMaxRunJobsPerGroupPut(que, 0); QueStatePut(que, SCHED_DISABLED); que->intResAvail = NULL; que->intResAssign = NULL; que->sizeResAvail = NULL; que->sizeResAssign = NULL; que->stringResAvail = NULL; que->stringResAssign = NULL; SetJobInit(&que->jobs); que->nextptr = NOQUE; } void QuePrint(que) Que *que; { int type, state; if (que == NOQUE) return; /* ignore */ printf("\tQueue Name = %s\n", QueNameGet(que) ? QueNameGet(que) : "null"); type = QueTypeGet(que); printf("\t\tType = %d ", type); switch (type) { case QTYPE_E: printf("(EXECUTION)"); break; case QTYPE_R: printf("(ROUTE)"); break; } printf("\n"); printf("\t\tNumber of Jobs = %d\n", QueNumJobsGet(que)); printf("\t\tPriority = %d\n", QuePriorityGet(que)); printf("\t\tMax Running Jobs Allowed = %d\n", QueMaxRunJobsGet(que)); printf("\t\tMax Running Jobs Allowed Per User = %d\n", QueMaxRunJobsPerUserGet(que)); printf("\t\tMax Running Jobs Allowed Per Group = %d\n", QueMaxRunJobsPerGroupGet(que)); state = QueStateGet(que); printf("\t\tState = %d ", state); switch (state) { case SCHED_DISABLED: printf("(DISABLED)"); break; case SCHED_ENABLED: printf("(ENABLED)"); break; } printf("\n"); IntResListPrint(que->intResAvail, "\t\tResources_available"); SizeResListPrint(que->sizeResAvail, "\t\tResources_available"); StringResListPrint(que->stringResAvail, "\t\tResources_available"); IntResListPrint(que->intResAssign, "\t\tResources_assigned"); SizeResListPrint(que->sizeResAssign, "\t\tResources_assigned"); StringResListPrint(que->stringResAssign, "\t\tResources_assigned"); SetJobPrint(QueJobsGet(que)); } /* Frees up malloc-ed elements of que. The Job elements must be malloc-ed since this function attempts to free that struct too! It will only free up the Job elements if the # of links (refcnts) to it is zero. */ void QueFree(que) Que *que; { if (que == NOQUE || !inMallocTable(que)) return; /* ignore if already free */ varstrFreeByPptr(que); mallocTableFreeByPptr(que); SetJobFree(&que->jobs); /* keep things consistent */ que->name = NULLSTR; } void QueJobInsert(que, job) Que *que; Job *job; { SetJobAdd(&que->jobs, job); QueNumJobsPut(que, QueNumJobsGet(que) + 1); } void QueJobDelete(que, job) Que *que; Job *job; { SetJobRemove(&que->jobs, job); QueNumJobsPut(que, QueNumJobsGet(que) - 1); } static Job *intExpr(j, q, func, operator, value, maxj, minj) Job *j; Que *q; int (*func)(); Comp operator; int value; Job **maxj; Job **minj; { switch (operator) { case OP_EQ: if (func(j) == value) return(j); break; case OP_NEQ: if (func(j) != value) return(j); break; case OP_LE: if (func(j) <= value) { return(j); } break; case OP_LT: if (func(j) < value) return(j); break; case OP_GE: if (func(j) >= value) return(j); break; case OP_GT: if (func(j) > value) return(j); break; case OP_MAX: if (j == q->jobs.head->job || *maxj == NOJOB || \ func(j) > func(*maxj)) { *maxj = j; } break; case OP_MIN: if (j == q->jobs.head->job || *minj == NOJOB || \ func(j) < func(*minj)) { *minj = j; } break; } return(NOJOB); } static Job *strExpr(j, q, strfunc, operator, valuestr, maxj, minj) Job *j; Que *q; char *(*strfunc)(); Comp operator; char *valuestr; Job **maxj; Job **minj; { switch (operator) { case OP_EQ: if (STRCMP(strfunc(j), == , valuestr)) return(j); break; case OP_NEQ: if (STRCMP(strfunc(j), != , valuestr)) return(j); break; case OP_LE: if (STRCMP(strfunc(j), <= , valuestr)) return(j); break; case OP_LT: if (STRCMP(strfunc(j), < , valuestr)) return(j); break; case OP_GE: if (STRCMP(strfunc(j), >= , valuestr)) return(j); break; case OP_GT: if (STRCMP(strfunc(j), > , valuestr)) return(j); break; case OP_MAX: if (j == q->jobs.head->job || STRCMP(strfunc(j), > , strfunc(*maxj))) { *maxj = j; } break; case OP_MIN: if (j == q->jobs.head->job || STRCMP(strfunc(j), < , strfunc(*minj))) { *minj = j; } break; } return(NOJOB); } static Job *dateTimeExpr(j, q, datetfunc, operator, datet, maxj, minj) Job *j; Que *q; DateTime(*datetfunc)(); Comp operator; DateTime datet; Job **maxj; Job **minj; { switch (operator) { case OP_EQ: if (DATETIMECMP(datetfunc(j), == , datet)) return(j); break; case OP_NEQ: if (DATETIMECMP(datetfunc(j), != , datet)) return(j); break; case OP_LE: if (DATETIMECMP(datetfunc(j), <= , datet)) return(j); break; case OP_LT: if (DATETIMECMP(datetfunc(j), < , datet)) return(j); break; case OP_GE: if (DATETIMECMP(datetfunc(j), >= , datet)) return(j); break; case OP_GT: if (DATETIMECMP(datetfunc(j), > , datet)) return(j); break; case OP_MAX: if (j == q->jobs.head->job || \ DATETIMECMP(datetfunc(j), > , datetfunc(*maxj))) { *maxj = j; } break; case OP_MIN: if (j == q->jobs.head->job || \ DATETIMECMP(datetfunc(j), < , datetfunc(*minj))) { *minj = j; } break; } return(NOJOB); } static Job *sizeExpr(j, q, sizefunc, operator, size, maxj, minj) Job *j; Que *q; Size(*sizefunc)(); Comp operator; Size size; Job **maxj; Job **minj; { switch (operator) { case OP_EQ: if (SIZECMP(sizefunc(j), == , size)) return(j); break; case OP_NEQ: if (SIZECMP(sizefunc(j), != , size)) return(j); break; case OP_LE: if (SIZECMP(sizefunc(j), <= , size)) return(j); break; case OP_LT: if (SIZECMP(sizefunc(j), < , size)) return(j); break; case OP_GE: if (SIZECMP(sizefunc(j), >= , size)) return(j); break; case OP_GT: if (SIZECMP(sizefunc(j), > , size)) return(j); break; case OP_MAX: if (j == q->jobs.head->job || \ SIZECMP(sizefunc(j), > , sizefunc(*maxj))) { *maxj = j; } break; case OP_MIN: if (j == q->jobs.head->job || \ SIZECMP(sizefunc(j), < , sizefunc(*minj))) { *minj = j; } break; } return(NOJOB); } /* QueJobFindInt: find a job in the que that matches the given */ /* parameter which can be of the form: */ /* func, op, value) */ /* where op is one of: GT, GE, LT, LE, EQ, NEQ */ /* NOTE: func, and value are of type Int */ /* if op is one of: MAX, MIN (operating on ints) */ Job *QueJobFindInt(Que *que, ...) { struct SetJobElement *sje; Job *j1; Job *maxj = NOJOB; Job *minj = NOJOB; va_list ap; /* arg pointer */ int (*func)(); Comp operator; int value; void *generic; if (que == NOQUE) return(NOJOB); va_start(ap, que); generic = va_arg(ap, void *); operator = va_arg(ap, Comp); func = (int (*)()) generic; /* conv to a func ret INT */ switch (operator) { case OP_EQ: case OP_NEQ: case OP_LE: case OP_LT: case OP_GE: case OP_GT: value = va_arg(ap, int); case OP_MAX: case OP_MIN: for (firstJobPtr(&sje, que->jobs.head); sje->job; nextJobPtr(&sje)) { if ((j1 = intExpr(sje->job, que, func, operator, value, &maxj, &minj)) != NOJOB) return(j1); } break; default: return(NOJOB); } va_end(ap); switch (operator) { case OP_MAX: return(maxj); case OP_MIN: return(minj); default: return(NOJOB); } } /* QueJobFindStr: find a job in the que that matches the given */ /* parameter which can be of the form: */ /* func, op, value) */ /* where op is one of: GT, GE, LT, LE, EQ, NEQ */ /* NOTE: func, and value are of type string */ Job *QueJobFindStr(Que *que, ...) { struct SetJobElement *sje; Job *j1; Job *maxj = NOJOB; Job *minj = NOJOB; va_list ap; /* arg pointer */ void *generic; Comp operator; char *(*strfunc)(); char *valuestr; if (que == NOQUE) return(NOJOB); va_start(ap, que); generic = va_arg(ap, void *); operator = va_arg(ap, Comp); strfunc = (char * (*)()) generic; /* conv to a func ret STRING */ switch (operator) { case OP_EQ: case OP_NEQ: case OP_LE: case OP_LT: case OP_GE: case OP_GT: valuestr = va_arg(ap, char *); case OP_MAX: case OP_MIN: for (firstJobPtr(&sje, que->jobs.head); sje->job; nextJobPtr(&sje)) { if ((j1 = strExpr(sje->job, que, strfunc, operator, valuestr, &maxj, &minj)) != NOJOB) return(j1); } break; default: return(NOJOB); } va_end(ap); switch (operator) { case OP_MAX: return(maxj); case OP_MIN: return(minj); default: return(NOJOB); } } /* QueJobFindDateTime: find a job in the que that matches the given */ /* parameter which can be of the form: */ /* func, op, value) */ /* where op is one of: GT, GE, LT, LE, EQ, NEQ */ /* NOTE: func, and value are of type Date */ /* if op is one of: MAX, MIN (operating on ints) */ Job *QueJobFindDateTime(Que *que, ...) { struct SetJobElement *sje; Job *j1; Job *maxj = NOJOB; Job *minj = NOJOB; va_list ap; /* arg pointer */ void *generic; Comp operator; DateTime(*datetfunc)(); DateTime datet; if (que == NOQUE) return(NOJOB); va_start(ap, que); generic = va_arg(ap, void *); operator = va_arg(ap, Comp); datetfunc = (DateTime(*)()) generic; /* conv to a func ret DATETIME*/ switch (operator) { case OP_EQ: case OP_NEQ: case OP_LE: case OP_LT: case OP_GE: case OP_GT: datet = va_arg(ap, DateTime); case OP_MAX: case OP_MIN: for (firstJobPtr(&sje, que->jobs.head); sje->job; nextJobPtr(&sje)) { if ((j1 = dateTimeExpr(sje->job, que, datetfunc, operator, datet, &maxj, &minj)) != NOJOB) return(j1); } break; default: return(NOJOB); } va_end(ap); switch (operator) { case OP_MAX: return(maxj); case OP_MIN: return(minj); default: return(NOJOB); } } /* QueJobFindSize: find a job in the que that matches the given */ /* parameter which can be of the form: */ /* func, op, value) */ /* where op is one of: GT, GE, LT, LE, EQ, NEQ */ /* NOTE: func, and value are of type Size */ Job *QueJobFindSize(Que *que, ...) { struct SetJobElement *sje; Job *j1; Job *maxj = NOJOB; Job *minj = NOJOB; va_list ap; /* arg pointer */ void *generic; Comp operator; Size(*sizefunc)(); Size size; if (que == NOQUE) return(NOJOB); va_start(ap, que); generic = va_arg(ap, void *); operator = va_arg(ap, Comp); sizefunc = (Size(*)()) generic; /* conv to a func ret TIME */ switch (operator) { case OP_EQ: case OP_NEQ: case OP_LE: case OP_LT: case OP_GE: case OP_GT: size = va_arg(ap, Size); case OP_MAX: case OP_MIN: for (firstJobPtr(&sje, que->jobs.head); sje->job; nextJobPtr(&sje)) { if ((j1 = sizeExpr(sje->job, que, sizefunc, operator, size, &maxj, &minj)) != NOJOB) return(j1); } break; default: return(NOJOB); } va_end(ap); switch (operator) { case OP_MAX: return(maxj); case OP_MIN: return(minj); default: return(NOJOB); } } /* QueFilterInt: Create "newque" of jobs by filtering the 'que' job */ /* using the specified parameters (func, operator, value) */ /* if op is one of: GT, GE, LT, LE, EQ, NEQ */ /* NOTE: func, and value are of type Int. */ /* RETURNS: newque */ Que *QueFilterInt(que, func, operator, value) Que *que; int (*func)(); Comp operator; int value; { struct SetJobElement *sje; Job *j1; Que *newque; if (que == NOQUE) return(NOQUE); newque = (Que *)malloc(sizeof(Que)); mallocTableAdd(newque, NULL, -1); /* -1 for temporary space */ #ifdef DEBUG printf("In QueFilterInt, added newque %x to mallocTable\n", newque); #endif assert(newque != NOQUE); QueInit(newque); QueNamePut(newque, "QueFilterInt"); switch (operator) { case OP_EQ: case OP_NEQ: case OP_LE: case OP_LT: case OP_GE: case OP_GT: for (firstJobPtr(&sje, que->jobs.head); sje->job; nextJobPtr(&sje)) { if ((j1 = intExpr(sje->job, que, func, operator, value, (Job **)NULL, (Job **)NULL)) != NOJOB) QueJobInsert(newque, j1); } break; default: return(NOQUE); } return(newque); } /* QueFilterStr: Create a new que of jobs by filtering the 'que' job */ /* using the specified parameters (strfunc, operator, valuestr) */ /* if op is one of: GT, GE, LT, LE, EQ, NEQ */ /* RETURNS: newque */ Que *QueFilterStr(que, strfunc, operator, valuestr) Que *que; char *(*strfunc)(); Comp operator; char *valuestr; { struct SetJobElement *sje; Job *j1; Que *newque; if (que == NOQUE) return(NOQUE); newque = (Que *)malloc(sizeof(Que)); mallocTableAdd(newque, NULL, -1); #ifdef DEBUG printf("In QueFilterStr, added newque %x to mallocTable\n", newque); #endif assert(newque != NOQUE); QueInit(newque); QueNamePut(newque, "QueFilterStr"); switch (operator) { case OP_EQ: case OP_NEQ: case OP_LE: case OP_LT: case OP_GE: case OP_GT: for (firstJobPtr(&sje, que->jobs.head); sje->job; nextJobPtr(&sje)) { if ((j1 = strExpr(sje->job, que, strfunc, operator, valuestr, (Job **)NULL, (Job **)NULL)) != NOJOB) QueJobInsert(newque, j1); } break; default: return(NOQUE); } return(newque); } /* QueFilterDateTime: Create a new que of jobs by filtering the 'que' job*/ /* using the specified parameters (datetfunc, operator, datet) */ /* if op is one of: GT, GE, LT, LE, EQ, NEQ */ /* RETURNS: newque ptr. */ Que *QueFilterDateTime(que, datetfunc, operator, datet) Que *que; DateTime(*datetfunc)(); Comp operator; DateTime datet; { struct SetJobElement *sje; Job *j1; Que *newque; if (que == NOQUE) return(NOQUE); newque = (Que *)malloc(sizeof(Que)); mallocTableAdd(newque, NULL, -1); #ifdef DEBUG printf("In QueFilterDateTime, added newque %x to mallocTable\n", newque); #endif QueInit(newque); QueNamePut(newque, "QueFilterDateTime"); switch (operator) { case OP_EQ: case OP_NEQ: case OP_LE: case OP_LT: case OP_GE: case OP_GT: for (firstJobPtr(&sje, que->jobs.head); sje->job; nextJobPtr(&sje)) { if ((j1 = dateTimeExpr(sje->job, que, datetfunc, operator, datet, (Job **)NULL, (Job **)NULL)) != NOJOB) QueJobInsert(newque, j1); } break; default: return(NOQUE); } return(newque); } /* QueFilterSize: Create a new que of jobs by filtering the 'que' job */ /* using the specified parameters (sizefunc, op, size) */ /* if op is one of: GT, GE, LT, LE, EQ, NEQ */ /* RETURNS: 0 of successful; non-zero otherwise. */ Que *QueFilterSize(que, sizefunc, operator, size) Que *que; Size(*sizefunc)(); Comp operator; Size size; { struct SetJobElement *sje; Job *j1; Que *newque; if (que == NOQUE) return(NOQUE); newque = (Que *)malloc(sizeof(Que)); mallocTableAdd(newque, NULL, -1); #ifdef DEBUG printf("In QueFilterSize, added newque %x to mallocTable\n", newque); #endif QueInit(newque); QueNamePut(newque, "QueFilterSize"); switch (operator) { case OP_EQ: case OP_NEQ: case OP_LE: case OP_LT: case OP_GE: case OP_GT: for (firstJobPtr(&sje, que->jobs.head); sje->job; nextJobPtr(&sje)) { if ((j1 = sizeExpr(sje->job, que, sizefunc, operator, size, (Job **)NULL, (Job **)NULL)) != NOJOB) QueJobInsert(newque, j1); } break; default: return(NOQUE); } return(newque); } /* set of Ques abstraction */ void SetQueInit(sq) SetQue *sq; { sq->head = NOQUE; sq->tail = NOQUE; } /* adds to the end of the list */ void SetQueAdd(sq, q) SetQue *sq; Que *q; { assert(sq != EMPTYSETQUE); assert((sq->head == NOQUE && sq->tail == NOQUE) || \ (sq->head != NOQUE && sq->tail != NOQUE)); assert(q != NOQUE); mallocTableAdd(q, sq, 0); #ifdef DEBUG printf("Added q %x to SetQue %x\n", q, sq); QuePrint(q); #endif q->nextptr = NOQUE; if (sq->head == NOQUE && sq->tail == NOQUE) { sq->head = q; sq->tail = q; } else { sq->tail->nextptr = q; sq->tail = q; } } void SetQueFree(sq) SetQue *sq; { Que *q, *qtmp; if (sq == EMPTYSETQUE) return; /* ignore */ for (q = sq->head; q; q = qtmp) { qtmp = q->nextptr; /* free up list of jobs attached to q */ QueFree(q); } /* Free up the Que structures themselves */ mallocTableFreeByPptr(sq); /* Assuming of course that sq is non-malloced! */ SetQueInit(sq); } Que *SetQueFindQueByName(sq, que_name) SetQue *sq; char *que_name; { Que *q; if (sq == EMPTYSETQUE) return(NOQUE); for (q = sq->head; q; q = q->nextptr) { if (STRCMP(QueNameGet(q) , == , que_name)) return(q); } return(NOQUE); } void SetQuePrint(sq) SetQue *sq; { Que *q; for (q = sq->head; q; q = q->nextptr) { QuePrint(q); printf("\n"); } } int inSetQue(que, sq) Que *que; SetQue *sq; { Que *q; if (sq == EMPTYSETQUE) return(0); for (q = sq->head; q; q = q->nextptr) { if (q == que) return(1); } return(0); } static int QuePartition(struct QueSortArgs *A, int p, int r) { Que *temptr; Que *temptr2; int i, j; int k; assert(A->keytype == INTKEY || A->keytype == STRINGKEY || \ A->keytype == DATETIMEKEY || A->keytype == SIZEKEY || \ A->keytype == FLOATKEY); i = p - 1; j = r + 1; while (TRUE) { switch (A->keytype) { case INTKEY: do { j--; } while ((A->order == ASC && A->key.ifunc(A->array[j]) > \ A->key.ifunc(A->array[p])) || \ (A->order == DESC && A->key.ifunc(A->array[j]) < \ A->key.ifunc(A->array[p]))); do { i++; } while ((A->order == ASC && A->key.ifunc(A->array[i]) < \ A->key.ifunc(A->array[p])) || \ (A->order == DESC && A->key.ifunc(A->array[i]) > \ A->key.ifunc(A->array[p]))); break; case FLOATKEY: do { j--; } while ((A->order == ASC && A->key.ffunc(A->array[j]) > \ A->key.ffunc(A->array[p])) || \ (A->order == DESC && A->key.ffunc(A->array[j]) < \ A->key.ffunc(A->array[p]))); do { i++; } while ((A->order == ASC && A->key.ffunc(A->array[i]) < \ A->key.ffunc(A->array[p])) || \ (A->order == DESC && A->key.ffunc(A->array[i]) > \ A->key.ffunc(A->array[p]))); break; case STRINGKEY: do { j--; } while ((A->order == ASC && \ STRCMP(A->key.sfunc(A->array[j]), > , A->key.sfunc(A->array[p]))) || \ (A->order == DESC && \ STRCMP(A->key.sfunc(A->array[j]), < , A->key.sfunc(A->array[p])))); do { i++; } while ((A->order == ASC && \ STRCMP(A->key.sfunc(A->array[i]), < , A->key.sfunc(A->array[p]))) || \ (A->order == DESC && \ STRCMP(A->key.sfunc(A->array[i]), > , A->key.sfunc(A->array[p])))); break; case DATETIMEKEY: do { j--; } while ((A->order == ASC && \ DATETIMECMP(A->key.dfunc(A->array[j]), > , A->key.dfunc(A->array[p]))) || \ (A->order == DESC && \ DATETIMECMP(A->key.dfunc(A->array[j]), < , A->key.dfunc(A->array[p])))); do { i++; } while ((A->order == ASC && \ DATETIMECMP(A->key.dfunc(A->array[i]), < , A->key.dfunc(A->array[p]))) || \ (A->order == DESC && \ DATETIMECMP(A->key.dfunc(A->array[i]), > , A->key.dfunc(A->array[p])))); break; case SIZEKEY: do { j--; } while ((A->order == ASC && \ SIZECMP(A->key.szfunc(A->array[j]), > , A->key.szfunc(A->array[p]))) || \ (A->order == DESC && \ SIZECMP(A->key.szfunc(A->array[j]), < , A->key.szfunc(A->array[p])))); do { i++; } while ((A->order == ASC && \ SIZECMP(A->key.szfunc(A->array[i]), < , A->key.szfunc(A->array[p]))) || \ (A->order == DESC && \ SIZECMP(A->key.szfunc(A->array[i]), > , A->key.szfunc(A->array[p])))); break; } if (i < j) { /* move the pointers around */ if (i + 1 == j) { temptr2 = A->array[i]; } else { temptr2 = A->array[i]->nextptr; } A->array[i]->nextptr = A->array[j]->nextptr; A->array[j]->nextptr = temptr2; if (i - 1 >= 0 && i - 1 < dynamicArraySize(A->array)) { A->array[i-1]->nextptr = A->array[j]; } if (j - 1 != i && j - 1 >= 0 && j - 1 < dynamicArraySize(A->array)) { A->array[j-1]->nextptr = A->array[i]; } if (A->set->head == A->array[i]) { A->set->head = A->array[j]; } if (A->set->tail == A->array[j]) { A->set->tail = A->array[i]; } /* update the entries on the array */ temptr = A->array[j]; A->array[j] = A->array[i]; A->array[i] = temptr; } else { return(j); } } /* while */ } static void QueQuickSort(struct QueSortArgs *A, int p, int r) { int q; if (p < r) { q = QuePartition(A, p, r); QueQuickSort(A, p, q); QueQuickSort(A, q + 1, r); } } int SetQueSortInt(s, key, order) SetQue *s; int (*key)(); int order; { Que **s_ptrs = NULL; int beforecnt, aftercnt; struct QueSortArgs A; Que *q; if (order != ASC && order != DESC) { fprintf(stderr, "SetQueSortInt: order != ASC and order !=DESC\n"); return(FAIL); } beforecnt = 0; for (q = s->head; q; q = q->nextptr) { s_ptrs = (Que **)extendDynamicArray(s_ptrs, beforecnt + 1, sizeof(Que *)); aftercnt = dynamicArraySize(s_ptrs); if (beforecnt == aftercnt) { fprintf(stderr, "SetQueSortInt: Unable to realloc s_ptrs"); if (aftercnt > 0) { freeDynamicArray(s_ptrs); } return(FAIL); } s_ptrs[beforecnt] = q; beforecnt++; } A.array = s_ptrs; A.set = s; A.key.ifunc = key; A.keytype = INTKEY; A.order = order; QueQuickSort(&A, 0, beforecnt - 1); freeDynamicArray(s_ptrs); return(SUCCESS); } int SetQueSortStr(s, key, order) SetQue *s; char *(*key)(); int order; { Que **s_ptrs = NULL; int beforecnt, aftercnt; struct QueSortArgs A; Que *q; if (order != ASC && order != DESC) { fprintf(stderr, "SetQueSortStr: order != ASC and order !=DESC\n"); return(FAIL); } beforecnt = 0; for (q = s->head; q; q = q->nextptr) { s_ptrs = (Que **)extendDynamicArray(s_ptrs, beforecnt + 1, sizeof(Que *)); aftercnt = dynamicArraySize(s_ptrs); if (beforecnt == aftercnt) { fprintf(stderr, "SetQueSortStr: Unable to realloc s_ptrs"); if (aftercnt > 0) { freeDynamicArray(s_ptrs); } return(FAIL); } s_ptrs[beforecnt] = q; beforecnt++; } A.array = s_ptrs; A.set = s; A.key.sfunc = key; A.keytype = STRINGKEY; A.order = order; QueQuickSort(&A, 0, beforecnt - 1); freeDynamicArray(s_ptrs); return(SUCCESS); } int SetQueSortDateTime(s, key, order) SetQue *s; DateTime(*key)(); int order; { Que **s_ptrs = NULL; int beforecnt, aftercnt; struct QueSortArgs A; Que *q; if (order != ASC && order != DESC) { fprintf(stderr, "SetQueSortDateTime: order != ASC and order !=DESC\n"); return(FAIL); } beforecnt = 0; for (q = s->head; q; q = q->nextptr) { s_ptrs = (Que **)extendDynamicArray(s_ptrs, beforecnt + 1, sizeof(Que *)); aftercnt = dynamicArraySize(s_ptrs); if (beforecnt == aftercnt) { fprintf(stderr, "SetQueSortDateTime: Unable to realloc s_ptrs"); if (aftercnt > 0) { freeDynamicArray(s_ptrs); } return(FAIL); } s_ptrs[beforecnt] = q; beforecnt++; } A.array = s_ptrs; A.set = s; A.key.dfunc = key; A.keytype = DATETIMEKEY; A.order = order; QueQuickSort(&A, 0, beforecnt - 1); freeDynamicArray(s_ptrs); return(SUCCESS); } int SetQueSortSize(s, key, order) SetQue *s; Size(*key)(); int order; { Que **s_ptrs = NULL; int beforecnt, aftercnt; struct QueSortArgs A; Que *q; if (order != ASC && order != DESC) { fprintf(stderr, "SetQueSortSize: order != ASC and order !=DESC\n"); return(FAIL); } beforecnt = 0; for (q = s->head; q; q = q->nextptr) { s_ptrs = (Que **)extendDynamicArray(s_ptrs, beforecnt + 1, sizeof(Que *)); aftercnt = dynamicArraySize(s_ptrs); if (beforecnt == aftercnt) { fprintf(stderr, "SetQueSortSize: Unable to realloc s_ptrs"); if (aftercnt > 0) { freeDynamicArray(s_ptrs); } return(FAIL); } s_ptrs[beforecnt] = q; beforecnt++; } A.array = s_ptrs; A.set = s; A.key.szfunc = key; A.keytype = SIZEKEY; A.order = order; QueQuickSort(&A, 0, beforecnt - 1); freeDynamicArray(s_ptrs); return(SUCCESS); } int SetQueSortFloat(s, key, order) SetQue *s; double(*key)(); int order; { Que **s_ptrs = NULL; int beforecnt, aftercnt; struct QueSortArgs A; Que *q; if (order != ASC && order != DESC) { fprintf(stderr, "SetQueSortSize: order != ASC and order !=DESC\n"); return(FAIL); } beforecnt = 0; for (q = s->head; q; q = q->nextptr) { s_ptrs = (Que **)extendDynamicArray(s_ptrs, beforecnt + 1, sizeof(Que *)); aftercnt = dynamicArraySize(s_ptrs); if (beforecnt == aftercnt) { fprintf(stderr, "SetQueSortSize: Unable to realloc s_ptrs"); if (aftercnt > 0) { freeDynamicArray(s_ptrs); } return(FAIL); } s_ptrs[beforecnt] = q; beforecnt++; } A.array = s_ptrs; A.set = s; A.key.ffunc = key; A.keytype = FLOATKEY; A.order = order; QueQuickSort(&A, 0, beforecnt - 1); freeDynamicArray(s_ptrs); return(SUCCESS); }