![]() |
User Manual, Developers Guide and API Documentation |
![]() |
00001 /******************************************************************************* 00002 * This file is part of openWNS (open Wireless Network Simulator) 00003 * _____________________________________________________________________________ 00004 * 00005 * Copyright (C) 2004-2007 00006 * Chair of Communication Networks (ComNets) 00007 * Kopernikusstr. 16, D-52074 Aachen, Germany 00008 * phone: ++49-241-80-27910, 00009 * fax: ++49-241-80-22242 00010 * email: info@openwns.org 00011 * www: http://www.openwns.org 00012 * _____________________________________________________________________________ 00013 * 00014 * openWNS is free software; you can redistribute it and/or modify it under the 00015 * terms of the GNU Lesser General Public License version 2 as published by the 00016 * Free Software Foundation; 00017 * 00018 * openWNS is distributed in the hope that it will be useful, but WITHOUT ANY 00019 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 00020 * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 00021 * details. 00022 * 00023 * You should have received a copy of the GNU Lesser General Public License 00024 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00025 * 00026 ******************************************************************************/ 00027 00028 #include <WNS/simulator/Application.hpp> 00029 #include <WNS/simulator/SignalHandler.hpp> 00030 00031 #include <WNS/testing/DetailedListener.hpp> 00032 #include <WNS/logger/Master.hpp> 00033 #include <WNS/Assure.hpp> 00034 #include <WNS/TypeInfo.hpp> 00035 #include <WNS/TestFixture.hpp> 00036 #include <WNS/events/scheduler/Interface.hpp> 00037 #include <WNS/simulator/Simulator.hpp> 00038 #include <WNS/simulator/UnitTests.hpp> 00039 #include <WNS/simulator/OutputPreparation.hpp> 00040 #include <WNS/events/MemberFunction.hpp> 00041 00042 //#include <WNS/module/CurrentVersion.hpp> 00043 #include <WNS/module/Base.hpp> 00044 00045 #include <WNS/simulator/AbortHandler.hpp> 00046 #include <WNS/simulator/InterruptHandler.hpp> 00047 #include <WNS/simulator/SegmentationViolationHandler.hpp> 00048 #include <WNS/simulator/SignalHandler.hpp> 00049 #include <WNS/simulator/CPUTimeExhaustedHandler.hpp> 00050 #ifdef WNS_SMARTPTR_DEBUGGING 00051 # include <WNS/SmartPtrBase.hpp> 00052 #endif 00053 00054 #ifdef WNS_SMARTPTR_DEBUGGING 00055 #include <WNS/SmartPtrBase.hpp> 00056 #endif 00057 00058 #ifdef WNS_SMARTPTR_DEBUGGING 00059 #include <WNS/SmartPtrBase.hpp> 00060 #endif 00061 00062 #include <cppunit/extensions/TestFactoryRegistry.h> 00063 #include <cppunit/ui/text/TestRunner.h> 00064 #include <cppunit/TestResult.h> 00065 #include <cppunit/CompilerOutputter.h> 00066 00067 #include <boost/program_options/value_semantic.hpp> 00068 00069 #include <sys/times.h> 00070 00071 #include <csignal> 00072 #include <dlfcn.h> 00073 #include <iomanip> 00074 #include <memory> 00075 #include <fstream> 00076 #include <climits> 00077 #ifdef CALLGRIND 00078 // For callgrind flavour, to turn on instrumentalisation 00079 #include <valgrind/callgrind.h> 00080 #endif 00081 00082 using namespace wns::simulator; 00083 00084 ModuleDependencyMismatchException::ModuleDependencyMismatchException() : 00085 wns::Exception("Module dependency not met!\n") 00086 { 00087 } 00088 00089 Application::Application() : 00090 status_(0), 00091 configFile_("config.py"), 00092 configuration_(), 00093 verbose_(false), 00094 testing_(false), 00095 compilerTestingOutput_(false), 00096 testNames_(), 00097 pyConfigPatches_(), 00098 options_(), 00099 arguments_(), 00100 programName_("openwns"), 00101 debuggerName_("gdb"), 00102 attachDebugger_(false), 00103 interactiveConfig_(false), 00104 logger_("WNS", "Application", NULL), 00105 extendedPrecision_(false), 00106 moduleViews_(), 00107 listLoadedModules_(false), 00108 loadedModules_(), 00109 lazyBinding_(false), 00110 absolutePath_(false), 00111 statusReport(), 00112 probeWriter() 00113 { 00114 options_.add_options() 00115 00116 ("help,?", 00117 "display this help and exit") 00118 00119 ("config-file,f", 00120 boost::program_options::value<std::string>(&configFile_)->default_value("config.py"), 00121 "load config from configuration file") 00122 00123 ("attach-debugger-on-segfault,s", 00124 boost::program_options::value<std::string>(&debuggerName_), 00125 "fire up gdb on segfault, arg = command for debugger") 00126 00127 ("stop-in-debugger-on-assure,d", 00128 boost::program_options::bool_switch(&wns::Assure::useSIGTRAP), 00129 "stop in debugger if an 'assure' fired (no exception will be thrown)") 00130 00131 ("interactive-configuration,i", 00132 boost::program_options::bool_switch(&interactiveConfig_), 00133 "after reading config start an interactive shell which allows modification of the configuration, use 'continue' to exit shell and run openWNS") 00134 00135 ("unit-tests,t", 00136 boost::program_options::bool_switch(&testing_), 00137 "test mode: run unit tests specified with -T or default suite if no tests with -T given") 00138 00139 ("compiler-unit-tests,c", 00140 boost::program_options::bool_switch(&compilerTestingOutput_), 00141 "the test output is made compiler compatible to improve interworking with your IDE, use with -t") 00142 00143 ("named-unit-tests,T", 00144 boost::program_options::value<TestNameContainer>(&testNames_), 00145 "run named unit test (defined multipple time for multiple tests), e.g. wns::pyconfig::tests::ParserTest, use with -t") 00146 00147 ("python-path,P", 00148 "print Python path and exit") 00149 00150 ("verbose,v", 00151 boost::program_options::bool_switch(&verbose_), 00152 "verbose mode (version information and verbose tests)") 00153 00154 ("patch-config,y", 00155 boost::program_options::value<PyConfigPatchContainer>(&pyConfigPatches_), 00156 "patch the configuration with the given Python expression") 00157 00158 ("extended-precision", 00159 boost::program_options::bool_switch(&extendedPrecision_), 00160 "enabled arithmetic operations with extended precision (80 bit) in x87 (disables strict IEEE754 compatibility)") 00161 00162 ("show-modules,M", 00163 boost::program_options::bool_switch(&listLoadedModules_), 00164 "show modules that have been loaded") 00165 00166 ("lazy-linking,l", 00167 boost::program_options::bool_switch(&lazyBinding_), 00168 "be lazy and link when needed (not at start-up)") 00169 ; 00170 } 00171 00172 Application::~Application() 00173 { 00174 std::cout << "\nwns::simulator::Application: shutdown complete\n"; 00175 } 00176 00177 void 00178 Application::doReadCommandLine(int argc, char* argv[]) 00179 { 00180 programName_ = std::string(argv[0]); 00181 00182 boost::program_options::store( 00183 boost::program_options::parse_command_line(argc, argv, options_), 00184 arguments_); 00185 boost::program_options::notify(arguments_); 00186 } 00187 00188 void 00189 Application::doInit() 00190 { 00191 if (!extendedPrecision_) 00192 { 00193 Application::disableX87ExtendedFloatingPointPrecision(); 00194 } 00195 00196 if (arguments_.count("help") > 0) 00197 { 00198 std::cout << options_ << "\n"; 00199 status_ = 0; 00200 exit(0); 00201 } 00202 00203 if (arguments_.count("python-path") > 0) 00204 { 00205 std::cout << getPathToPyConfig() << std::endl; 00206 status_ = 0; 00207 exit(0); 00208 } 00209 00210 // if -s is specified we need to attach the debugger 00211 attachDebugger_ = arguments_.count("attach-debugger-on-segfault") > 0; 00212 00213 #ifdef __x86_32__ 00214 // Patch path for 32bit Python 00215 configuration_.patch("import sys\n" 00216 "import os\n" 00217 "import os.path\n" 00218 "newPathOK = os.path.exists('/usr/lib32/python2.6')\n" 00219 "oldPathOK = os.path.exists('/usr/lib32/python2.5')\n" 00220 "assert newPathOK or oldPathOK, '32bit Python not installed'\n" 00221 "if newPathOK:\n" 00222 " sys.path.insert(0, '/usr/lib32/python2.6')\n" 00223 " sys.path.insert(0, '/usr/lib32/python2.6/lib-dynload')\n" 00224 " sys.path.insert(0, '/usr/lib32/python2.6/dist-packages/Numeric')\n" 00225 " sys.path.insert(0, '/usr/lib32/python2.6/dist-packages')\n" 00226 " sys.path.insert(0, '/usr/lib32/python2.6/dist-packages/psycopg2')\n" 00227 " sys.path.insert(0, '/usr/lib32/python2.6/dist-packages/numpy/core')\n" 00228 "else:\n" 00229 " sys.path.insert(0, '/usr/lib32/python2.5')\n" 00230 " sys.path.insert(0, '/usr/lib32/python2.5/lib-dynload')\n" 00231 " sys.path.insert(0, '/usr/lib32/python2.5/site-packages/Numeric')\n" 00232 " sys.path.insert(0, '/usr/lib32/python2.5/site-packages')\n" 00233 " sys.path.insert(0, '/usr/lib32/python2.5/site-packages/psycopg2')\n" 00234 " sys.path.insert(0, '/usr/lib32/python2.5/site-packages/numpy/core')\n"); 00235 #endif 00236 00237 // patch pyconfig (sys.path, command line patches ...) 00238 configuration_.appendPath(getPathToPyConfig()); 00239 configuration_.appendPath("."); 00240 configuration_.patch("__file__ = \""+configFile_+"\"\n"); // Python script should know its own name 00241 configuration_.load(configFile_); 00242 00243 // backward compatibility: patch "WNS" variable into the configuration 00244 configuration_.patch("import openwns\n" 00245 "WNS = openwns.getSimulator()\n"); 00246 00247 for(PyConfigPatchContainer::const_iterator it = pyConfigPatches_.begin(); 00248 it != pyConfigPatches_.end(); 00249 ++it) 00250 { 00251 configuration_.patch(*it); 00252 } 00253 00254 if(interactiveConfig_) 00255 { 00256 configuration_.patch("import pdb\n" 00257 "import rlcompleter\n" 00258 "pdb.Pdb.complete = rlcompleter.Completer(locals()).complete\n" 00259 "pdb.set_trace()\n"); 00260 } 00261 00262 // after pyconfig is patched, bring up Simulator singelton 00263 if (testing_) 00264 { 00265 wns::simulator::getSingleton().setInstance(new wns::simulator::UnitTests(getWNSView())); 00266 } 00267 else 00268 { 00269 wns::simulator::getSingleton().setInstance(new wns::simulator::Simulator(getWNSView())); 00270 } 00271 00272 // reset logger, now set with correct MasterLogger 00273 pyconfig::View wnsView = getWNSView(); 00274 logger_ = logger::Logger(wnsView.get<wns::pyconfig::View>("logger")); 00275 00276 // after this we can install the signal handlers as well as the 00277 // unexpected handlers, because both need the SimulatorSingleton 00278 00279 // for the backtrace to work we need to set out own unexpected handler 00280 // for exceptions 00281 std::set_unexpected(wns::simulator::Application::unexpectedHandler); 00282 00283 // register signal handlers 00284 wns::simulator::SignalHandler& handler = wns::simulator::GlobalSignalHandler::Instance(); 00285 00286 // Abort 00287 handler.addSignalHandler( 00288 SIGABRT, 00289 wns::simulator::AbortHandler()); 00290 00291 // Segfault 00292 handler.addSignalHandler( 00293 SIGSEGV, 00294 wns::simulator::SegmentationViolationHandler( 00295 attachDebugger_, 00296 debuggerName_, 00297 programName_)); 00298 00299 // Interrupt (Ctrl+c) 00300 handler.addSignalHandler( 00301 SIGINT, 00302 wns::simulator::InterruptHandler()); 00303 00304 // bring up the Monitor for the event scheduler, may only exists until the 00305 // master logger is shut down, since it has a logger 00306 if (!wnsView.isNone("eventSchedulerMonitor")) 00307 { 00308 wns::pyconfig::View monitorConfig = wnsView.getView("eventSchedulerMonitor"); 00309 eventSchedulerMonitor_.reset(new wns::events::scheduler::Monitor(monitorConfig)); 00310 eventSchedulerMonitor_->startObserving(wns::simulator::getEventScheduler()); 00311 } 00312 00313 if (listLoadedModules_) 00314 { 00315 std::cout << "The following Modules are available before dynamic loading:" << std::endl; 00316 for(module::Factory::CreateMap::iterator i = module::Factory::getMap()->begin(); 00317 i != module::Factory::getMap()->end(); 00318 ++i) 00319 { 00320 std::cout << "\t"<< i->first << std::endl; 00321 } 00322 } 00323 00324 long int nModules = wnsView.len("modules"); 00325 for(int i=0; i<nModules; ++i) 00326 { 00327 moduleViews_.push_back(wnsView.getView("modules", i)); 00328 } 00329 00330 loadModules(); 00331 00332 // prepare probes output directory according to the configured strategy 00333 00334 pyconfig::View outputStrategyView = wnsView.getView("outputStrategy"); 00335 00336 std::auto_ptr<OutputPreparationStrategy> outputPreparationStrategy( 00337 OutputPreparationStrategyFactory::creator( 00338 outputStrategyView.get<std::string>("__plugin__"))->create()); 00339 00340 outputPreparationStrategy->prepare(wnsView.get<std::string>("outputDir")); 00341 00342 // if we're not in testing mode, we need some special preparation ... 00343 if (!testing_) 00344 { 00345 writeFingerprint(); 00346 MESSAGE_SINGLE(NORMAL, logger_, "Start StatusReport"); 00347 this->statusReport.start(configuration_.getView("WNS")); 00348 this->statusReport.writeStatus(false); 00349 00350 } 00351 // register CPU cycles probe 00352 cpuCyclesProbe_ = wns::probe::bus::ContextCollectorPtr( 00353 new wns::probe::bus::ContextCollector( 00354 wnsView.get<std::string>("cpuCyclesProbeBusName"))); 00355 } 00356 00357 void 00358 Application::doRun() 00359 { 00360 00361 00362 // StartUp: 00363 std::list<module::Base*>::iterator itr; 00364 std::list<module::Base*>::iterator itrEnd = loadedModules_.end(); 00365 00366 MESSAGE_SINGLE(NORMAL, logger_, "Start up modules"); 00367 for (itr = loadedModules_.begin(); itr != itrEnd; ++itr) 00368 { 00369 (*itr)->configure(); 00370 } 00371 00372 // Unit tests are processed here 00373 if(testing_) 00374 { 00375 CppUnit::TestFactoryRegistry& defaultRegistry = CppUnit::TestFactoryRegistry::getRegistry(wns::testsuite::Default()); 00376 CppUnit::TestSuite* masterSuite = new CppUnit::TestSuite("AllTests"); 00377 CppUnit::TestSuite* defaultSuite = new CppUnit::TestSuite("DefaultTests"); 00378 defaultSuite->addTest(defaultRegistry.makeTest()); 00379 defaultSuite->addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest()); 00380 masterSuite->addTest(defaultSuite); 00381 00382 // register disabled tests 00383 CppUnit::TestFactoryRegistry& disabledRegistry = 00384 CppUnit::TestFactoryRegistry::getRegistry(wns::testsuite::Disabled()); 00385 masterSuite->addTest(disabledRegistry.makeTest()); 00386 00387 // register performance tests 00388 CppUnit::TestFactoryRegistry& performanceRegistry = 00389 CppUnit::TestFactoryRegistry::getRegistry(wns::testsuite::Performance()); 00390 masterSuite->addTest(performanceRegistry.makeTest()); 00391 00392 // register spikes 00393 CppUnit::TestFactoryRegistry& spikeRegistry = 00394 CppUnit::TestFactoryRegistry::getRegistry(wns::testsuite::Spike()); 00395 masterSuite->addTest(spikeRegistry.makeTest()); 00396 00397 // setup testrunner 00398 CppUnit::TextTestRunner runner; 00399 std::auto_ptr<CppUnit::TestListener> listener; 00400 if(verbose_) 00401 { 00402 listener.reset(new wns::testing::DetailedListener()); 00403 } 00404 else 00405 { 00406 listener.reset(new CppUnit::TextTestProgressListener()); 00407 } 00408 runner.eventManager().addListener(listener.get()); 00409 runner.addTest(masterSuite); 00410 00411 if(compilerTestingOutput_) 00412 { 00413 runner.setOutputter(new CppUnit::CompilerOutputter(&runner.result(), std::cerr)); 00414 } 00415 00416 // Built tests (either all, or only specific ones given on the 00417 // command line) 00418 if(!testNames_.empty()) 00419 { 00420 00421 for(TestNameContainer::const_iterator ii = testNames_.begin(); 00422 ii != testNames_.end(); 00423 ++ii) 00424 { 00425 status_ = runner.run(*ii, false, true, false) ? status_ : 1; 00426 } 00427 } 00428 else 00429 { 00430 status_ = runner.run("DefaultTests", false, true, false) ? 0 : 1; 00431 } 00432 00433 } 00434 // normal simulation 00435 else 00436 { 00437 // install signal handler for graceful shutdown 00438 wns::simulator::SignalHandler& handler = wns::simulator::GlobalSignalHandler::Instance(); 00439 handler.addSignalHandler( 00440 SIGXCPU, 00441 wns::simulator::CPUTimeExhaustedHandler(wns::simulator::getEventScheduler(), SIGXCPU)); 00442 00443 double period = 00444 this->getWNSView().get<double>("probesWriteInterval"); 00445 00446 if(period != 0.0) 00447 { 00448 MESSAGE_SINGLE(NORMAL, logger_, "Starting periodic writing of probes every " << period << "s"); 00449 this->probeWriter.startPeriodicTimeout(period, period); 00450 } 00451 00452 // create and configure simulation model 00453 if (!getWNSView().isNone("simulationModel")) 00454 { 00455 wns::pyconfig::View simModelConfig = 00456 getWNSView().get("simulationModel"); 00457 00458 std::string modelName = simModelConfig.get<std::string>("nameInFactory"); 00459 ISimulationModelCreator* creator = 00460 ISimulationModelFactory::creator(modelName); 00461 00462 MESSAGE_SINGLE(NORMAL, logger_, "Creating simulation model: " << modelName); 00463 simulationModel_.reset(creator->create(simModelConfig)); 00464 MESSAGE_SINGLE(NORMAL, logger_, "Startup simulation model: " << modelName); 00465 simulationModel_->startup(); 00466 } 00467 00468 // The ProbeBus must be configured AFTER all modules have been loaded (the 00469 // modules may add implementations to static factories which can be accessed 00470 // by the ProbeBusRegistry) 00471 wns::simulator::getProbeBusRegistry()->startup(); 00472 00473 // queue event for end of simulation 00474 Time maxSimTime = getWNSView().get<wns::simulator::Time>("maxSimTime"); 00475 if (maxSimTime > 0.0) 00476 { 00477 wns::simulator::getEventScheduler()->stopAt(maxSimTime); 00478 } 00479 00480 this->statusReport.writeStatus(false, "WNSStatusBeforeEventSchedulerStart.dat"); 00481 00482 MESSAGE_SINGLE(NORMAL, logger_, "Start Scheduler"); 00483 #ifdef CALLGRIND 00484 // If we run in flavour callgrind we are only interested in collecting 00485 // profiling traces of the main event loop. So we start instrumentalization 00486 // here. Startup and shutdown are of no interest to us. 00487 CALLGRIND_START_INSTRUMENTATION; 00488 #endif 00489 00490 struct tms start, stop; 00491 times(&start); 00492 00493 wns::simulator::getEventScheduler()->start(); 00494 00495 times(&stop); 00496 cpuCyclesProbe_->put(stop.tms_utime - start.tms_utime); 00497 00498 00499 #ifdef CALLGRIND 00500 // Stop tracing profiling information 00501 CALLGRIND_STOP_INSTRUMENTATION; 00502 #endif 00503 00504 // shutdown the simulation if it has been created before 00505 if (simulationModel_.get() != NULL) 00506 { 00507 simulationModel_->shutdown(); 00508 simulationModel_.reset(); 00509 } 00510 00511 // uninstall signal handler for graceful shutdown, can only be 00512 // used in event loop 00513 handler.removeSignalHandler(SIGXCPU); 00514 00515 MESSAGE_SINGLE(NORMAL, logger_, "Sending shutdown signal"); 00516 (*wns::simulator::getShutdownSignal())(); 00517 00518 MESSAGE_SINGLE(NORMAL, logger_, "Simulation finished"); 00519 } 00520 } 00521 00522 void 00523 Application::doShutdown() 00524 { 00525 00526 #ifdef WNS_SMARTPTR_DEBUGGING 00527 MESSAGE_SINGLE(NORMAL, logger_, "SmartPtr debugging:"); 00528 wns::SmartPtrBase::printAllExistingPointers(); 00529 #endif 00530 00531 if (!testing_) 00532 { 00533 stopProbes(); 00534 } 00535 00536 // delete ProbeBusRegisty (auto_ptr) 00537 probeBusRegistry.reset(); 00538 00539 wns::simulator::getEventScheduler()->reset(); 00540 00541 #ifdef WNS_SMARTPTR_DEBUGGING 00542 wns::SmartPtrBase::printAllExistingPointers(); 00543 #endif 00544 MESSAGE_SINGLE(NORMAL, logger_, "Calling shutDown for all modules"); 00545 for(std::list<module::Base*>::iterator itr = loadedModules_.begin(); 00546 itr != loadedModules_.end(); 00547 ++itr) 00548 { 00549 (*itr)->shutDown(); 00550 } 00551 00552 MESSAGE_SINGLE(NORMAL, logger_, "Destroying all modules"); 00553 while(loadedModules_.empty() == false) 00554 { 00555 wns::module::Base* mm = *(loadedModules_.begin()); 00556 MESSAGE_SINGLE(NORMAL, logger_, "Destroying module " << wns::TypeInfo::create(*mm)); 00557 delete mm; 00558 loadedModules_.erase(loadedModules_.begin()); 00559 } 00560 00561 // print final stats and shut down the event scheduler monitor 00562 if (eventSchedulerMonitor_.get() != NULL) 00563 { 00564 eventSchedulerMonitor_->logStatistics(); 00565 eventSchedulerMonitor_.reset(); 00566 } 00567 00568 // deregister all signal handler before shutting down master logger 00569 wns::simulator::GlobalSignalHandler::Instance().removeAllSignalHandlers(); 00570 00571 // restore default state 00572 std::set_unexpected(std::terminate); 00573 00574 // Reset the logger, no MasterLogger is set, no output will be available 00575 logger_ = logger::Logger("WNS", "Application", NULL); 00576 00577 // This is the very last thing to shut down! Keep the MasterLogger up as 00578 // long as possible 00579 wns::simulator::getSingleton().shutdownInstance(); 00580 00581 // Run post processing hook in Python 00582 if (getWNSView().get<bool>("postProcessing()") == false) 00583 { 00584 throw wns::Exception("postProcessing() failed!"); 00585 } 00586 00587 } 00588 00589 00590 std::string 00591 Application::getPathToPyConfig() 00592 { 00593 // if this thing here fails you the user can set PYCONFIGPATH ... 00594 char path[PATH_MAX]; 00595 // /proc/self/exe is a link to the executable (openwns) 00596 ssize_t length = readlink( "/proc/self/exe", path, sizeof(path)-1 ); 00597 if (length <= 0) 00598 { 00599 std::cerr << "Warning: could not determine path for PyConfig (readlink('/proc/self/exe') failed."; 00600 return "./PyConfig"; 00601 } 00602 00603 path[length] = '\0'; 00604 00605 std::string fullPath(path); 00606 // find the last of occurence of '/' and replace with '\0' (terminates the 00607 // string there). this strips the executable name 00608 size_t pos = fullPath.find_last_of('/'); 00609 if(pos == std::string::npos) 00610 { 00611 std::cerr << "Warning: could not determine path for PyConfig from " << fullPath; 00612 return "./PyConfig"; 00613 } 00614 00615 std::string pathToOpenWNSExe = fullPath.substr(0, pos); 00616 // next to bin we can find the lib dir and below that the PyConfigs 00617 std::stringstream ss; 00618 ss << pathToOpenWNSExe << "/../lib/PyConfig/"; 00619 return ss.str(); 00620 } 00621 00622 wns::pyconfig::View 00623 Application::getWNSView() const 00624 { 00625 return configuration_.get("openwns.simulator.config"); 00626 } 00627 00628 int 00629 Application::doStatus() const 00630 { 00631 return status_; 00632 } 00633 00634 void 00635 Application::unexpectedHandler() 00636 { 00637 std::cerr << "openWNS: caught an unexpected exception!\n"; 00638 wns::simulator::getMasterLogger()->outputBacktrace(); 00639 exit(1); 00640 } 00641 00642 void 00643 Application::disableX87ExtendedFloatingPointPrecision() 00644 { 00645 unsigned int mode = 0x27F; 00646 asm("fldcw %0" : : "m" (*&mode)); 00647 } 00648 00649 00650 void 00651 Application::loadModules() 00652 { 00653 //std::list<wns::module::VersionInformation> moduleVersions; 00654 00655 if(verbose_) 00656 { 00657 //std::cout << wns::module::CurrentVersion.getNiceString() << std::endl; 00658 std::cout << "Loading..." << std::endl; 00659 } 00660 00661 //moduleVersions.push_back(wns::module::CurrentVersion); 00662 00663 if (!moduleViews_.empty()) 00664 { 00665 std::list<pyconfig::View> moduleViewsTmp = moduleViews_; 00666 00667 std::list<pyconfig::View>::iterator itr = moduleViewsTmp.begin(); 00668 size_t numberOfErrors = 0; 00669 std::string errorStr; 00670 00671 // walk through the list, every time a module can be successfully loaded it 00672 // is removed from the list and we start from the beginning of the list. 00673 // This will be done until the list is empty non of the remaining modules 00674 // can be loaded.It can happen that module can't be loaded the first 00675 // time. This is because the module might have dependencies on other 00676 // modules which are not loaded yet. 00677 while (!moduleViewsTmp.empty()) 00678 { 00679 if (numberOfErrors == moduleViewsTmp.size()) 00680 { 00681 std::cout << "ModuleFactory contains the following modules:" << std::endl; 00682 for(wns::module::Factory::CreateMap::iterator i = wns::module::Factory::getMap()->begin(); 00683 i != wns::module::Factory::getMap()->end(); 00684 ++i) 00685 { 00686 std::cout << "\t"<< i->first << std::endl; 00687 } 00688 throw wns::Exception( 00689 "Can't load all specified modules. Reason:\n" + 00690 errorStr); 00691 } 00692 00693 std::string libName = itr->get<std::string>("libname"); 00694 std::string moduleName = itr->get<std::string>("__plugin__"); 00695 00696 if(verbose_) 00697 { 00698 std::cout << std::setw(8) << "Library: " << libName << "\n" 00699 << "Module: " << moduleName << "\n"; 00700 } 00701 // If the ModuleFactory knows the Module the library has been opened 00702 // before (may be due to static linkage). Then we don't need to load the 00703 // library by hand. 00704 if (wns::module::Factory::knows(moduleName) == false) 00705 { 00706 bool success = wns::module::Base::load(libName, absolutePath_, verbose_, lazyBinding_); 00707 if(success == false) 00708 { 00709 // continue with next candidate 00710 errorStr += std::string(dlerror()); 00711 numberOfErrors += 1; 00712 ++itr; 00713 continue; 00714 } 00715 } 00716 // it seems we found a loadable module -> append to module list 00717 wns::module::Creator* moduleCreator = wns::module::Factory::creator(moduleName); 00718 wns::module::Base* m = moduleCreator->create(*itr); 00719 loadedModules_.push_back(m); 00720 //wns::module::VersionInformation v = m->getVersionInformation(); 00721 //moduleVersions.push_back(v); 00722 if(verbose_) 00723 { 00724 //std::cout << v.getNiceString() << std::endl; 00725 std::cout << std::endl; 00726 } 00727 moduleViewsTmp.erase(itr); 00728 // After a loadable module has been found and an error happened 00729 // before (another module could not be loaded), the first module 00730 // in the list is the one that could not be loaded. Thus we put 00731 // it to the end. 00732 if(numberOfErrors > 0) 00733 { 00734 moduleViewsTmp.push_back((*moduleViewsTmp.begin())); 00735 moduleViewsTmp.erase(moduleViewsTmp.begin()); 00736 } 00737 itr = moduleViewsTmp.begin(); 00738 numberOfErrors = 0; 00739 } 00740 00741 if(listLoadedModules_) 00742 { 00743 std::cout << "The following Modules are available after dynamic loading:" << std::endl; 00744 for(wns::module::Factory::CreateMap::iterator i = wns::module::Factory::getMap()->begin(); 00745 i != wns::module::Factory::getMap()->end(); 00746 ++i) 00747 { 00748 std::cout << "\t"<< i->first << std::endl; 00749 } 00750 } 00751 00752 } 00753 } 00754 00755 void 00756 Application::stopProbes() 00757 { 00758 probeWriter.cancelPeriodicRealTimeout(); 00759 00760 MESSAGE_BEGIN(NORMAL, logger_, m, "Writing Probes"); 00761 MESSAGE_END(); 00762 00763 try { 00764 statusReport.writeStatus(true); 00765 } 00766 catch(...) { 00767 std::cerr << "couldn't write status file.\n"; 00768 } 00769 statusReport.stop(); 00770 00771 // Trigger output for ProbeBusses 00772 wns::simulator::getProbeBusRegistry()->forwardOutput(); 00773 } 00774 00775 00776 00777 void Application::writeFingerprint() 00778 { 00779 std::string fingerprintName = getWNSView().get<std::string>("outputDir") + "/WNSFingerprint.dat"; 00780 std::ofstream fingerprint(fingerprintName.c_str()); 00781 if(!fingerprint.good()) 00782 throw wns::Exception("Couldn't create fingerprint file."); 00783 00784 fingerprint << "Version information not supported any more" << std::endl; 00785 fingerprint.close(); 00786 } 00787
1.5.5