Keep track of time using fractions of seconds.

This commit is contained in:
Gunnar Beutner 2012-07-25 12:59:17 +02:00
parent 1af31791ea
commit 1eb25ad4e9
23 changed files with 136 additions and 115 deletions

View File

@ -82,12 +82,12 @@ void Application::RunEventLoop(void)
while (!m_ShuttingDown) { while (!m_ShuttingDown) {
Object::ClearHeldObjects(); Object::ClearHeldObjects();
long sleep = Timer::ProcessTimers(); double sleep = Timer::ProcessTimers();
if (m_ShuttingDown) if (m_ShuttingDown)
break; break;
Event::ProcessEvents(boost::get_system_time() + boost::posix_time::seconds(sleep)); Event::ProcessEvents(boost::get_system_time() + boost::posix_time::milliseconds(sleep * 1000));
} }
Component::UnloadAll(); Component::UnloadAll();

View File

@ -96,14 +96,14 @@ string ConfigObject::GetSource(void) const
return value; return value;
} }
void ConfigObject::SetCommitTimestamp(time_t ts) void ConfigObject::SetCommitTimestamp(double ts)
{ {
GetProperties()->Set("__tx", static_cast<long>(ts)); GetProperties()->Set("__tx", ts);
} }
time_t ConfigObject::GetCommitTimestamp(void) const double ConfigObject::GetCommitTimestamp(void) const
{ {
long value = 0; double value = 0;
GetProperties()->Get("__tx", &value); GetProperties()->Get("__tx", &value);
return value; return value;
} }
@ -117,9 +117,7 @@ void ConfigObject::Commit(void)
assert(!dobj || dobj == self); assert(!dobj || dobj == self);
m_Container->CheckObject(self); m_Container->CheckObject(self);
time_t now; SetCommitTimestamp(Utility::GetTime());
time(&now);
SetCommitTimestamp(now);
} }
void ConfigObject::Unregister(void) void ConfigObject::Unregister(void)

View File

@ -78,7 +78,7 @@ public:
void SetSource(const string& value); void SetSource(const string& value);
string GetSource(void) const; string GetSource(void) const;
time_t GetCommitTimestamp(void) const; double GetCommitTimestamp(void) const;
void Commit(void); void Commit(void);
void Unregister(void); void Unregister(void);
@ -104,7 +104,7 @@ private:
static map<pair<string, string>, Dictionary::Ptr> m_PersistentTags; static map<pair<string, string>, Dictionary::Ptr> m_PersistentTags;
void SetCommitTimestamp(time_t ts); void SetCommitTimestamp(double ts);
static bool TypeAndNameGetter(const ConfigObject::Ptr& object, pair<string, string> *key); static bool TypeAndNameGetter(const ConfigObject::Ptr& object, pair<string, string> *key);
static bool TypePredicate(const ConfigObject::Ptr& object, string type); static bool TypePredicate(const ConfigObject::Ptr& object, string type);

View File

