Code Search for Developers
 
 
  

sink_decision.c from EmStar at Krugle


Show sink_decision.c syntax highlighted



char sink_decision_c_cvsid[] = "$Id: sink_decision.c,v 1.7 2007/01/08 01:06:26 mlukac Exp $";

#include "sink_types.h"

int sort_sneigh_view(const void *a, const void *b) {
  return ( ((sneigh_t *) a)->etx_to_sink + ((sneigh_t *) a)->localetx ) - 
    ( ((sneigh_t *) b)->etx_to_sink + ((sneigh_t *) b)->localetx );
}


int sink_decide_status(void *data, int interval, g_event_t *event)
{

  sink_tree_state_t *sts = (sink_tree_state_t *) data;

  //  int i = 0;
  //  int num_sn = nlist_qlen(sts);
  elog(LOG_DEBUG(15), "decide status");


  sneigh_t *sn = nlist_top(sts);
  for ( ; sn != NULL; sn = nlist_next(sn)) {
    
    switch(sn->status) {

    case NEIGHBOR_STANDBY:
      /*
       * STANDBY to ACTIVE
       */
      if (sn->localetx != 0 && 
	 sn->fdr != 0 && 
	 sn->rdr != 0 && 
	 sn->sink_node != 0) {
	elog(LOG_DEBUG(5), "STANDBY to ACTIVE: neighbor %i", sn->node_id);
	sn->status = NEIGHBOR_ACTIVE;
      }
      break;

    case NEIGHBOR_ACTIVE:
      /*
       * ACTIVE to STALE
       */    

/*       elog(LOG_WARNING, "%i %i %ld %i %ld %i", */
/* 	   sn->node_id, */
/* 	   sn->ssync_dropped, */
/* 	   msec_since(&sn->ssync_dropped_timer), */
/* 	   NEIGHBOR_ACT_TO_STALE, */
/* 	   msec_since(&sn->last_info.last_heard), */
/* 	   NEIGHBOR_ACT_TO_STALE */
/* 	   ); */
      if (sn->ssync_dropped && 
	  msec_since(&sn->ssync_dropped_timer) > NEIGHBOR_ACT_TO_STALE &&
	  (sn->last_info.state == DEAD  || sn->last_info.state == NB_UNKNOWN) &&
	  msec_since(&sn->last_info.last_heard) > NEIGHBOR_ACT_TO_STALE ) {
	/* if dropped from statesync table and timer out */
	elog(LOG_DEBUG(5), "%i not in table > 1m: now STALE", sn->node_id);
	sn->status = NEIGHBOR_STALE;
      } else if ((sn->last_info.state == DEAD  || sn->last_info.state == NB_UNKNOWN) && msec_since(&sn->last_info.last_heard) > NEIGHBOR_STALE_TO_DEAD) {
	elog(LOG_DEBUG(5), "ssync says not dropped, but %i dead > 5m: now STALE", sn->node_id);
	sn->status = NEIGHBOR_STALE;
      }
		 
      
      break;

    case NEIGHBOR_STALE:
      /*
       * STALE to ACTIVE
       */
      if (!sn->ssync_dropped && 
	  !((sn->last_info.state == DEAD  || sn->last_info.state == NB_UNKNOWN) && 
	    msec_since(&sn->last_info.last_heard) > NEIGHBOR_ACT_TO_STALE)) {
	elog(LOG_DEBUG(5), "%i prom to now ACT: ssync", sn->node_id);
	sn->status = NEIGHBOR_ACTIVE;
      }

      /*
       * STALE to DEAD
       */
      if (sn->ssync_dropped && 
	  msec_since(&sn->ssync_dropped_timer) > NEIGHBOR_STALE_TO_DEAD &&
	  (sn->last_info.state == DEAD  || sn->last_info.state == NB_UNKNOWN) &&
	  msec_since(&sn->last_info.last_heard) > NEIGHBOR_STALE_TO_DEAD) {
	elog(LOG_DEBUG(5), "%i not in tables > 5m: now DEAD", sn->node_id);
	sn->status = NEIGHBOR_DEAD;
      }
      break;

    case NEIGHBOR_DEAD:
      /*
       * DEAD to ACTIVE
       */
      if (!sn->ssync_dropped &&
	  !((sn->last_info.state == DEAD  || sn->last_info.state == NB_UNKNOWN) && 
	    msec_since(&sn->last_info.last_heard) > NEIGHBOR_ACT_TO_STALE)) {
	sn->status = NEIGHBOR_ACTIVE;
	elog(LOG_DEBUG(5), "%i prom to now ACT: ssync", sn->node_id);
	break;
      }

      /* DEAD to STALE */

      if (msec_since(&sn->last_info.last_heard) < NEIGHBOR_STALE_TO_DEAD) {
	sn->status = NEIGHBOR_STALE;
	elog(LOG_DEBUG(5), "%i prom to now STALE: time", sn->node_id);
      }

    
    default:
      elog(LOG_WARNING, "unknown state!");
    }

  }

  sink_decide_next_hop(sts);
  elog(LOG_DEBUG(5), "done decide next hop");
  return TIMER_RENEW;
}


