/*
 *	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     07-Apr-1992	Added CERN fixes.
*	V01.3	JRR	17-Jun-1992	Added header.
*	V01.4	JRR	07-Dec-1992	Modified for C prototypes.
*/
/*++ pipeqdiag.c - Network Queueing System
 *
 * $Source: /usr2/jrroma/nqs/nqs-3.30/lib/RCS/pipeqdiag.c,v $
 *
 * DESCRIPTION:
 *
 *
 *	This module contains four (4) functions that diagnose
 *	pipe queue transaction codes.  These four functions are
 * 	used by pipe queue servers to analyze the severity of
 *	transaction codes.
 *
 *	The four functions are:
 *
 *		int	pipeqretry(),
 *		int	pipeqenable(),
 *		void	pipeqexitifbad(),	and
 *		long	pipeqfailinfo().
 *
 *	Pipeqretry() accepts a transaction code, and returns
 *	a code indicating the need to reschedule the destination,
 *	and also a judgement on whether the destination might
 *	ever accept the request in the future.
 *
 *	Pipeqenable() accepts a transaction code, and returns
 *	boolean TRUE (non-zero), if a message packet should be
 *	sent to inform the local NQS daemon that the queue dest-
 *	ination associated with the transaction code, should be
 *	completely enabled (retry mode exited).
 *
 *	Pipeqexitifbad() accepts a transaction code, and exits
 *	if that transaction code is fatal (i.e, there is no point in
 *	retrying ANY destination for the request in the foreseeable
 *	future.)
 *
 *	Pipeqfailinfo() accepts a FAILED transaction code, and returns
 *	a value that later can be or'd into a request completion
 *	code, should all destinations fail in non-retriable ways.
 *	Pipeqfailinfo() is not useful unless called with a
 *	non-retriable, non-fatal transaction code.
 *
 *
 *
 *	Author:
 *	-------
 *	Brent A. Kingsbury, Sterling Software Incorporated.
 *	April 25, 1986.
 *
 *
 * STANDARDS VIOLATIONS:
 *   None.
 *
 * REVISION HISTORY: ($Revision: 1.4 $ $Date: 1992/12/22 15:46:20 $ $State: Exp $)
 * $Log: pipeqdiag.c,v $
 * Revision 1.4  1992/12/22  15:46:20  jrroma
 * Version 3.30
 *
 * Revision 1.3  92/06/18  13:24:26  jrroma
 * Added gnu header
 * 
 * Revision 1.2  92/05/06  10:18:54  jrroma
 * Version 3.20
 * 
 * Revision 1.1  92/04/07  13:44:32  jrroma
 * Initial revision
 * 
 *
 */

#include "informcc.h"		/* NQS information completion codes */
#include "requestcc.h"		/* NQS request completion codes */
#include "transactcc.h"		/* NQS transaction completion codes */


/*** pipeqretry
 *
 *
 *	int pipeqretry():
 *
 *	Identify a possibly retriable transaction event for a destination
 *	from the transaction completion code.
 *
 *	Returns:
 *		+1: if the transaction completion code indicates
 *		    a condition at the destination such that it
 *		    is possible that the request might someday be
 *		    queued and/or delivered to that destination
 *		    after waiting a suitable amount of time (i.e.
 *		    TCMP_NOLOCALDAE).
 *
 *		-1: if the transaction completion code indicates
 *		    a serious condition or failure at the destination
 *		    such that the destination should be disabled for
 *		    an appropriate length of time in the hope that
 *		    the situation at the destination machine will
 *		    be fixed.  In all likelihood though, it will
 *		    never be possible to queue and/or deliver the
 *		    request to the destination in question (i.e.
 *		    TCMP_NETDBERR).
 *
 *		 0: if the transaction completion code indicates
 *		    a condition whereby the destination was fine,
 *		    but that the request will never be accepted
 *		    there (i.e. TCMP_ACCESSDEN).
 */
int pipeqretry (code)
register long code;		/* Completion code */
{
	code &= XCI_FULREA_MASK;/* Clear information bits */
	switch (code) {
	case TCMP_QUEBUSY:
	case TCML_QUEBUSY:
	    return(2);
	case TCMP_CONNBROKEN:
	case TCMP_CONNTIMOUT:
	case TCML_ENFILE:
	case TCMP_ENFILE:
	case TCML_ENOBUFS:
	case TCMP_ENOBUFS:
	case TCML_ENOMEM:
	case TCMP_ENOMEM:
	case TCML_ENOSPC:
	case TCMP_ENOSPC:
	case TCML_ERRORRETRY:
	case TCMP_ERRORRETRY:
	case TCML_ETIMEDOUT:
	case TCML_INSQUESPA:
	case TCMP_INSQUESPA:
	case TCMP_MAXNETCONN:
	case TCML_NOESTABLSH:
	case TCMP_NOESTABLSH:
	case TCML_NOLOCALDAE:
	case TCMP_NOLOCALDAE:
	case TCML_NOMOREPROC:
	case TCMP_NOMOREPROC:
	case TCMP_NONETDAE:
	case TCML_NOPORTAVAI:
	case TCML_QUEDISABL:
	case TCMP_QUEDISABL:
		return (1);	/* Reschedule destination, and the request */
				/* might someday be accepted here */
	case TCML_ACCESSDEN:
	case TCMP_ACCESSDEN:
	case TCML_FATALABORT:
	case TCMP_FATALABORT:
	case TCMP_NOACCAUTH:
	case TCML_NOSUCHFORM:
	case TCMP_NOSUCHFORM:
	case TCML_QUOTALIMIT:
	case TCMP_QUOTALIMIT:
	case TCMP_RRFUNKNMID:
	case TCML_WROQUETYP:
	case TCMP_WROQUETYP:
		return (0);	/* The request will never be accepted at */
				/* this destination */
	default:
		return (-1);	/* Reschedule destination, although the */
	}			/* request will probably never be accepted */
}				/* here */


