Show conn-dump.c syntax highlighted
/*
*
* 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.
*
*/
/*
* conn-dump: An app that dumps neighbor info to a file
*
* This app doesn't really do anything other than print the list of
* neighbors to a file every time it changes.
*/
#include <emrun/emrun.h>
#include <link/link.h>
#include <link/neighbor.h>
#include <stdio.h> /* fopen, fclose, fprintf */
typedef struct app_state{
char tracefile[200];
FILE *fd;
} app_state_t;
void open_tracefile(app_state_t *u)
{
if((u->fd = fopen(u->tracefile, "w")) == NULL){
elog(LOG_ERR,"couldn't open file '%s': %d",u->tracefile,errno);
exit(1);
}
}
void close_tracefile(app_state_t *u)
{
if(fclose(u->fd)==EOF){
elog(LOG_ERR,"couldn't close file '%s': %d",u->tracefile,errno);
}
}
/*
* Simple callback activated when we are asked to shut down by emrun
*/
void neighbor_app_shutdown(void *data)
{
elog(LOG_NOTICE, "neighbor application shutting down");
close_tracefile((app_state_t *)data);
exit(0);
}
int new_neighbor_list(neighbor_t *nb_list, int count, void *data)
{
int i;
app_state_t *u = (app_state_t *)data;
char *state;
elog(LOG_DEBUG(0), "Whoo hoo - new neighbor list received!");
elog(LOG_DEBUG(0), "Our currently active neighbors are:");
for (i = 0; i < count; i++) {
if (nb_list[i].state == NB_UNKNOWN) state = "NB_UNKNOWN";
else if (nb_list[i].state == SELF) state = "SELF";
else if (nb_list[i].state == ASYMMETRIC) state = "ASYMMETRIC";
else if (nb_list[i].state == ACTIVE) state = "ACTIVE";
else if (nb_list[i].state == DEAD) state = "DEAD";
else state = "NONE";
fprintf(u->fd,"%d %d 0x%x %s %f %f %s %f %f %d %ld %ld %ld %ld\n",
my_node_id,
nb_list[i].node_id,
nb_list[i].if_id,
print_if_id(nb_list[i].if_id),
nb_list[i].loc.x,
nb_list[i].loc.y,
state,
nb_list[i].conn_from,
nb_list[i].conn_to,
nb_list[i].period,
nb_list[i].last_heard.tv_sec,
nb_list[i].last_heard.tv_usec,
nb_list[i].last_ack.tv_sec,
nb_list[i].last_ack.tv_usec
);
fflush(u->fd);
elog(LOG_DEBUG(0),"%d %d 0x%x %s %f %f %s %f %f %d %ld %ld %ld %ld",
my_node_id,
nb_list[i].node_id,
nb_list[i].if_id,
print_if_id(nb_list[i].if_id),
nb_list[i].loc.x,
nb_list[i].loc.y,
state,
nb_list[i].conn_from,
nb_list[i].conn_to,
nb_list[i].period,
nb_list[i].last_heard.tv_sec,
nb_list[i].last_heard.tv_usec,
nb_list[i].last_ack.tv_sec,
nb_list[i].last_ack.tv_usec
);
}
elog(LOG_DEBUG(0), "waiting for new list...");
/* Note that WE are responsible for freeing nb_list. In this simple
* example, we just free it immediately. In your real app, you will
* probably want to save the array until the next one arrives. */
free(nb_list);
return EVENT_RENEW; /* return EVENT_DONE if you want no more updates */
}
void usage(void)
{
fprintf(stderr,
"conn-dump release: %s\n"
"\n"
"usage: conn-dump [-f trace file]\n",
CVSTAG
);
exit(1);
}
int main(int argc, char *argv[])
{
int arg;
app_state_t u;
neighbor_opts_t n_opts = {
link_opts: {
/* if there are multiple network interfaces you could use this
* to specify which one you want the neighborlist for. */
link_index: LINK_INDEX_AUTO
},
new_list: new_neighbor_list,
data: &u
};
emrun_opts_t emrun_opts = {
shutdown: neighbor_app_shutdown,
data: &u
};
/* everything in emstar needs this initialization */
misc_init(&argc, argv, CVSTAG);
opterr = 0;
while ((arg = getopt(argc,argv,"hf:")) != EOF) {
switch (arg){
case 'h':
usage();
break;
case 'f':
sprintf(u.tracefile,"%s-%d",optarg,my_node_id);
elog_g(LOG_NOTICE,"tracefile: '%s'",u.tracefile);
break;
default:
usage();
break;
}
}
/* advance past parsed options */
argc -= optind;
argv += optind;
/* Open a link to the neighborlist service */
if (g_neighbors(&n_opts, NULL) < 0) {
elog(LOG_CRIT, "couldn't open neighborlist %s: %m",
link_name(&n_opts.link_opts));
exit(1);
}
open_tracefile(&u);
/* Connect ourselves to emrun, to get shutdown commands */
emrun_init(&emrun_opts); /* this should be the last initialization */
elog_g(LOG_NOTICE, "neighbor service running");
g_main();
return 0;
}
See more files for this project here