/* BTP library - Banana Tree Protocol
 * Copyright (C) 1999-2001  The Regents of the University of Michigan
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the 
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA  02111-1307, USA.
 */


#include "b_conn.h"
#include "btp_node.h"
#include "btp_proto.h"
#include "btp_tree.h"
#include "btp_debug.h"



/* ************************************************************ */


BtpNode* 
btp_node_new (BtpTree* tree, gchar* hostname, gint port, BConn* conn)
{
  BtpNode* node;

  g_return_val_if_fail (tree, NULL);
  g_return_val_if_fail (hostname, NULL);
  g_return_val_if_fail (port, NULL);

  node = g_new0 (BtpNode, 1);
  node->tree = tree;
  node->hostname = g_strdup (hostname);
  node->port = port;

  if (conn)
    {
      node->conn = conn;
      conn->funcs = &btp_proto_funcs;
      conn->user_data = node;
    }
  else
    {
      node->conn = b_conn_new (hostname, port, (BGroup*) tree,
			       &btp_proto_funcs, node);
    }

  btp_tree_add_node (node);

  return node;
}


/* Returns TRUE if deleted, FALSE if delete is delayed */
gboolean
btp_node_delete (BtpNode* node)
{
  g_return_val_if_fail (node, TRUE);
  g_return_val_if_fail (!node->is_deleting, FALSE);

  BTPP (1, "btp_node_delete %p\n", node);

  /* Make sure we are completely removed from the tree */
  if (node->tree)
    {
      btp_tree_remove_child (node);
      btp_tree_remove_sibling (node);
      btp_tree_remove_node (node);

      if (node->tree->root == node)
	node->tree->root = NULL;
      
      if (node->tree->parent == node)
	node->tree->parent = NULL;

      if (node->tree->gparent == node)
	node->tree->gparent = NULL;

      if (node->tree->new_parent == node)
	node->tree->new_parent = NULL;
    }

  if (node->hostname)
    {
      g_free (node->hostname);
      node->hostname = NULL;
    }
  node->port = 0;

  if (node->shortcut_ping_timeout)
    {
      g_source_remove (node->shortcut_ping_timeout);
      node->shortcut_ping_timeout = 0;
    }

  if (node->shortcut_add_timeout)
    {
      g_source_remove (node->shortcut_add_timeout);
      node->shortcut_add_timeout = 0;
    }

  if (node->conn)
    {
      if (b_conn_is_connected (node->conn))
	{
	  node->is_deleting = TRUE;
	  b_conn_close (node->conn);
	  return FALSE;
	}
      else
	{
	  b_conn_delete (node->conn);
	  node->conn = NULL;
	}
    }

  memset (node, 0, sizeof (*node));
  g_free (node);

  return TRUE;
}


void
btp_node_print (FILE* file, BtpNode* node)
{
  if (!node)
    {
      fprintf (file, "<null>");
      return;
    }
  
  fprintf (file, "%s:%d "
	   "[is_del = %d, is_bad = %d, "
	   "fo = %d, fo_dist = %d, "
	   "ov_dist = %d, scp_to = %u, sca_to = %u, "
	   "relation = %s, shortcut = %d, new_parent = %d ",
	   node->hostname?node->hostname:"<null>", node->port,
	   node->is_deleting, node->is_bad_parent,
	   node->follow, node->follow_distance, 
	   node->overlay_distance, node->shortcut_ping_timeout, 
	   node->shortcut_add_timeout,
	   btp_tree_relation_to_string(node),
	   btp_tree_is_shortcut(node),
	   btp_tree_is_new_parent(node));
  fprintf (file, "conn = ");
  b_conn_print (file, node->conn);
}


syntax highlighted by Code2HTML, v. 0.9.1