|
From: S R. <kiw...@ma...> - 2009-10-26 14:44:05
|
On Oct 26, 2009, at 09:21 , Konstantin Litvinenko wrote:
> On 26.10.2009 14:49, S Roderick wrote:
>
>>> 3. Collect all events (not LogingEvents) in a rt buffer and send
>>> they
>>> into a sink - serialize and send to socket for example.
>>> 4. On other side of sink you may have some listener that receive,
>>> deserialize and invoke log4cpp with preconfigured nonrt
>>> categories/appenders to do real logging.
>>
>> We actually just send LoggingEvents through the buffer. What
>> benefit do
>> you see with sending events that are not LoggingEvents? Aren't they
>> going to contain the same data?
>
> Can you tell me more about 'send LoggingEvents through the buffer'.
> From my point of view to decouple rt part from non-rt you should send
> these event away from rt part in rt manner. Than you should receive it
> in non-rt agent and replay.
Below is the function in the derived RTCategory class. It uses a
log4cpp::LoggingEvent that has rt_string instances, instead of
std::string. The "log_port" object is a reference to a real-time
buffer of log4cpp::LoggingEvent instances, which is implemented and
managed by Orocos. This port has already been setup during the non-
realtime configuration part of the application.
void Category::callAppenders(const log4cpp::LoggingEvent& event) throw()
{
if (log_port.ready())
{
log_port.Push(event);
}
// let our parent categories append
if (getAdditivity() && (getParent() != NULL)) {
getParent()->callAppenders(event);
}
}
This is completely hard real-time as long as a) LoggingEvent uses
rt_string, and b) you don't run out of memory (which is an entirely
separate discussion we're having at the Orocos project). But
fundamentally, the real-time-ness of the above is provided by Orocos,
as long as a) holds.
>> As part of this, you would need to
>> completely override all the logging functions in RTCategory to take
>> rt_string objects instead of std::string.
>
> No, you shouldn't.
Well, yes and no. All calls that end up in the above
Category::callAppenders() function that can be called from real-time,
must _not_ use std::string. So I think you have to change all
log4cpp::Category functions that end up calling
logUnconditionally2(), to take rt_string instead of std::string.
>
>> It seems like we would be
>> completely replacing the Category and LoggingEvent classes, where as
>> with my current implementation we build a slightly different
>> LoggingEvent class, and we override just a couple of functions in the
>> RTCategory class. One of my primary aims going in to this was to
>> reuse
>> as much of log4cpp as possible.
>
> You need to override only one function - _logUnconditionally2 because
> all other logging functions uses only this one to actually log
> something.
Like I said earlier, my intent was to reuse as much of log4cpp as
possible, rather than ending up writing my own. So I opted to put the
Category and logging functions in the real-time part of the system,
and everything else (ie appenders and layouts) in the non-RT part. I
use Orocos' existing real-time buffers in between the two parts. A
log4cpp::appender lives inside an Orocos::Appender, which manages
taking data off the buffer and giving it to the log4cpp::appender. The
user's RT code logs on categories just like normal.
Consequences of this
1) LoggingEvent uses rt_string instead of std::string (to support a)
above)
2) all log4cpp Category functions used to log must take rt_strings
instead of std::strings. This also means that logUnconditionally() and
logUnconditionally2() take rt_strings.
3) the user application must create all categories at the start of
runtime. They can not be created on the fly (unless we further modify
HierarchyMaintainer to use a std::map with a real-time allocator -
quite doable, but I wanted to avoid that, if possible). This
constraint is overall not a big deal (IMHO) to real-time users, as we
are used to pre-allocating anything anyway.
Hope this helps
Stephen
|