23 #include "log_thread.h"
27 #include <blackboard/blackboard.h>
28 #include <core/exceptions/system.h>
29 #include <interfaces/SwitchInterface.h>
30 #include <logging/logger.h>
39 # include <sys/endian.h>
40 #elif defined(__MACH__) && defined(__APPLE__)
41 # include <sys/_endian.h>
45 #include <arpa/inet.h>
82 const char * scenario,
84 :
Thread(
"BBLoggerThread",
Thread::OPMODE_WAITFORWAKEUP),
88 set_name(
"BBLoggerThread(%s)", iface_uid);
90 buffering_ = buffering;
92 uid_ = strdup(iface_uid);
93 logdir_ = strdup(logdir);
94 scenario_ = strdup(scenario);
95 start_ =
new Time(start_time);
97 queue_mutex_ =
new Mutex();
105 Interface::parse_uid(uid_, type_, id_);
109 struct tm *tmp = localtime(&(now.
get_timeval()->tv_sec));
110 strftime(date, 21,
"%F-%H-%M-%S", tmp);
113 &filename_,
"%s/%s-%s-%s-%s.log", LOGDIR, scenario_, type_.c_str(), id_.c_str(), date)
137 queue_mutex_ =
new Mutex();
146 mode_t m = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
147 int fd = open(filename_, O_RDWR | O_CREAT | O_EXCL, m);
151 f_data_ = fdopen(fd,
"w+");
193 name(),
"Logging %s to %s%s", iface_->
uid(), filename_, is_master_ ?
" as master" :
"");
205 for (
unsigned int q = 0; q < 2; ++q) {
206 while (!queues_[q].empty()) {
207 void *t = queues_[q].front();
232 if (enabled && !enabled_) {
234 session_start_ = num_data_items_;
235 }
else if (!enabled && enabled_) {
237 "Logging disabled (wrote %u entries), flushing",
238 (num_data_items_ - session_start_));
256 threads_ = thread_list;
260 BBLoggerThread::write_header()
263 memset(&header, 0,
sizeof(header));
264 header.
file_magic = htonl(BBLOGGER_FILE_MAGIC);
266 #if BYTE_ORDER_ == BIG_ENDIAN_
272 strncpy(header.
scenario, (
const char *)scenario_, BBLOG_SCENARIO_SIZE - 1);
274 strncpy(header.
interface_id, iface_->
id(), BBLOG_INTERFACE_ID_SIZE - 1);
277 long start_time_sec, start_time_usec;
281 if (fwrite(&header,
sizeof(header), 1, f_data_) != 1) {
289 BBLoggerThread::update_header()
292 #if _POSIX_MAPPED_FILES
293 void *h = mmap(NULL,
sizeof(
bblog_file_header), PROT_WRITE, MAP_SHARED, fileno(f_data_), 0);
294 if (h == MAP_FAILED) {
296 "Failed to mmap log (%s), "
297 "not updating number of data items",
306 "Memory mapped files not available, "
307 "not updating number of data items on close");
312 BBLoggerThread::write_chunk(
const void *chunk)
316 Time d = *now_ - *start_;
317 long rel_time_sec, rel_time_usec;
321 if ((fwrite(&ehead,
sizeof(ehead), 1, f_data_) == 1)
322 && (fwrite(chunk, data_size_, 1, f_data_) == 1)) {
325 num_data_items_ += 1;
334 unsigned int write_queue = act_queue_;
335 queue_mutex_->
lock();
336 act_queue_ = 1 - act_queue_;
340 while (!queue.empty()) {
341 void *c = queue.front();
361 "Unhandled message type: %s via %s",
366 for (ThreadList::iterator i = threads_.begin(); i != threads_.end(); ++i) {
371 switch_if_->set_enabled(enabled_);
387 void *c = malloc(iface_->datasize());
388 memcpy(c, iface_->datachunk(), iface_->datasize());
389 queue_mutex_->lock();
390 queues_[act_queue_].push_locked(c);
391 queue_mutex_->unlock();
394 queue_mutex_->lock();
395 write_chunk(iface_->datachunk());
396 queue_mutex_->unlock();
400 logger->
log_error(name(),
"Exception when data changed");
407 unsigned int instance_serial)
throw()
409 session_start_ = num_data_items_;
414 unsigned int instance_serial)
throw()
417 "Writer removed (wrote %u entries), flushing",
418 (num_data_items_ - session_start_));
BlackBoard logger thread.
virtual void bb_interface_writer_added(fawkes::Interface *interface, unsigned int instance_serial)
A writing instance has been opened for a watched interface.
virtual ~BBLoggerThread()
Destructor.
virtual void init()
Initialize the thread.
virtual void bb_interface_data_changed(fawkes::Interface *interface)
BlackBoard data changed notification.
const char * get_filename() const
Get filename.
virtual void bb_interface_writer_removed(fawkes::Interface *interface, unsigned int instance_serial)
A writing instance has been closed for a watched interface.
virtual void finalize()
Finalize the thread.
virtual bool bb_interface_message_received(fawkes::Interface *interface, fawkes::Message *message)
BlackBoard message received notification.
void set_threadlist(fawkes::ThreadList &thread_list)
Set threadlist and master status.
virtual void loop()
Code to execute in the thread.
BBLoggerThread(const char *iface_uid, const char *logdir, bool buffering, bool flushing, const char *scenario, fawkes::Time *start_time)
Constructor.
void set_enabled(bool enabled)
Enable or disable logging.
BlackBoard * blackboard
This is the BlackBoard instance you can use to interact with the BlackBoard.
BlackBoard interface listener.
void bbil_add_message_interface(Interface *interface)
Add an interface to the message received watch list.
void bbil_add_writer_interface(Interface *interface)
Add an interface to the writer addition/removal watch list.
void bbil_add_data_interface(Interface *interface)
Add an interface to the data modification watch list.
virtual Interface * open_for_reading(const char *interface_type, const char *identifier, const char *owner=NULL)=0
Open interface for reading.
virtual void unregister_listener(BlackBoardInterfaceListener *listener)
Unregister BB interface listener.
virtual Interface * open_for_writing(const char *interface_type, const char *identifier, const char *owner=NULL)=0
Open interface for writing.
virtual void register_listener(BlackBoardInterfaceListener *listener, ListenerRegisterFlag flag=BBIL_FLAG_ALL)
Register BB event listener.
virtual void close(Interface *interface)=0
Close interface.
Clock * clock
By means of this member access to the clock is given.
File could not be opened.
Base class for exceptions in Fawkes.
Base class for all Fawkes BlackBoard interfaces.
const char * type() const
Get type of interface.
const unsigned char * hash() const
Get interface hash.
void write()
Write from local copy into BlackBoard memory.
const char * id() const
Get identifier of interface.
const char * uid() const
Get unique identifier of interface.
unsigned int datasize() const
Get data size.
void clear()
Clear the queue.
virtual void log_warn(const char *component, const char *format,...)=0
Log warning message.
virtual void log_info(const char *component, const char *format,...)=0
Log informational message.
Logger * logger
This is the Logger member used to access the logger.
Base class for all messages passed through interfaces in Fawkes BlackBoard.
virtual void log_info(const char *component, const char *format,...)
Log informational message.
virtual void log_debug(const char *component, const char *format,...)
Log debug message.
virtual void log_error(const char *component, const char *format,...)
Log error message.
Mutex mutual exclusion lock.
void lock()
Lock this mutex.
void unlock()
Unlock the mutex.
System ran out of memory and desired operation could not be fulfilled.
DisableSwitchMessage Fawkes BlackBoard Interface Message.
EnableSwitchMessage Fawkes BlackBoard Interface Message.
SwitchInterface Fawkes BlackBoard Interface.
void set_enabled(const bool new_enabled)
Set enabled value.
Thread class encapsulation of pthreads.
const char * name() const
Get name of thread.
void set_name(const char *format,...)
Set name of thread.
void set_coalesce_wakeups(bool coalesce=true)
Set wakeup coalescing.
A class for handling time.
void get_timestamp(long &sec, long &usec) const
Get time stamp.
Time & stamp()
Set this time to the current time.
const timeval * get_timeval() const
Obtain the timeval where the time is stored.
Fawkes library namespace.