/*******************************************************************************
* E.S.O. - VLT project
#
# "@(#) $Id: evhTestSTD_COMMANDS.C,v 1.87 1999/01/13 14:32:09 vltsccm Exp $" 
*
* who       when      what
* --------  --------  ----------------------------------------------
* gchiozzi  15/04/99  created
*/

/************************************************************************
*   NAME
*   waAPPLICATION - Application class for the example
* 
*   SYNOPSIS
*
*   
*   PARENT CLASS
*   evhSTD_COMMANDS
* 
*   DESCRIPTION
*   Application class for the example.
*   It implements handling for the SETVAL, GETVAL and TEST commands 
*   and inherits from the evhSTD_COMMANDS base class the handling of 
*   all VLT standad commands.
*   SETVAL and GETVAL are transferred (rerouted) to the process
*   defined in the constructor parameters.
*   A database point provides standard status information.
*
*   PUBLIC METHODS
*
*   waAPPLICATION(int argc, char *argv[],
*		  const dbSYMADDRESS  dbPoint );
*     The constructor accepts as parameters the command line
*     arguments and the symbolic address for the root point 
*     of the application database.
*     It expects the following arguments on the command line
*       - process name in argv[0].
*       - destination environment in argv[1].
*       - destination process in argv[2].
*     
*   virtual ~waAPPLICATION();
*     Destructor
*
*   virtual evhCB_COMPL_STAT  TransferCB(msgMESSAGE &msg, void *udata);
*     Callback used to handle any command to be transferred
*     to the final destination.
*     A new waTRANSFER object is created to handle asynchronously
*     any received command.
*
*   virtual evhCB_COMPL_STAT  TestCB(msgMESSAGE &msg, void *udata);
*     Callback to handle the TEST command.
*     It just sends back a reply with the same message buffer 
*     of the incoming command. 
*
*   ccsCOMPL_STAT PrintCLineHelp(void);
*   ccsCOMPL_STAT ParseArguments(int argc, char *argv[]);
*     Smple methods to parse command line parameters
*
*   PRIVATE DATA MEMBERS
*
*   char *procname;   Name of the process
*   char *destenv;    Destination environment for the process
*   char *destproc;   Destinaiton process for the final desitnaiton
*                     of transfer commands
*
*
*   FILES
*
*   ENVIRONMENT
*
*   COMMANDS
*
*   RETURN VALUES
*
*   CAUTIONS 
*   The example is as complete and coherent as possible, 
*   but in order to keep the size limited some error handling
*   had to be skipped or simplified. 
*
*   EXAMPLES
*
*   SEE ALSO
*
*   BUGS   
* 
*------------------------------------------------------------------------
*/

#define _POSIX_SOURCE 1
#include "vltPort.h"

static char *rcsId="@(#) $Id$"; 
static void *use_rcsId = ((void)&use_rcsId,(void *) &rcsId);


#include "waAPPLICATION.h"

/*
 * Defines 
 */

/* Names of new commands */
#define   waSETVAL_CMD   "SETVAL"
#define   waGETVAL_CMD   "GETVAL"

/* Timeout for the transfer commands. */
#define   waTRANSFER_TIMEOUT     20

/**
 * Constructor.
 */
waAPPLICATION::waAPPLICATION(int argc, char *argv[],
			     const dbSYMADDRESS  dbPoint):
  evhSTD_COMMANDS(dbPoint)
{
   /**
    * Attach the callbacks for the new commands.
    * Nothing is necessary for callbacks overriding
    * commands already implemented in the base classes
    */ 
    evhMSG_TYPE_KEY key(msgTYPE_COMMAND);
    evhOBJ_CALLBACK cb(this);
    
    evhHandler->AddCallback(key.Command(waSETVAL_CMD),
			    cb.Proc((evhCB_METHOD)TransferCB));
    evhHandler->AddCallback(key.Command(waGETVAL_CMD),
			    cb.Proc((evhCB_METHOD)TransferCB));

    /**
     * Parses the command line arguments
     */

    if(ParseArguments(argc, argv) == FAILURE)
      ErrAdd("eccs",eccsERR_GENERIC_TXT,__FILE_LINE__,
	     "Error parsing command line arguments");
    else
      {
      eccsLOG_1(("Application started (proc name: %.30s, DB root point: "
		 "%.30s, DestEnv: %.30s, DestProc: %.30s)", 
		 procname, DbPoint(), destenv, destproc));
      logData("eccs","Application started (proc name: %.30s, DB root point: "
	       "%.30s, DestEnv: %.30s, DestProc: %.30s)", 
	       procname, DbPoint(), destenv, destproc);
      }
} /* end waAPPLICATION::waAPPLICATION() */


