Packets: Extend collection parser documentation
g0dil [Tue, 19 Aug 2008 10:33:15 +0000 (10:33 +0000)]
Scheduler: Watchdog configuration support

git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@898 270642c3-0616-0410-b53a-bc976706d245

Packets/Mainpage.dox
Scheduler/FIFORunner.cc
Scheduler/FIFORunner.cci
Scheduler/FIFORunner.hh
Scheduler/Scheduler.cci
Scheduler/Scheduler.hh
Scheduler/Scheduler.test.cc
doclib/senf.css

index 0fae42e..6ae0de7 100644 (file)
         invalid packets since the packet will not be validated against it's protocol.
 
 
-    \section packet_usage_fields Protocol fields
+    \section packet_usage_fields Field access
 
     When working with concrete protocols, the packet library provides direct access to all the
     protocol information.
     This is a very abstract description of the parser structure. For a more concrete description, we
     need to differentiate between the different parser types
 
-    \subsection packet_usage_fields_value Value parsers
+    \subsection packet_usage_fields_value Simple fields (Value parsers)
 
     We have already seen value parsers: These are the lowest level building blocks witch parse
     numbers, addresses etc. They return some type of value and can be assigned such a value. More
 
     Remember, that a parser does \e not contain any data: It only points into the raw data
     container. This is also true for the collection parsers. VectorParser and ListParser provide an
-    interface which looks like an STL container to access the elements.
+    interface which looks like an STL container to access a sequence of elements.
 
-    We will use an MLDv2 Query as an example (see <a
-    href="http://tools.ietf.org/html/rfc3810#section-5">RFC 3810</a>).
+    We will use an \c MLDv2QueryPacket as an example (see <a
+    href="http://tools.ietf.org/html/rfc3810#section-5">RFC 3810</a>). Here an excerpt of the
+    relevant fields:
+
+    <table class="fields">
+    <tr><td>nrOfSources</td><td>Integer</td><td>Number of multicast sources in this packet</td></tr>
+    <tr><td>sources</td><td>Vector of IPv6 Addresses</td><td>Multicast sources</td></tr>
+    </table>
+
+    To demonstrate nested collections, we use the \c MLDv2ReportPacket as an example. The relevant
+    fields of this packet are;
+    
+    <table class="fields">
+    <tr><td>nrOfRecords</td><td>Integer</td><td>Number of multicast address records</td></tr>
+    <tr><td>records</td><td>List of Records</td><td>List of multicast groups and sources</td></tr>
+    </table>
+
+    Each Record is a composite with the following relevant fields:
+
+    <table class="fields">
+    <tr><td>nrSources</td><td>Integer</td><td>Number of sources in this record</td></tr>
+    <tr><td>sources</td><td>Vector of IPv6 Addresses</td><td>Multicast sources</td></tr>
+    </table>
+    
+    The first example will iterate over the sources in a \c MLDv2QueryPacket:
 
     \code
     MLDv2QueryPacket mld = ...;
 
     Beside other fields, the MLDv2Query consists of a list of source addresses. The \c sources()
     member returns a VectorParser for these addresses. The collection parsers can only be accessed
-    completely using a container wrapper. This is, what we do in above example.
+    completely using a container wrapper. The container wrapper type is available as the \c
+    container member of the collection parser, here it is \c
+    MLDv2QueryPacket::Parser::sources_t::container.
 
-    The wrapper can also be used to manipulate that list. Here we copy a list of addresses from an
-    \c std::vector into the packet:
+    Using this wrapper, we can not only read the data, we can also manipulate the source list. Here
+    we copy a list of addresses from an \c std::vector into the packet:
 
     \code
     std::vector<senf::INet6Address> addrs (...);
     std::copy(addrs.begin(), addrs.end(), sources.begin())
     \endcode
 