int sink_tree_me_in_path(sneigh_t *sn)
{
  int inpath = 0;
  int i = 0;
  for (i = 0; i < sn->hops_to_sink; ++i) {
    if (sn->path_to_sink[i] == my_node_id) {
      inpath = 1;
      break;
    }
  }
  return inpath;
}

void sink_decide_next_hop(sink_tree_state_t *sts)
{
  elog(LOG_DEBUG(15), "decide next hop");
  /* Sort by etx */
  int num_sn = nlist_qlen(sts);

  if (num_sn == 0)
    return;

  sneigh_t *(sneigh_view[num_sn]);
  sink_nlist_fill_array(sts, sneigh_view);
  
  qsort(sneigh_view, num_sn, sizeof(sneigh_t *),
	sort_sneigh_view);

  int i = 0;
  buf_t *buf = buf_new();
  bufprintf(buf, "\n\t\tSorted by etx for node %i\n", my_node_id);
  for (i = 0; i < num_sn; ++i) {
    bufprintf(buf, "\t\t\t %i %i %f through %i ",
	      sneigh_view[i]->node_id,
	      sneigh_view[i]->sink_node,
	      sneigh_view[i]->etx_to_sink + sneigh_view[i]->localetx,
	      sneigh_view[i]->my_next_hop);
    /* figure out new status */

    switch(sneigh_view[i]->status) {
    case 0:
      bufprintf(buf, "%s", "STANDBY");
      break;
    case 1:
      bufprintf(buf, "%s", "ACTIVE");
      break;
    case 2:
      bufprintf(buf, "%s", "STALE");
      break;
    case 4:
      bufprintf(buf, "%s", "DEAD");
      break;
    default:
      bufprintf(buf, "?");
    }
    bufprintf(buf, "\n");
  }

  elog(LOG_DEBUG(0), "%s", buf->buf);
  buf_free(buf);

  /* need to check if there is a sink */
  /* need to update stale/standby status */

  if (sts->is_sink)
    return;

  sneigh_t *sn = NULL;
  int activefound = 0;
  for (i = 0; i < num_sn; ++i) {
    if (sneigh_view[i]->status == NEIGHBOR_ACTIVE && 
	sneigh_view[i]->sink_node != 0 &&
	sneigh_view[i]->ip != 0 &&
	sneigh_view[i]->my_next_hop != my_node_id &&
	!sink_tree_me_in_path(sneigh_view[i])) {
      activefound = 1;
      if (sn == NULL) {

	elog(LOG_DEBUG(0), "none found yet, using %i etx %f",
	     sneigh_view[i]->node_id, sneigh_view[i]->localetx + sneigh_view[i]->etx_to_sink);
	sn = sneigh_view[i];

      } else if ( (sn->localetx + sn->etx_to_sink) > 
		  (sneigh_view[i]->localetx + sneigh_view[i]->etx_to_sink) ) {

	elog(LOG_DEBUG(0), "node %i etx %f < node %i etx %f !!!! -- switching to %i",
	     sneigh_view[i]->node_id, sneigh_view[i]->localetx + sneigh_view[i]->etx_to_sink,
	     sn->node_id, sn->localetx + sn->etx_to_sink, sneigh_view[i]->node_id);
	sn = sneigh_view[i];	

      } else {

	elog(LOG_DEBUG(0), "node %i etx %f > node %i etx %f !!!! -- keeping %i",
	     sneigh_view[i]->node_id, sneigh_view[i]->localetx + sneigh_view[i]->etx_to_sink,
	     sn->node_id, sn->localetx + sn->etx_to_sink, sn->node_id);

      }
    } else {
      continue;
    }
  }
#if 0
  sneigh_t *sn = NULL;
  i = 0;
  while (sn == NULL && i < num_sn) {
    if (sneigh_view[i]->status == NEIGHBOR_ACTIVE && 
	sneigh_view[i]->sink_node != 0 &&
	sneigh_view[i]->ip != 0 &&
	sneigh_view[i]->my_next_hop != my_node_id) {
      sn = sneigh_view[i];
      elog(LOG_WARNING, "FOUND ROUTE! using %i as prev hop", sn->node_id);
      break;
    }
    ++i;
  }
#endif
#if 0
  i = 0; /* pick a stale node if that is all we have! */
  while (sn == NULL && i < num_sn) {
    elog(LOG_WARNING, "No active nodes found! trying stale!");
    if (sneigh_view[i]->status == NEIGHBOR_STALE &&
	sneigh_view[i]->sink_node != 0 &&
	sneigh_view[i]->my_next_hop != my_node_id) {
      sn = sneigh_view[i];
      elog(LOG_WARNING, "FOUND stale ROUTE! using %i as prev hop", sn->node_id);
    }
    ++i;
  }
#endif

  if (sn == NULL) {
    elog(LOG_WARNING, "No usable nodes found!");
  } /* else if (sn->node_id == (sts->prev_next_hop != NULL ? sts->prev_next_hop->node_id : 0)) {
    elog(LOG_WARNING, "No change in next hop...");
    }*/
  else {
    
    if (sn->node_id != (sts->prev_next_hop != NULL ? sts->prev_next_hop->node_id : 0))
      sts->prev_next_hop = sts->curr_next_hop;
    sts->curr_next_hop = sn;
    sts->curr_sink = sn->sink_node;
    
    elog(LOG_WARNING, "Next hop changed from %i to %i",
	 sts->prev_next_hop == NULL ? 0 : sts->prev_next_hop->node_id,
	 sts->curr_next_hop->node_id);
    
    time_t now = time(NULL);
    if (now - sts->status_notify_delay > 60) {
      g_status_dev_notify(sts->sink_status);
      g_status_dev_notify(sts->sink_status_next_hop);
      sts->status_notify_delay = now;
    }
    if (g_timer_isset(sts->pub_timer) == 0) {
      if (g_timer_add(3000, sink_tree_repub_hops, sts, NULL, &sts->pub_timer) < 0) {
	elog(LOG_CRIT, "Unable to start in sink mode");
	exit(1);
      }
    }
    
  }

}


