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