23 #include "log_thread.h"
26 #include <blackboard/blackboard.h>
27 #include <logging/logger.h>
28 #include <core/exceptions/system.h>
29 #include <interfaces/SwitchInterface.h>
38 # include <sys/endian.h>
39 #elif defined(__MACH__) && defined(__APPLE__)
40 # include <sys/_endian.h>
44 #include <arpa/inet.h>
48 using namespace fawkes;
78 const char *logdir,
bool buffering,
bool flushing,
80 :
Thread(
"BBLoggerThread",
Thread::OPMODE_WAITFORWAKEUP),
84 set_name(
"BBLoggerThread(%s)", iface_uid);
86 __buffering = buffering;
87 __flushing = flushing;
88 __uid = strdup(iface_uid);
89 __logdir = strdup(logdir);
90 __scenario = strdup(scenario);
91 __start =
new Time(start_time);
93 __queue_mutex =
new Mutex();
101 Interface::parse_uid(__uid, &__type, &__id);
105 struct tm *tmp = localtime(&(now.
get_timeval()->tv_sec));
106 strftime(date, 21,
"%F-%H-%M-%S", tmp);
108 if (asprintf(&__filename,
"%s/%s-%s-%s-%s.log", LOGDIR, __scenario,
109 __type, __id, date) == -1) {
124 delete __queue_mutex;
136 __queue_mutex =
new Mutex();
140 __num_data_items = 0;
145 mode_t m = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
146 int fd = open(__filename, O_RDWR | O_CREAT | O_EXCL, m);
150 __f_data = fdopen(fd,
"w+");
178 __switch_if->
write();
192 __is_master ?
" as master" :
"");
205 for (
unsigned int q = 0; q < 2; ++q) {
206 while (!__queues[q].empty()) {
207 void *t = __queues[q].front();
234 if (enabled && !__enabled) {
236 (__num_data_items - __session_start));
237 __session_start = __num_data_items;
238 }
else if (!enabled && __enabled) {
240 (__num_data_items - __session_start));
259 __threads = thread_list;
263 BBLoggerThread::write_header()
266 memset(&header, 0,
sizeof(header));
267 header.
file_magic = htonl(BBLOGGER_FILE_MAGIC);
269 #if __BYTE_ORDER == __BIG_ENDIAN
275 strncpy(header.
scenario, (
const char *)__scenario, BBLOG_SCENARIO_SIZE);
277 strncpy(header.
interface_id, __iface->
id(), BBLOG_INTERFACE_ID_SIZE);
280 long start_time_sec, start_time_usec;
284 if (fwrite(&header,
sizeof(header), 1, __f_data) != 1) {
292 BBLoggerThread::update_header()
295 #if _POSIX_MAPPED_FILES
297 fileno(__f_data), 0);
298 if (h == MAP_FAILED) {
300 "not updating number of data items",
309 "not updating number of data items on close");
314 BBLoggerThread::write_chunk(
const void *chunk)
318 Time d = *__now - *__start;
319 long rel_time_sec, rel_time_usec;
323 if ( (fwrite(&ehead,
sizeof(ehead), 1, __f_data) == 1) &&
324 (fwrite(chunk, __data_size, 1, __f_data) == 1) ) {
325 if (__flushing) fflush(__f_data);
326 __num_data_items += 1;
336 unsigned int write_queue = __act_queue;
337 __queue_mutex->
lock();
338 __act_queue = 1 - __act_queue;
342 while (! queue.empty() ) {
343 void *c = queue.front();
358 if ((enm = dynamic_cast<SwitchInterface::EnableSwitchMessage *>(message)) != NULL) {
360 }
else if ((dism = dynamic_cast<SwitchInterface::DisableSwitchMessage *>(message)) != NULL) {
363 logger->
log_debug(name(),
"Unhandled message type: %s via %s",
364 message->type(), interface->uid());
367 for (ThreadList::iterator i = __threads.begin(); i != __threads.end(); ++i) {
372 __switch_if->set_enabled(__enabled);
373 __switch_if->write();
382 if (!__enabled)
return;
388 void *c = malloc(__iface->datasize());
389 memcpy(c, __iface->datachunk(), __iface->datasize());
390 __queue_mutex->lock();
391 __queues[__act_queue].push_locked(c);
392 __queue_mutex->unlock();
395 __queue_mutex->lock();
396 write_chunk(__iface->datachunk());
397 __queue_mutex->unlock();
401 logger->
log_error(name(),
"Exception when data changed");
408 unsigned int instance_serial)
throw()
410 __session_start = __num_data_items;
415 unsigned int instance_serial)
throw()
417 logger->
log_info(name(),
"Writer removed (wrote %u entries), flushing",
418 (__num_data_items - __session_start));