Ejemplo n.º 1
0
/**
 * Check whether we're seen as coordinator by all the nodes in our clique.
 * NOTE: This function assumes that we see ourself as coord.
 *
 * \return true if the whole clique agrees that we are coord, false otherwise
 */
static bool
clique_sees_self_as_coord(void)
{
  exa_nodeid_t node_id;

  for (node_id = 0; node_id < self->view.num_seen; node_id++)
    if (exa_nodeset_contains(&self->view.clique, node_id))
      {
	sup_node_t *node = sup_cluster_node(&cluster, node_id);

	EXA_ASSERT(node);

	if (!self_sees(node))
	  return false;

	if (!exa_nodeset_equals(&node->view.clique, &self->view.clique))
	  return false;

	if (node->view.coord != self->view.coord)
	  return false;
      }

  __trace("clique_sees_self_as_coord -> YES");

  return true;
}
Ejemplo n.º 2
0
/**
 * Check equality of two views.
 *
 * Two views are equal if both their nodes seen and
 * their coordinators are equal.
 *
 * \param[in] v1  View
 * \param[in] v2  View
 *
 * \return true if views are equal, false otherwise
 */
bool
sup_view_equals(const sup_view_t *v1, const sup_view_t *v2)
{
  EXA_ASSERT(v1 && v2);

  return (v1->coord == v2->coord
	  && exa_nodeset_equals(&v1->nodes_seen, &v2->nodes_seen));
}
Ejemplo n.º 3
0
/**
 * Called in state ACCEPT to process a ping.
 *
 * \param[in] ping  Ping to process
 */
static void
state_accept_process_ping(const sup_ping_t *ping)
{
  switch (ping->view.state)
    {
    case SUP_STATE_UNKNOWN:
      /* Not possible */
      break;

    case SUP_STATE_CHANGE:
      /* Ignore: the event that triggered the sender's state change will
       * eventually be seen by us, and our view will change too
       */
      break;

    case SUP_STATE_ACCEPT:
      if (self_is_coord())
	{
	  /* If the sender sees ourself as its coordinator and has accepted
	   * our proposed clique, check if we have reached the point where all
	   * nodes have accepted.
	   *
	   * If so, commit the clique. This will eventually trigger the commit
	   * on all other nodes.
	   */
	  if (ping->view.coord == self->id
	      && ping->view.accepted == self->view.accepted)
	    {
	      if (clique_has_accepted(self->view.accepted))
		{
		  __trace(":):) ALL IN CLIQUE HAVE ACCEPTED VIEW WITH GEN %u",
			 self->view.accepted);
		  commit_clique();
		}
	    }
	}
      break;

    case SUP_STATE_COMMIT:
      if (!self_is_coord())
	{
	  /* If the sender views the same clique as us and its committed
	   * generation is equal to our accepted generation, commit.
	   */
	  if (exa_nodeset_equals(&ping->view.clique, &accepted_clique)
	      && ping->view.committed == self->view.accepted
	      && ping->view.committed > self->view.committed)
	    {
	      __trace("saw commit %u from %u and i accepted %u => i commit %u",
		      ping->view.committed, ping->sender, self->view.accepted,
		      self->view.accepted);
	      commit_clique();
	    }
	}
      break;
    }
}
Ejemplo n.º 4
0
/**
 * Before sending a ping.
 */
static void
sup_pre_ping(void)
{
  update_last_seen();

#ifdef USE_YAOURT
  if (yaourt_event_wait(EXAMSG_CSUPD_ID, "sup_pre_ping") != 0)
    self_view_changed = true;
#endif

  if (self_view_changed || other_view_changed)
    {
      exa_nodeset_t new_clique;
      bool clique_changed;
      exa_nodeid_t coord;

      __trace("RECALCULATING CLIQUE");

      sup_clique_compute(&cluster, &new_clique);
      clique_changed = !exa_nodeset_equals(&new_clique, &self->view.clique);
      if (clique_changed)
	{
	  exa_nodeset_copy(&self->view.clique, &new_clique);
	  coord = exa_nodeset_first(&self->view.clique);
	  if (coord != self->view.coord)
	    {
	      __trace("new coord: %u", coord);
	      self->view.coord = coord;
	    }
	}

#ifdef DEBUG
      {
	char clique_str[EXA_MAX_NODES_NUMBER + 1];
	exa_nodeset_to_bin(&self->view.clique, clique_str);
	__trace("Clique: %s %s", clique_str, clique_changed ? "CHANGED" : "");
      }
#endif
    }

  if (self_view_changed || other_view_changed)
    {
      __trace("*** SUP_MSHIP_CHANGE ***");
      set_state(SUP_STATE_CHANGE);
    }

#ifdef WITH_TRACE
  dump_view(0);
#endif
}
Ejemplo n.º 5
0
/**
 * Check whether all nodes in our clique have accepted the clique
 * (aka membership) whose generation is given.
 *
 * \param[in] gen  Membership generation
 *
 * \return true if all have accepted, false otherwise
 */
static bool
clique_has_accepted(sup_gen_t gen)
{
  exa_nodeid_t node_id;

  for (node_id = 0; node_id < self->view.num_seen; node_id++)
    if (exa_nodeset_contains(&self->view.clique, node_id))
      {
	sup_node_t *node = sup_cluster_node(&cluster, node_id);

	EXA_ASSERT(node);

	if (!self_sees(node))
	  return false;

	if (!exa_nodeset_equals(&node->view.clique, &self->view.clique))
	  return false;

	if (node->view.accepted != gen)
	  return false;
      }

  return true;
}
Ejemplo n.º 6
0
/**
 * Called in state CHANGE to process a ping.
 *
 * \param[in] ping  Ping to process
 */
static void
state_change_process_ping(const sup_ping_t *ping)
{
  switch (ping->view.state)
    {
    case SUP_STATE_UNKNOWN:
      /* Not possible */
      break;

    case SUP_STATE_CHANGE:
      if (self_is_coord())
	{
	  __trace("i'm coord");

	  /* Go to state ACCEPT if all the nodes in our clique see us as
	   * their coordinator. This will initiate the agreement phase.
	   */
	  if (clique_sees_self_as_coord())
	    {
	      __trace("+++ EVERYONE IN MY CLIQUE SEES ME AS COORD");

	      accept_clique(next_gen());
	      __trace("\t=> new state=%s, accepted=%u",
		     sup_state_name(self->view.state),
		     self->view.accepted);
	    }
	}
      break;

    case SUP_STATE_ACCEPT:
      if (!self_is_coord())
	{
	  /* Go to state ACCEPT if the sender is our coordinator, views the
	   * same clique as us and its accepted clique generation is higher
	   * than ours.
	   */
	  if (ping->sender == self->view.coord
	      && exa_nodeset_equals(&ping->view.clique, &self->view.clique)
	      && ping->view.accepted > self_highest_gen())
	    {
	      __trace("coord ok, view ok, accepted ok => i accept");
	      accept_clique(ping->view.accepted);
	    }
	}
      break;

    case SUP_STATE_COMMIT:
      if (!self_is_coord())
	{
	  /* Commit the membership if we accepted it */
	  if (exa_nodeset_equals(&ping->view.clique, &accepted_clique)
	      && ping->view.committed == self->view.accepted
	      && ping->view.committed > self->view.committed)
	    {
	      __trace("saw commit %u from %u and i accepted %u => i commit %u",
		      ping->view.committed, ping->sender, self->view.accepted,
		      self->view.accepted);
	      commit_clique();
	    }
	}
      break;
    }
}