/*
 * nqsd/nqs_wakreq.c
 * 
 * DESCRIPTION:
 *
 *	Wakeup requests that are being held by -a times which have now
 *	occurred.
 *
 *	Original Author:
 *	-------
 *	Brent A. Kingsbury, Sterling Software Incorporated.
 *	August 12, 1985.
 */

#include <libnqs/license.h>
#include <libnqs/proto.h>
#include <libnqs/nqsxvars.h>	       	/* Global vars and directories */

#include <libsal/license.h>
#include <libsal/proto.h>
#include <libsal/defines.h>

static void wakeupset ( struct nqsqueue *queueset );

/*** nqs_wakreq
 *
 *
 *	void nqs_wakreq():
 *
 *	Move all requests in all queue waiting sets whose -a times have
 *	occurred, to the eligible to run request sets in their respective
 *	queues.
 */
void nqs_wakreq()
{

	wakeupset (Nonnet_queueset);	/* Wakeup requests in non-network */
					/* queues */
	wakeupset (Net_queueset);	/* Wakeup requests in network queues*/
}


/*** wakeupset
 *
 *
 *	void wakeupset():
 *
 *	Move all requests in all waiting sets whose -a times have occurred,
 *	to the eligible to run request sets in their respective queues, as
 *	present in the given queue set.
 */
static void wakeupset (struct nqsqueue *queueset)
{
	struct nqsqueue *queue;
	struct request *prevreq;
	struct request *req;
	time_t timenow;			/* Current GMT time */

	time (&timenow);		/* Get current time */
	queue = queueset;
	while (queue != (struct nqsqueue *) 0) {
	    prevreq = (struct request *)0;
	    req = queue->waitset;
	    while (req != (struct request *)0) {
		if ( (req->start_time > timenow) && (req->status & RQF_AFTER )){
		    /*
		     *  This request has a start time in the
		     *  future.  Set the virtual alarm to wake
		     *  it up later.
		     */
		    nqs_vtimer (&req->start_time, nqs_wakreq);
		    prevreq = req;
		    req = req->next;
		} else {
		    sal_dprintf(SAL_DEBUG_INFO, SAL_DEBUG_MSG_DEBUGHIGH, "nqs_wakreq: Request %d.[%d] is eligible\n",
				req->v1.req.orig_seqno, req->v1.req.orig_mid);
		    /*
		     *  This request is now eligible for execution.
		     *  Remove the request from the waiting set and
		     *  place it in the eligible queue set.
		     */
		    if (prevreq == (struct request *)0) {
			queue->waitset = req->next;
		    }
		    else prevreq->next = req->next;
		    queue->q.waitcount--;
		    /*
		     *  Add the request to the eligible to run
		     *  set.
		     */
		    a2s_a2qset (req, queue);
		    /*
		     *  Continue scanning the waiting set of
		     *  requests for the queue.
		     */
		    if (prevreq == (struct request *)0) {
			req = queue->waitset;
		    }
		    else req = prevreq->next;
		} 
	    }
	    queue = queue->next;
	}
	/*
	 *  Request(s) may be eligible for spawning.
	 */
	bsc_spawn();			/* Maybe spawn batch reqs */
	dsc_spawn();			/* Maybe spawn device reqs */
	psc_spawn();			/* Maybe spawn pipe reqs */
	/*
	 *  Update queue states whose images are out of date in the NQS
	 *  database.
	 */
	queue = queueset;
	while (queue != (struct nqsqueue *)0) {
	   if (queue->q.status & QUE_UPDATE) {
	       /*
		*  Update queue image and clear the QUE_UPDATE
	        *  bit.
	        */
		udb_qorder (queue);
	    }
	    queue = queue->next;
	}
}
