00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "deployer-funcs.hpp"
00023 #include <rtt/Logger.hpp>
00024 #include <cstdio>
00025 #include <iostream>
00026 #include <sstream>
00027 #include <string>
00028 #include <functional>
00029 #include <boost/program_options.hpp>
00030 #include <boost/program_options/positional_options.hpp>
00031 #include <boost/assign/list_of.hpp>
00032 #include <boost/algorithm/string/case_conv.hpp>
00033
00034 #if defined(ORO_BUILD_LOGGING) && defined(OROSEM_LOG4CPP_LOGGING)
00035
00036 #include <log4cpp/Category.hh>
00037 #include <log4cpp/FileAppender.hh>
00038 #include <log4cpp/PatternLayout.hh>
00039 #include <log4cpp/PropertyConfigurator.hh>
00040 #endif
00041
00042 namespace po = boost::program_options;
00043
00044 using namespace RTT;
00045 using namespace std;
00046
00047 #define ORO_xstr(s) ORO_str(s)
00048 #define ORO_str(s) #s
00049
00050 namespace OCL
00051 {
00052
00053
00054 std::map<std::string, RTT::Logger::LogLevel> logMap =
00055 boost::assign::map_list_of
00056 ("never", RTT::Logger::Debug)
00057 ("fatal", RTT::Logger::Fatal)
00058 ("critical", RTT::Logger::Critical)
00059 ("error", RTT::Logger::Error)
00060 ("warning", RTT::Logger::Warning)
00061 ("info", RTT::Logger::Info)
00062 ("debug", RTT::Logger::Debug)
00063 ("realtime", RTT::Logger::RealTime);
00064
00065 int deployerParseCmdLine(int argc,
00066 char** argv,
00067 std::string& siteFile,
00068 std::vector<std::string>& scriptFiles,
00069 std::string& name,
00070 bool& requireNameService,
00071 po::variables_map& vm,
00072 po::options_description* otherOptions)
00073 {
00074 std::string logLevel("info");
00075 po::options_description options;
00076 po::options_description allowed("Allowed options");
00077 po::positional_options_description pos;
00078 allowed.add_options()
00079 ("help,h",
00080 "Show program usage")
00081 ("version",
00082 "Show program version")
00083 ("start,s",
00084 po::value< std::vector<std::string> >(&scriptFiles),
00085 "Deployment XML or script file (eg 'config-file.xml' or 'script.ops')")
00086 ("site-file",
00087 po::value<std::string>(&siteFile),
00088 "Site deployment XML file (eg 'Deployer-site.cpf' or 'Deployer-site.xml')")
00089 ("log-level,l",
00090 po::value<std::string>(&logLevel),
00091 "Level at which to log from RTT (case-insensitive) Never,Fatal,Critical,Error,Warning,Info,Debug,Realtime")
00092 ("no-consolelog",
00093 "Turn off RTT logging to the console (will still log to 'orocos.log')")
00094 ("require-name-service",
00095 "Require CORBA name service")
00096 ("DeployerName",
00097 po::value<std::string>(&name),
00098 "Name of deployer component (the --DeployerName flag is optional)")
00099 ;
00100 pos.add("DeployerName", 1);
00101
00102
00103 options.add(allowed);
00104 if (NULL != otherOptions)
00105 {
00106 options.add(*otherOptions);
00107 }
00108
00109 try
00110 {
00111 po::store(po::command_line_parser(argc, argv).
00112 options(options).positional(pos).run(),
00113 vm);
00114 po::notify(vm);
00115
00116
00117 if (vm.count("help"))
00118 {
00119 std::cout << options << std::endl;
00120 return 1;
00121 }
00122
00123
00124 if (vm.count("version"))
00125 {
00126 std::cout<< " OROCOS Toolchain version '" ORO_xstr(RTT_VERSION) "'";
00127 #ifdef __GNUC__
00128 std::cout << " ( GCC " ORO_xstr(__GNUC__) "." ORO_xstr(__GNUC_MINOR__) "." ORO_xstr(__GNUC_PATCHLEVEL__) " )";
00129 #endif
00130 #ifdef OROPKG_OS_LXRT
00131 std::cout<<" -- LXRT/RTAI.";
00132 #endif
00133 #ifdef OROPKG_OS_GNULINUX
00134 std::cout<<" -- GNU/Linux.";
00135 #endif
00136 #ifdef OROPKG_OS_XENOMAI
00137 std::cout<<" -- Xenomai.";
00138 #endif
00139 std::cout << endl;
00140 return 1;
00141 }
00142
00143
00144 if (vm.count("no-consolelog"))
00145 {
00146 RTT::Logger::Instance()->mayLogStdOut(false);
00147 log(Warning) << "Console logging disabled" << endlog();
00148 }
00149
00150 if (vm.count("require-name-service"))
00151 {
00152 requireNameService = true;
00153 log(Info) << "CORBA name service required." << endlog();
00154 }
00155
00156
00157 logLevel = boost::algorithm::to_lower_copy(logLevel);
00158 if (vm.count("log-level"))
00159 {
00160 if (0 != logMap.count(logLevel))
00161 {
00162 RTT::Logger::Instance()->setLogLevel(logMap[logLevel]);
00163 }
00164 else
00165 {
00166 std::cout << "Did not understand log level: "
00167 << logLevel << std::endl
00168 << options << std::endl;
00169 return -1;
00170 }
00171 }
00172 if (vm.count("DeployerName")) {
00173 if (name.find_last_of(".xml") != string::npos ||
00174 name.find_last_of(".cpf") != string::npos ||
00175 name.find_last_of(".osd") != string::npos ||
00176 name.find_last_of(".ops") != string::npos )
00177 log(Warning) <<"The given Deployer name "<<name <<" resembles a filename. Did you forget to use '-s' ?"<<endlog();
00178 }
00179 }
00180 catch (std::logic_error e)
00181 {
00182 std::cerr << "Exception:" << e.what() << std::endl << options << std::endl;
00183 return -1;
00184 }
00185
00186 return 0;
00187 }
00188
00189 #ifdef ORO_BUILD_RTALLOC
00190
00191 void validate(boost::any& v,
00192 const std::vector<std::string>& values,
00193 memorySize* target_type, int)
00194 {
00195
00196
00197
00198 po::validators::check_first_occurrence(v);
00199
00200
00201 const std::string& memSize = po::validators::get_single_string(values);
00202
00203
00204
00205
00206
00207
00208
00209
00210 float value=0;
00211 char units='\0';
00212 if (2 == sscanf(memSize.c_str(), "%f%c", &value, &units))
00213 {
00214 float multiplier=1;
00215 if (islower(units))
00216 {
00217 units = toupper(units);
00218 }
00219 switch (units)
00220 {
00221 case 'G':
00222 multiplier *= 1024;
00223
00224 case 'M':
00225 multiplier *= 1024;
00226
00227 case 'K':
00228 multiplier *= 1024;
00229 break;
00230 default:
00231 std::stringstream e;
00232 e << "Invalid units in rtalloc-mem-size option: " << memSize
00233 << ". Valid units: 'k','m','g' (case-insensitive).";
00234 throw po::invalid_option_value(e.str());
00235 }
00236 value *= multiplier;
00237 }
00238 else if (1 == sscanf(memSize.c_str(), "%f", &value))
00239 {
00240
00241 }
00242 else
00243 {
00244 throw po::invalid_option_value("Could not parse rtalloc-mem-size option: " + memSize);
00245 }
00246
00247
00248
00249
00250
00251
00252 if (! (0 <= value) )
00253 {
00254 std::stringstream e;
00255 e << "Invalid memory size of " << value << " given. Value must be >= 0.";
00256 throw po::invalid_option_value(e.str());
00257 }
00258
00259 v = memorySize((size_t)value);
00260 }
00261
00262
00263 boost::program_options::options_description deployerRtallocOptions(memorySize& rtallocMemorySize)
00264 {
00265 boost::program_options::options_description rtallocOptions("Real-time memory allocation options");
00266 rtallocOptions.add_options()
00267 ("rtalloc-mem-size",
00268 po::value<memorySize>(&rtallocMemorySize)->default_value(rtallocMemorySize),
00269 "Amount of memory to provide for real-time memory allocations (e.g. 10000, 1K, 4.3m)\n"
00270 "NB the minimum size depends on TLSF build options, but it is several kilobytes.")
00271 ;
00272 return rtallocOptions;
00273 }
00274
00275 #endif // ORO_BUILD_RTALLOC
00276
00277
00278 #if defined(ORO_BUILD_LOGGING) && defined(OROSEM_LOG4CPP_LOGGING)
00279
00280 boost::program_options::options_description deployerRttLog4cppOptions(std::string& rttLog4cppConfigFile)
00281 {
00282 po::options_description rttLog4cppOptions("RTT/Log4cpp options");
00283 rttLog4cppOptions.add_options()
00284 ("rtt-log4cpp-config-file",
00285 po::value<std::string>(&rttLog4cppConfigFile),
00286 std::string("Log4cpp configuration file to support RTT category '" + RTT::Logger::log4cppCategoryName + "'\n"+
00287 "WARNING Configure only this category. Use deployment files to configure realtime logging!").c_str())
00288 ;
00289 return rttLog4cppOptions;
00290 }
00291
00292 int deployerConfigureRttLog4cppCategory(const std::string& rttLog4cppConfigFile)
00293 {
00294
00295
00296 if (!rttLog4cppConfigFile.empty())
00297 {
00298 try
00299 {
00300 log4cpp::PropertyConfigurator::configure(rttLog4cppConfigFile);
00301 }
00302 catch (log4cpp::ConfigureFailure& e)
00303 {
00304 std::cerr << "ERROR: Unable to read/parse log4cpp configuration file\n"
00305 << e.what() << std::endl;
00306 return false;
00307 }
00308 }
00309 else
00310 {
00311
00312 log4cpp::PatternLayout* layout=0;
00313 log4cpp::Appender* appender=0;
00314 appender = new log4cpp::FileAppender(RTT::Logger::log4cppCategoryName,
00315 "orocos.log");
00316
00317 layout = new log4cpp::PatternLayout();
00318
00319 layout->setConversionPattern("%d{%Y%m%dT%T.%l} [%p] %m%n");
00320 appender->setLayout(layout);
00321
00322 log4cpp::Category& category =
00323 log4cpp::Category::getInstance(RTT::Logger::log4cppCategoryName);
00324 category.setAppender(appender);
00325
00326 }
00327 return true;
00328 }
00329
00330 #endif // OROSEM_LOG4CPP_LOGGING
00331
00332
00333 }