Fawkes API Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * bblogger_plugin.cpp - Fawkes BlackBoard Logger Plugin 00004 * 00005 * Created: Sat Nov 07 23:21:36 2009 00006 * Copyright 2009 Tim Niemueller [www.niemueller.de] 00007 * 00008 ****************************************************************************/ 00009 00010 /* This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. 00014 * 00015 * This program is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 * GNU Library General Public License for more details. 00019 * 00020 * Read the full text in the LICENSE.GPL file in the doc directory. 00021 */ 00022 00023 #include "bblogger_plugin.h" 00024 #include "log_thread.h" 00025 00026 #include <utils/time/time.h> 00027 00028 #include <set> 00029 00030 #include <cstring> 00031 #include <cerrno> 00032 #include <sys/types.h> 00033 #include <sys/stat.h> 00034 #include <unistd.h> 00035 00036 using namespace fawkes; 00037 00038 /** @class BlackBoardLoggerPlugin "bblogger_plugin.h" 00039 * BlackBoard logger plugin. 00040 * This plugin logs one or more (or even all) interfaces to data files 00041 * for later replay or analyzing. 00042 * 00043 * @author Tim Niemueller 00044 */ 00045 00046 /** Constructor. 00047 * @param config Fawkes configuration 00048 */ 00049 BlackBoardLoggerPlugin::BlackBoardLoggerPlugin(Configuration *config) 00050 : Plugin(config) 00051 { 00052 std::set<std::string> ifaces; 00053 00054 std::string prefix = "/fawkes/bblogger/"; 00055 std::string replay_prefix = "/fawkes/bblogreplay/"; 00056 00057 std::string scenario = ""; 00058 try { 00059 scenario = config->get_string((prefix + "scenario").c_str()); 00060 } catch (Exception &e) { 00061 e.append("No scenario defined, configure %sscenario", prefix.c_str()); 00062 throw; 00063 } 00064 00065 /* 00066 bool generate_replay_config = false; 00067 try { 00068 generate_replay_config = config->get_bool((prefix + "generate_replay_config").c_str()); 00069 } catch (Exception &e) {} // ignored, use default set above 00070 */ 00071 00072 std::string scenario_prefix = prefix + scenario + "/"; 00073 std::string ifaces_prefix = scenario_prefix + "interfaces/"; 00074 00075 std::string logdir = LOGDIR; 00076 bool buffering = true; 00077 bool flushing = false; 00078 try { 00079 logdir = config->get_string((scenario_prefix + "logdir").c_str()); 00080 } catch (Exception &e) { /* ignored, use default set above */ } 00081 try { 00082 buffering = config->get_bool((scenario_prefix + "buffering").c_str()); 00083 } catch (Exception &e) { /* ignored, use default set above */ } 00084 try { 00085 flushing = config->get_bool((scenario_prefix + "flushing").c_str()); 00086 } catch (Exception &e) { /* ignored, use default set above */ } 00087 00088 struct stat s; 00089 int err = stat(logdir.c_str(), &s); 00090 if (err != 0) { 00091 char buf[1024]; 00092 Exception se ("Cannot access logdir %s (%s)", 00093 logdir.c_str(), strerror_r(errno, buf, 1024)); 00094 if (mkdir(logdir.c_str(), 0755) != 0) { 00095 se.append("Failed to create log directory (%s)", 00096 strerror_r(errno, buf, 1024)); 00097 throw se; 00098 } 00099 } else if ( ! S_ISDIR(s.st_mode) ) { 00100 throw Exception("Logdir path %s is not a directory", logdir.c_str()); 00101 } 00102 00103 // We do not have the framework clock available at this point, but for the start 00104 // time of the log we are only interested in the system time anyway 00105 Time start; 00106 00107 char date[21]; 00108 Time now; 00109 struct tm *tmp = localtime(&(now.get_timeval()->tv_sec)); 00110 strftime(date, 21, "%F-%H-%M-%S", tmp); 00111 std::string replay_cfg_prefix = replay_prefix + scenario + "-" + date + "/logs/"; 00112 00113 Configuration::ValueIterator *i = config->search(ifaces_prefix.c_str()); 00114 while (i->next()) { 00115 std::string iface_name = std::string(i->path()).substr(ifaces_prefix.length()); 00116 iface_name = iface_name.substr(0, iface_name.find("/")); 00117 00118 //printf("Adding sync thread for peer %s\n", peer.c_str()); 00119 BBLoggerThread *log_thread = new BBLoggerThread(i->get_string().c_str(), 00120 logdir.c_str(), 00121 buffering, flushing, 00122 scenario.c_str(), &start); 00123 00124 std::string filename = log_thread->get_filename(); 00125 config->set_string((replay_cfg_prefix + iface_name + "/file").c_str(), filename); 00126 00127 thread_list.push_back(log_thread); 00128 } 00129 delete i; 00130 00131 if ( thread_list.empty() ) { 00132 throw Exception("No interfaces configured for logging, aborting"); 00133 } 00134 00135 BBLoggerThread *bblt = dynamic_cast<BBLoggerThread *>(thread_list.front()); 00136 bblt->set_threadlist(thread_list); 00137 } 00138 00139 PLUGIN_DESCRIPTION("Write BlackBoard interface data to files") 00140 EXPORT_PLUGIN(BlackBoardLoggerPlugin)