static char rcsid[] = "$Header: dfs_init.c,v 820.1 86/12/04 19:44:13 root Exp $";
static char sccsid[]="%W% %Y% %Q% %G%";

/************************************************************************
*									*
*				Copyright 1984				*
*			VALID LOGIC SYSTEMS INCORPORATED		*
*									*
*	This listing contains confidential proprietary information	*
*	which is not to be disclosed to unauthorized persons without	*
*	written consent of an officer of Valid Logic Systems 		*
*	Incorporated.							*
*									*
*	The copyright notice appearing above is included to provide	*
*	statutory protection in the event of unauthorized or 		*
*	unintentional public disclosure.				*
*									*
************************************************************************/

/*
 * Initialize the Distributed File System.
 * This just means attaching it to the
 * Remote Procedure Call mechanism.
 *
 *	Bakul Shah
 *
 * bvs 840313 -- original (based on ../efs/efs_init.c)
 * jht 841115,16,26-29 -- complete conversion to use prpc.
 * jht 850213 -- init dfsPktHdr_t containing version/functionality info for pkts
 * jht 850312 -- straighten out rpc vs prpc for exception handling context.
 * jht 850401 -- fill out the gathering of statistics.
 * jht 850416 -- support for rwip() to do implicit ilock()/iunlock().
 */

#include "../h/param.h"
#include "../h/socket.h"
#include "../h/mbuf.h"
#include "../net/if.h"

#include "../vnet/vnet.h"
#include "../conn/conn.h"
#include "../rpc/rpc.h"
#include "../dfs/dfs.h"


#define dfs_externABORT(op)	extern	int		dfsABORT_/**/op()
#define dfs_externA(op)	\
	dfs_externABORT(op)

#define dfs_entryABORT(op) {	"op",					\
				(int) 0,	/* Use count */		\
				dfsServer_/**/op			\
			   }
#define dfs_entryA	\
	dfs_entryABORT

#define dfs_extern(op)	extern	caddr_t			dfsServer_/**/op()

#define dfs_entry(op)	{	"op",					\
				(int) 0,	/* Use count */		\
				dfsServer_/**/op			\
			}

#define dfs_Entry(alias,op) {	"alias",					\
				(int) 0,	/* Use count */		\
				dfsServer_/**/op			\
			}

#define dfs_null()	{	"",					\
				(int) 0,	/* Use count */		\
				NULL		/* Call  hndlr */	\
			}

/*
 * ABORT-handlers
 *
 * For now there are NONE:
 * The prpc_... code (asynchronously) sets
 *
 *	RPCFLAGS_ABORTED in p_rpcflags
 *
 * which the appropriate
 * dfsServer_mumble() checks just before
 * DFS_RETURN(results)-ing to prpc_serverMain().
 */

/*
 * Routines that do all the hard work
 */
dfs_extern(null);
dfs_extern(echo);
dfs_extern(ilock);
dfs_extern(iunlock);
dfs_extern(irele);
dfs_extern(iupdat);
dfs_extern(ilink);
dfs_extern(access);
dfs_extern(openi);
dfs_extern(rwip);
dfs_extern(ioctl);
dfs_extern(itrunc);
dfs_extern(syncip);
dfs_extern(namei);
dfs_extern(direnter);
dfs_extern(dirremove);
dfs_extern(maknode);
dfs_extern(mkdir);
dfs_extern(rmdir);


/*
 * Table of DFS operations interfaces.
 */
rpc_entry_t dfs_optable[] = {
	dfs_entry(null),	/*  0 */
	dfs_entry(echo),	/*  1 */
	dfs_entryA(ilock),	/*  2 */
	dfs_entry(iunlock),	/*  3 */
	dfs_entry(irele),	/*  4 */
	dfs_entry(iupdat),	/*  5 */
	dfs_entry(access),	/*  6 */
	dfs_entry(rwip),	/*  7 */
	dfs_entry(ioctl),	/*  8 */
	dfs_entry(itrunc),	/*  9 */
	dfs_entry(syncip),	/* 10 */
	dfs_entry(openi),	/* 11 */
	dfs_entry(ilink),	/* 12 */
	dfs_null(),		/* 13 */	/* Unneeded */
	dfs_null(),		/* 14 */	/* Unneeded */
	dfs_null(),		/* 15 */	/* Unneeded */
	dfs_entryA(namei),	/* 16 */
	dfs_entry(direnter),	/* 17 */
	dfs_entry(dirremove),	/* 18 */
	dfs_entryA(maknode),	/* 19 */
	dfs_entry(mkdir),	/* 20 */
	dfs_entry(rmdir),	/* 21 */
#ifdef	DFS_NEW_RWIP
	dfs_Entry(lokRwip,rwip),/* 22 */ /* serverSide to ilock()/iunlock() */
#endif	DFS_NEW_RWIP
};

