sympathy_status.c from EmStar at Krugle
Show sympathy_status.c syntax highlighted
/* ex: set tabstop=2 expandtab shiftwidth=2 softtabstop=2: */
/*
*
* Copyright (c) 2003 The Regents of the University of California. All
* rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Neither the name of the University nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/*
*
* Author: Nithya Ramanthan
*
*/
#include <sympathy.h>
#include <time.h>
typedef struct {
/* Always keep request as the first field since its assumed */
char request[10];
int printed_usage;
/* Has the same index into it as sink.status_srcs[] */
int printed_root_cause[SMAX_SRCS];
int printed_rc_period[SMAX_SRCS];
} sympathy_client_data_t;
typedef void (* node_metrics_print_t) (buf_t* buf, sympathy_node_info_t* stat,
int html);
static
void print_summary(sympathy_node_info_t* stat, Sfail_summary_t* fail);
typedef node_metrics_print_t (* get_print_funct_t) (char type);
typedef void (* generic_t)(buf_t* buf);
static
void print_failure_info(buf_t* buf, sympathy_node_info_t* stat, int html);
/*** Static Functions ***/
static
char* tos_packet_to_string(int i) {
switch(i) {
case(SBEACON): return "BEACON";
case(SNEIGHBOR_ADVERT): return "NEIGHBOR";
case(SPATH_ADVERT): return "ROUTE";
case(SNON_ROUTING_PKT): return "GENERAL";
case(SYMPATHY_PKT): return "SYMPATHY";
default: return "Unknown";
}
return "Unknown";
}
static
char* get_comp_string(char* comp_name, int app_type)
{
DECLARE_STATIC_BUF_RING(buf, 1, FUSD_MAX_NAME_LENGTH);
if (comp_name) sprintf(buf, "Comp %s(%d)",
comp_name, app_type);
else sprintf(buf, "\nComp %d", app_type);
return buf;
}
static
char* print_pd_of_event(int val, struct timeval* event_time)
{
unsigned long diff = misc_tv_offset_msec(event_time, &start_time);
DECLARE_STATIC_BUF_RING(buf, 1, 20);
if (event_time->tv_sec == 0) return "INF";
diff /= METRICS_PERIOD_MSEC; /* Convert to #periods */
if (val > 0) sprintf(buf, "pd %d", (int) diff);
return buf;
}
int get_minutes_since_event(struct timeval* event_time)
{
struct timeval now;
gettimeofday(&now, NULL);
misc_tv_sub(&now, event_time);
return((int) now.tv_sec/60);
}
static
char* print_minutes_since_event(int val, struct timeval* event_time)
{
DECLARE_STATIC_BUF_RING(buf, 1, 20);
int min_data = get_minutes_since_event(event_time);
if (val > 0) snprintf(buf, 20, "%d mins", min_data);
else sprintf(buf, "INF");
return buf;
}
sympathy_node_info_t* iter_next_hop(sympathy_node_info_t* stat, int* iter, int sink_id)
{
sympathy_node_info_t* stat2;
if ((!stat) || (stat->next_hop.next_hop == sink_id)
|| (stat->next_hop.next_hop == 0)
|| (stat->addr == sink_id)) return NULL;
(*iter) += 1;
if (*iter >= 15) {
elog(LOG_ERR, "ERROR: VERY BAD: Suspecting a routing loop!!\n");
*iter = -1;
return NULL;
}
else if (!(stat2 = find_status_ptr(stat->next_hop.next_hop)))
{
elog(LOG_ERR, "Unable to find node %d 's next-hop: %d\n",
stat->addr, stat->next_hop.next_hop);
return NULL;
}
else return stat2;
}
/* Prints the neighbor list for one node */
static void
print_node_neighbors(buf_t* buf, sympathy_node_info_t* stat, int html)
{
neighbor_t* neighbors = stat->neighbors;
sneighbor_info_t* neighbor_info = stat->neighbor_info;
int i, num_neighbors = stat->num_neighbors;
if(!neighbors_valid(stat)) return;
if (num_neighbors > 0)
{
bufprintf(buf, "\nNode-ID\t Egress\t Ingress Avg Rssi Age[min] Avg-ingress Max-change(Mins-since)\n");
bufprintf(buf, "---------------------------------------------------------------\n");
for (i = 0; i < num_neighbors; i++)
{
if (neighbors[i].node_id > 0)
{
bufprintf(buf, "%d\t %d\t %d\t %d\t %d\t %d\t\t %d(%d)\n",
neighbors[i].node_id, (int) neighbors[i].conn_to,
(int) neighbors[i].conn_from,
neighbor_info[i].avg_rssi,
get_minutes_since_event(&neighbor_info[i].time_added),
neighbor_info[i].avg_ingress,
neighbor_info[i].max_ingress_change,
get_minutes_since_event(&neighbor_info[i].time_max_change));
}
}
bufprintf(buf, "\n");
}
if ((stat->addr != my_node_id) &&
((stat->metrics_valid) || route_valid(stat)) &&
(stat->next_hop.sink > 0))
{
bufprintf(buf, "\nSink Next-Hop Quality Age[min] Num-changes\n");
bufprintf(buf, "-----------------------------------------------\n");
bufprintf(buf,"%-4d %-8d %-7d %-4s %-5d\n", stat->next_hop.sink,
stat->next_hop.next_hop, stat->next_hop.quality,
print_minutes_since_event(stat->next_hop_info.num_changes,
&stat->next_hop_info.time_changed),
stat->next_hop_info.num_changes);
bufprintf(buf, "\n");
}
}
static void
print_node_neighbors_html(buf_t* buf, sympathy_node_info_t* stat, int html)
{
neighbor_t* temp;
neighbor_t* neighbors = stat->neighbors;
int i, j, k, num_neighbors = stat->num_neighbors;
sneighbor_info_t* neighbor_info = stat->neighbor_info;
neighbor_t* ordered_nbrs[MAX_NEIGHBORS];
if(!neighbors_valid(stat)) return;
if (num_neighbors > 0)
{
bufprintf(buf, "<table frame=void cellspacing=5 cellpadding=6>\n");
bufprintf(buf, "<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>",
"Node-ID", "Egress", "Ingress", "Age[min]",
"Avg-ingress", "Max-change(Mins-since)");
bufprintf(buf, "<tr><td colspan=6>%s</td></tr>", "----------------------------------------------------------------------------------------------------------");
/* order the nodes by ID */
for(i = 0; i < num_neighbors; i++)
{
ordered_nbrs[i] = &neighbors[i];
for (j = i - 1, k = i;
(j >= 0) && (ordered_nbrs[k]->node_id < ordered_nbrs[j]->node_id);
j--, k--)
{
//swap
temp = ordered_nbrs[k];
ordered_nbrs[k] = ordered_nbrs[j];
ordered_nbrs[j] = temp;
}
}
/* print the neighbors */
for (i = 0; i < num_neighbors; i++)
{
if (ordered_nbrs[i]->node_id > 0)
{
bufprintf(buf, "<tr><td>%d</td><td>%d</td><td>%d</td><td>%d</td><td>%d</td><td>%d(%d)</td></tr>",
ordered_nbrs[i]->node_id,
(int) ordered_nbrs[i]->conn_to,
(int) ordered_nbrs[i]->conn_from,
get_minutes_since_event(&neighbor_info[i].time_added),
neighbor_info[i].avg_ingress,
neighbor_info[i].max_ingress_change,
get_minutes_since_event(&neighbor_info[i].time_max_change));
}
}
bufprintf(buf, "</table><br><br>");
}
if ((stat->addr != my_node_id) &&
((stat->metrics_valid) || route_valid(stat)) &&
(stat->next_hop.sink > 0))
{
bufprintf(buf, "<table frame=void cellspacing=5 cellpadding=6>\n");
bufprintf(buf, "<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>\n",
"Sink", "Next-Hop", "Quality", "Age[min]", "Num-changes");
bufprintf(buf, "<tr><td colspan=5>%s</td></tr>",
"-------------------------------------------------------------------");
bufprintf(buf, "<tr><td>%d</td><td>%d</td><td>%d</td><td>%s</td><td>%d</td></tr>\n",
stat->next_hop.sink, stat->next_hop.next_hop,
stat->next_hop.quality,
print_minutes_since_event(stat->next_hop_info.num_changes,
&stat->next_hop_info.time_changed),
stat->next_hop_info.num_changes);
bufprintf(buf, "</table><br>\n");
}
bufprintf(buf, "<br><br>");
}
/* Prints the packet table for one node */
static void
print_node_packet_table(buf_t* buf, sympathy_node_info_t* stat, int html)
{
int i;
stats_ctr_t* tmp_ctr;
char* suffix;
sympathy_node_app_info_t* snode;
/* Print packets received in error */
if (stat->addr == my_node_id) {
bufprintf(buf, "\n#Pkts rx in error from unidentifiable nodes");
}
else bufprintf(buf, "\n#Pkts rx in error");
bufprintf(buf, "/mins since last: %d(%d)/%s\n",
stat->errs_rx.ctr, stat->errs_rx.agg_prev_epoch,
print_minutes_since_event(stat->errs_rx.ctr,
&stat->errs_rx.last_updated));
/* Print the packet table */
/* If this is the sink, then the packet table is packets that were
* transmitted by the sink */
if (stat->addr == my_node_id)
bufprintf(buf, "\n%-17s %-5s %-18s\n",
"Tos-type", "#Tx", "Mins-since-last");
else
bufprintf(buf, "\n%-17s %-5s %-18s\n",
"Tos-type", "#Rx", "Mins-since-last");
bufprintf(buf, "---------------------------------------\n");
for (i = 0; i < SNON_ROUTING_PKT; i++)
{
if (stat->tos_packets[i].ctr > 0)
{
bufprintf(buf, "%d:%-15s %d(%d%-4s %s(%s%-2s\n",
i, tos_packet_to_string(i),
stat->tos_packets[i].ctr, stat->tos_packets[i].agg_prev_epoch,
")",
print_minutes_since_event(stat->tos_packets[i].ctr,
&stat->tos_packets[i].last_updated),
print_pd_of_event(stat->tos_packets[i].ctr,
&stat->tos_packets[i].last_updated), ")");
}
}
/* APP-Layer-Unicast */
bufprintf(buf, "%d:%-14s %d(%d%-5s %s(%s%-2s\n",
SNON_ROUTING_PKT, "app",
stat->tos_packets[SNON_ROUTING_PKT].ctr +
stat->tos_packets[SYMPATHY_PKT].ctr,
stat->tos_packets[SNON_ROUTING_PKT].agg_prev_epoch +
stat->tos_packets[SYMPATHY_PKT].agg_prev_epoch,
")",
print_minutes_since_event(stat->tos_packets[SNON_ROUTING_PKT].ctr,
&stat->tos_packets[SNON_ROUTING_PKT].last_updated),
print_pd_of_event(stat->tos_packets[SNON_ROUTING_PKT].ctr,
&stat->tos_packets[SNON_ROUTING_PKT].last_updated), ")");
/* Non-sympathy app-layer */
for (i = 0; i < sink.num_apps_registered; i++)
{
if (stat->node_app_info[i].sink_pkt_rx.ctr > 0)
{
bufprintf(buf, " =>%-9s %d(%d%-5s %s(%s)\n",
get_comp_string(stat->node_app_info[i].comp_name, sink.app_type[i]),
stat->node_app_info[i].sink_pkt_rx.ctr,
stat->node_app_info[i].sink_pkt_rx.agg_prev_epoch,
")",
print_minutes_since_event(stat->node_app_info[i].app_stats_rx_from_node.ctr,
&stat->node_app_info[i].app_stats_rx_from_node.last_updated),
print_pd_of_event(stat->node_app_info[i].app_stats_rx_from_node.ctr,
&stat->node_app_info[i].app_stats_rx_from_node.last_updated));
}
}
if (stat->addr == my_node_id) return;
/* Sympathy Layer */
for (i = 0; i < 2; i++)
{
if (i == 0)
{
tmp_ctr = &stat->sympathy_stats_rx;
suffix = "stats";
}
else if (i == 1) {
tmp_ctr = &stat->metrics_rx;
suffix = "metrics";
}
if (tmp_ctr->ctr > 0) {
bufprintf(buf, " =>Symp-%-9s %d(%d%-5s %s(%s)\n",
suffix, tmp_ctr->ctr, tmp_ctr->agg_prev_epoch,
")",
print_minutes_since_event(tmp_ctr->ctr, &tmp_ctr->last_updated),
print_pd_of_event(tmp_ctr->ctr, &tmp_ctr->last_updated));
}
}
for (i = 0; i < sink.num_apps_registered; i++)
{
snode = &stat->node_app_info[i];
bufprintf(buf, " =>%s-stats %d(%d%-5s %s(%s)\n",
get_comp_string(snode->comp_name, sink.app_type[i]),
stat->node_app_info[i].app_stats_rx_from_node.ctr,
stat->node_app_info[i].app_stats_rx_from_node.agg_prev_epoch,
")",
print_minutes_since_event(snode->app_stats_rx_from_node.ctr,
&snode->app_stats_rx_from_node.last_updated),
print_pd_of_event(snode->app_stats_rx_from_node.ctr,
&snode->app_stats_rx_from_node.last_updated));
}
}
static void
print_node_packet_table_html(buf_t* buf, sympathy_node_info_t* stat, int html)
{
int i;
stats_ctr_t* tmp_ctr;
char* suffix;
sympathy_node_app_info_t* snode;
/* Print packets received in error */
bufprintf(buf, "<table frame=void cellspacing=5 cellpadding=6>");
if (stat->addr == my_node_id) {
bufprintf(buf, "<tr><td>#Pkts rx in error from unidentifiable nodes");
}
else bufprintf(buf, "<tr><td>#Pkts rx in error");
bufprintf(buf, "/mins since last: %d(%d)/%s</td></tr></table><br>\n",
stat->errs_rx.ctr, stat->errs_rx.agg_prev_epoch,
print_minutes_since_event(stat->errs_rx.ctr,
&stat->errs_rx.last_updated));
/* Print the packet table */
/* If this is the sink, then the packet table is packets that were
* transmitted by the sink */
bufprintf(buf, "<table frame=void cellspacing=5 cellpadding=6>");
if (stat->addr == my_node_id)
bufprintf(buf, "<tr><td>%s</td><td>%s</td><td>%s</td></tr>\n",
"Tos-type", "#Tx", "Mins-since-last");
else
bufprintf(buf, "<tr><td>%s</td><td>%s</td><td>%s</td></tr>\n",
"Tos-type", "#Rx", "Mins-since-last");
bufprintf(buf, "<tr><td colspan=3>%s</td></tr>", "--------------------------------------------------------");
for (i = 0; i < SNON_ROUTING_PKT; i++)
{
if (stat->tos_packets[i].ctr > 0)
{
bufprintf(buf, "<tr><td>%d:%s</td>\n",
i, tos_packet_to_string(i));
bufprintf(buf, "<td>%d(%d)</td>",
stat->tos_packets[i].ctr, stat->tos_packets[i].agg_prev_epoch);
bufprintf(buf,"<td>%s(%s)</td></tr>",
print_minutes_since_event(stat->tos_packets[i].ctr,
&stat->tos_packets[i].last_updated),
print_pd_of_event(stat->tos_packets[i].ctr,
&stat->tos_packets[i].last_updated));
}
}
/* APP-Layer-Unicast */
bufprintf(buf, "<tr><td>%d:app</td>\n", SNON_ROUTING_PKT);
bufprintf(buf, "<td>%d(%d)</td>\n",
stat->tos_packets[SNON_ROUTING_PKT].ctr +
stat->tos_packets[SYMPATHY_PKT].ctr,
stat->tos_packets[SNON_ROUTING_PKT].agg_prev_epoch +
stat->tos_packets[SYMPATHY_PKT].agg_prev_epoch);
bufprintf(buf, "<td>%s(%s)</td></tr>\n",
print_minutes_since_event(stat->tos_packets[SNON_ROUTING_PKT].ctr,
&stat->tos_packets[SNON_ROUTING_PKT].last_updated),
print_pd_of_event(stat->tos_packets[SNON_ROUTING_PKT].ctr,
&stat->tos_packets[SNON_ROUTING_PKT].last_updated));
/* Non-sympathy app-layer */
for (i = 0; i < sink.num_apps_registered; i++) {
if (stat->node_app_info[i].sink_pkt_rx.ctr > 0)
{
bufprintf(buf, "<tr><td> =>%s</td><td> %d(%d)</td>\n",
get_comp_string(stat->node_app_info[i].comp_name,
sink.app_type[i]),
stat->node_app_info[i].sink_pkt_rx.ctr,
stat->node_app_info[i].sink_pkt_rx.agg_prev_epoch);
bufprintf(buf, "<td>%s(%s)</td></tr>\n",
print_minutes_since_event(stat->node_app_info[i].app_stats_rx_from_node.ctr,
&stat->node_app_info[i].app_stats_rx_from_node.last_updated),
print_pd_of_event(stat->node_app_info[i].app_stats_rx_from_node.ctr,
&stat->node_app_info[i].app_stats_rx_from_node.last_updated));
}
}
/* Sympathy Layer */
for (i = 0; i < 2; i++)
{
if (i == 0)
{
tmp_ctr = &stat->sympathy_stats_rx;
suffix = "stats";
}
else if (i == 1) {
tmp_ctr = &stat->metrics_rx;
suffix = "metrics";
}
if (tmp_ctr->ctr > 0) {
bufprintf(buf, "<tr><td> =>Symp-%s</td>\n", suffix);
bufprintf(buf, "<td>%d(%d)</td>\n",
tmp_ctr->ctr, tmp_ctr->agg_prev_epoch);
bufprintf(buf, "<td>%s(%s)</td></tr>\n",
print_minutes_since_event(tmp_ctr->ctr, &tmp_ctr->last_updated),
print_pd_of_event(tmp_ctr->ctr, &tmp_ctr->last_updated));
}
}
for (i = 0; i < sink.num_apps_registered; i++)
{
snode = &stat->node_app_info[i];
bufprintf(buf, "<tr><td> =>Symp-%s</td>\n",
get_comp_string(snode->comp_name, sink.app_type[i]));
bufprintf(buf, "<td>%d(%d)</td>\n",
stat->node_app_info[i].app_stats_rx_from_node.ctr,
stat->node_app_info[i].app_stats_rx_from_node.agg_prev_epoch);
bufprintf(buf, "<td>%s(%s)</td></tr>\n",
print_minutes_since_event(snode->app_stats_rx_from_node.ctr,
&snode->app_stats_rx_from_node.last_updated),
print_pd_of_event(snode->app_stats_rx_from_node.ctr,
&snode->app_stats_rx_from_node.last_updated));
}
bufprintf(buf, "</table><br><br>\n");
}
/* Prints the route info for one node */
static void
print_node_route_info(buf_t* buf, sympathy_node_info_t* stat, int html)
{
sympathy_node_info_t* stat2 = stat;
int sctr, i = 0;
int iter = 0;
if (stat->next_hop.next_hop == 0) return;
/* Check if this node IS the sink */
if (stat->addr == stat->next_hop.sink) return;
/* First print out route to sink */
if (html) bufprintf(buf, "<table frame=void cellspacing=5 cellpadding=6><tr><td>");
bufprintf(buf, "Route");
if (!route_valid(stat)) bufprintf(buf, "(INVALID)");
bufprintf(buf, ":%d -> %d", stat->addr, stat->next_hop.next_hop);
while ((stat2 = iter_next_hop(stat2, &iter, stat->next_hop.sink))) {
bufprintf(buf, " -> %d ", stat2->next_hop.next_hop);
}
if (iter < 0) bufprintf(buf, "ERROR: VERY BAD Suspecting a routing loop!!\n");
if (html) {
bufprintf(buf, "</td></tr></table><table frame=void cellspacing=5 cellpadding=6><tr><td>");
}
else bufprintf(buf, ";\t ");
/* Now print children */
sctr = 0;
for (i = 0; i < SMAX_SRCS; i++)
{
if ((sink.status_srcs[i].next_hop.next_hop == stat->addr)
&& (sink.status_srcs[i].metrics_valid))
{
bufprintf(buf, "node %d, ", sink.status_srcs[i].addr);
sctr++;
}
}
if (sctr > 1) bufprintf(buf, "are children\n");
else if (sctr == 1) {
bufprintf(buf, "is a child\n");
}
if (html) bufprintf(buf, "</td></tr></table><br>\n");
}
/* Prints the components stats for one node */
static void
print_node_components_stats(buf_t* buf, sympathy_node_info_t* stat, int html)
{
int i;
sympathy_node_app_info_t* snode;
/* Print no data if this is the sink */
if (stat->addr == my_node_id) return;
/* Print information received from pinging of nodes */
if (stat->neighbor_buf->len > 0) {
bufprintf(buf, "\n*** Data Returned From Pings:\n%s", stat->neighbor_buf->buf);
clear_buf(&stat->neighbor_buf);
}
if (stat->sympathy_stats_rx.ctr > 0)
{
bufprintf(buf, "\nReported Stats from Components\n");
bufprintf(buf, "-------------------------------\n");
bufprintf(buf, "#metrics tx/expected/#stats tx: %d(%d)/%d(%d)/%d(%d)\n",
stat->num_metrics_tx.ctr, stat->num_metrics_tx.agg_prev_epoch,
sink.expected_num_sympathy_metrics.ctr,
sink.expected_num_sympathy_metrics.agg_prev_epoch,
stat->num_stats_tx.ctr, stat->num_stats_tx.agg_prev_epoch);
bufprintf(buf, "#pkts rx CRC error: %d(%d)\n",
stat->num_pkts_crc_error.ctr,
stat->num_pkts_crc_error.agg_prev_epoch);
bufprintf(buf, "#pkts rx/routed-succ/failed/dropped: %d(%d)/%d(%d)/%d(%d)/%d(%d)\n",
stat->num_pkts_rx.ctr,
stat->num_pkts_rx.agg_prev_epoch,
stat->num_pkts_tx_succeeded.ctr,
stat->num_pkts_tx_succeeded.agg_prev_epoch,
stat->num_pkts_tx_failed.ctr,
stat->num_pkts_tx_failed.agg_prev_epoch,
stat->num_pkts_dropped.ctr,
stat->num_pkts_dropped.agg_prev_epoch);
}
for (i = 0; i < sink.num_apps_registered; i++)
{
snode = &stat->node_app_info[i];
if ((snode->app_stats_rx_from_node.ctr > 0) ||
event_valid(&snode->sink_pkt_tx.last_updated)) {
/* Check if we have printed out the title yet */
if (stat->sympathy_stats_rx.ctr == 0)
{
bufprintf(buf, "\nReported Stats from Components\n");
bufprintf(buf, "------------------------------------\n");
}
bufprintf(buf, "\n%s: \n",
get_comp_string(snode->comp_name, sink.app_type[i]));
bufprintf(buf, "#reqs node rx/#reqs sink tx: %d(%d)/%d(%d)\n",
snode->node_num_pkts_rx.ctr,
snode->node_num_pkts_rx.agg_prev_epoch,
snode->sink_pkt_tx.ctr, snode->sink_pkt_tx.agg_prev_epoch);
bufprintf(buf, "#pkts node tx/sink rx/sink expected rx: %d(%d)/%d(%d)/%d(%d)\n",
snode->node_num_pkts_tx.ctr,
snode->node_num_pkts_tx.agg_prev_epoch,
snode->sink_pkt_rx.ctr,
snode->sink_pkt_rx.agg_prev_epoch,
snode->sink_pkt_expected_rx.ctr,
snode->sink_pkt_expected_rx.agg_prev_epoch);
bufprintf(buf, "#send failures/max Q occupancy/#pkts dropped: %d(%d)/%d(%d)/%d(%d)\n",
snode->node_send_failures.ctr,
snode->node_send_failures.agg_prev_epoch,
snode->node_max_queue_occupancy.ctr,
snode->node_max_queue_occupancy.agg_prev_epoch,
snode->node_num_pkts_dropped.ctr,
snode->node_num_pkts_dropped.agg_prev_epoch);
}
if (snode->generic_stats_buf->len > 0)
{
bufprintf(buf, "\n%s Generic: %s\n",
get_comp_string(snode->comp_name, sink.app_type[i]),
snode->generic_stats_buf->buf);
clear_buf(&snode->generic_stats_buf);
}
}
}
static void
print_node_components_stats_html(buf_t* buf, sympathy_node_info_t* stat, int html)
{
int i;
sympathy_node_app_info_t* snode;
/* Print no data if this is the sink */
if (stat->addr == my_node_id) return;
/* Print information received from pinging of nodes */
if (stat->neighbor_buf->len > 0)
{
bufprintf(buf, "<table frame=void cellspacing=5 cellpadding=6>\n");
bufprintf(buf, "<tr><td>Data Returned From Pings:</td></tr><tr><td>%s</td></tr></table><br><br>\n", stat->neighbor_buf->buf);
clear_buf(&stat->neighbor_buf);
}
if (stat->sympathy_stats_rx.ctr > 0)
{
bufprintf(buf, "<table frame=void cellspacing=5 cellpadding=6>");
bufprintf(buf, "<tr><td>Reported Stats from Components</td></tr>\n");
bufprintf(buf, "<tr><td>%s</td></tr></table>", "**********************************");
bufprintf(buf, "<table frame=void cellspacing=5 cellpadding=6>");
bufprintf(buf, "<tr><td>**Sympathy:</td></tr>\n");
bufprintf(buf, "<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>\n", "#metrics tx", "#stats tx", "#metrics expected", "#pkts rx CRC error","#pkts routed succ", "failed", "#pkts dropped");
bufprintf(buf, "<tr><td colspan=7>%s</td></tr>", "-----------------------------------------------------------------------------------------------------------------------------------------------------");
bufprintf(buf, "<tr><td>%d(%d)</td><td>%d(%d)</td><td>%d(%d)</td><td>%d(%d)</td><td>%d(%d)</td><td>%d(%d)</td><td>%d(%d)</td></tr>\n",
stat->num_metrics_tx.ctr, stat->num_metrics_tx.agg_prev_epoch,
stat->num_stats_tx.ctr, stat->num_stats_tx.agg_prev_epoch,
sink.expected_num_sympathy_metrics.ctr,
sink.expected_num_sympathy_metrics.agg_prev_epoch,
stat->num_pkts_crc_error.ctr,
stat->num_pkts_crc_error.agg_prev_epoch,
stat->num_pkts_tx_succeeded.ctr,
stat->num_pkts_tx_succeeded.agg_prev_epoch,
stat->num_pkts_tx_failed.ctr,
stat->num_pkts_tx_failed.agg_prev_epoch,
stat->num_pkts_dropped.ctr,
stat->num_pkts_dropped.agg_prev_epoch);
bufprintf(buf, "</table><br><br>");
}
for (i = 0; i < sink.num_apps_registered; i++)
{
snode = &stat->node_app_info[i];
if ((snode->app_stats_rx_from_node.ctr > 0) ||
event_valid(&snode->sink_pkt_tx.last_updated)) {
/* Check if we have printed out the title yet */
if (stat->sympathy_stats_rx.ctr == 0)
{
bufprintf(buf, "<table frame=void cellspacing=5 cellpadding=6>");
bufprintf(buf, "<tr><td colspan=5>Reported Stats from Components</td></tr>\n");
bufprintf(buf, "<tr><td>%s</td></tr></table>", "**********************************");
}
bufprintf(buf, " <table frame=void cellspacing=5 cellpadding=6>");
bufprintf(buf, "<tr><td>%s:</td></tr>\n",
get_comp_string(snode->comp_name, sink.app_type[i]));
bufprintf(buf, "<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>\n",
"#reqs node rx", "#reqs sink tx", "#pkts node tx",
"sink rx", "sink expected rx");
bufprintf(buf, "<tr><td colspan=5>%s</td></tr>", "----------------------------------------------------------------------------------------------------");
bufprintf(buf, "<tr><td>%d(%d)</td><td>%d(%d)</td><td>%d(%d)</td><td>%d(%d)</td><td>%d(%d)</td></tr>\n",
snode->node_num_pkts_rx.ctr,
snode->node_num_pkts_rx.agg_prev_epoch,
snode->sink_pkt_tx.ctr,
snode->sink_pkt_tx.agg_prev_epoch,
snode->node_num_pkts_tx.ctr,
snode->node_num_pkts_tx.agg_prev_epoch,
snode->sink_pkt_rx.ctr,
snode->sink_pkt_rx.agg_prev_epoch,
snode->sink_pkt_expected_rx.ctr,
snode->sink_pkt_expected_rx.agg_prev_epoch);
bufprintf(buf, "<tr><td>%s</td><td>%s</td><td>%s</td></tr>\n",
"#send failures","max Q occupancy","#pkts dropped");
bufprintf(buf, "<tr><td colspan=5>%s</td></tr>", "----------------------------------------------------------------------------------------------------");
bufprintf(buf, "<tr><td>%d(%d)</td><td>%d(%d)</td><td>%d(%d)</td></tr>\n",
snode->node_send_failures.ctr,
snode->node_send_failures.agg_prev_epoch,
snode->node_max_queue_occupancy.ctr,
snode->node_max_queue_occupancy.agg_prev_epoch,
snode->node_num_pkts_dropped.ctr,
snode->node_num_pkts_dropped.agg_prev_epoch);
}
if (snode->generic_stats_buf->len > 0)
{
bufprintf(buf, "<table frame=void cellspacing=5 cellpadding=6>");
bufprintf(buf, "<tr><td>%s Generic: %s</td></tr></table>\n",
get_comp_string(snode->comp_name, sink.app_type[i]),
snode->generic_stats_buf->buf);
clear_buf(&snode->generic_stats_buf);
}
bufprintf(buf, "<br><br>\n");
}
}
static void print_failed_info(buf_t* buf,
int root_cause, buf_t* fault_buf, char* comp_name, int addr)
{
if (root_cause == SFL_OK) return;
bufprintf(buf, " * %s Failure; Root-Cause %s \n", comp_name,
decode_root_cause(root_cause, addr));
if (fault_buf) bufprintf(buf, " %s", fault_buf->buf);
}
static void
print_header(buf_t* buf, sympathy_node_info_t* stat, int html)
{
time_t timep;
char* atime;
if (html) bufprintf(buf, "<table cellspacing=5 cellpadding=6><tr>\n");
else bufprintf(buf, "\n************* ");
if (stat->addr == my_node_id)
{
time(&timep);
atime = asctime(localtime(&timep));
if (html) bufprintf(buf, "<td>%s</td></tr>\n", atime);
else bufprintf(buf, "%s", atime);
}
else {
if (html) bufprintf(buf, "</tr>\n");
else bufprintf(buf, "\n");
}
if (html) bufprintf(buf, "<tr><td>");
bufprintf(buf, "Node %d", stat->addr);
/* If this node is the sink, specify that! */
if (stat->addr == my_node_id)
{
int min = get_minutes_since_event(&start_time);
if (html) {
bufprintf(buf, " (Sink)</td></tr><tr><td>Time awake: %d(mins)</td></tr>\n", min);
}
else bufprintf(buf, " (Sink), Time awake: %d(mins),", min);
}
else {
if (html) {
bufprintf(buf, "</td></tr><tr><td>Time awake: %d(mins)</td></tr>\n", stat->time_awake_mins.ctr);
}
else bufprintf(buf, ", Time awake: %d(mins),", stat->time_awake_mins.ctr);
}
if (html) {
bufprintf(buf, "<tr><td>Metric Pd: %d</td></tr></table><br>\n", sink.metric_pd);
}
else bufprintf(buf, " Metric Pd: %d\n",sink.metric_pd);
print_failure_info(buf, stat, html);
if ((stat->topology_info) && (stat->topology_info->len > 0)) {
if (html) bufprintf(buf, "<table cellspacing=5 cellpadding=6>\n<tr><td>");
bufprintf(buf, "%s\n", stat->topology_info->buf);
if (html) bufprintf(buf, "</td></tr>\n</table><br><br>\n");
}
if (stat->congestion_detected) bufprintf(buf, "Congestion Detected!\n");
}
static void
print_node_metrics(buf_t* buf, sympathy_node_info_t* stat, int html)
{
print_header(buf, stat, html);
print_node_route_info(buf, stat, html);
if (html) print_node_packet_table_html(buf, stat, html);
else print_node_packet_table(buf, stat, html);
if (html) print_node_components_stats_html(buf, stat, 1);
else print_node_components_stats(buf, stat, html);
if (html) {
print_node_neighbors_html(buf, stat, 1);
bufprintf(buf, "<br>\n");
}
else print_node_neighbors(buf, stat, html);
}
static node_metrics_print_t get_node_metrics_funct(char type)
{
node_metrics_print_t print = NULL;
switch(type) // get function to call for each node
{
case 'n': print = print_node_neighbors;
break;;
case 'p': print = print_node_packet_table;
break;
case 'r': print = print_node_route_info;
break;
case 'c': print = print_node_components_stats;
break;
default: elog(LOG_ERR, "Invalid metrics type %c!\n", type);
break;
}
return print;
}
static node_metrics_print_t get_node_metrics_funct_html(char type)
{
node_metrics_print_t print = NULL;
switch(type) // get function to call for each node
{
case 'n': print = print_node_neighbors_html;
break;;
case 'p': print = print_node_packet_table_html;
break;
case 'r': print = print_node_route_info;
break;
case 'c': print = print_node_components_stats_html;
break;
default: elog(LOG_ERR, "Invalid metrics type %c!\n", type);
break;
}
return print;
}
static
void metrics_cmd_summary(buf_t* buf)
{
bufprintf(buf, "\nCommand Summary\n\n");
bufprintf(buf, "\tKey letters:\n");
bufprintf(buf, "\t\tn - neighbor list\n");
bufprintf(buf, "\t\tp - packet table\n");
bufprintf(buf, "\t\tr - route info\n");
bufprintf(buf, "\t\tc - components' stats\n\n");
bufprintf(buf, "\tAll metrics:\n");
bufprintf(buf, "\t\t1) For all nodes- no command needed\n");
bufprintf(buf, "\t\t2) For one node- nodeID#\n");
bufprintf(buf, "\t\t\texample: 5 (retrieves all metrics for node 5)\n");
bufprintf(buf, "\tOne type of metrics:\n");
bufprintf(buf, "\t\t1) For all nodes- a + key letter\n");
bufprintf(buf, "\t\t\texample: an (retrieves all neighbor lists)\n");
bufprintf(buf, "\t\t2) For one node- key letter + nodeID#\n");
bufprintf(buf, "\t\t\texample: r17 (retrieves route info for node 17)\n\n");
}
static
void metrics_cmd_summary_html(buf_t* buf)
{
bufprintf(buf, "<br><a name=\"Command Summary\"><h3>Command Summary</h3></a>\n");
bufprintf(buf, "<ul><li><h4>Key letters:</h4><ul>\n");
bufprintf(buf, "<li>n - neighbor list\n");
bufprintf(buf, "<li>p - packet table\n");
bufprintf(buf, "<li>r - route info\n");
bufprintf(buf, "<li>c - components' stats</ul>\n");
bufprintf(buf, "<li><h4>All metrics:</h4><ol>\n");
bufprintf(buf, "<li>For all nodes- no command needed\n");
bufprintf(buf, "<li>For one node- nodeID#<br>\n");
bufprintf(buf, "<pre> example: 5 (retrieves all metrics for node 5)</pre></ol>\n");
bufprintf(buf, "<li><h4>One type of metrics:</h4><ol>\n");
bufprintf(buf, "<li> For all nodes- a + key letter<br>\n");
bufprintf(buf, "<pre> example: an (retrieves all neighbor lists)</pre>\n");
bufprintf(buf, "<li>For one node- key letter + nodeID#<br>\n");
bufprintf(buf, "<pre> example: r17 (retrieves route info for node 17)</pre>");
bufprintf(buf, "</ol></ul><br><br>\n");
}
void order_by_id(sympathy_node_info_t* ordered[SMAX_SRCS])
{
int i, j, k;
sympathy_node_info_t* temp;
for(i = 0; i < sink.num_srcs; i++)
{
ordered[i] = &sink.status_srcs[i];
for (j = i - 1, k = i;
(j >= 0) && (ordered[k]->addr < ordered[j]->addr); j--, k--)
{
//swap
temp = ordered[k];
ordered[k] = ordered[j];
ordered[j] = temp;
}
}
}
static int
sympathy_print_metrics_template(int html,
status_context_t *info, buf_t *buf)
{
int i, j, sctr;
char* request = NULL;
buf_t *temp = buf_new();
request = (char*)sd_client_data(sd_curr_client(info));
sympathy_node_info_t* status_srcs_cpy[SMAX_SRCS];
sympathy_node_info_t* stat;
node_metrics_print_t mprint;
get_print_funct_t gnmf;
if (html) {
gnmf = get_node_metrics_funct_html;
}
else {
gnmf = get_node_metrics_funct;
}
if (request && ((*request) > 0))
{
char first = request[0];
if (first != 'a')
{
if (isdigit(first)) // print all metrics for one node
{
int nodeid = atoi(request);
if ((nodeid < 0) || ((sctr = find_status(nodeid)) < 0))
{
elog(LOG_ERR, "Can't find node %d!\n", nodeid);
goto done;
}
stat = &sink.status_srcs[sctr];
print_node_metrics(buf, stat, html);
goto done;
}
else // print one type of metrics for one node
{
mprint = gnmf(first);
if(mprint) {
char id[200] = "";
j = 1;
if(j < strlen(request)) strcat(id, &request[j]);
else elog(LOG_ERR, "Must supply node id %s!\n", id);
int idnum = atoi(id);
if ((idnum < 0) || ((sctr = find_status(idnum)) < 0))
{
elog(LOG_ERR, "Can't find node %d!\n", idnum);
goto done;
}
stat = &sink.status_srcs[sctr];
mprint(buf, stat, html);
}
else {
elog(LOG_ERR, "Invalid metrics request: %s!\n", request);
goto done;
}
}
}
// (first == 'a'), print one type of metrics for all nodes
if (strlen(request) < 2)
{
elog(LOG_ERR, "Invalid metrics request: %s\n", request);
goto done;
}
mprint = gnmf(request[1]);
if(mprint)
{
order_by_id(status_srcs_cpy);
for (i = 0; i < sink.num_srcs; i++)
{
mprint(temp, status_srcs_cpy[i], html);
if(buf_len(temp) > 0) { // print "Node x:" only if it has metrics
if(html) {
bufprintf(buf, "<h3>Node %d:</h3><br>", status_srcs_cpy[i]->addr);
}
else bufprintf(buf, "Node %d:\n", status_srcs_cpy[i]->addr);
mprint(buf, status_srcs_cpy[i], html);
}
}
buf_free(temp);
temp = buf_new();
bufprintf(buf, "\n\n");
}
else elog(LOG_ERR, "Invalid metrics request: %s!\n", request);
goto done;
}
order_by_id(status_srcs_cpy);
for (i = 0; i < sink.num_srcs; i++) // print all metrics for all nodes
{
print_node_metrics(buf, status_srcs_cpy[i], html);
}
/* Command summary */
{
status_client_t* curr = sd_curr_client(info);
sympathy_client_data_t* m = (sympathy_client_data_t *)sd_client_data(curr);
if (m) {
if (!m->printed_usage) {
if (html) metrics_cmd_summary_html(buf);
else metrics_cmd_summary(buf);
m->printed_usage = 1;
}
}
}
done:
buf_free(temp);
return STATUS_MSG_COMPLETE;
}
static
int sympathy_print_metrics(status_context_t *info, buf_t *buf)
{
return sympathy_print_metrics_template(0, info, buf);
}
static
int sympathy_print_metrics_binary(status_context_t *info, buf_t *buf)
{
int i, j, ctr;
sympathy_node_info_t* stat;
for (i = 0; i < sink.num_srcs; i++) {
ctr = 0;
stat = &sink.status_srcs[i];
{
sympathy_metrics_t m = {
address: stat->addr,
congestion_detected: stat->congestion_detected,
num_neighbors: stat->num_neighbors,
num_heard_this_node: stat->num_heard_this_node,
time_awake_minutes: stat->time_awake_mins.ctr,
};
memcpy(&m.route, &stat->next_hop, sizeof(stat->next_hop));
for (j = 0; j < NUM_TOS_PKT_TYPES; j++) {
m.tos_packets[j] = stat->tos_packets[j].ctr;
}
for (j = 0; j < stat->num_neighbors; j++) {
if ((stat->neighbors[j].node_id> 0) &&
(stat->neighbors[j].node_id!= TOS_BCAST_ADDR)) {
m.neighbors[ctr].addr = stat->neighbors[j].node_id;
ctr++;
}
}
print_summary(stat, &m.failure);
bufcpy(buf, &m, sizeof(sympathy_metrics_t));
}
}
return STATUS_MSG_COMPLETE;
}
static
int sympathy_print_metrics_xml(status_context_t *info, buf_t *buf)
{
buf_t* binary_buf = buf_new();
sympathy_print_metrics_binary(info, binary_buf);
sympathy_metrics_t* m = (sympathy_metrics_t *)binary_buf->buf;
int i = 0;
int j = 0;
int num_nodes = binary_buf->len / (sizeof(sympathy_metrics_t));
while (i < num_nodes) {
bufprintf(buf, "\n\n<sympathy_data mote_id=\"%d\" time_awake_mins=\"%d\"\n",
m[i].address, m[i].time_awake_minutes);
bufprintf(buf, "<sink>%d</sink>\n", m[i].is_sink ? 1 : 0);
if (m[i].failure.node_failure_category > SFL_OK) {
bufprintf(buf, "<failure_type>%d</failure_type>\n",
m[i].failure.node_failure_category );
bufprintf(buf, "<root_cause>\"%s\"</root_cause>\n",
decode_root_cause(m[i].failure.failure_root_cause,m[i].address));
bufprintf(buf, "<failure_localization>\"%s\"</failure_localization>\n",decode_localization(m[i].failure.failure_localization));
}
bufprintf(buf, "<congestion_detected>%d</congestion_detected>\n",
m[i].congestion_detected ? 1: 0);
bufprintf(buf, "<packet_table>\n");
for (j = 0; j < NUM_TOS_PKT_TYPES; j++) {
if (m[i].tos_packets[j] > 0) {
bufprintf(buf, " <packet type=\"%s\" number_rx=\"%d\" />\n",
tos_packet_to_string(j), m[i].tos_packets[j]);
}
}
bufprintf(buf, "</packet_table>\n");
//<!-- print the following ONLY when they change -->
bufprintf(buf, "<neighbor_list>\n");
{
for (j = 0; j < m[i].num_neighbors; j++) {
bufprintf(buf, " <node mote_id=\"%d\"/>\n",
m[i].neighbors[j].addr);
}
}
bufprintf(buf, "</neighbor_list>\n");
//<!-- print the following ONLY when we received an update -->
if (!m[i].is_sink) {
bufprintf(buf, "<routing_table>\n");
bufprintf(buf, "<sink mote_id=\"%d\" next_hop_address=\"%d\" path_quality=\"%d\"/>\n",
m[i].route.sink, m[i].route.next_hop, m[i].route.quality);
bufprintf(buf, "</routing_table>\n");
}
//<!-- print the following ONLY when it changed. -->
bufprintf(buf, "<num_neighbors_heard_this_node>%d</num_neighbors_heard_this_node>\n",
m[i].num_heard_this_node);
i++;
}
buf_free(binary_buf);
return STATUS_MSG_COMPLETE;
}
static
int sympathy_print_metrics_html(status_context_t *info, buf_t *buf)
{
return sympathy_print_metrics_template(1, info, buf);
}
static
int sympathy_metrics_write(status_context_t *ctx, char cmd[], size_t size)
{
status_client_t* curr = sd_curr_client(ctx);
sympathy_client_data_t* m = (sympathy_client_data_t *)sd_client_data(curr);
if (size < 10) sprintf(m->request, "%s", cmd);
else elog(LOG_ERR, "Size of command: %d is > 10!\n", size);
return STATUS_WRITE_NOTIFY_CLIENT;
}
static
int sympathy_device_close(status_context_t *ctx)
{
status_client_t* curr = sd_curr_client(ctx);
if (curr) g_free(sd_client_data(curr));
return 0;
}
static
int sympathy_device_open(status_context_t *ctx)
{
status_client_t* curr = sd_curr_client(ctx);
sympathy_client_data_t* m = g_new0(sympathy_client_data_t, 1);
if (curr) sd_set_client_data(curr, m);
return 0;
}
static
void print_failure_info(buf_t* buf, sympathy_node_info_t* stat, int html)
{
int i;
if (stat->failure_type == SFL_OK) return;
if (html) {
bufprintf(buf, "<br><table frame=void cellspacing=5 cellpadding=6><tr><td>");
}
bufprintf(buf, " ** ");
if (stat->failure_localization == S_SELF) bufprintf(buf, "Root ");
bufprintf(buf, "Failure (%d); Root-Cause: %s (%d periods)\n",
stat->failure_type,
decode_root_cause(stat->failure_root_cause, stat->addr),
sink.metric_pd - stat->period_root_caused + 1);
if (stat->failure_localization != S_SELF) {
bufprintf (buf, "; Localized to ");
/* See if root cause if congestion at the node or just
* another failure */
{
sympathy_node_info_t* tmp_stat = find_status_ptr(stat->source_node_failure);
if (tmp_stat) {
if (tmp_stat->congestion_detected) {
bufprintf (buf, "Congestion at");
}
else {
bufprintf(buf, "%s at", decode_root_cause(tmp_stat->failure_root_cause, tmp_stat->addr));
}
}
bufprintf(buf, " node %d\n", stat->source_node_failure);
}
}
bufprintf(buf, "%s \n", stat->fault_buf->buf);
if (html) bufprintf(buf, "</td></tr><tr><td>");
if (html) bufprintf(buf, "</td></tr><tr><td></table>\n<br>");
/* If the root-cause is less severe than no-neighbors, then print
* component failures */
if (stat->failure_root_cause < SRC_NO_NEIGHBORS) {
for (i = 0; i < sink.num_apps_registered; i++)
{
if (html) {
bufprintf(buf, "<table frame=void cellspacing=5 cellpadding=6>");
}
if (sink.app_type[i] < SCOMP_LAST)
{
if (html) bufprintf(buf, "<tr><td>");
print_failed_info(buf, stat->node_app_info[i].failure_root_cause,
stat->node_app_info[i].fault_buf,
stat->node_app_info[i].comp_name, stat->addr);
if (html) bufprintf(buf, "</tr></td>");
}
if (html) bufprintf(buf, "</table>\n");
}
if (html) bufprintf(buf, "</table>\n<br>");
}
}
/*** External functions ***/
int event_valid(struct timeval* t)
{
int min_data = get_minutes_since_event(t);
return (min_data <= EPOCH_MSEC/60000);
}
int neighbors_valid(sympathy_node_info_t* stat)
{
if (stat->addr == my_node_id) return 1;
return(stat->metrics_valid ||
event_valid(&stat->tos_packets[SNEIGHBOR_ADVERT].last_updated));
}
int route_valid(sympathy_node_info_t* stat)
{
if (stat->addr == my_node_id) return 1;
return(stat->metrics_valid ||
event_valid(&stat->tos_packets[SPATH_ADVERT].last_updated));
}
static
int check_set_client_data(status_context_t *info, sympathy_node_info_t* stat)
{
status_client_t* curr = sd_curr_client(info);
sympathy_client_data_t* m = sd_client_data(curr);
/* First find the index for this node */
int i = find_status(stat->addr);
if (!m) {
elog(LOG_ERR, "No client data for node: %d\n", stat->addr);
return 1;
}
if (i < 0) {
elog(LOG_ERR, "Can't find index for node %d\n", stat->addr);
return 1;
}
/* We print the data if it hasnt been printed yet this period, or
* if the failure is a node-crash or node-reboot */
if ((m->printed_rc_period[i] != sink.metric_pd)
|| (((stat->failure_root_cause == SRC_NODE_REBOOTED)
|| (stat->failure_root_cause == SRC_NODE_FAILED))
&& (m->printed_root_cause[i] != stat->failure_root_cause))) {
m->printed_rc_period[i] = sink.metric_pd;
m->printed_root_cause[i] = stat->failure_root_cause;
return 1;
}
return 0;
}
static
void print_summary_info(status_context_t* ctx, buf_t* buf, int print_all,
int html)
{
int i;
sympathy_node_info_t* stat;
if (sink.metric_pd < TRACK_FAILURE_WINDOW_SIZE - 1) goto done;
/* Treat the sink separately because if the sink has a failure
* then there is no need to print the failures of other nodes */
if ((stat = find_status_ptr(my_node_id))) {
if (check_set_client_data(ctx, stat)) {
if ((print_all) || (stat->failure_type > SFL_OK)) {
print_header(buf, stat, html);
}
}
}
for (i = 0; i < sink.num_srcs; i++)
{
stat = &sink.status_srcs[i];
/* This check will also check if stat->addr != to the sink, so we don't
* have to do that check again */
if (check_set_client_data(ctx, stat)) {
if ((print_all) || (stat->failure_type > SFL_OK)) {
print_header(buf, stat, html);
print_node_route_info(buf, stat, html);
if (html) {
bufprintf(buf, "<br><table frame=void cellspacing=5 cellpadding=6>\n<tr><td>");
}
if (stat->packet.ctr > 0) {
bufprintf(buf, "Heard from node %s (%s) ago\n",
print_minutes_since_event(stat->packet.ctr,
&stat->packet.last_updated),
print_pd_of_event(stat->packet.ctr,
&stat->packet.last_updated));
}
else bufprintf(buf, "\nNever heard from this node!!\n");
if (html) bufprintf(buf, "</tr></td>\n</table>\n<br>");
}
}
}
done: return;
}
/* Summary file will print info for all nodes:
* - header info, any failures, route, time since heard from node */
static
int sympathy_print_summary(status_context_t *info, buf_t *buf)
{
print_summary_info(info, buf, 1, 0);
#ifdef USE_BAYES
bufprintf(buf,getClassificationsFromBayes());
#endif
return STATUS_MSG_COMPLETE;
}
static
void print_summary(sympathy_node_info_t* stat, Sfail_summary_t* fail)
{
int j;
fail->node = stat->addr;
fail->node_failure_category = stat->failure_type;
fail->failure_root_cause = stat->failure_root_cause;
fail->failure_localization = stat->failure_localization;
for (j = 0; j < SCOMP_LAST; j++) {
fail->comp_failure[j] = stat->node_app_info[j].failure_type;
}
}
static
int sympathy_print_summary_bin(status_context_t *info, buf_t *buf)
{
Sfail_summary_t fail = {
metric_pd: sink.metric_pd,
};
int i;
sympathy_node_info_t* stat;
for (i = 0; i < sink.num_srcs; i++)
{
stat = &sink.status_srcs[i];
if (check_set_client_data(info, stat)) {
print_summary(stat, &fail);
bufcpy(buf, &fail, sizeof(Sfail_summary_t));
}
}
return STATUS_MSG_COMPLETE;
}
/* Gives current status of all components registered with sympathy
* and shows how to change parameters */
static
int sympathy_print_status(status_context_t *info, buf_t *buf)
{
int i, j;
sympathy_node_info_t* stat;
sympathy_node_app_info_t* snode;
bufprintf(buf, "Node\t Comp-Name\t Min Pkt Rx(%%)\n");
for (i = 0; i < sink.num_srcs; i++) {
stat = &sink.status_srcs[i];
if (stat->addr > 0) {
for (j = 0; j < sink.num_apps_registered; j++) {
snode = &stat->node_app_info[j];
bufprintf(buf, "%d \t %s \t %d\n", stat->addr, snode->comp_name,
snode->pkt_reception_percent);
}
}
}
bufprintf(buf, "\n*****\nTo change a node's minimum required percent of packets expected by the sink, write:\n");
bufprintf(buf, "\t\tnode=<id>:comp_name=<string>:rx_percent=<int>\n");
bufprintf(buf, "**NOTE: This will override assignment from the corresponding component on the sink!\n");
return STATUS_MSG_COMPLETE;
}
static
int sympathy_status_html(status_context_t *info, buf_t *buf)
{
int i, j;
sympathy_node_info_t* stat;
sympathy_node_app_info_t* snode;
sympathy_node_info_t* status_srcs_cpy[SMAX_SRCS];
order_by_id(status_srcs_cpy);
bufprintf(buf, "<table frame=void cellspacing=5 cellpadding=6>\n");
bufprintf(buf, "<tr><td>%s</td><td>%s</td><td>%s</td></tr>\n",
"Node", "Comp-Name", "Min Pkt Rx(%)");
bufprintf(buf, "<tr><td colspan=3>-----------------------------------------------------------</td></tr>");
for (i = 0; i < sink.num_srcs; i++) {
stat = status_srcs_cpy[i];
if (stat->addr > 0) {
for (j = 0; j < sink.num_apps_registered; j++) {
snode = &stat->node_app_info[j];
bufprintf(buf, "<tr><td>%d</td><td>%s</td><td>%d</td></tr>\n",
stat->addr, snode->comp_name,
snode->pkt_reception_percent);
}
}
}
bufprintf(buf, "</table>");
return STATUS_MSG_COMPLETE;
}
int find_comp_name_index(char* comp_name, sympathy_node_info_t* stat) {
int j;
for (j = 0; j < sink.num_apps_registered; j++) {
if (strcmp(stat->node_app_info[j].comp_name, comp_name) == 0) return j;
}
return -1;
}
static
int sympathy_status_write(status_context_t *ctx, char* cmd, size_t size)
{
parser_state_t* ps = misc_parse_init(cmd, MISC_PARSE_COLON_SCHEME);
sympathy_node_info_t* stat = NULL;
char comp_name[100] = {};
int rx_percent = -1;
while (misc_parse_next_kvp(ps) >= 0) {
if (!ps->value) {
elog(LOG_ERR, "Key of %s requires a value!\n", ps->key);
goto error;
}
if (strcmp(ps->key, "node") == 0) {
if (!(stat = find_status_ptr(atoi(ps->value)))) {
elog(LOG_ERR, "ERROR: Unable to find node %d!\n", atoi(ps->value));
goto error;
}
}
else if (strcmp(ps->key, "comp_name") == 0) {
sprintf(comp_name, "%s", ps->value);
}
else if (strcmp(ps->key, "rx_percent") == 0) {
rx_percent = atoi(ps->value);
}
else {
elog(LOG_ERR, "Unrecognized key: %s\n", ps->key);
goto error;
}
}
if ((stat) && (rx_percent > -1) && (strlen(comp_name) > 0)) {
int index = find_comp_name_index(comp_name, stat);
if (index > -1) {
elog(LOG_NOTICE, "Changing reception percent for comp_name %s from %d to %d\n",
comp_name, stat->node_app_info[index].pkt_reception_percent,
rx_percent);
stat->node_app_info[index].pkt_reception_percent = rx_percent;
stat->node_app_info[index].pkt_reception_locked = 1;
}
else goto error;
}
else goto error;
misc_parse_cleanup(ps);
return STATUS_WRITE_DONE;
error:
misc_parse_cleanup(ps);
elog(LOG_ERR, "ERROR: Bad argument(%s)! cat device for usage!\n",cmd);
return EVENT_ERROR(EINVAL);
}
static
int sympathy_print_failures(status_context_t *info, buf_t *buf)
{
print_summary_info(info, buf, 0, 0);
return STATUS_MSG_COMPLETE;
}
static
int sympathy_failures_html(status_context_t *info, buf_t *buf)
{
print_summary_info(info, buf, 0, 1);
return STATUS_MSG_COMPLETE;
}
void initialize_devices()
{
status_dev_opts_t sopts = {
device: {
},
};
/* Create a status device */
sopts.device.devname = sympathy_device(SSINK_COMP_STATUS);
sopts.printable = sympathy_print_status;
sopts.html = sympathy_status_html;
sopts.write = sympathy_status_write;
if (g_status_dev(&sopts, &sink.sink_status) < 0) {
elog(LOG_ERR, "Unable to open status device %s: %m\n", sopts.device.devname);
}
/* FOR all devices */
sopts.close = sympathy_device_close;
sopts.open = sympathy_device_open;
/* For specific devices */
sopts.device.devname = sympathy_device(SMETRICS_STATUS);
sopts.printable = sympathy_print_metrics;
sopts.html = sympathy_print_metrics_html;
sopts.xml = sympathy_print_metrics_xml;
sopts.write = sympathy_metrics_write;
sopts.binary = sympathy_print_metrics_binary;
if (g_status_dev(&sopts, &sink.metrics_status) < 0) {
elog(LOG_ERR, "Unable to open status device %s: %m\n", sopts.device.devname);
}
sopts.device.devname = sympathy_device(SFAIL_STATUS);
sopts.printable = sympathy_print_failures;
sopts.html = sympathy_failures_html;
sopts.xml = 0;
sopts.write = 0;
if (g_status_dev(&sopts, &sink.fail_status) < 0) {
elog(LOG_ERR, "Unable to open status device %s: %m\n", sopts.device.devname);
}
sopts.device.devname = sympathy_device(SFAILURE_SUMMARY_STATUS);
sopts.printable = sympathy_print_summary;
sopts.binary = sympathy_print_summary_bin;
if (g_status_dev(&sopts, &sink.summary_status) < 0) {
elog(LOG_ERR, "Unable to open status device: %s: %m\n", sopts.device.devname);
}
/* Battery device */
{
status_dev_opts_t opts = {
device: {
devname: sympathy_device(SYMPATHY_BATTERY_DEVICE)
},
write: sbattery_write,
printable: sbattery_print,
html: sbattery_html
};
if (g_status_dev(&opts, NULL) < 0) {
printf("unable to create status dev 1\n");
}
}
}
See more files for this project here