Move Console from Scheduler into Utils
[senf.git] / Scheduler / ClockService.cc
index 010bd20..7bba90d 100644 (file)
@@ -1,8 +1,8 @@
 // $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 CheckErrno(op,args) if (op args < 0) throw SystemException(# op, errno)
-
-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()
-{
-    CheckErrno( sigemptyset, (&alrm_set) );
-    CheckErrno( sigaddset, (&alrm_set, SIGALRM) );
-}
-
-prefix_ void senf::ClockService::Impl::block()
-{
-    CheckErrno( sigprocmask, (SIG_BLOCK, &alrm_set, 0) );
-}
-
-prefix_ void senf::ClockService::Impl::unblock()
-{
-    CheckErrno( sigprocmask, (SIG_UNBLOCK, &alrm_set, 0) );
-}
-
-prefix_ void senf::ClockService::Impl::timer(int)
-{
-    boost::posix_time::ptime time (boost::posix_time::microsec_clock::universal_time());
-    if (ClockService::instance().checkSkew(time))
-        ClockService::instance().clockSkew(
-            time, ClockService::instance().heartbeat_ + boost::posix_time::seconds(
-                ClockService::CheckInterval));
-    ClockService::instance().heartbeat_ = time;
-}
-
-///////////////////////////////////////////////////////////////////////////
-// senf::ClockService
-
-prefix_ senf::ClockService::~ClockService()
-{
-    setitimer(ITIMER_REAL, &impl_->olditimer, 0);
-    sigaction(SIGALRM, &impl_->oldaction, 0);
-}
-
-////////////////////////////////////////
-// private members
-
-prefix_ senf::ClockService::ClockService()
-    : base_ (boost::posix_time::microsec_clock::universal_time()), 
-      heartbeat_ (base_), impl_(new ClockService::Impl())
-{
-    struct sigaction action;
-    action.sa_handler = & senf::ClockService::Impl::timer;
-    CheckErrno( sigemptyset, (&action.sa_mask) );
-    action.sa_flags = SA_RESTART;
-    CheckErrno( sigaction, (SIGALRM, &action, &impl_->oldaction) );
-
-    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;
-    CheckErrno( setitimer, (ITIMER_REAL, &itimer, &impl_->olditimer) );
-    impl_->unblock();
-}
-
-prefix_ void senf::ClockService::restart_i()
-{
-    impl_->block(); // if any syscall fails, the alarm signal stays blocked which is correct
-    base_ = boost::posix_time::microsec_clock::universal_time();
-    heartbeat_ = base_;
-
-    struct sigaction action;
-    action.sa_handler = & senf::ClockService::Impl::timer;
-    CheckErrno( sigemptyset, (&action.sa_mask) );
-    action.sa_flags = SA_RESTART;
-    CheckErrno( sigaction, (SIGALRM, &action, 0) );
-
-    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;
-    CheckErrno( setitimer, (ITIMER_REAL, &itimer, 0) );
-    impl_->unblock();
-}
-
-prefix_ void senf::ClockService::updateSkew(boost::posix_time::ptime time)
+prefix_ void
+senf::parseClockServiceInterval(console::ParseCommandInfo::TokensRange const & tokens,
+                                ClockService::clock_type & out)
 {
-    Impl::Blocker alrmBlocker (impl_.get());
-    struct itimerval itimer;
-    CheckErrno( 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)));
+    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////////////////////////////////////////