/*
 *	Network Queueing System (NQS)
 *  This version of NQS is Copyright (C) 1992  John Roman
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 1, or (at your option)
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
/*
*  PROJECT:     Network Queueing System
*  AUTHOR:      John Roman
*
*  Modification history:
*
*       Version Who     When            Description
*       -------+-------+---------------+-------------------------
*       V01.10  JRR                     Initial version.
*       V01.2   JRR     12-Feb-1992	Fixed declaration of static rtns.
*	V01.3	JRR	17-Jun-1992	Added header.
*	V01.4	JRR	20-Nov-1992	Modified for C prototypes.
*	V01.5	JRR	01-Mar-1994	Added support for SOLARIS.
*/
/*++ nqs_deque.c - Network Queueing System
 *
 * $Source: /usr2/jrroma/nqs/nqs-3.35.6/src/RCS/nqs_deque.c,v $
 *
 * DESCRIPTION:
 *
 *	Remove the specified request from its containing queue.
 *	The NQS database description of the queue is NOT updated
 *	by this function.
 *
 *
 *	Author:
 *	-------
 *	Brent A. Kingsbury, Sterling Software Incorporated.
 *	August 12, 1985.
 *
 *
 * STANDARDS VIOLATIONS:
 *   None.
 *
 * REVISION HISTORY: ($Revision: 1.5 $ $Date: 1994/03/30 20:36:33 $ $State: Exp $)
 * $Log: nqs_deque.c,v $
 * Revision 1.5  1994/03/30  20:36:33  jrroma
 * Version 3.35.6
 *
 * Revision 1.4  92/12/22  15:39:51  jrroma
 * Version 3.30
 * 
 * Revision 1.3  92/06/18  17:30:59  jrroma
 * Added gnu header
 * 
 * Revision 1.2  92/02/12  13:36:17  jrroma
 * Fixed declaration of static routines.
 * 
 * Revision 1.1  92/02/12  13:35:01  jrroma
 * Initial revision
 * 
 *
 */

#include "nqs.h"			/* NQS constants and data types */
#include "nqsxvars.h"			/* NQS global variables */

#ifndef __CEXTRACT__
#if __STDC__

static void deqerr ( void );
static int located ( struct request *chain, struct request *target, struct request **ptrprevreq );

#else /* __STDC__ */

static void deqerr (/* void */);
static int located (/* struct request *chain, struct request *target, struct request **ptrprevreq */);

#endif /* __STDC__ */
#endif /* __CEXTRACT__ */

/*** nqs_deque
 *
 *
 *	void nqs_deque():
 *
 *	Remove the specified request from its containing queue.
 *	The NQS database description of the queue is NOT updated
 *	by this function.  However the QUE_UPDATE flag is SET
 *	to indicate that an update in required.
 */
void nqs_deque (request)
struct request *request;		/* Req structure */
{
	struct nqsqueue *queue;		/* Queue holding request */
	struct request *prevreq;	/* Previous request in queue */

	/*
	 *  Search the departing or staging-out set.
	 */
	queue = request->queue;		/* Containing queue */
	if (!located (queue->departset, request, &prevreq)) {
	    /*
	     *  The specified request is not in the departing or
	     *  staging-out set.  Check the running set (run set).
	     */
	    if (!located (queue->runset, request, &prevreq)) {
		/*
		 *  The specified request is not in the running request
		 *  set for the specified queue.  Check the stage-in set.
		 */
		if (!located (queue->stageset, request, &prevreq)) {
		    /*
		     *  The specified request is not in the stage-in request
		     *  set for the specified queue.  Check eligible to run
		     *  set (queued set).
		     */
		    if (!located (queue->queuedset, request, &prevreq)) {
			/*
			 *  The specified request is not in the eligible
			 *  run set.  Check the waiting set.
			 */
			if (!located (queue->waitset, request, &prevreq)) {
			    /*
			     *  The specified request is not in the
			     *  set of waiting requests.  Check the hold
			     *  set.
			     */
			    if (!located (queue->holdset, request, &prevreq)) {
				/*
				 *  The specified request is not in set
				 *  of holding requests.  Search the
				 *  arriving set.
				 */
				if (!located (queue->arriveset, request,
					      &prevreq)) {
				    /*
				     *  The specified request is
				     *  not in the specified
				     *  queue!
				     */
				    deqerr();
				    return;
				}
				if (prevreq == (struct request *) 0) {
				    queue->arriveset=request->next;
				}
				else prevreq->next = request->next;
				queue->q.arrivecount--;
			    }
			    else {
				/*
				 *  The specified request was located
				 *  in the holding set.
				 */
				if (prevreq == (struct request *) 0) {
				    queue->holdset = request->next;
				}
				else prevreq->next = request->next;
				queue->q.holdcount--;
			    }
			}
			else {
			    /*
			     *  The specified request was located in
			     *  the waiting set.
			     */
			    if (prevreq == (struct request *) 0) {
				queue->waitset = request->next;
			    }
			    else prevreq->next = request->next;
			    queue->q.waitcount--;
			}
		    }
		    else {
			/*
			 *  The specified request was located within
			 *  the eligible queued set.
			 */
			if (prevreq == (struct request *) 0) {
			    queue->queuedset = request->next;
			}
			else prevreq->next = request->next;
			queue->q.queuedcount--;
		    }
		}
		else {
		    /*
		     *  The specified request was located within the
		     *  staging-in request set.
		     */
		    if (prevreq == (struct request *) 0) {
			queue->stageset = request->next;
		    }
		    else prevreq->next = request->next;
		    queue->q.stagecount--;
		}
	    }
	    else {
		/*
		 *  The specified request was located within the running
		 *  request set for the specified queue.
		 */
		if (prevreq == (struct request *) 0) {
			queue->runset = request->next;
		}
		else prevreq->next = request->next;
		queue->q.runcount--;
	    }
	}
	else {
	    /*
	     *  The specified request was located with the departing or
	     *  staging-out set for the specified queue/
	     */
	    if (prevreq == (struct request *) 0) {
		queue->departset = request->next;
	    }
	    else prevreq->next = request->next;
	    queue->q.departcount--;
	}
	queue->q.status |= QUE_UPDATE;	/* Set update required flag */
}


/*** located
 *
 *
 *	int located():
 *
 *	Locate the specified request in the specified request chain.
 *	Returns:
 *
 *		1 if the request is present in the chain;
 *		0 otherwise.
 */
static int located (chain, target, ptrprevreq)
register struct request *chain;		/* Request chain */
register struct request *target;	/* Target request */
struct request **ptrprevreq;		/* Pointer of where to return */
					/* ptr to prev req in chain, if */
					/* successful */
{
	register struct request *prevreq;

	prevreq = (struct request *) 0;
	while (chain != target) {
		if (chain == (struct request *) 0) return (0);
		/*
		 *  Loop to locate request in chain.
		 */
		prevreq = chain;
		chain = chain->next;
	}
	*ptrprevreq = prevreq;
	return (1);
}


/*** deqerr
 *
 *
 *	void deqerr():
 *
 *	Report the error that the specified request is not in the
 *	specified queue, and therefore cannot be removed!
 */
static void deqerr()
{
	printf ("E$NQS internal error.\n");
	printf ("I$Attempt to remove request from wrong queue in ");
	printf ("nqs_deque().\n");
	fflush (stdout);
}