-    Collection parsers may also be nested. To access a nested collection parser, such a container
-    wrapper should be allocated for each level. An MLD Report (which is a composite parser) includes
-    a list of multicast address records called \c records(). Each record is again a composite which
-    contains a list of sources called \c sources():
+    Collection parsers may be nested. To access a nested collection parser, a container wrapper must
+    be allocated for each level. An MLD Report (which is a composite parser) includes a list of
+    multicast address records called \c records(). Each record is again a composite which contains a
+    list of sources called \c sources():
 
     \code
     MLDv2ReportPacket report = ...;
index 10cfdc2..ffaf11e 100644 (file)
@@ -36,7 +36,7 @@
 ///////////////////////////////cc.p////////////////////////////////////////
 
 prefix_ senf::scheduler::FIFORunner::FIFORunner()
-    : tasks_ (), next_ (tasks_.end()), hangCount_ (0)
+    : tasks_ (), next_ (tasks_.end()), watchdogMs_ (1000), watchdogCount_(0), hangCount_ (0)
 {
     struct sigevent ev;
     ::memset(&ev, 0, sizeof(ev));
@@ -120,16 +120,16 @@ prefix_ void senf::scheduler::FIFORunner::run()
     TaskList::iterator end (TaskList::current(null));
     next_ = tasks_.begin();
     struct itimerspec timer;
-    timer.it_interval.tv_sec = 0;
-    timer.it_interval.tv_nsec = 0;
-    timer.it_value.tv_sec = 1;
-    timer.it_value.tv_nsec = 0;
+    timer.it_interval.tv_sec = watchdogMs_ / 1000;
+    timer.it_interval.tv_nsec = (watchdogMs_ % 1000) * 1000000ul;
+    timer.it_value.tv_sec = timer.it_interval.tv_sec;
+    timer.it_value.tv_nsec = timer.it_interval.tv_nsec;
+    if (timer_settime(watchdogId_, 0, &timer, 0) < 0)
+        SENF_THROW_SYSTEM_EXCEPTION("timer_settime()");
     while (next_ != end) {
         TaskInfo & task (*next_);
         if (task.runnable) {
             task.runnable = false;
-            if (timer_settime(watchdogId_, 0, &timer, 0) < 0)
-                SENF_THROW_SYSTEM_EXCEPTION("timer_settime()");
             runningName_ = task.name;
 #       ifdef SENF_DEBUG
             runningBacktrace_ = task.backtrace;
@@ -137,12 +137,17 @@ prefix_ void senf::scheduler::FIFORunner::run()
             TaskList::iterator i (next_);
             ++ next_;
             tasks_.splice(tasks_.end(), tasks_, i);
+            watchdogCount_ = 1;
             task.run();
         }
         else
             ++ next_;
     }
+    watchdogCount_ = 0;
+    timer.it_interval.tv_sec = 0;
+    timer.it_interval.tv_nsec = 0;
     timer.it_value.tv_sec = 0;
+    timer.it_value.tv_nsec = 0;
     if (timer_settime(watchdogId_, 0, &timer, 0) < 0)
         SENF_THROW_SYSTEM_EXCEPTION("timer_settime()");
     tasks_.erase(end);
@@ -152,15 +157,20 @@ prefix_ void senf::scheduler::FIFORunner::run()
 prefix_ void senf::scheduler::FIFORunner::watchdog(int, siginfo_t * si, void *)
 {
     FIFORunner & runner (*static_cast<FIFORunner *>(si->si_value.sival_ptr));
-    ++ runner.hangCount_;
-    write(1, "\n\n*** Scheduler task hanging: ", 30);
-    write(1, runner.runningName_.c_str(), runner.runningName_.size());
-    write(1, "\n", 1);
+    if (runner.watchdogCount_ > 0) {
+        ++ runner.watchdogCount_;
+        if (runner.watchdogCount_ > 2) {
+            ++ runner.hangCount_;
+            write(1, "\n\n*** Scheduler task hanging: ", 30);
+            write(1, runner.runningName_.c_str(), runner.runningName_.size());
+            write(1, "\n", 1);
 #ifdef SENF_DEBUG
-    write(1, "Task was initialized at\n", 24);
-    write(1, runner.runningBacktrace_.c_str(), runner.runningBacktrace_.size());
+            write(1, "Task was initialized at\n", 24);
+            write(1, runner.runningBacktrace_.c_str(), runner.runningBacktrace_.size());
 #endif
-    write(1, "\n", 1);
+            write(1, "\n", 1);
+        }
+    }
 }
 
 ///////////////////////////////cc.e////////////////////////////////////////
index 1061f4d..6d2f52a 100644 (file)
@@ -51,6 +51,17 @@ prefix_ void senf::scheduler::FIFORunner::enqueue(TaskInfo * task)
 #endif
 }
 