/*** pipeqenable
 *
 *
 *	int pipeqenable():
 *
 *	Analyze a transaction code, and return boolean TRUE (non-zero),
 *	if a message packet should be sent informing the local NQS
 *	daemon that the queue destination associated with the transaction
 *	code, should be completely enabled (retry mode exited).
 */
int pipeqenable (code)
register long code;			/* Completion code */
{
	code &= XCI_FULREA_MASK;	/* Clear information bits */
	switch (code) {
	case TCML_ACCESSDEN:
	case TCMP_ACCESSDEN:
	case TCML_BADCDTFIL:
	case TCMP_BADCDTFIL:
	case TCML_COMPLETE:
	case TCMP_COMPLETE:
	case TCMP_CONTINUE:
	case TCML_NOACCAUTH:
	case TCMP_NOACCAUTH:
	case TCML_NOSUCHFORM:
	case TCMP_NOSUCHFORM:
	case TCML_NOSUCHREQ:
	case TCMP_NOSUCHREQ:
	case TCML_NOSUCHSIG:
	case TCMP_NOSUCHSIG:
	case TCML_NOTREQOWN:
	case TCMP_NOTREQOWN:
	case TCML_PATHLEN:
	case TCMP_PATHLEN:
	case TCML_QUEBUSY:
	case TCMP_QUEBUSY:
        case TCML_QUOTALIMIT:
	case TCMP_QUOTALIMIT:
	case TCML_REQCOLLIDE:
	case TCMP_REQCOLLIDE:
	case TCML_REQDELETE:
	case TCMP_REQDELETE:
	case TCML_REQRUNNING:
	case TCMP_REQRUNNING:
	case TCML_REQSIGNAL:
	case TCMP_REQSIGNAL:
	case TCMP_RRFUNKNMID:
	case TCML_SUBMITTED:
	case TCMP_SUBMITTED:
	case TCML_WROQUETYP:
	case TCMP_WROQUETYP:
		return (1);		/* Return TRUE */
	}
	return (0);
}


/*** pipeqexitifbad
 *
 *
 *	void pipeqexitifbad ():
 *
 *	Analyze the transaction code.  If the code indicates
 *	that there is no point in trying ANY more destinations,
 *	exit.  Otherwise return.
 *
 */
void pipeqexitifbad (code)
register long code;			/* Completion code */
{
	code &= XCI_FULREA_MASK;	/* Clear information bits */
	switch (code) {
	case TCML_BADCDTFIL:
		serexit (RCM_BADCDTFIL, (char *) 0);
	case TCMP_BADCDTFIL:
		/*
		 *  The remote peer machine dropped the ball.
		 *  The only thing we can do is silently clean up.
		 */
		serexit (RCM_PIPREQDEL, (char *) 0);
	case TCML_NOACCAUTH:
		serexit (RCM_NOACCAUTH, (char *) 0);
	case TCMP_NONSECPORT:
		serexit (RCM_NONSECPORT, (char *) 0);
	case TCML_NOSUCHREQ:
	case TCMP_NOSUCHREQ:
		serexit (RCM_PIPREQDEL, (char *) 0);
	case TCML_PATHLEN:
	case TCMP_PATHLEN:
		serexit (RCM_PATHLEN, (char *) 0);
	case TCML_REQCOLLIDE:
	case TCMP_REQCOLLIDE:
		serexit (RCM_REQCOLLIDE, (char *) 0);
	}
}


/*** pipeqfailinfo
 *
 *
 *	long pipeqfailinfo():
 *
 *	Return the proper RCI_ information bit code for the specified
 *	FAILED transaction completion code.
 */
long pipeqfailinfo (code)
register long code;			/* Completion code */
{
	code &= XCI_FULREA_MASK;	/* Clear information bits */
	switch (code) {
	case TCML_ACCESSDEN:
	case TCMP_ACCESSDEN:
		return (RCI_ACCESSDEN);
	case TCMP_CLIMIDUNKN:
		return (RCI_CLIMIDUNKN);
	case TCML_EFBIG:
	case TCMP_EFBIG:
		return (RCI_EFBIG);
	case TCML_FATALABORT:
	case TCMP_FATALABORT:
		return (RCI_FATALABORT);
	case TCMP_INTERNERR:
		return (RCI_PEERINTERR);
	case TCMP_MIDCONFLCT:
		return (RCI_MIDCONFLICT);
	case TCMP_NETDBERR:
		return (RCI_PEERNETDB);
	case TCML_NETNOTSUPP:
		return (RCI_NETNOTSUPP);
	case TCMP_NETPASSWD:
		return (RCI_NETPASSWD);
	case TCMP_NOACCAUTH:
		return (RCI_PEERNOACATH);
	case TCML_NOSUCHFORM:
	case TCMP_NOSUCHFORM:
		return (RCI_NOSUCHFORM);
	case TCML_NOSUCHQUE:
	case TCMP_NOSUCHQUE:
		return (RCI_NOSUCHQUE);
	case TCML_PROTOFAIL:
	case TCMP_PROTOFAIL:
		return (RCI_PROTOFAIL);
	case TCML_QUOTALIMIT:
	case TCMP_QUOTALIMIT:
		return (RCI_QUOTALIMIT);
	case TCMP_RRFUNKNMID:
		return (RCI_RRFUNKNMID);
	case TCMP_SELMIDUNKN:
		return (RCI_PEERMIDUNKN);
	case TCML_WROQUETYP:
	case TCMP_WROQUETYP:
		return (RCI_WROQUETYP);
	default:
		return (RCI_UNAFAILURE);
	}
}
