/****************************************************************************
Program: $Id: rtgpoll.c,v 1.22 2003/09/25 15:56:04 rbeverly Exp $
Author: $Author: rbeverly $
Date: $Date: 2003/09/25 15:56:04 $
Description: RTG SNMP get dumps to MySQL database
****************************************************************************/
#define _REENTRANT
#include "common.h"
#include "rtg.h"
/* Yes. Globals. */
stats_t stats =
{PTHREAD_MUTEX_INITIALIZER, 0, 0, 0, 0, 0, 0, 0, 0, 0.0};
char *target_file = NULL;
target_t *current = NULL;
MYSQL mysql;
int entries = 0;
/* dfp is a debug file pointer. Points to stderr unless debug=level is set */
FILE *dfp = NULL;
/* Main rtgpoll */
int main(int argc, char *argv[]) {
crew_t crew;
pthread_t sig_thread;
sigset_t signal_set;
struct timeval now;
double begin_time, end_time, sleep_time;
char *conf_file = NULL;
char errstr[BUFSIZE];
int ch, i;
dfp = stderr;
/* Check argument count */
if (argc < 3)
usage(argv[0]);
/* Set default environment */
config_defaults(&set);
/* Parse the command-line. */
while ((ch = getopt(argc, argv, "c:dhmt:vz")) != EOF)
switch ((char) ch) {
case 'c':
conf_file = optarg;
break;
case 'd':
set.dboff = TRUE;
break;
case 'h':
usage(argv[0]);
break;
case 'm':
set.multiple++;
break;
case 't':
target_file = optarg;
break;
case 'v':
set.verbose++;
break;
case 'z':
set.withzeros = TRUE;
break;
}
if (set.verbose >= LOW)
printf("RTG version %s starting.\n", VERSION);
/* Initialize signal handler */
sigemptyset(&signal_set);
sigaddset(&signal_set, SIGHUP);
sigaddset(&signal_set, SIGUSR1);
sigaddset(&signal_set, SIGUSR2);
sigaddset(&signal_set, SIGTERM);
sigaddset(&signal_set, SIGINT);
sigaddset(&signal_set, SIGQUIT);
if (!set.multiple)
checkPID(PIDFILE);
if (pthread_sigmask(SIG_BLOCK, &signal_set, NULL) != 0)
printf("pthread_sigmask error\n");
/* Read configuration file to establish local environment */
if (conf_file) {
if ((read_rtg_config(conf_file, &set)) < 0) {
printf("Could not read config file: %s\n", conf_file);
exit(-1);
}
} else {
conf_file = malloc(BUFSIZE);
if (!conf_file) {
printf("Fatal malloc error!\n");
exit(-1);
}
for(i=0;i<CONFIG_PATHS;i++) {
snprintf(conf_file, BUFSIZE, "%s%s", config_paths[i], DEFAULT_CONF_FILE);
if (read_rtg_config(conf_file, &set) >= 0) {
break;
}
if (i == CONFIG_PATHS-1) {
snprintf(conf_file, BUFSIZE, "%s%s", config_paths[0], DEFAULT_CONF_FILE);
if ((write_rtg_config(conf_file, &set)) < 0) {
fprintf(stderr, "Couldn't write config file.\n");
exit(-1);
}
}
}
}
/* hash list of targets to be polled */
entries = hash_target_file(target_file);
if (entries <= 0) {
fprintf(stderr, "Error updating target list.");
exit(-1);
}
if (set.verbose >= LOW)
printf("Initializing threads (%d).\n", set.threads);
pthread_mutex_init(&(crew.mutex), NULL);
pthread_cond_init(&(crew.done), NULL);
pthread_cond_init(&(crew.go), NULL);
crew.work_count = 0;
/* Initialize the SNMP session */
if (set.verbose >= LOW)
printf("Initializing SNMP (v%d, port %d).\n", set.snmp_ver, set.snmp_port);
init_snmp("RTG");
/* Attempt to connect to the MySQL Database */
if (!(set.dboff)) {
if (rtg_dbconnect(set.dbdb, &mysql) < 0) {
fprintf(stderr, "** Database error - check configuration.\n");
exit(-1);
}
if (!mysql_ping(&mysql)) {
if (set.verbose >= LOW)
printf("connected.\n");
} else {
printf("server not responding.\n");
exit(-1);
}
}
if (set.verbose >= HIGH)
printf("\nStarting threads.\n");
for (i = 0; i < set.threads; i++) {
crew.member[i].index = i;
crew.member[i].crew = &crew;
if (pthread_create(&(crew.member[i].thread), NULL, poller, (void *) &(crew.member[i])) != 0)
printf("pthread_create error\n");
}
if (pthread_create(&sig_thread, NULL, sig_handler, (void *) &(signal_set)) != 0)
printf("pthread_create error\n");
/* give threads time to start up */
sleep(1);
if (set.verbose >= LOW)
printf("RTG Ready.\n");
/* Loop Forever Polling Target List */
while (1) {
lock = TRUE;
gettimeofday(&now, NULL);
begin_time = (double) now.tv_usec / 1000000 + now.tv_sec;
PT_MUTEX_LOCK(&(crew.mutex));
init_hash_walk();
current = getNext();
crew.work_count = entries;
PT_MUTEX_UNLOCK(&(crew.mutex));
if (set.verbose >= LOW)
timestamp("Queue ready, broadcasting thread go condition.");
PT_COND_BROAD(&(crew.go));
PT_MUTEX_LOCK(&(crew.mutex));
while (crew.work_count > 0) {
PT_COND_WAIT(&(crew.done), &(crew.mutex));
}
PT_MUTEX_UNLOCK(&(crew.mutex));
gettimeofday(&now, NULL);
lock = FALSE;
end_time = (double) now.tv_usec / 1000000 + now.tv_sec;
stats.poll_time = end_time - begin_time;
stats.round++;
sleep_time = set.interval - stats.poll_time;
if (waiting) {
if (set.verbose >= HIGH)
printf("Processing pending SIGHUP.\n");
entries = hash_target_file(target_file);
waiting = FALSE;
}
if (set.verbose >= LOW) {
snprintf(errstr, sizeof(errstr), "Poll round %d complete.", stats.round);
timestamp(errstr);
print_stats(stats);
}
if (sleep_time <= 0)
stats.slow++;
else
sleepy(sleep_time);
} /* while */
/* Disconnect from the MySQL Database, exit. */
if (!(set.dboff))
rtg_dbdisconnect(&mysql);
exit(0);
}
/* Signal Handler. USR1 increases verbosity, USR2 decreases verbosity.
HUP re-reads target list */
void *sig_handler(void *arg)
{
sigset_t *signal_set = (sigset_t *) arg;
int sig_number;
while (1) {
sigwait(signal_set, &sig_number);
switch (sig_number) {
case SIGHUP:
if(lock) {
waiting = TRUE;
}
else {
entries = hash_target_file(target_file);
waiting = FALSE;
}
break;
case SIGUSR1:
set.verbose++;
break;
case SIGUSR2:
set.verbose--;
break;
case SIGTERM:
case SIGINT:
case SIGQUIT:
if (set.verbose >= LOW)
printf("Quiting: received signal %d.\n", sig_number);
rtg_dbdisconnect(&mysql);
unlink(PIDFILE);
exit(1);
break;
}
}
}
void usage(char *prog)
{
printf("rtgpoll - RTG v%s\n", VERSION);
printf("Usage: %s [-dmz] [-vvv] [-c <file>] -t <file>\n", prog);
printf("\nOptions:\n");
printf(" -c <file> Specify configuration file\n");
printf(" -d Disable database inserts\n");
printf(" -t <file> Specify target file\n");
printf(" -v Increase verbosity\n");
printf(" -m Allow multiple instances\n");
printf(" -z Database zero delta inserts\n");
printf(" -h Help\n");
exit(-1);
}
syntax highlighted by Code2HTML, v. 0.9.1