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) {
Object::ClearHeldObjects();
long sleep = Timer::ProcessTimers();
double sleep = Timer::ProcessTimers();
if (m_ShuttingDown)
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();

View File

@ -96,14 +96,14 @@ string ConfigObject::GetSource(void) const
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);
return value;
}
@ -117,9 +117,7 @@ void ConfigObject::Commit(void)
assert(!dobj || dobj == self);
m_Container->CheckObject(self);
time_t now;
time(&now);
SetCommitTimestamp(now);
SetCommitTimestamp(Utility::GetTime());
}
void ConfigObject::Unregister(void)

View File

@ -78,7 +78,7 @@ public:
void SetSource(const string& value);
string GetSource(void) const;
time_t GetCommitTimestamp(void) const;
double GetCommitTimestamp(void) const;
void Commit(void);
void Unregister(void);
@ -104,7 +104,7 @@ private:
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 TypePredicate(const ConfigObject::Ptr& object, string type);

View File

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

View File

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

View File

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

View File

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

View File

@ -57,7 +57,8 @@ void StreamLogger::ProcessLogEntry(const LogEntry& entry)
{
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);

View File

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

View File

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

View File

@ -255,3 +255,18 @@ void Utility::NullDeleter(void *obj)
{
/* 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 double GetTime(void);
private:
static bool m_SSLInitialized;

View File

@ -29,50 +29,50 @@ CheckResult::CheckResult(const 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);
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);
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);
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);
return value;
}

View File

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

View File

@ -48,9 +48,7 @@ void NagiosCheckTask::ScriptFunc(const ScriptTask::Ptr& task, const vector<Varia
NagiosCheckTask ct(task, process);
time_t now;
time(&now);
ct.m_Result.SetScheduleStart(now);
ct.m_Result.SetScheduleStart(Utility::GetTime());
process->Start(boost::bind(&NagiosCheckTask::ProcessFinishedHandler, ct));
}
@ -92,9 +90,7 @@ void NagiosCheckTask::ProcessFinishedHandler(NagiosCheckTask ct)
ct.m_Result.SetState(state);
time_t now;
time(&now);
ct.m_Result.SetScheduleEnd(now);
ct.m_Result.SetScheduleEnd(Utility::GetTime());
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)
throw_exception(invalid_argument("Missing argument: Service must be specified."));
time_t now;
time(&now);
double now = Utility::GetTime();
CheckResult cr;
cr.SetScheduleStart(now);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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