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 |