User Manual, Developers Guide and API Documentation

Application.cpp

Go to the documentation of this file.
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 

Generated on Mon May 21 03:31:58 2012 for openWNS by  doxygen 1.5.5