//Copyright, 2002-2003, Astra Network Inc.  All Rights Reserved

//This source code has been published by Astra Network Inc. However, any
//use, reproduction, modification, distribution or transfer of this
//software, or any software which includes or is based upon any of this
//code, is only permitted if expressly authorized by a written license
//agreement from Astra. Contact your Astra representative directly for
//more information.

/*!
 * \file HC_Nodelist.c
 * Collection of functions relating to node lists.
 */

#include "checkpoint_int.h"

/*! 
 * Find the index of the line in the nodelist containing this node/
 * function-type pair.
 * \param sequence Sequence object.
 * \param nodenum Node number to look for.
 * \param type Type of node to look for.
 * \return The index of the line
 */
static long
HCI_FindNode (HC_Sequence_t *sequence, long nodenum, HC_TypeTag_t type)
{
  long index;

  sequence = sequence;

  if (nodenum <= 0)
    return (HC_INVALIDNODE);

  if (sequence)
    {
      for (index = 0; index < sequence->num_nodes; index++)
	if (sequence->node_list[index].node_number == nodenum)
	  if (sequence->node_list[index].type_tag == type)
	    return (index);

      return (HC_INVALIDNODE);
    }

  return (HC_INVALIDSEQUENCE);
}

/*! 
 * Call the normal function for the given node.
 * \param sequence Sequence object.
 * \param nodenum Node number of the normal function.
 * \param userdata User-defined data.
 * \return An error code.
 */
int
HCI_CallNormal (HC_Sequence_t *sequence, long nodenum, void *userdata)
{
  int (*NormalFunc) (HC_Sequence_t *sequence, void *userdata);
  long nodelist_index;

  if (nodenum <= 0)
    return (HC_INVALIDNODE);

  if (sequence)
    {
      nodelist_index = HCI_FindNode (sequence, nodenum, HC_NORMALFUNC);
      if (nodelist_index >= 0)
	NormalFunc = sequence->node_list[nodelist_index].data;
      else
	return (HC_INVALIDNODE);

      if (NormalFunc)
	return (NormalFunc (sequence, userdata));
      else
	return (HC_INVALIDNODE);
    }
  return (HC_INVALIDSEQUENCE);
}

/*! 
 * Call the rollback function for the given node.
 * \param sequence Sequence object.
 * \param nodenum Node number of the rollback function.
 * \param userdata User-defined data.
 * \param checkpoint The checkpoint value last cleared in the normal function.
 * \return An error code.
 */
int
HCI_CallRollback (HC_Sequence_t *sequence, long nodenum,
		  void *userdata, unsigned long checkpoint)
{
  int (*RollbackFunc) (HC_Sequence_t *sequence, void *userdata,
		       unsigned long checkpoint);
  long nodelist_index;

  if (nodenum <= 0)
    return (HC_INVALIDNODE);

  if (sequence)
    {
      nodelist_index = HCI_FindNode (sequence, nodenum, HC_ROLLBACKFUNC);

      if (nodelist_index >= 0)
	RollbackFunc = sequence->node_list[nodelist_index].data;
      else
	return (HC_RollBackSuccess (sequence, 0));	// If no rollback, just return OK

      if (RollbackFunc)
	return (RollbackFunc (sequence, userdata, checkpoint));
      else
	return (HC_RollBackSuccess (sequence, 0));
      // Maybe they defined a rollback, but just set NULL?
    }
  return (HC_INVALIDSEQUENCE);
}

/*! 
 * Call the policy function for the given node.
 * \param sequence Sequence object.
 * \param nodenum Node number of the policy function.
 * \param userdata User-defined data.
 * \param event The event that has occured.
 * \param policy_data The policy-specific data.
 * \return An error code.
 */
int
HCI_CallPolicy (HC_Sequence_t *sequence, long nodenum,
		void *userdata, HC_PolicyEvent_t event, long policy_data)
{
  int (*PolicyFunc) (HC_Sequence_t *sequence,
		     void *userdata, HC_PolicyEvent_t event, long policy_data);
  long nodelist_index;

  if (nodenum <= 0)
    return (HC_INVALIDNODE);

  if (sequence)
    {
      nodelist_index = HCI_FindNode (sequence, nodenum, HC_POLICYFUNC);

      if (nodelist_index >= 0)
	PolicyFunc = sequence->node_list[nodelist_index].data;
      else
	PolicyFunc = HC_DefaultPolicy;

      if (!PolicyFunc)
	PolicyFunc = HC_DefaultPolicy;

      return (PolicyFunc (sequence, userdata, event, policy_data));
    }
  return (HC_INVALIDSEQUENCE);
}