#if 0



  /*
   * 
   * code from ssync 
   *
   */

  /* make active if previously dead... but now we hear from it */
  if (sn->localetx != 0 && 
      sn->fdr != 0 &&      /* can only be active if neighbor
			      information is filled... and there is
			      a sink node */
      sn->rdr != 0 && 
      sn->sink_node != 0) {
    sn->status = NEIGHBOR_ACTIVE;     
  }
  
  /* mark the timed out ones as stale */
  sneigh_t *sn = nlist_top(sts);
  for ( ; sn != NULL; sn = nlist_next(sn)) {


    if (sink_table_lookup(table, count, sn->node_id) == -1 && 
	msec_since(&sn->ssync_status_timer) > NEIGHBOR_ACT_TO_STALE)
      {
	sn->status = NEIGHBOR_STALE;
	elog(LOG_WARNING, "%i not in table > 1m: now STALE", sn->node_id);
	
      } 
    else if (sink_table_lookup(table, count, sn->node_id) == -1 && 
	msec_since(&sn->ssync_status_timer) > NEIGHBOR_STALE_TO_DEAD) 
      {
	sn->status = NEIGHBOR_DEAD;
	elog(LOG_WARNING, "%i not in table > 5m: now DEAD", sn->node_id);
      }
    
  }

  /*
   *
   * code from process_ns
   *
   */
  /* to mark active, must have enough information and there must be
     a sink node */
  if (sn->fdr != 0 && sn->rdr != 0 && 
      sn->sink_node != sn->node_id && sn->sink_node != 0) {
    sn->status = NEIGHBOR_ACTIVE; 
  } /* else leave the existing state */

  /* find anything that is missing and mark as stale anything new mark as active */
  int num_sn = nlist_qlen(sts);
  sneigh_t *(sneigh_view[num_sn]);
  nlist_fill_array(sts, sneigh_view);
  for (i = 0; i < num_sn; ++i) {

    if (sneigh_view[i]->status == NEIGHBOR_STANDBY)
      continue;

    /*
     * Demote state 
     */ 

    /* removed from neighbor table... should never happen */
    if (find_neighbor_t(nb_list, count, sneigh_view[i]->node_id) == -1) {
      sneigh_view[i]->status = NEIGHBOR_STALE;
      elog(LOG_WARNING, "%i now STALE: missing", sneigh_view[i]->node_id);
    }

    /* has been dead for more than a minute */
    if (
	(sneigh_view[i]->last_info.state == DEAD ||
	 sneigh_view[i]->last_info.state == NB_UNKNOWN) &&
	msec_since(&sneigh_view[i]->last_info.last_heard) > NEIGHBOR_ACT_TO_STALE
	) 
      {
	sneigh_view[i]->status = NEIGHBOR_STALE;
	elog(LOG_WARNING, "%i now STALE: timeout", sneigh_view[i]->node_id);
      } i

    /* has been stale for more than 5 mins */
    else if (
	     sneigh_view[i]->status == NEIGHBOR_STALE &&
	     msec_since(&sneigh_view[i]->last_info.last_heard) > NEIGHBOR_STALE_TO_DEAD
	     )
      {
	sneigh_view[i]->status = NEIGHBOR_DEAD;
	elog(LOG_WARNING, "%i now DEAD: timeout", sneigh_view[i]->node_id);
      } 

    /*
     * Promote state
     */
    
    /* has been stale for less than a min */
    else if (sneigh_view[i]->status == NEIGHBOR_STALE && 
	     msec_since(&sneigh_view[i]->last_info.last_heard) < NEIGHBOR_ACT_TO_STALE)
      {
	sneigh_view[i]->status = NEIGHBOR_ACTIVE;
	elog(LOG_WARNING, "%i prom to now ACT: time", sneigh_view[i]->node_id);
      }
    
    /* has been dead for less than 5 min */
    else if (sneigh_view[i]->status == NEIGHBOR_DEAD && 
	     msec_since(&sneigh_view[i]->last_info.last_heard) < NEIGHBOR_STALE_TO_DEAD)
      {
	sneigh_view[i]->status = NEIGHBOR_STALE;
	elog(LOG_WARNING, "%i now prom to STALE: time", sneigh_view[i]->node_id);
      }
    
  }
  


#endif




See more files for this project here

EmStar

EmStar is a software system for developing and deploying wireless sensor networks involving Linux-based platforms. As the wireless sensor network community has attempted to deploy more complex designs---large-scale, long-lived systems that need self-organization and adaptivity---a number of difficult software design issues have arisen. Advances in software design have not kept pace with the capabilities of hardware. This is because designing for an adaptive, efficient, and useful sensor network has turned out to be surprisingly complex and difficult. EmStar is a Linux-based software framework, whose goal is to dramatically reduce this complexity, enabling work to be shared and reused, and simplifying and speeding the design of new sensor network applications.

Project homepage: http://cvs.cens.ucla.edu/emstar/
Programming language(s): C,Shell Script
License: other

  process_ns.c
  sink_decision.c
  sink_main.c
  sink_nlist.c
  sink_status.c
  sink_tree.c
  sink_types.h