Fawkes API  Fawkes Development Version
bblogger_plugin.cpp
1 
2 /***************************************************************************
3  * bblogger_plugin.cpp - Fawkes BlackBoard Logger Plugin
4  *
5  * Created: Sat Nov 07 23:21:36 2009
6  * Copyright 2009 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Library General Public License for more details.
19  *
20  * Read the full text in the LICENSE.GPL file in the doc directory.
21  */
22 
23 #include "bblogger_plugin.h"
24 #include "log_thread.h"
25 
26 #include <utils/time/time.h>
27 
28 #include <set>
29 
30 #include <cstring>
31 #include <cerrno>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <unistd.h>
35 
36 using namespace fawkes;
37 
38 /** @class BlackBoardLoggerPlugin "bblogger_plugin.h"
39  * BlackBoard logger plugin.
40  * This plugin logs one or more (or even all) interfaces to data files
41  * for later replay or analyzing.
42  *
43  * @author Tim Niemueller
44  */
45 
46 /** Constructor.
47  * @param config Fawkes configuration
48  */
50  : Plugin(config)
51 {
52  std::set<std::string> ifaces;
53 
54  std::string prefix = "/fawkes/bblogger/";
55  std::string replay_prefix = "/fawkes/bblogreplay/";
56 
57  std::string scenario = "";
58  try {
59  scenario = config->get_string((prefix + "scenario").c_str());
60  } catch (Exception &e) {
61  e.append("No scenario defined, configure %sscenario", prefix.c_str());
62  throw;
63  }
64 
65  /*
66  bool generate_replay_config = false;
67  try {
68  generate_replay_config = config->get_bool((prefix + "generate_replay_config").c_str());
69  } catch (Exception &e) {} // ignored, use default set above
70  */
71 
72  std::string scenario_prefix = prefix + scenario + "/";
73  std::string ifaces_prefix = scenario_prefix + "interfaces/";
74 
75  std::string logdir = LOGDIR;
76  bool buffering = true;
77  bool flushing = false;
78  try {
79  logdir = config->get_string((scenario_prefix + "logdir").c_str());
80  } catch (Exception &e) { /* ignored, use default set above */ }
81  try {
82  buffering = config->get_bool((scenario_prefix + "buffering").c_str());
83  } catch (Exception &e) { /* ignored, use default set above */ }
84  try {
85  flushing = config->get_bool((scenario_prefix + "flushing").c_str());
86  } catch (Exception &e) { /* ignored, use default set above */ }
87 
88  struct stat s;
89  int err = stat(logdir.c_str(), &s);
90  if (err != 0) {
91  char buf[1024];
92  Exception se ("Cannot access logdir %s (%s)",
93  logdir.c_str(), strerror_r(errno, buf, 1024));
94  if (mkdir(logdir.c_str(), 0755) != 0) {
95  se.append("Failed to create log directory (%s)",
96  strerror_r(errno, buf, 1024));
97  throw se;
98  }
99  } else if ( ! S_ISDIR(s.st_mode) ) {
100  throw Exception("Logdir path %s is not a directory", logdir.c_str());
101  }
102 
103  // We do not have the framework clock available at this point, but for the start
104  // time of the log we are only interested in the system time anyway
105  Time start;
106 
107  char date[21];
108  Time now;
109  struct tm *tmp = localtime(&(now.get_timeval()->tv_sec));
110  strftime(date, 21, "%F-%H-%M-%S", tmp);
111  std::string replay_cfg_prefix = replay_prefix + scenario + "-" + date + "/logs/";
112 
113  Configuration::ValueIterator *i = config->search(ifaces_prefix.c_str());
114  while (i->next()) {
115  std::string iface_name = std::string(i->path()).substr(ifaces_prefix.length());
116  iface_name = iface_name.substr(0, iface_name.find("/"));
117 
118  //printf("Adding sync thread for peer %s\n", peer.c_str());
119  BBLoggerThread *log_thread = new BBLoggerThread(i->get_string().c_str(),
120  logdir.c_str(),
121  buffering, flushing,
122  scenario.c_str(), &start);
123 
124  std::string filename = log_thread->get_filename();
125  config->set_string((replay_cfg_prefix + iface_name + "/file").c_str(), filename);
126 
127  thread_list.push_back(log_thread);
128  }
129  delete i;
130 
131  if ( thread_list.empty() ) {
132  throw Exception("No interfaces configured for logging, aborting");
133  }
134 
135  BBLoggerThread *bblt = dynamic_cast<BBLoggerThread *>(thread_list.front());
137 }
138 
139 PLUGIN_DESCRIPTION("Write BlackBoard interface data to files")
140 EXPORT_PLUGIN(BlackBoardLoggerPlugin)
Plugin interface class.
Definition: plugin.h:33
const timeval * get_timeval() const
Obtain the timeval where the time is stored.
Definition: time.h:109
BlackBoardLoggerPlugin(fawkes::Configuration *config)
Constructor.
const char * get_filename() const
Get filename.
Definition: log_thread.cpp:220
Fawkes library namespace.
virtual bool get_bool(const char *path)=0
Get value from configuration which is of type bool.
virtual ValueIterator * search(const char *path)=0
Iterator with search results.
A class for handling time.
Definition: time.h:91
virtual bool next()=0
Check if there is another element and advance to this if possible.
BlackBoard logger thread.
Definition: log_thread.h:46
BlackBoard logger plugin.
Base class for exceptions in Fawkes.
Definition: exception.h:36
ThreadList thread_list
Thread list member.
Definition: plugin.h:53
virtual std::string get_string() const =0
Get string value.
virtual const char * path() const =0
Path of value.
void set_threadlist(fawkes::ThreadList &thread_list)
Set threadlist and master status.
Definition: log_thread.cpp:254
void push_back(Thread *thread)
Add thread to the end.
Iterator interface to iterate over config values.
Definition: config.h:72
Interface for configuration handling.
Definition: config.h:67
virtual void set_string(const char *path, std::string &s)=0
Set new value in configuration of type string.
void append(const char *format,...)
Append messages to the message list.
Definition: exception.cpp:341
virtual std::string get_string(const char *path)=0
Get value from configuration which is of type string.