/*
 *	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.20  JRR     16-Jan-1992	Added support for RS6000.
*	V01.3	JRR	17-Jun-1992	Added header.
*	V01.4	JRR	06-Nov-1992	Added support for HPUX.
*	V01.5	JRR	06-Apr-1993	Added support for DECOSF
*					(by removing conditionals).
*/
/*++ openqord.c - Network Queueing System
 *
 * $Source: /usr2/jrroma/nqs/nqs-3.34/lib/RCS/openqord.c,v $
 *
 * DESCRIPTION:
 *
 *	Open the queue ordering file for the specified queue descriptor,
 *	if there are requests in the queue.
 *
 *
 *	Author:
 *	-------
 *	Brent A. Kingsbury, Sterling Software Incorporated.
 *	August 12, 1985.
 *
 *
 * STANDARDS VIOLATIONS:
 *   None.
 *
 * REVISION HISTORY: ($Revision: 1.5 $ $Date: 1993/07/13 21:31:32 $ $State: Exp $)
 * $Log: openqord.c,v $
 * Revision 1.5  1993/07/13  21:31:32  jrroma
 * Version 3.34
 *
 * Revision 1.4  92/11/06  13:51:22  jrroma
 * Added support for HPUX.
 * 
 * Revision 1.3  92/06/18  13:24:22  jrroma
 * Added gnu header
 * 
 * Revision 1.2  92/01/16  17:02:11  jrroma
 * Added support for RS6000.
 * 
 * Revision 1.1  92/01/16  17:01:23  jrroma
 * Initial revision
 * 
 *
 */

#include "nqs.h"		/* NQS definitions */
#include "nqsxdirs.h"		/* NQS directories */
#include <string.h>

/*
 *	Configurable parameters.
 */
#define	MAX_RETRY	50	/* Maximum queue ordering file retry limit */


/*** openqord
 *
 *
 *	int openqord():
 *
 *	Open the queue ordering file for the specified queue descriptor,
 *	of there are requests in the queue.
 *
 *	Returns:
 *	      >=0: if the queue has requests, and the queue ordering
 *		   file was successfully opened.  The value returned
 *		   is the file descriptor opened to read the queue
 *		   ordering file.
 *	       -1: if there are no requests in the queue (no queue
 *		   ordering file is opened).
 *	       -2: if there ARE requests in the queue, but some terrible
 *		   error prevented us from opening the queue ordering
 *		   file.
 *	       -3: if the queue has been deleted.
 */
int openqord (struct confd *queuefile, struct gendescr *descr)
{
	char path [MAX_PATHNAME+1];	/* Queue ordering file pathname */
	char quename [MAX_QUEUENAME+1];	/* Name of queue */
	register int fd;		/* Queue ordering file descriptor */
	int retry;			/* Race condition retry */
	long position;			/* Offset in NQS database file of */
					/* the queue file descriptor */
	long blockpos;			/* The block offset in the NQS */
					/* queue file descriptor file of the */
					/* queue descriptor */

	position = telldb (queuefile);	/* Remember offset of descriptor */
	blockpos = blockdb (position) * ATOMICBLKSIZ;
	strcpy (quename, descr->v.que.namev.name);
	/*
	 *  Open the request queue ordering file.
	 */
	retry = 0;			/* Retry count */
	fd = -1;			/* Queue ordering file not open */
	while (retry <= MAX_RETRY &&
	      (descr->v.que.departcount || descr->v.que.runcount ||
	       descr->v.que.stagecount || descr->v.que.queuedcount ||
	       descr->v.que.waitcount || descr->v.que.holdcount ||
	       descr->v.que.arrivecount)) {
		if (descr->v.que.type == QUE_NET) {
			sprintf (path, "%s/n%08x%04x", Nqs_qorder,
				 telldb(queuefile), descr->v.que.orderversion);
		}
		else {
			sprintf (path, "%s/q%08x%04x", Nqs_qorder,
				 telldb(queuefile), descr->v.que.orderversion);
		}
		if ((fd = open (path, O_RDONLY)) == -1) {
			/*
			 *  We did not succeed in opening the queue
			 *  ordering file (because a queue update JUST
			 *  occurred)....  We may get in a race here
			 *  with the daemon.  However the likelihood
			 *  of this race going on for more than 1 or
			 *  2 iterations is VERY low.  We are simply
			 *  paying the price for not using locks (which
			 *  would also slow everyone down all of the
			 *  time, and make this whole thing less portable....
			 */
			seekdb (queuefile, blockpos);	/* Seek back to load */
							/* block */
			descr = nextdb (queuefile);	/* Read descr */
			while (descr != (struct gendescr *)0 &&
			       telldb (queuefile) < position) {
				descr = nextdb (queuefile);
			}
			if (descr == (struct gendescr *)0 ||
			    telldb(queuefile) > position ||
			    strcmp (descr->v.que.namev.name, quename)) {
				/*
				 *  The queue has been deleted, or
				 *  replaced by another queue!
				 */
				return (-3);		/* No such queue */
			}
			else retry += 1;		/* Keep counter */
		} 
		else retry = MAX_RETRY+1;		/* Set for exit */
	}
	if (fd == -1) {			/* Queue ordering file not open */
		if (descr->v.que.departcount || descr->v.que.runcount ||
		    descr->v.que.stagecount || descr->v.que.queuedcount ||
		    descr->v.que.waitcount || descr->v.que.holdcount ||
		    descr->v.que.arrivecount) {
			/*
			 *  Something is wrong since the queue exists and
			 *  has reqs, but no queue ordering file.
			 */
			return (-2);	/* Unable to open queue file! */
		}
		return (-1);		/* No requests in the queue */
	}
	return (fd);			/* Return the opened file descriptor */
}
