// $Id$
//
-// Copyright (C) 2007
-// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
-// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+// Copyright (C) 2007
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
//
// This program is free software; you can redistribute it and/or modify
//#include "ClockService.ih"
// Custom includes
-#include <errno.h>
-#include <signal.h>
-#include <sys/time.h>
-#include <pthread.h>
-#include "../Utils/Exception.hh"
+#include <boost/regex.hpp>
+#include "../Utils/Console/Console.hh"
//#include "ClockService.mpp"
#define prefix_
///////////////////////////////cc.p////////////////////////////////////////
-#define CheckError(op,args) if (op args < 0) throw SystemException(# op, errno)
-
-///////////////////////////////////////////////////////////////////////////
-// senf::ClockService::Impl
-
-struct senf::ClockService::Impl
-{
- Impl();
-
- void block();
- void unblock();
-
- struct Blocker {
- Blocker(Impl * i) : impl(i) { impl->block(); }
- ~Blocker() { impl->unblock(); }
- Impl * impl;
- };
-
- static void timer(int);
-
- struct sigaction oldaction;
- struct itimerval olditimer;
- sigset_t alrm_set;
-};
-
-prefix_ senf::ClockService::Impl::Impl()
-{
- CheckError( sigemptyset, (&alrm_set) );
- CheckError( sigaddset, (&alrm_set, SIGALRM) );
-}
-
-prefix_ void senf::ClockService::Impl::block()
-{
- CheckError( sigprocmask, (SIG_BLOCK, &alrm_set, 0) );
-}
-
-prefix_ void senf::ClockService::Impl::unblock()
-{
- CheckError( sigprocmask, (SIG_UNBLOCK, &alrm_set, 0) );
-}
-
-prefix_ void senf::ClockService::Impl::timer(int)
-{
- ClockService::instance().timer();
-}
-
-///////////////////////////////////////////////////////////////////////////
-// senf::ClockService
-
-prefix_ senf::ClockService::~ClockService()
+prefix_ void
+senf::parseClockServiceInterval(console::ParseCommandInfo::TokensRange const & tokens,
+ ClockService::clock_type & out)
{
- setitimer(ITIMER_REAL, &impl_->olditimer, 0);
- sigaction(SIGALRM, &impl_->oldaction, 0);
-}
-
-////////////////////////////////////////
-// private members
-
-prefix_ senf::ClockService::ClockService()
- : impl_(new ClockService::Impl())
-{
- restart_m(false);
-}
-
-prefix_ void senf::ClockService::timer()
-{
- boost::posix_time::ptime time (boost::posix_time::microsec_clock::universal_time());
- if (checkSkew(time))
- clockSkew(time, heartbeat_ + boost::posix_time::seconds(
- ClockService::CheckInterval));
- heartbeat_ = time;
-}
-
-prefix_ void senf::ClockService::restart_m(bool restart)
-{
- if (restart)
- // if any syscall fails, the alarm signal stays blocked which is correct
- impl_->block();
-
- base_ = boost::posix_time::microsec_clock::universal_time();
- heartbeat_ = base_;
-
- struct sigaction action;
- action.sa_handler = & senf::ClockService::Impl::timer;
- CheckError( sigemptyset, (&action.sa_mask) );
- action.sa_flags = SA_RESTART;
- CheckError( sigaction, (SIGALRM, &action, restart ? 0 : &impl_->oldaction) );
-
- restartTimer(restart);
-
- impl_->unblock();
-}
-
-prefix_ void senf::ClockService::restartTimer(bool restart)
-{
- struct itimerval itimer;
- itimer.it_interval.tv_sec = CheckInterval;
- itimer.it_interval.tv_usec = 0;
- itimer.it_value.tv_sec = CheckInterval;
- itimer.it_value.tv_usec = 0;
- CheckError( setitimer, (ITIMER_REAL, &itimer, restart ? 0 : &impl_->olditimer) );
-}
-
-prefix_ void senf::ClockService::updateSkew(boost::posix_time::ptime time)
-{
- Impl::Blocker alrmBlocker (impl_.get());
-
- // Make a second 'checkSkew' test, this time with SIGALRM blocked. See
- // senf::ClockService::now_i()
-
- if (checkSkew(time)) {
- struct itimerval itimer;
- CheckError( getitimer, (ITIMER_REAL, &itimer) );
- clockSkew(time, (heartbeat_
- + boost::posix_time::seconds(CheckInterval)
- - boost::posix_time::seconds(itimer.it_value.tv_sec)
- - boost::posix_time::microseconds(itimer.it_value.tv_usec)));
- heartbeat_ = time;
- restartTimer();
+ out = 0;
+ std::string value;
+ {
+ senf::console::CheckedArgumentIteratorWrapper arg (tokens);
+ senf::console::parse( *(arg++), value );
+ }
+ static boost::sregex_iterator::regex_type rx ("[mun]?[dhms]");
+ boost::sregex_iterator i (value.begin(), value.end(), rx);
+ boost::sregex_iterator const i_end;
+ std::string::const_iterator j (value.begin());
+ for (; i != i_end; ++i) {
+ boost::sregex_iterator::value_type::value_type match ((*i)[0]);
+ long double v (boost::lexical_cast<long double>(std::string(j, match.first)));
+ char scale (0);
+ char unit (0);
+ if (match.length() == 2) {
+ scale = *match.first;
+ unit = *boost::next(match.first);
+ } else {
+ SENF_ASSERT( match.length() == 1);
+ unit = *match.first;
+ }
+ switch (scale) {
+ case 0: break;
+ case 'n': v /= 1000.0;
+ case 'u': v /= 1000.0;
+ case 'm': v /= 1000.0;
+ }
+ switch (unit) {
+ case 'd': v *= 24.0;
+ case 'h': v *= 60.0;
+ case 'm': v *= 60.0;
+ case 's': v *= 1000000000.0;
+ }
+ out += senf::ClockService::nanoseconds(senf::ClockService::int64_type(v));
+ j = match.second;
}
+ if (j != value.end())
+ throw senf::console::SyntaxErrorException();
}
///////////////////////////////cc.e////////////////////////////////////////