From: g0dil Date: Tue, 19 Aug 2008 10:33:15 +0000 (+0000) Subject: Packets: Extend collection parser documentation X-Git-Url: http://g0dil.de/git?p=senf.git;a=commitdiff_plain;h=d785ab5820076da44b4a71b05cc231ef7e97c7bf Packets: Extend collection parser documentation Scheduler: Watchdog configuration support git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@898 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Packets/Mainpage.dox b/Packets/Mainpage.dox index 0fae42e..6ae0de7 100644 --- a/Packets/Mainpage.dox +++ b/Packets/Mainpage.dox @@ -396,7 +396,7 @@ 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. @@ -447,7 +447,7 @@ 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 @@ -496,10 +496,33 @@ 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 RFC 3810). + We will use an \c MLDv2QueryPacket as an example (see RFC 3810). Here an excerpt of the + relevant fields: + + + + +
nrOfSourcesIntegerNumber of multicast sources in this packet
sourcesVector of IPv6 AddressesMulticast sources
+ + To demonstrate nested collections, we use the \c MLDv2ReportPacket as an example. The relevant + fields of this packet are; + + + + +
nrOfRecordsIntegerNumber of multicast address records
recordsList of RecordsList of multicast groups and sources
+ + Each Record is a composite with the following relevant fields: + + + + +
nrSourcesIntegerNumber of sources in this record
sourcesVector of IPv6 AddressesMulticast sources
+ + The first example will iterate over the sources in a \c MLDv2QueryPacket: \code MLDv2QueryPacket mld = ...; @@ -515,10 +538,12 @@ 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 addrs (...); @@ -527,10 +552,10 @@ 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 = ...; diff --git a/Scheduler/FIFORunner.cc b/Scheduler/FIFORunner.cc index 10cfdc2..ffaf11e 100644 --- a/Scheduler/FIFORunner.cc +++ b/Scheduler/FIFORunner.cc @@ -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(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//////////////////////////////////////// diff --git a/Scheduler/FIFORunner.cci b/Scheduler/FIFORunner.cci index 1061f4d..6d2f52a 100644 --- a/Scheduler/FIFORunner.cci +++ b/Scheduler/FIFORunner.cci @@ -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 { diff --git a/Scheduler/FIFORunner.hh b/Scheduler/FIFORunner.hh index adf088f..464d4f4 100644 --- a/Scheduler/FIFORunner.hh +++ b/Scheduler/FIFORunner.hh @@ -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_; }; diff --git a/Scheduler/Scheduler.cci b/Scheduler/Scheduler.cci index f8a565e..5379b6f 100644 --- a/Scheduler/Scheduler.cci +++ b/Scheduler/Scheduler.cci @@ -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 { diff --git a/Scheduler/Scheduler.hh b/Scheduler/Scheduler.hh index 89e9d23..4a7a74d 100644 --- a/Scheduler/Scheduler.hh +++ b/Scheduler/Scheduler.hh @@ -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: diff --git a/Scheduler/Scheduler.test.cc b/Scheduler/Scheduler.test.cc index 0501762..b45b1a3 100644 --- a/Scheduler/Scheduler.test.cc +++ b/Scheduler/Scheduler.test.cc @@ -209,7 +209,7 @@ namespace { void blockingHandler() { - delay(1200); + delay(2200); Scheduler::instance().terminate(); } diff --git a/doclib/senf.css b/doclib/senf.css index f253059..9296c7a 100644 --- a/doclib/senf.css +++ b/doclib/senf.css @@ -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%; }