@ -44,7 +44,7 @@ void Logger::Write(LogSeverity severity, const string& facility,
const string& message) const string& message)
{ {
LogEntry entry; LogEntry entry;
time(&entry.Timestamp); entry.Timestamp = Utility::GetTime();
entry.Severity = severity; entry.Severity = severity;
entry.Facility = facility; entry.Facility = facility;
entry.Message = message; entry.Message = message;

View File

@ -42,7 +42,7 @@ enum LogSeverity
* @ingroup base * @ingroup base
*/ */
struct LogEntry { struct LogEntry {
time_t Timestamp; double Timestamp;
LogSeverity Severity; LogSeverity Severity;
string Facility; string Facility;
string Message; string Message;

View File

@ -130,7 +130,7 @@ void Process::WorkerThreadProc(void)
void Process::InitTask(void) void Process::InitTask(void)
{ {
time(&m_Result.ExecutionStart); m_Result.ExecutionStart = Utility::GetTime();
#ifdef _MSC_VER #ifdef _MSC_VER
m_FP = _popen(m_Command.c_str(), "r"); m_FP = _popen(m_Command.c_str(), "r");
@ -178,7 +178,7 @@ bool Process::RunTask(void)
} }
#endif /* _MSC_VER */ #endif /* _MSC_VER */
time(&m_Result.ExecutionEnd); m_Result.ExecutionEnd = Utility::GetTime();
#ifndef _MSC_VER #ifndef _MSC_VER
if (WIFEXITED(status)) { if (WIFEXITED(status)) {

View File

@ -25,8 +25,8 @@ namespace icinga
struct ProcessResult struct ProcessResult
{ {
time_t ExecutionStart; double ExecutionStart;
time_t ExecutionEnd; double ExecutionEnd;
long ExitStatus; long ExitStatus;
string Output; string Output;
}; };

View File

@ -57,7 +57,8 @@ void StreamLogger::ProcessLogEntry(const LogEntry& entry)
{ {
char timestamp[100]; char timestamp[100];
tm tmnow = *localtime(&entry.Timestamp); time_t ts = entry.Timestamp;
tm tmnow = *localtime(&ts);
strftime(timestamp, sizeof(timestamp), "%Y/%m/%d %H:%M:%S", &tmnow); strftime(timestamp, sizeof(timestamp), "%Y/%m/%d %H:%M:%S", &tmnow);

View File

@ -36,12 +36,11 @@ Timer::Timer(void)
* *
* @returns Time when the next timer is due. * @returns Time when the next timer is due.
*/ */
long Timer::ProcessTimers(void) double Timer::ProcessTimers(void)
{ {
long wakeup = 30; double wakeup = 30;
time_t st; double st = Utility::GetTime();
time(&st);
Timer::CollectionType::iterator prev, i; Timer::CollectionType::iterator prev, i;
for (i = m_Timers.begin(); i != m_Timers.end(); ) { for (i = m_Timers.begin(); i != m_Timers.end(); ) {
@ -55,15 +54,14 @@ long Timer::ProcessTimers(void)
continue; continue;
} }
time_t now; double now = Utility::GetTime();
time(&now);
if (timer->m_Next <= now) { if (timer->m_Next <= now) {
timer->Call(); timer->Call();
/* time may have changed depending on how long the /* time may have changed depending on how long the
* timer call took - we need to fetch the current time */ * timer call took - we need to fetch the current time */
time(&now); now = Utility::GetTime();
timer->Reschedule(now + timer->GetInterval()); timer->Reschedule(now + timer->GetInterval());
} }
@ -76,8 +74,7 @@ long Timer::ProcessTimers(void)
assert(wakeup > 0); assert(wakeup > 0);
time_t et; double et = Utility::GetTime();
time(&et);
stringstream msgbuf; stringstream msgbuf;
msgbuf << "Timers took " << et - st << " seconds"; msgbuf << "Timers took " << et - st << " seconds";
@ -93,13 +90,11 @@ long Timer::ProcessTimers(void)
*/ */
void Timer::Call(void) void Timer::Call(void)
{ {
time_t st; double st = Utility::GetTime();
time(&st);
OnTimerExpired(GetSelf()); OnTimerExpired(GetSelf());
time_t et; double et = Utility::GetTime();
time(&et);
if (et - st > 3) { if (et - st > 3) {
stringstream msgbuf; stringstream msgbuf;
@ -113,7 +108,7 @@ void Timer::Call(void)
* *
* @param interval The new interval. * @param interval The new interval.
*/ */
void Timer::SetInterval(unsigned long interval) void Timer::SetInterval(double interval)
{ {
m_Interval = interval; m_Interval = interval;
} }
@ -123,7 +118,7 @@ void Timer::SetInterval(unsigned long interval)
* *
* @returns The interval. * @returns The interval.
*/ */
unsigned long Timer::GetInterval(void) const double Timer::GetInterval(void) const
{ {
return m_Interval; return m_Interval;
} }
@ -139,7 +134,7 @@ void Timer::Start(void)
m_Timers.push_back(GetSelf()); m_Timers.push_back(GetSelf());
Reschedule(time(NULL) + m_Interval); Reschedule(Utility::GetTime() + m_Interval);
} }
/** /**
@ -157,7 +152,7 @@ void Timer::Stop(void)
* *
* @param next The time when this timer should be called again. * @param next The time when this timer should be called again.
*/ */
void Timer::Reschedule(time_t next) void Timer::Reschedule(double next)
{ {
m_Next = next; m_Next = next;
} }

View File

@ -39,21 +39,21 @@ public:
Timer(void); Timer(void);
void SetInterval(unsigned long interval); void SetInterval(double interval);
unsigned long GetInterval(void) const; double GetInterval(void) const;
static long ProcessTimers(void); static double ProcessTimers(void);
void Start(void); void Start(void);
void Stop(void); void Stop(void);
void Reschedule(time_t next); void Reschedule(double next);
boost::signal<void(const Timer::Ptr&)> OnTimerExpired; boost::signal<void(const Timer::Ptr&)> OnTimerExpired;
private: private:
unsigned long m_Interval; /**< The interval of the timer. */ double m_Interval; /**< The interval of the timer. */
time_t m_Next; /**< When the next event should happen. */ double m_Next; /**< When the next event should happen. */
static Timer::CollectionType m_Timers; static Timer::CollectionType m_Timers;

View File

@ -255,3 +255,18 @@ void Utility::NullDeleter(void *obj)
{ {
/* Nothing to do here. */ /* Nothing to do here. */
} }
/**
* Returns the current UNIX timestamp including fractions of seconds.
*
* @returns The current time.
*/
double Utility::GetTime(void)
{
struct timeval tv;
if (gettimeofday(&tv, NULL) < 0)
throw PosixException("gettimeofday() failed", errno);
return tv.tv_sec + tv.tv_usec / 1000000.0;
}

View File

@ -46,6 +46,8 @@ public:
static void NullDeleter(void *obj); static void NullDeleter(void *obj);
static double GetTime(void);
private: private:
static bool m_SSLInitialized; static bool m_SSLInitialized;

View File

@ -29,50 +29,50 @@ CheckResult::CheckResult(const MessagePart& message)
: MessagePart(message) : MessagePart(message)
{ } { }
void CheckResult::SetScheduleStart(time_t ts) void CheckResult::SetScheduleStart(double ts)
{ {
Set("schedule_start", static_cast<long>(ts)); Set("schedule_start", ts);
} }
time_t CheckResult::GetScheduleStart(void) const double CheckResult::GetScheduleStart(void) const
{ {
long value = 0; double value = 0;
Get("schedule_start", &value); Get("schedule_start", &value);
return static_cast<time_t>(value); return value;
} }
void CheckResult::SetScheduleEnd(time_t ts) void CheckResult::SetScheduleEnd(double ts)
{ {
Set("schedule_end", static_cast<long>(ts)); Set("schedule_end", ts);
} }
time_t CheckResult::GetScheduleEnd(void) const double CheckResult::GetScheduleEnd(void) const
{ {
long value = 0; double value = 0;
Get("schedule_end", &value); Get("schedule_end", &value);
return static_cast<time_t>(value); return value;
} }
void CheckResult::SetExecutionStart(time_t ts) void CheckResult::SetExecutionStart(double ts)
{ {
Set("execution_start", static_cast<long>(ts)); Set("execution_start", ts);
} }
time_t CheckResult::GetExecutionStart(void) const double CheckResult::GetExecutionStart(void) const
{ {
long value = 0; double value = 0;
Get("execution_start", &value); Get("execution_start", &value);
return static_cast<time_t>(value); return value;
} }
void CheckResult::SetExecutionEnd(time_t ts) void CheckResult::SetExecutionEnd(double ts)
{ {
Set("execution_end", static_cast<long>(ts)); Set("execution_end", ts);
} }
time_t CheckResult::GetExecutionEnd(void) const double CheckResult::GetExecutionEnd(void) const
{ {
long value = 0; double value = 0;
Get("execution_end", &value); Get("execution_end", &value);
return value; return value;
} }

View File

@ -29,17 +29,17 @@ public:
CheckResult(void); CheckResult(void);
CheckResult(const MessagePart& message); CheckResult(const MessagePart& message);
void SetScheduleStart(time_t ts); void SetScheduleStart(double ts);
time_t GetScheduleStart(void) const; double GetScheduleStart(void) const;
void SetScheduleEnd(time_t ts); void SetScheduleEnd(double ts);
time_t GetScheduleEnd(void) const; double GetScheduleEnd(void) const;
void SetExecutionStart(time_t ts); void SetExecutionStart(double ts);
time_t GetExecutionStart(void) const; double GetExecutionStart(void) const;
void SetExecutionEnd(time_t ts); void SetExecutionEnd(double ts);
time_t GetExecutionEnd(void) const; double GetExecutionEnd(void) const;
void SetState(ServiceState state); void SetState(ServiceState state);
ServiceState GetState(void) const; ServiceState GetState(void) const;

View File

@ -48,9 +48,7 @@ void NagiosCheckTask::ScriptFunc(const ScriptTask::Ptr& task, const vector<Varia
NagiosCheckTask ct(task, process); NagiosCheckTask ct(task, process);
time_t now; ct.m_Result.SetScheduleStart(Utility::GetTime());
time(&now);
ct.m_Result.SetScheduleStart(now);
process->Start(boost::bind(&NagiosCheckTask::ProcessFinishedHandler, ct)); process->Start(boost::bind(&NagiosCheckTask::ProcessFinishedHandler, ct));
} }
@ -92,9 +90,7 @@ void NagiosCheckTask::ProcessFinishedHandler(NagiosCheckTask ct)
ct.m_Result.SetState(state); ct.m_Result.SetState(state);
time_t now; ct.m_Result.SetScheduleEnd(Utility::GetTime());
time(&now);
ct.m_Result.SetScheduleEnd(now);
ct.m_Task->FinishResult(ct.m_Result.GetDictionary()); ct.m_Task->FinishResult(ct.m_Result.GetDictionary());
} }

View File

@ -26,8 +26,7 @@ void NullCheckTask::ScriptFunc(const ScriptTask::Ptr& task, const vector<Variant
if (arguments.size() < 1) if (arguments.size() < 1)
throw_exception(invalid_argument("Missing argument: Service must be specified.")); throw_exception(invalid_argument("Missing argument: Service must be specified."));
time_t now; double now = Utility::GetTime();
time(&now);
CheckResult cr; CheckResult cr;
cr.SetScheduleStart(now); cr.SetScheduleStart(now);

View File

@ -175,35 +175,48 @@ bool Service::IsReachable(void) const
return true; return true;
} }
void Service::SetNextCheck(time_t nextCheck) void Service::SetSchedulingOffset(long offset)
{ {
SetTag("next_check", (long)nextCheck); SetTag("scheduling_offset", offset);
} }
time_t Service::GetNextCheck(void) long Service::GetSchedulingOffset(void)
{ {
long value; long value;
if (!GetTag("scheduling_offset", &value)) {
value = rand();
SetSchedulingOffset(value);
}
return value;
}
void Service::SetNextCheck(double nextCheck)
{
SetTag("next_check", nextCheck);
}
double Service::GetNextCheck(void)
{
double value;
if (!GetTag("next_check", &value)) { if (!GetTag("next_check", &value)) {
value = time(NULL) + rand() % GetCheckInterval(); UpdateNextCheck();
SetNextCheck(value); return GetNextCheck();
} }
return value; return value;
} }
void Service::UpdateNextCheck(void) void Service::UpdateNextCheck(void)
{ {
time_t now, previous, next, interval; double interval;
time(&now);
previous = GetNextCheck();
if (GetStateType() == StateTypeSoft) if (GetStateType() == StateTypeSoft)
interval = GetRetryInterval(); interval = GetRetryInterval();
else else
interval = GetCheckInterval(); interval = GetCheckInterval();
next = (now - previous % interval) + interval; double now = Utility::GetTime();
SetNextCheck(next); double adj = fmod(now + GetSchedulingOffset(), interval);
SetNextCheck(now - adj + interval);
} }
void Service::SetChecker(const string& checker) void Service::SetChecker(const string& checker)
@ -273,12 +286,12 @@ CheckResult Service::GetLastCheckResult(void) const
return CheckResult(value); return CheckResult(value);
} }
void Service::SetLastStateChange(time_t ts) void Service::SetLastStateChange(double ts)
{ {
SetTag("last_state_change", static_cast<long>(ts)); SetTag("last_state_change", static_cast<long>(ts));
} }
time_t Service::GetLastStateChange(void) const double Service::GetLastStateChange(void) const
{ {
long value; long value;
if (!GetTag("last_state_change", &value)) if (!GetTag("last_state_change", &value))
@ -286,14 +299,14 @@ time_t Service::GetLastStateChange(void) const
return value; return value;
} }
void Service::SetLastHardStateChange(time_t ts) void Service::SetLastHardStateChange(double ts)
{ {
SetTag("last_hard_state_change", static_cast<long>(ts)); SetTag("last_hard_state_change", ts);
} }
time_t Service::GetLastHardStateChange(void) const double Service::GetLastHardStateChange(void) const
{ {
long value; double value;
if (!GetTag("last_hard_state_change", &value)) if (!GetTag("last_hard_state_change", &value))
value = IcingaApplication::GetInstance()->GetStartTime(); value = IcingaApplication::GetInstance()->GetStartTime();
return value; return value;
@ -301,9 +314,6 @@ time_t Service::GetLastHardStateChange(void) const
void Service::ApplyCheckResult(const CheckResult& cr) void Service::ApplyCheckResult(const CheckResult& cr)
{ {
time_t now;
time(&now);
ServiceState old_state = GetState(); ServiceState old_state = GetState();
ServiceStateType old_stateType = GetStateType(); ServiceStateType old_stateType = GetStateType();
@ -330,6 +340,8 @@ void Service::ApplyCheckResult(const CheckResult& cr)
SetLastCheckResult(cr); SetLastCheckResult(cr);
if (old_state != GetState()) { if (old_state != GetState()) {
double now = Utility::GetTime();
SetLastStateChange(now); SetLastStateChange(now);
if (old_stateType != GetStateType()) if (old_stateType != GetStateType())

View File

@ -63,8 +63,11 @@ public:
bool IsReachable(void) const; bool IsReachable(void) const;
void SetNextCheck(time_t nextCheck); long GetSchedulingOffset(void);
time_t GetNextCheck(void); void SetSchedulingOffset(long offset);
void SetNextCheck(double nextCheck);
double GetNextCheck(void);
void UpdateNextCheck(void); void UpdateNextCheck(void);
void SetChecker(const string& checker); void SetChecker(const string& checker);
@ -85,11 +88,11 @@ public:
void SetLastCheckResult(const CheckResult& result); void SetLastCheckResult(const CheckResult& result);
CheckResult GetLastCheckResult(void) const; CheckResult GetLastCheckResult(void) const;
void SetLastStateChange(time_t ts); void SetLastStateChange(double ts);
time_t GetLastStateChange(void) const; double GetLastStateChange(void) const;
void SetLastHardStateChange(time_t ts); void SetLastHardStateChange(double ts);
time_t GetLastHardStateChange(void) const; double GetLastHardStateChange(void) const;
void ApplyCheckResult(const CheckResult& cr); void ApplyCheckResult(const CheckResult& cr);

View File

@ -60,11 +60,9 @@ void CheckerComponent::Stop(void)
void CheckerComponent::CheckTimerHandler(void) void CheckerComponent::CheckTimerHandler(void)
{ {
time_t now;
time(&now);
Logger::Write(LogDebug, "checker", "CheckTimerHandler entered."); Logger::Write(LogDebug, "checker", "CheckTimerHandler entered.");
double now = Utility::GetTime();
long tasks = 0; long tasks = 0;
while (!m_Services.empty()) { while (!m_Services.empty()) {

View File

@ -96,8 +96,7 @@ void CIBSyncComponent::CheckResultRequestHandler(const Endpoint::Ptr& sender, co
CIB::OnCheckResultReceived(params); CIB::OnCheckResultReceived(params);
service.ApplyCheckResult(cr); service.ApplyCheckResult(cr);
time_t now; time_t now = Utility::GetTime();
time(&now);
CIB::UpdateTaskStatistics(now, 1); CIB::UpdateTaskStatistics(now, 1);
} }

View File

@ -112,8 +112,8 @@ void CompatComponent::DumpServiceStatus(ofstream& fp, Service service)
{ {
string output; string output;
string perfdata; string perfdata;
time_t schedule_start = -1, schedule_end = -1; double schedule_start = -1, schedule_end = -1;
time_t execution_start = -1, execution_end = -1; double execution_start = -1, execution_end = -1;
if (service.HasLastCheckResult()) { if (service.HasLastCheckResult()) {
CheckResult cr = service.GetLastCheckResult(); CheckResult cr = service.GetLastCheckResult();
output = cr.GetOutput(); output = cr.GetOutput();
@ -124,8 +124,8 @@ void CompatComponent::DumpServiceStatus(ofstream& fp, Service service)
perfdata = cr.GetPerformanceDataRaw(); perfdata = cr.GetPerformanceDataRaw();
} }
time_t execution_time = (execution_end - execution_start); double execution_time = (execution_end - execution_start);
time_t latency = (schedule_end - schedule_start) - execution_time; double latency = (schedule_end - schedule_start) - execution_time;
int state = service.GetState(); int state = service.GetState();
@ -194,6 +194,8 @@ void CompatComponent::StatusTimerHandler(void)
ofstream statusfp; ofstream statusfp;
statusfp.open("status.dat.tmp", ofstream::out | ofstream::trunc); statusfp.open("status.dat.tmp", ofstream::out | ofstream::trunc);
statusfp << std::fixed;
statusfp << "# Icinga status file" << "\n" statusfp << "# Icinga status file" << "\n"
<< "# This file is auto-generated. Do not modify this file." << "\n" << "# This file is auto-generated. Do not modify this file." << "\n"
<< "\n"; << "\n";
@ -222,6 +224,8 @@ void CompatComponent::StatusTimerHandler(void)
ofstream objectfp; ofstream objectfp;
objectfp.open("objects.cache.tmp", ofstream::out | ofstream::trunc); objectfp.open("objects.cache.tmp", ofstream::out | ofstream::trunc);
objectfp << std::fixed;
objectfp << "# Icinga object cache file" << "\n" objectfp << "# Icinga object cache file" << "\n"
<< "# This file is auto-generated. Do not modify this file." << "\n" << "# This file is auto-generated. Do not modify this file." << "\n"
<< "\n"; << "\n";

View File

@ -357,7 +357,7 @@ void DiscoveryComponent::ProcessDiscoveryMessage(const string& identity, const D
ComponentDiscoveryInfo::Ptr info = boost::make_shared<ComponentDiscoveryInfo>(); ComponentDiscoveryInfo::Ptr info = boost::make_shared<ComponentDiscoveryInfo>();
time(&(info->LastSeen)); info->LastSeen = Utility::GetTime();
string node; string node;
if (message.GetNode(&node) && !node.empty()) if (message.GetNode(&node) && !node.empty())
@ -451,8 +451,7 @@ void DiscoveryComponent::DiscoveryTimerHandler(void)
{ {
EndpointManager::Ptr endpointManager = EndpointManager::GetInstance(); EndpointManager::Ptr endpointManager = EndpointManager::GetInstance();
time_t now; double now = Utility::GetTime();
time(&now);
/* check whether we have to reconnect to one of our upstream endpoints */ /* check whether we have to reconnect to one of our upstream endpoints */
ConfigObject::TMap::Range range = ConfigObject::GetObjects("endpoint"); ConfigObject::TMap::Range range = ConfigObject::GetObjects("endpoint");

View File

@ -38,7 +38,7 @@ public:
set<string> Subscriptions; set<string> Subscriptions;
set<string> Publications; set<string> Publications;
time_t LastSeen; double LastSeen;
}; };
/** /**