Example #1
0
void *sync_poller(void *thread_args) {

	// phoenix async poller;
	worker_t *worker = (worker_t *) thread_args;
	crew_t *crew = worker -> crew;
	// target_t *entry = NULL;

	target_t *_current_local = NULL;

	PT_MUTEX_LOCK(&crew -> mutex);
	PT_COND_WAIT(&crew->go, &crew->mutex);
	PT_MUTEX_UNLOCK(&crew -> mutex);

	for( ; ; ) {

		PT_MUTEX_LOCK(&crew -> mutex);

		current = _current_local = getNext();
		crew -> _sent_work_count--;

		if (_current_local == NULL && crew->_sent_work_count <= 0) {

			crew -> _send_worker_count--;
			PT_COND_BROAD(&crew -> _sending_done);
			PT_COND_WAIT(&crew -> go, &crew -> mutex);
//		} else if (_current_local == NULL) {
//			PT_COND_WAIT(&crew->go, &crew->mutex);
//			// PT_MUTEX_UNLOCK(&crew -> mutex);
//			continue;
//			// return 0;
//		} else if (crew->_sent_work_count <= 0) {
//			PT_COND_BROAD(&crew->_sending_done);
//			// PT_MUTEX_UNLOCK(&crew -> mutex);
//			continue;
//			// return 0;
			PT_MUTEX_UNLOCK(&crew -> mutex);
			continue;
		}

		PT_MUTEX_UNLOCK(&crew -> mutex);

//		PT_MUTEX_LOCK(&crew->mutex);
//		current = getNext();
//		if (status == STAT_SUCCESS) entry->last_value = result;
//		if (init == NEW) entry->init = LIVE;
//		 signal for our control thread;
//		 but should also check for number of threads completed;
//		PT_MUTEX_UNLOCK(&crew->mutex);

//		while (current == NULL) {
//			PT_COND_WAIT(&crew -> go, &crew -> mutex);
//			_current_local = NULL;
//		}
//
//		if (current != NULL) {
//			_current_local = current;
//			// printf("[ info] thread [%d] work_count index: %d\n", worker->index, crew -> _send_work_count);
//		}
		// make a copy of current and then unlock;

		// preparing snmp session;
		// we got what we need from current entry
		// moving to next entry for other wating threads;

			printf(
				"[ info] thread [%d] processing -> host: %s, oid: %s\n",
				worker -> index,
				_current_local -> host,
			    _current_local -> objoid
			);

		// making a snmp session ...

		// struct session *_host_ss = stuepd you are, this is a ptr! sohuld be initialized 1st :- ;
		struct session *_host_ss = calloc(1, sizeof(struct session));
		// stuepd you are, this is a ptr! sohuld be initialized 1st :- ;
		// struct host *hp;

		/* startup all hosts */
		// for (hs = sessions, hp = hosts; hp->name; hs++, hp++) {

		struct snmp_session _sess;

		struct snmp_pdu *pdu = NULL;
		struct snmp_pdu *response = NULL;

		snmp_sess_init(&_sess);

		/* initialize session */
		_sess.version = SNMP_VERSION_2c;
		_sess.peername = strdup(_current_local-> host);
		_sess.community = strdup(_current_local -> community);
		_sess.community_len = strlen(_sess.community);

//		/* default callback */
//		_sess.callback = asynch_response;
//		_sess.callback_magic = _host_ss;
//
		if (!(_host_ss -> _sess = snmp_sess_open(&_sess))) {

			//, snmp_api_errstring(snmp_errno)
			printf("[error] %s!\n", snmp_api_errstring(snmp_errno));
			// exit(-1);
			// snmp_perror(snmp_errno);
			continue;

		}

//		printf("[ info] thread [%d] &sess: %llu, _host_ss -> _sess: %llu\n", worker->index,
//		       &sess, _host_ss -> _sess);

//		struct snmp_session *_ss_ptr = snmp_sess_session(_host_ss -> _sess);

		_host_ss -> _oid_name = strdup(_current_local -> objoid);
		// also translate this in to snmp format;
		_host_ss -> _oid_len = sizeof(_host_ss -> _oid) / sizeof(_host_ss -> _oid[0]);

		if (!read_objid(_host_ss -> _oid_name, _host_ss -> _oid, &_host_ss -> _oid_len)) {
			snmp_perror("read_objid");
			exit(1);
		}

		pdu = snmp_pdu_create(SNMP_MSG_GET);	/* send the first GET */
		snmp_add_null_var(pdu, _host_ss -> _oid, _host_ss -> _oid_len);

		int _status = snmp_sess_synch_response(_host_ss -> _sess, pdu, &response);

		// int print_result (int status, struct snmp_session *sp, struct snmp_pdu *pdu)
		print_result(_status, &_sess, response);

		// analyzing the result;
		// and making it look like correct one (limits and correctness check);
		// if out of range for example we have the following stats update;
		// PT_MUTEX_LOCK(&stats.mutex);
		// stats.out_of_range++;
		// PT_MUTEX_UNLOCK(&stats.mutex);

		snmp_sess_close(_host_ss -> _sess);

		/* Collect response and process stats */
		PT_MUTEX_LOCK(&stats.mutex);
		// when we have a snmp result, updating a starts counters;
		PT_MUTEX_UNLOCK(&stats.mutex);

		// decreasing work counter;


	} // for (;;)

}
Example #2
0
void *poller(void *thread_args)
{
    worker_t *worker = (worker_t *) thread_args;
    crew_t *crew = worker->crew;
    target_t *entry = NULL;
    void *sessp = NULL;
    struct snmp_session session;
    struct snmp_pdu *pdu = NULL;
    struct snmp_pdu *response = NULL;
    oid anOID[MAX_OID_LEN];
    size_t anOID_len = MAX_OID_LEN;
    struct variable_list *vars = NULL;
    unsigned long long result = 0;
    unsigned long long last_value = 0;
    unsigned long long insert_val = 0;
    int status = 0, bits = 0, init = 0;
    char query[BUFSIZE];
    char storedoid[BUFSIZE];
    char result_string[BUFSIZE];

    if (set.verbose >= HIGH)
	printf("Thread [%d] starting.\n", worker->index);
    if (MYSQL_VERSION_ID > 40000)
       mysql_thread_init();
    else 
       my_thread_init();

    while (1) {
	if (set.verbose >= DEVELOP)
	    printf("Thread [%d] locking (wait on work)\n", worker->index);

	PT_MUTEX_LOCK(&crew->mutex);

	while (current == NULL) {
		PT_COND_WAIT(&crew->go, &crew->mutex);
	}
	if (set.verbose >= DEVELOP)
	    printf("Thread [%d] done waiting, received go (work cnt: %d)\n", worker->index, crew->work_count);

	if (current != NULL) {
	    if (set.verbose >= HIGH)
	      printf("Thread [%d] processing %s %s (%d work units remain in queue)\n", worker->index, current->host, current->objoid, crew->work_count);
	    snmp_sess_init(&session);
		if (set.snmp_ver == 2)
	      session.version = SNMP_VERSION_2c;
		else
	      session.version = SNMP_VERSION_1;
	    session.peername = current->host;
		session.remote_port = set.snmp_port;
	    session.community = current->community;
	    session.community_len = strlen(session.community);

	    sessp = snmp_sess_open(&session);
	    anOID_len = MAX_OID_LEN;
	    pdu = snmp_pdu_create(SNMP_MSG_GET);
	    read_objid(current->objoid, anOID, &anOID_len);
	    entry = current;
	    last_value = current->last_value;
	    init = current->init;
	    insert_val = 0;
	    bits = current->bits;
	    strncpy(storedoid, current->objoid, sizeof(storedoid));
		current = getNext();
	}
	if (set.verbose >= DEVELOP)
	    printf("Thread [%d] unlocking (done grabbing current)\n", worker->index);
	PT_MUTEX_UNLOCK(&crew->mutex);
	snmp_add_null_var(pdu, anOID, anOID_len);
	if (sessp != NULL) 
	   status = snmp_sess_synch_response(sessp, pdu, &response);
	else
	   status = STAT_DESCRIP_ERROR;

	/* Collect response and process stats */
	PT_MUTEX_LOCK(&stats.mutex);
	if (status == STAT_DESCRIP_ERROR) {
	    stats.errors++;
            printf("*** SNMP Error: (%s) Bad descriptor.\n", session.peername);
	} else if (status == STAT_TIMEOUT) {
	    stats.no_resp++;
	    printf("*** SNMP No response: (%s@%s).\n", session.peername,
	       storedoid);
	} else if (status != STAT_SUCCESS) {
	    stats.errors++;
	    printf("*** SNMP Error: (%s@%s) Unsuccessuful (%d).\n", session.peername,
	       storedoid, status);
	} else if (status == STAT_SUCCESS && response->errstat != SNMP_ERR_NOERROR) {
	    stats.errors++;
	    printf("*** SNMP Error: (%s@%s) %s\n", session.peername,
	       storedoid, snmp_errstring(response->errstat));
	} else if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) {
	    stats.polls++;
	} 
	PT_MUTEX_UNLOCK(&stats.mutex);

	/* Liftoff, successful poll, process it */
	if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) {
	    vars = response->variables;
#ifdef OLD_UCD_SNMP
            sprint_value(result_string, anOID, anOID_len, vars);
#else
	    snprint_value(result_string, BUFSIZE, anOID, anOID_len, vars);
#endif
	    switch (vars->type) {
		/*
		 * Switch over vars->type and modify/assign result accordingly.
		 */
		case ASN_COUNTER64:
		    if (set.verbose >= DEBUG) printf("64-bit result: (%s@%s) %s\n", session.peername, storedoid, result_string);
		    result = vars->val.counter64->high;
		    result = result << 32;
		    result = result + vars->val.counter64->low;
		    break;
		case ASN_COUNTER:
		    if (set.verbose >= DEBUG) printf("32-bit result: (%s@%s) %s\n", session.peername, storedoid, result_string);
		    result = (unsigned long) *(vars->val.integer);
		    break;
		case ASN_INTEGER:
		    if (set.verbose >= DEBUG) printf("Integer result: (%s@%s) %s\n", session.peername, storedoid, result_string);
		    result = (unsigned long) *(vars->val.integer);
		    break;
		case ASN_GAUGE:
		    if (set.verbose >= DEBUG) printf("32-bit gauge: (%s@%s) %s\n", session.peername, storedoid, result_string);
		    result = (unsigned long) *(vars->val.integer);
		    break;
		case ASN_TIMETICKS:
		    if (set.verbose >= DEBUG) printf("Timeticks result: (%s@%s) %s\n", session.peername, storedoid, result_string);
		    result = (unsigned long) *(vars->val.integer);
		    break;
		case ASN_OPAQUE:
		    if (set.verbose >= DEBUG) printf("Opaque result: (%s@%s) %s\n", session.peername, storedoid, result_string);
		    result = (unsigned long) *(vars->val.integer);
		    break;
		default:
		    if (set.verbose >= DEBUG) printf("Unknown result type: (%s@%s) %s\n", session.peername, storedoid, result_string);
	    }

		/* Gauge Type */
		if (bits == 0) {
			if (result != last_value) {
				insert_val = result;
				if (set.verbose >= HIGH)
					printf("Thread [%d]: Gauge change from %lld to %lld\n", worker->index, last_value, insert_val);
			} else {
				if (set.withzeros) 
					insert_val = result;
				if (set.verbose >= HIGH)
					printf("Thread [%d]: Gauge steady at %lld\n", worker->index, insert_val);
			}
	    /* Counter Wrap Condition */
	    } else if (result < last_value) {
			PT_MUTEX_LOCK(&stats.mutex);
              stats.wraps++;
			PT_MUTEX_UNLOCK(&stats.mutex);
	      if (bits == 32) insert_val = (THIRTYTWO - last_value) + result;
	      else if (bits == 64) insert_val = (SIXTYFOUR - last_value) + result;
	      if (set.verbose >= LOW) {
	         printf("*** Counter Wrap (%s@%s) [poll: %llu][last: %llu][insert: %llu]\n",
	         session.peername, storedoid, result, last_value, insert_val);
	      }
	    /* Not a counter wrap and this is not the first poll */
	    } else if ((last_value >= 0) && (init != NEW)) {
		insert_val = result - last_value;
	        /* Print out SNMP result if verbose */
	        if (set.verbose == DEBUG)
		  printf("Thread [%d]: (%lld-%lld) = %llu\n", worker->index, result, last_value, insert_val);
	        if (set.verbose == HIGH)
		  printf("Thread [%d]: %llu\n", worker->index, insert_val);
            /* last_value < 0, so this must be the first poll */
	    } else {
                if (set.verbose >= HIGH) printf("Thread [%d]: First Poll, Normalizing\n", worker->index);
	    }

		/* Check for bogus data, either negative or unrealistic */
	    if (insert_val > entry->maxspeed || result < 0) {
			if (set.verbose >= LOW) printf("*** Out of Range (%s@%s) [insert_val: %llu] [oor: %lld]\n",
				session.peername, storedoid, insert_val, entry->maxspeed);
			insert_val = 0;
			PT_MUTEX_LOCK(&stats.mutex);
			stats.out_of_range++;
			PT_MUTEX_UNLOCK(&stats.mutex);
	    }

		if (!(set.dboff)) {
			if ( (insert_val > 0) || (set.withzeros) ) {
				PT_MUTEX_LOCK(&crew->mutex);
				snprintf(query, sizeof(query), "INSERT INTO %s VALUES (%d, NOW(), %llu)",
					entry->table, entry->iid, insert_val);
				if (set.verbose >= DEBUG) printf("SQL: %s\n", query);
				status = mysql_query(&mysql, query);
				if (status) printf("*** MySQL Error: %s\n", mysql_error(&mysql));
				PT_MUTEX_UNLOCK(&crew->mutex);

				if (!status) {
					PT_MUTEX_LOCK(&stats.mutex);
					stats.db_inserts++;
					PT_MUTEX_UNLOCK(&stats.mutex);
				} 
			} /* insert_val > 0 or withzeros */	
		} /* !dboff */

	} /* STAT_SUCCESS */

        if (sessp != NULL) {
           snmp_sess_close(sessp);
           if (response != NULL) snmp_free_pdu(response);
        }

	if (set.verbose >= DEVELOP)
	    printf("Thread [%d] locking (update work_count)\n", worker->index);
	PT_MUTEX_LOCK(&crew->mutex);
	crew->work_count--;
	/* Only if we received a positive result back do we update the
	   last_value object */
	if (status == STAT_SUCCESS) entry->last_value = result;
	if (init == NEW) entry->init = LIVE;
	if (crew->work_count <= 0) {
	    if (set.verbose >= HIGH) printf("Queue processed. Broadcasting thread done condition.\n");
		PT_COND_BROAD(&crew->done);
	}
	if (set.verbose >= DEVELOP)
	    printf("Thread [%d] unlocking (update work_count)\n", worker->index);

		PT_MUTEX_UNLOCK(&crew->mutex);
    }				/* while(1) */
}
Example #3
0
/* Main rated */
int main(int argc, char *argv[]) {
    crew_t crew;
    pthread_t sig_thread;
    sigset_t signal_set;
    struct timeval begin_time, end_time;
    unsigned long sleep_time;
    unsigned long poll_time;
    unsigned long long polls;
    unsigned long long last_poll;
    double rate;
    char *conf_file = NULL;
    char *table;
    char errstr[BUFSIZE];
    int ch, i, freed;
    struct timespec ts;

    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:p:dhmDt:vz")) != EOF)
	switch ((char) ch) {
	case 'c':
	    conf_file = optarg;
	    break;
	case 'd':
	    set->dbon = FALSE;
	    break;
	case 'D':
	    set->daemon = FALSE;
	    break;
	case 'h':
	    usage(argv[0]);
	    break;
	case 'm':
	    set->multiple++;
	    break;
	case 'p':
	    pid_file = optarg;
	    break;
	case 't':
	    target_file = optarg;
	    break;
	case 'v':
	    set->verbose++;
	    break;
	case 'z':
	    set->withzeros = TRUE;
	    break;
	}

    debug(LOW, "rated version %s starting.\n", VERSION);

    if (set->daemon) {
        if (daemon_init() < 0)
            fatal("Could not fork daemon!\n");
        debug(LOW, "Daemon detached\n");
    }

    pthread_mutex_init(&stats.mutex, NULL);

    /* 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(pid_file, set);

    if (pthread_sigmask(SIG_BLOCK, &signal_set, NULL) != 0)
        fatal("pthread_sigmask error\n");

    /* start a thread to catch signals */
    if (pthread_create(&sig_thread, NULL, sig_handler, (void *) &(signal_set)) != 0)
	fatal("pthread_create error\n");

    /* Read configuration file to establish local environment */
    if (conf_file) {
        if ((read_rated_config(conf_file, set)) < 0) 
            fatal("Could not read config file: %s\n", conf_file);
    } else {
        conf_file = malloc(BUFSIZE);
        if (!conf_file) 
            fatal("Fatal malloc error!\n");
        for(i=0;i<CONFIG_PATHS;i++) {
            snprintf(conf_file, BUFSIZE, "%s%s", config_paths[i], DEFAULT_CONF_FILE); 
            if (read_rated_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_rated_config(conf_file, set)) < 0) 
                    fatal("Couldn't write config file.\n");
            }
        }
    }

    /* these probably aren't thread safe*/
    init_snmp("rated");
    /* TODO only do this if we're debugging or not daemonised? */
    snmp_enable_stderrlog();
    /* output oids numerically - this is equivalent to -On in the snmp tools */
    netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, NETSNMP_OID_OUTPUT_NUMERIC);

    if (set->dbon) {
        /* load the database driver */
        /* we need a db connection before we parse the targets file so we can check and create tables */
        if (!(db_init(set) && db_connect(set)))
            fatal("** Database error - check configuration.\n");

        /* create our own internal tables */
        table = db_check_and_create_data_table(RATED);
        if (table == NULL)
            fatal("** Database error - couldn't create rated table.\n");
        else
            free(table);
        if (!db_check_and_create_oids_table(OIDS))
            fatal("** Database error - couldn't create oids table.\n");
    }

    /* build list of hosts to be polled */
    head = hash_target_file(target_file);
    if (head == NULL)
        fatal("Error updating target list.");

    if (hosts < set->threads) {
        debug(LOW, "Number of hosts is less than configured number of threads, defaulting to %i.\n", hosts);
        set->threads = hosts;
    }

    debug(LOW, "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.current = NULL;

    debug(HIGH, "Starting threads...");
    crew.running = set->threads;
    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)
	    fatal("pthread_create error\n");
	debug(HIGH, " %i", i);
	}
    debug(HIGH, " done\n");

    /* spin waiting for all threads to start up */
    debug(HIGH, "Waiting for thread startup.\n");
    ts.tv_sec = 0;
    ts.tv_nsec = 10000000; /* 10 ms */
    gettimeofday(&begin_time, NULL);
    while (crew.running > 0 ) {
	nanosleep(&ts, NULL);
    }
    gettimeofday(&end_time, NULL);
    debug(HIGH, "Waited %lu milliseconds for thread startup.\n", timediff(end_time, begin_time));

    debug(LOW, "rated ready.\n");

    /* Loop Forever Polling Target List */
    while (1) {
	/* check if we've been signalled */
	if (quitting) {
            debug(LOW, "Quitting: received signal %i.\n", quit_signal);
            if (set->dbon)
                db_disconnect();
            /* one final stat output */
            print_stats(stats, set);
            unlink(pid_file);
            exit(1);
	} else if (waiting) {
            debug(HIGH, "Processing pending SIGHUP.\n");
            /* this just rebuilds the target list
             * so all of the targets will reset to a first poll */
            /* none of the threads should be running at this point so we shouldn't need a lock */
            freed = free_host_list(head);
            debug(HIGH, "Freed %i hosts\n", freed);
            head = hash_target_file(target_file);
            waiting = FALSE;
	}

        last_poll = stats.polls;

	gettimeofday(&begin_time, NULL);

	PT_MUTEX_LOCK(&(crew.mutex));
        crew.current = head;

	debug(LOW, "Queue ready, broadcasting thread go condition.\n");

	PT_COND_BROAD(&(crew.go));
	PT_MUTEX_UNLOCK(&(crew.mutex));

        /*
         * wait for signals from threads finishing
         * we have to use a do loop because when this starts up the running count will be zero
         * so wait at least once until we get a signal that some thread is done before checking for zero
         */
	PT_MUTEX_LOCK(&(crew.mutex));
        do {
            PT_COND_WAIT(&(crew.done), &(crew.mutex));
        } while (crew.running > 0);
	PT_MUTEX_UNLOCK(&(crew.mutex));

        if (quitting_now)
            continue;

	gettimeofday(&end_time, NULL);
	poll_time = timediff(end_time, begin_time);
        polls = stats.polls - last_poll;
        rate = ((double) polls / poll_time) * 1000;
        /* don't underflow */
        if (poll_time < set->interval) {
	    sleep_time = set->interval - poll_time;
        } else {
            sleep_time = 0;
            stats.slow++;
        }

        /* have to call this before we increment the round counter */
        calc_stats(&stats, poll_time);

        stats.round++;
	debug(LOW, "Poll round %d completed %llu getnexts in %lu ms (%.0f/s).\n", stats.round, polls, poll_time, rate);
        /* insert the internal poll data for this round into the rated table */
        if (set->dbon)
            db_insert(RATED, 0, end_time, stats.polls - last_poll, rate);

	if (set->verbose >= LOW) {
            print_stats(stats, set);
        }

        if (sleep_time > 0) {
            sleepy(sleep_time, set);
        } else {
            debug(LOW, "Slow poll, not sleeping\n");
        }
    } /* while(1) */
    exit(0);
}
Example #4
0
/* 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:p:dhmDt:vz")) != EOF)
	switch ((char) ch) {
	case 'c':
	    conf_file = optarg;
	    break;
	case 'd':
	    set->dboff = TRUE;
	    break;
	case 'D':
	    set->daemon = FALSE;
	    break;
	case 'h':
	    usage(argv[0]);
	    break;
	case 'm':
	    set->multiple++;
	    break;
	case 'p':
	    pid_file = optarg;
	    break;
	case 't':
	    target_file = optarg;
	    break;
	case 'v':
	    set->verbose++;
	    break;
	case 'z':
	    set->withzeros = TRUE;
	    break;
	}

	debug(LOW, "RTG version %s starting.\n", VERSION);

	if (set->daemon) {
		if (daemon_init() < 0)
			fatal("Could not fork daemon!\n");
		debug(LOW, "Daemon detached\n");
	}


    /* 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(pid_file, set);

    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) 
		fatal("Could not read config file: %s\n", conf_file);
    } else {
      conf_file = malloc(BUFSIZE);
      if (!conf_file) 
         fatal("Fatal malloc error!\n");
      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) 
				fatal("Couldn't write config file.\n");
        }
      }
    }


    /* hash list of targets to be polled */
    init_hash();
	entries = hash_target_file(target_file);
    if (entries <= 0) 
		fatal("Error updating target list.");

	debug(LOW, "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 */
	debug(LOW, "Initializing SNMP (port %d).\n", set->snmp_port);
    init_snmp("RTG");

    /* Attempt to connect to the MySQL Database */
#ifndef FEATURES
 #if HAVE_MYSQL
    if (!(set->dboff)) {
		if (mysql_dbconnect(set->dbdb, &mysql) < 0) 
			fatal("** Database error - check configuration.\n");
		if (!mysql_ping(&mysql))
			debug(LOW, "connected.\n");
		else
			fatal("server not responding.\n");
    }
 #endif
#else
 #if HAVE_MYSQL
	my_init();
 #endif
#endif


	debug(HIGH, "\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);

	debug(LOW, "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) {
		if (set->daemon)
			sysloginfo("Queue ready, broadcasting thread go condition.");
		else
        	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) {
		debug(HIGH, "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);
		if (set->daemon)
			sysloginfo(errstr);
		else
			timestamp(errstr);
	    print_stats(stats, set);
    }

	if (sleep_time <= 0)
	    stats.slow++;
	else
	    sleepy(sleep_time, set);
    } /* while */

#ifndef FEATURES
  #if HAVE_MYSQL
    /* Disconnect from the MySQL Database, exit. */
    if (!(set->dboff))
	mysql_dbdisconnect(&mysql);
  #endif
#endif
    exit(0);
}
Example #5
0
void *poller(void *thread_args)
{
    worker_t *worker = (worker_t *) thread_args;
    crew_t *crew = worker->crew;
    target_t *entry = NULL;
    void *sessp = NULL;
    struct snmp_session session;
    struct snmp_pdu *pdu = NULL;
    struct snmp_pdu *response = NULL;
    oid anOID[MAX_OID_LEN];
    size_t anOID_len = MAX_OID_LEN;
    struct variable_list *vars = NULL;
    unsigned long long result = 0;
    unsigned long long last_value = 0;
    unsigned long long insert_val = 0;
    int poll_status = 0, db_status = 0, bits = 0, init = 0;
    char query[BUFSIZE];
    char storedoid[BUFSIZE];
    char result_string[BUFSIZE];
    int cur_work = 0;
    int prev_work = 99999999;
    int loop_count = 0;


#ifdef FEATURES
	/* Per thread SQL connection testing */
  #if HAVE_MYSQL
	MYSQL mysql;
  #elif HAVE_PGSQL
	PGconn *pgsql;
  #endif
	double rate = 0;
	struct timezone tzp;
	struct timeval current_time;
	struct timeval last_time;

	/* for thread settings */
	int oldstate, oldtype;
#endif

	debug(HIGH, "Thread [%d] starting.\n", worker->index);

    pthread_cleanup_push(cleanup_db, NULL);



    /* Attempt to connect to the MySQL Database */
#ifdef FEATURES
	/* Per thread MySQL connection testing */
    if (!(set->dboff)) {
	/* load the database driver */
	if (!(db_init(set))) {
		fatal("** Database error - check configuration.\n");
	}
	/* connect to the database */
	if (!(db_connect(set))) {
		fatal("server not responding.\n");
	}
		/* set up cancel function for exit */
		pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
		pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
    }
#endif /* FEATURES */

    while (1) {

/*        if(loop_count >= POLLS_PER_TRANSACTION) {
            debug(HIGH, "Thread [%d] doing commit on %d\n", worker->index, POLLS_PER_TRANSACTION);
            db_status = db_commit(); 
            loop_count = 0;
        }
*/

#ifdef FEATURES
	/* see if we've been cancelled before we start another loop */
	pthread_testcancel();
#endif
	debug(DEVELOP, "Thread [%d] locking (wait on work)\n", worker->index);

	PT_MUTEX_LOCK(&crew->mutex);
#ifdef FEATURES
	/* add an unlock to the cancel stack */
	pthread_cleanup_push(cancel_lock, &crew->mutex);	
#endif

	while (current == NULL) {
		PT_COND_WAIT(&crew->go, &crew->mutex);
	}
	debug(DEVELOP, "Thread [%d] done waiting, received go (work cnt: %d)\n",
		worker->index, crew->work_count);
        cur_work = crew->work_count;
/*         if(cur_work > prev_work) {
            debug(HIGH, "Thread [%d] doing commit at %d\n", worker->index,time(NULL));
            db_status = db_commit(); 
            loop_count = 0;
        }
*/
        prev_work = cur_work;

	if (current != NULL) {
		debug(DEVELOP, "Thread [%d] processing %s %s (%d work units remain in queue)\n",
			worker->index, current->host->host, current->objoid, crew->work_count);
	    snmp_enable_stderrlog(); 
            snmp_sess_init(&session);
		if (current->host->snmp_ver == 2)
			session.version = SNMP_VERSION_2c;
		else
			session.version = SNMP_VERSION_1;
	    session.peername = current->host->host;
	    session.community = current->host->community;
		session.remote_port = set->snmp_port;
	    session.community_len = strlen(session.community);

	    sessp = snmp_sess_open(&session);
	    anOID_len = MAX_OID_LEN;
	    pdu = snmp_pdu_create(SNMP_MSG_GET);
	    read_objid(current->objoid, anOID, &anOID_len);
	    entry = current;
	    last_value = current->last_value;
#ifdef FEATURES
		/* save the time so we can calculate rate */
		last_time = current->last_time;
#endif
	    init = current->init;
	    insert_val = 0;
	    bits = current->bits;
	    strncpy(storedoid, current->objoid, sizeof(storedoid));
		current = getNext();
	}
	debug(DEVELOP, "Thread [%d] unlocking (done grabbing current)\n", worker->index);
	PT_MUTEX_UNLOCK(&crew->mutex);
#ifdef FEATURES
	/* take the unlock off the cancel stack */
	pthread_cleanup_pop(FALSE);
#endif

	snmp_add_null_var(pdu, anOID, anOID_len);
	if (sessp != NULL) 
	   poll_status = snmp_sess_synch_response(sessp, pdu, &response);
	else
	   poll_status = STAT_DESCRIP_ERROR;

	/* Collect response and process stats */
	PT_MUTEX_LOCK(&stats.mutex);
	if (poll_status == STAT_DESCRIP_ERROR) {
	    stats.errors++;
            printf("*** SNMP Error: (%s) Bad descriptor.\n", session.peername);
	} else if (poll_status == STAT_TIMEOUT) {
	    stats.no_resp++;
	    printf("*** SNMP No response: (%s@%s).\n", session.peername,
	       storedoid);
	} else if (poll_status != STAT_SUCCESS) {
	    stats.errors++;
	    printf("*** SNMP Error: (%s@%s) Unsuccessuful (%d).\n", session.peername,
	       storedoid, poll_status);
	} else if (poll_status == STAT_SUCCESS && response->errstat != SNMP_ERR_NOERROR) {
	    stats.errors++;
	    printf("*** SNMP Error: (%s@%s) %s\n", session.peername,
	       storedoid, snmp_errstring(response->errstat));
	} else if (poll_status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR && response->variables->type == SNMP_NOSUCHINSTANCE) {
	    stats.errors++;
	    printf("*** SNMP Error: No Such Instance Exists (%s@%s)\n", session.peername, storedoid);
	} else if (poll_status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) {
	    stats.polls++;
	} 
	PT_MUTEX_UNLOCK(&stats.mutex);

	/* Liftoff, successful poll, process it */
#ifdef FEATURES
	/* Get the current time */
	gettimeofday(&current_time, &tzp);
#endif

	if (poll_status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR && response->variables->type != SNMP_NOSUCHINSTANCE) {
	    vars = response->variables;
#ifdef OLD_UCD_SNMP
            sprint_value(result_string, anOID, anOID_len, vars);
#else
	    snprint_value(result_string, BUFSIZE, anOID, anOID_len, vars);
#endif
	    switch (vars->type) {
		/*
		 * Switch over vars->type and modify/assign result accordingly.
		 */
		case ASN_COUNTER64:
		    debug(DEBUG, "64-bit result: (%s@%s) %s\n", session.peername, storedoid, result_string);
		    result = vars->val.counter64->high;
		    result = result << 32;
		    result = result + vars->val.counter64->low;
		    break;
		case ASN_COUNTER:
		    debug(DEBUG, "32-bit result: (%s@%s) %s\n", session.peername, storedoid, result_string);
		    result = (unsigned long) *(vars->val.integer);
		    break;
		case ASN_INTEGER:
		    debug(DEBUG, "Integer result: (%s@%s) %s\n", session.peername, storedoid, result_string);
		    result = (unsigned long) *(vars->val.integer);
		    break;
		case ASN_GAUGE:
		    debug(DEBUG, "32-bit gauge: (%s@%s) %s\n", session.peername, storedoid, result_string);
		    result = (unsigned long) *(vars->val.integer);
		    break;
		case ASN_TIMETICKS:
		    debug(DEBUG, "Timeticks result: (%s@%s) %s\n", session.peername, storedoid, result_string);
		    result = (unsigned long) *(vars->val.integer);
		    break;
		case ASN_OPAQUE:
		    debug(DEBUG, "Opaque result: (%s@%s) %s\n", session.peername, storedoid, result_string);
		    result = (unsigned long) *(vars->val.integer);
		    break;
		case ASN_OCTET_STR:
		    debug(DEBUG, "String Result: (%s@%s) %s\n", session.peername, storedoid, result_string);
#ifdef HAVE_STRTOLL
		    result = strtoll(vars->val.string, NULL, 0);
#else
		    result = strtol(vars->val.string, NULL, 0);
#endif
		    break;
		default:
		    debug(LOW, "Unknown result type: (%s@%s) %s\n", session.peername, storedoid, result_string);
	    }

		/* Gauge Type */
		if (bits == 0) {
			if (result != last_value) {
				insert_val = result;
				debug(DEVELOP, "Thread [%d]: Gauge change from %lld to %lld\n", worker->index, last_value, insert_val);
			} else {
				if (set->withzeros) 
					insert_val = result;
				debug(DEVELOP, "Thread [%d]: Gauge steady at %lld\n", worker->index, insert_val);
			}
	    /* Counter Wrap Condition */
	    } else if (result < last_value) {
			PT_MUTEX_LOCK(&stats.mutex);
              stats.wraps++;
			PT_MUTEX_UNLOCK(&stats.mutex);
	      if (bits == 32) insert_val = (THIRTYTWO - last_value) + result;
	      else if (bits == 64) insert_val = (SIXTYFOUR - last_value) + result;

#ifdef FEATURES
			rate = insert_val / timediff(current_time, last_time);
#endif

	      debug(LOW, "*** Counter Wrap (%s@%s) [poll: %llu][last: %llu][insert: %llu]\n",
	         session.peername, storedoid, result, last_value, insert_val);
	    /* Not a counter wrap and this is not the first poll */
	    } else if ((last_value >= 0) && (init != NEW)) {
		insert_val = result - last_value;

#ifdef FEATURES
			rate = insert_val / timediff(current_time, last_time);
#endif
		
	        /* Print out SNMP result if verbose */
	        if (set->verbose == DEBUG)
		  printf("Thread [%d]: (%lld-%lld -- %llu) = %llu\n", worker->index, result, last_value, insert_val,rate);
	        if (set->verbose == HIGH)
		  printf("Thread [%d]: %llu\n", worker->index, insert_val);
            /* last_value < 0, so this must be the first poll */
	    } else {
#ifdef FEATURES
			/* set up this result for the next poll */
			entry->last_value = result;
#endif
			debug(HIGH, "Thread [%d]: First Poll, Normalizing\n", worker->index);
	    }

		/* Check for bogus data, either negative or unrealistic */
	    if (insert_val > entry->maxspeed || result < 0) {
			debug(LOW, "*** Out of Range (%s@%s) [insert_val: %llu] [oor: %lld]\n",
				session.peername, storedoid, insert_val, entry->maxspeed);
			insert_val = 0;
#ifdef FEATURES
			rate = 0;
#endif
			PT_MUTEX_LOCK(&stats.mutex);
			stats.out_of_range++;
			PT_MUTEX_UNLOCK(&stats.mutex);
	    }

		if (!(set->dboff)) {
			if ( (insert_val > 0) || (set->withzeros) ) {
#ifndef FEATURES
				/* MP - since we have our own database connection we don't need to lock it anymore */
				PT_MUTEX_LOCK(&crew->mutex);
#endif

                                debug(DEVELOP, "db_insert sent: %s %d %d %e\n",entry->table,entry->iid,insert_val,rate);
				/* insert into the database */
				db_status = db_insert(entry->table, entry->iid, insert_val, rate);

#ifndef FEATURES
				/* MP - since we have our own database connection we don't need to lock it anymore */
				PT_MUTEX_UNLOCK(&crew->mutex);
#endif

				if (db_status) {
					PT_MUTEX_LOCK(&stats.mutex);
					stats.db_inserts++;
					PT_MUTEX_UNLOCK(&stats.mutex);
				} else {
					fatal("Fatal database error.\n");
				}
			} /* insert_val > 0 or withzeros */	
		} /* !dboff */

	} /* STAT_SUCCESS */

/*	debug(HIGH, "Thread [%d] doing commit\n", worker->index);
        db_status = db_commit(); */

        if (sessp != NULL) {
           snmp_sess_close(sessp);
           if (response != NULL) snmp_free_pdu(response);
        }

	debug(DEVELOP, "Thread [%d] locking (update work_count)\n", worker->index);
	PT_MUTEX_LOCK(&crew->mutex);
	crew->work_count--;
	/* Only if we received a positive result back do we update the
	   last_value object */
	if (poll_status == STAT_SUCCESS) {
		entry->last_value = result;
		if (init == NEW) entry->init = LIVE;
	}

#ifdef FEATURES
	/* always update the time */
	entry->last_time = current_time;	
#endif

	if (crew->work_count <= 0) {
	    debug(HIGH, "Queue processed. Broadcasting thread done condition.\n");
		PT_COND_BROAD(&crew->done);
	}
	debug(DEVELOP, "Thread [%d] unlocking (update work_count)\n", worker->index);

		PT_MUTEX_UNLOCK(&crew->mutex);

        loop_count++;
    }				/* while(1) */
    pthread_cleanup_pop(FALSE);

/* Not reached */
}
Example #6
0
void cancel_lock(void *arg)
{
    /* to be called from the cleanup handler */
    PT_MUTEX_UNLOCK(arg);
}