#define NOPS (sizeof(dfs_optable) / sizeof(*dfs_optable))
int	sizeof_dfs_optable = NOPS;


/*
 * Process-level RPC interfaces.
 */
extern int prpc_return();
extern int prpc_error();
extern int prpc_receiveCall();
extern int prpc_receiveAbort();
extern int prpc_serverException();


/*
 * Our exception handlers for client & server
 */
extern int	dfsClient_exception();
extern int	dfsServer_exception();


/*
 * RPC class tables.
 */
rpc_clientClass_t dfsClientClass =		/* Client */
{
	(rpc_clientClass_t *)0,	/* Forward chain in class-list		*/
	"DFS",			/* Class name				*/
	RPC_CLASS_DFS,		/* Class number				*/
	prpc_return,		/* Function to invoke with RETURN pkt	*/
	prpc_error,		/* Function to invoke with ERROR	*/
	prpc_serverException,	/* Function to invoke upon EXCEPTION	*/
	0,			/* Maximum failure rate (exponent)	*/
	60			/* Maximum wait (in HZ) for a call	*/
};

rpc_serverClass_t dfsServerClass =		/* Server */
{
	(rpc_serverClass_t *)0,	/* Forward chain in class-list		*/
	"DFS",			/* Class name				*/
	RPC_CLASS_DFS,		/* Class number				*/
	prpc_receiveCall,	/* Function to invoke with CALL pkt	*/
	prpc_receiveAbort,	/* Function to invoke with ABORT	*/
	prpc_serverException,	/* Function to invoke upon EXCEPTION	*/
	0,			/* Maximum failure rate (exponent)	*/
	60,			/* Maximum wait (in HZ) for a call	*/
	NOPS,			/* Number of operations			*/
	dfs_optable		/* Operation-table for this service	*/
};


int	dfs_enabled	= 0;	/* 0 ==> DFS   not enabled; ~0 ==> enabled */
int	dfs_debug	= 4;	/* 0 ==> debug not enabled; ~0 ==> enabled */
				/* 2 ==> BETA  test			   */
				/* 4 ==> ALPHA test			   */
				/* 8 ==> Development			   */

				/* Secs until DFS will break locks @ server*/
int	dfs_lock_time	= DFS_INODE_LOCK_TIME;

#ifdef	DFS_PACKETHDR
 dfsPktHdr_t	myDfsPktHdr  = {8,	/* Major Version #		  */
				0,	/* Revision #			  */
				0};	/* Bitmap of functions we support */
#endif	DFS_PACKETHDR

/*
 * Instantiate DFS
 *
 * Returns	 0 iff already enabled;
 *		!0 iff successfully enabled.
 */
dfs_init()	/* One-shot initialization */
{

	if (!dfs_enable())
		return	NULL;		/* Was already enabled */
#ifdef	DFS_PACKETHDR
	myDfsPktHdr.functions = DFS_FUNCTIONS;	/* What we support */
#endif	DFS_PACKETHDR

	return 1;
}

/*
 * Attach DFS Classes to the RPC interfaces.
 */
dfs_enable()
{
	dfs_incTotal(enable);
	if (dfs_enabled)
		return NULL;		/* Already enabled! */
	else	dfs_enabled = 1;

	/*
	 * Point RPC at the service-controlling
	 * data structures.
	 */
	rpc_clientAttach(&dfsClientClass);
	rpc_serverAttach(&dfsServerClass);

	/*
	 * Attach the process-RPC exception-handling routines.
	 *
	 * dfsClient_exception() can sleep in xlock() from xrele()
	 *	==> must be a process.
	 * dfsServer_exception() can sleep in biowait() from irele()
	 *	==> must be a process.
	 */
	prpc_attachServerHandler(dfsClient_exception);
	prpc_attachServerHandler(dfsServer_exception);
	return 1;
}

/*
 * Dettach DFS Classes from the RPC interfaces.
 */
dfs_disable()
{
	dfs_incTotal(disable);
	if (dfs_enabled)
		dfs_enabled = 0;	/* Decline further work	*/

	else	return NULL;		/* Already disabled!	*/

	/*
	 * BUG: dfs_disable() should check for work in progress.
	 */
	/*
	 * Detach the service-controlling
	 * data structures from RPC.
	 */
	rpc_clientDetach(&dfsClientClass);
	rpc_serverDetach(&dfsServerClass);

	/*
	 * Detach the process-RPC exception-handling routines.
	 */
	prpc_detachServerHandler(dfsClient_exception);
	prpc_detachServerHandler(dfsServer_exception);
	return 1;
}
