1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
/*
* timer.cc: This file contains all the code for the timer thread,
* which simply updates the timestamp when needed.
*/
#include "trafstats.h"
extern pthread_cond_t timer_gonogo;
extern pthread_mutex_t timelock;
extern pthread_mutex_t timergonogolock;
extern int verbosity;
extern bool run;
extern char* timestamp;
extern PgDatabase *dbconn;
void timerSigHandler(int sig) {
if(verbosity >= LOG_DEBUG) {
syslog(LOG_DEBUG,"[timer] Received signal %d",
sig);
}
switch(sig) {
case SIGUSR1: // Ended from main thread.
// FALLTHRU
case SIGINT: // ^C pressed or ended from the main thread
// FALLTHRU
case SIGTERM: // Killed from the command prompt.
if(verbosity >= LOG_DEBUG) {
syslog(LOG_DEBUG,"[timer] Received signal %d, exiting.",
sig);
}
break;
default:
if(verbosity >= LOG_WARNING) {
syslog(LOG_WARNING,"[timer] Received unaccounted for signal %d",sig);
}
break;
}
}
void *timerThread(void *d) {
timer_options *topts=(struct timer_options *)d;
if(verbosity>=LOG_DEBUG) {
syslog(LOG_DEBUG,"[timer] New timestamp every %d seconds, calling database using <%s>",
topts->interval,
topts->db_connstr);
}
// First try to connect to the database.
//
// pthread_mutex_lock(&timergonogolock);
if(verbosity>=LOG_DEBUG) {
syslog(LOG_DEBUG,"[timer] Contacting database.");
}
PgDatabase* dbconn = new PgDatabase(topts->db_connstr);
if(dbconn->ConnectionBad()) { // Failed connect.
if(verbosity>=LOG_CRIT) {
syslog(LOG_CRIT,"[timer]: Failed second connecion to database: %s",
dbconn->ErrorMessage());
if(verbosity>=LOG_DEBUG) {
syslog(LOG_DEBUG,"[timer] Connection string was: <%s>",topts->db_connstr);
}
}
run=0;
pthread_cond_broadcast(&timer_gonogo);
// pthread_mutex_unlock(&timergonogolock);
pthread_exit(NULL);
} // Okay, it worked.
char *query;
if((topts->interval % 3600) == 0) {
query="SELECT DATE_TRUNC('hour',now())";
} else {
query="SELECT DATE_TRUNC('minute',now())";
}
if(verbosity>=LOG_DEBUG) {
syslog(LOG_DEBUG,"[timer] Using query <%s>.",query);
}
timestamp=(char *) malloc(TS_TIMESTAMP_SIZE);
int ok=dbconn->ExecCommandOk(query);
if(verbosity>=LOG_DEBUG) {
syslog(LOG_DEBUG,"[timer] Postgres result: %d", ok);
syslog(LOG_DEBUG,"[timer] Postgres error: %s", dbconn->ErrorMessage());
}
/* Don't ask me why, but the above returns false even though the
* query worked fine.
if(!ok) {
if(verbosity >= LOG_ERR) {
syslog(LOG_ERR,"[timer] Failed to get timestamp: %s",
dbconn->ErrorMessage());
}
}
*/
snprintf(timestamp,TS_TIMESTAMP_SIZE,"%s",(char*)(dbconn->GetValue(0,0)));
if(verbosity >= LOG_INFO) {
syslog(LOG_INFO,"[timer] Initial timestamp: %s",timestamp);
if(verbosity>=LOG_DEBUG) {
syslog(LOG_DEBUG,"[timer] Timer is GO.");
}
}
pthread_cond_broadcast(&timer_gonogo);
// pthread_mutex_unlock(&timergonogolock);
if(verbosity >= LOG_DEBUG) {
syslog(LOG_DEBUG,"[timer] Activating signal handlers.");
}
signal(SIGINT,timerSigHandler);
signal(SIGUSR1,timerSigHandler);
signal(SIGTERM,timerSigHandler);
if(verbosity>=LOG_DEBUG) {
syslog(LOG_DEBUG,"[timer] Starting loop.");
}
while (run) {
int slept=sleep(topts->interval);
if(slept > 0) { // Awakened by a signal
if (!run) {
if(verbosity >= LOG_DEBUG) {
syslog(LOG_DEBUG,"[timer] Exiting.");
}
break;
}
}
pthread_mutex_lock(&timelock);
dbconn->ExecCommandOk(query);
snprintf(timestamp,TS_TIMESTAMP_SIZE,"%s",(char*)(dbconn->GetValue(0,0)));
if(verbosity>=LOG_INFO) {
syslog(LOG_INFO, "[timer] New timestamp: <%s>",
timestamp);
}
pthread_mutex_unlock(&timelock);
}
if(verbosity >= LOG_INFO) {
syslog(LOG_INFO,"[timer] Shutting down gracefully.");
}
pthread_exit(NULL);
}
|