+prefix_ void senf::scheduler::FIFORunner::taskTimeout(unsigned ms)
+{
+    watchdogMs_ = ms;
+}
+
+prefix_ unsigned senf::scheduler::FIFORunner::taskTimeout()
+    const
+{
+    return watchdogMs_;
+}
+
 prefix_ unsigned senf::scheduler::FIFORunner::hangCount()
     const
 {
index adf088f..464d4f4 100644 (file)
@@ -100,6 +100,9 @@ namespace scheduler {
         
         void run();                     ///< Run queue
 
+        void taskTimeout(unsigned ms);  ///< Set task timeout to \a ms milliseconds
+        unsigned taskTimeout() const;   ///< Get task timeout in milliseconds
+
         unsigned hangCount() const;     ///< Number of task expirations
                                         /**< The FIFORunner manages a watchdog which checks, that a
                                              single task does not run continuously for a longer time
@@ -114,10 +117,12 @@ namespace scheduler {
         TaskList tasks_;
         TaskList::iterator next_;
         timer_t watchdogId_;
+        unsigned watchdogMs_;
         std::string runningName_;
 #   ifdef SENF_DEBUG
         std::string runningBacktrace_;
 #   endif
+        unsigned watchdogCount_;
         unsigned hangCount_;
     };
 
index f8a565e..5379b6f 100644 (file)
@@ -134,6 +134,17 @@ prefix_ senf::ClockService::clock_type senf::Scheduler::eventTime()
     return manager_.eventTime();
 }
 
+prefix_ void senf::Scheduler::taskTimeout(unsigned ms)
+{
+    runner_.taskTimeout(ms);
+}
+
+prefix_ unsigned senf::Scheduler::taskTimeout()
+    const
+{
+    return runner_.taskTimeout();
+}
+
 prefix_ unsigned senf::Scheduler::hangCount()
     const
 {
index 89e9d23..4a7a74d 100644 (file)
@@ -314,6 +314,8 @@ namespace senf {
                                              delivered \e not the time it should have been delivered
                                              (in the case of timers). */
 
+        void taskTimeout(unsigned ms);
+        unsigned taskTimeout() const;
         unsigned hangCount() const;
 
     protected:
index 0501762..b45b1a3 100644 (file)
@@ -209,7 +209,7 @@ namespace {
 
     void blockingHandler()
     {
-        delay(1200);
+        delay(2200);
         Scheduler::instance().terminate();
     }
 
index f253059..9296c7a 100644 (file)
@@ -295,6 +295,33 @@ table.senf th {
         font-weight: bold;
 }
 
+table.fields {
+        width: 95%;
+        margin: 10pt auto;
+        border: 1px solid #AAAAAA;
+        padding: 2px;
+        border-spacing: 0;
+}
+
+table.fields td,th {
+        border: 2px solid white;
+        background-color: #EEEEEE;
+        padding: 2px 4px;
+        text-align: left;
+        vertical-align: top;
+}
+
+table.fields th {
+        background-color: #DDDDDD;
+        text-align: center;
+        font-weight: bold;
+}
+
+table.fields td:first-child {
+        width: 25%;
+        font-style: italic;
+}
+
 table.fixedcolumn td:first-child {
         width: 35%; 
 }