/**
 * Constructor.
 */
waAPPLICATION::~waAPPLICATION()
{
   /**
    * Detach the callbacks for the new commands.
    * Nothing is necessary for callbacks overriding
    * commands already implemented in the base classes
    */ 
    evhMSG_TYPE_KEY key(msgTYPE_COMMAND);
    evhOBJ_CALLBACK cb(this);

    evhHandler->DelCallback(key.Command(waSETVAL_CMD),
			    cb.Proc((evhCB_METHOD)TransferCB));
    evhHandler->DelCallback(key.Command(waGETVAL_CMD),
			    cb.Proc((evhCB_METHOD)TransferCB));

}  /* end waAPPLICATION::~waAPPLICATION() */

/**
 * Callback used to handle every command that has to
 * be transferred to the process defined at object construction.
 */
evhCB_COMPL_STAT waAPPLICATION::TransferCB(msgMESSAGE &msg, void *)
{
    evhCB_COMPL_STAT stat = evhCB_NO_DELETE;
    
    ErrReset();

    eccsLogComment("Received command %.30s (%.30s)",
		   msg.Command(), msg.Buffer());

    /*
     * Allocates an instance of waTRANSFER by using
     * the static factory method of the class.
     * This object takes care of tranferring the command
     * to the destination and handling the replies.
     * It works asynchronously and destroys itself when
     * the job is completed and the last reply has been
     * sent to the originator of the command.
     */
    if(waTRANSFER::TransferCommand(destenv, 
				   destproc,
				   msg,
				   waTRANSFER_TIMEOUT) == FAILURE)
      {
      ErrAdd("eccs",eccsERR_GENERIC_TXT,__FILE_LINE__,
	     "Transfer failed");
      /*
       * An error reply must be sent here to comply to
       * VLT standards
       */
      if( msg.SendReply(ErrStack()) == FAILURE )
	{
	ErrAdd("evh",evhERR_SEND_REPLY,__FILE_LINE__);
	ErrStackClose();
	}
      }

    return (stat);

} /* end waAPPLICATION::TransferCB()*/


/**
 * Callback used to handle the TEST command.
 * The standard implementation provides by 
 * the base class evhSTD_COMMANDS is overridden here
 */
evhCB_COMPL_STAT waAPPLICATION::TestCB(msgMESSAGE &msg, void *)
{
    evhCB_COMPL_STAT stat = evhCB_NO_DELETE;
    
    ErrReset();

    eccsLogComment("Received command %.30s (%.30s)",
		   msg.Command(), msg.Buffer());

    /**
     * Just sends back a final reply with the same buffer
     */
    if( msg.SendReply(msg.Buffer()) == FAILURE )
	{
	/*
	 * This is not a critical error
	 * I just log it.
	 */
	ErrAdd("evh",evhERR_SEND_REPLY,__FILE_LINE__);
	ErrStackClose();
	}

    return (stat);

} /* end waAPPLICATION::TestCB()*/

/**
 * This is a simple support method to print
 * a command line help if at process startup the 
 * command line parameters are not succesfully parsed
 * It used by ParseArguments().
 */ 
ccsCOMPL_STAT waAPPLICATION::PrintCLineHelp(void)
{

    fprintf(stderr,"*****************************************************\n");
    fprintf(stderr,"*    waSetValue                                     *\n");
    fprintf(stderr,"*****************************************************\n");
    fprintf(stderr,"                                                     \n");
    fprintf(stderr,"Usage: waSetValue destenv destproc\n");
    fprintf(stderr,"\n");

    return SUCCESS;

} /* end waAPPLICATION::PrintCLineHelp() */

/**
 * This method parses the command line parameters
 * at application startup and fills in the parms 
 * structure
 */
ccsCOMPL_STAT waAPPLICATION::ParseArguments(int argc, char *argv[])
{
  ccsCOMPL_STAT stat = SUCCESS;

  if(argc != 3)
    {
    PrintCLineHelp();
    stat = FAILURE;
    }
  else
    {
    procname = argv[0];
    destenv  = argv[1];
    destproc = argv[2];
    }
  
  return stat;

} /* end waAPPLICATION::ParseArguments() */



/*___oOo___*/
