Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Nov 5, 2009, 9:22:22 PM (14 years ago)
Author:
rgrieder
Message:

Synchronised sandbox with current code trunk. There should be a few bug fixes.

Location:
sandbox
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • sandbox

  • sandbox/src/libraries/core/Core.cc

    r5782 r6038  
    3737
    3838#include <cassert>
    39 #include <fstream>
    40 #include <cstdlib>
    41 #include <cstdio>
    42 #include <boost/version.hpp>
    43 #include <boost/filesystem.hpp>
     39#include <vector>
    4440
    4541#ifdef ORXONOX_PLATFORM_WINDOWS
     
    5046#  undef min
    5147#  undef max
    52 #elif defined(ORXONOX_PLATFORM_APPLE)
    53 #  include <sys/param.h>
    54 #  include <mach-o/dyld.h>
    55 #else /* Linux */
    56 #  include <sys/types.h>
    57 #  include <unistd.h>
    58 #endif
    59 
    60 #include "SpecialConfig.h"
     48#endif
     49
     50#include "util/Clock.h"
    6151#include "util/Debug.h"
    6252#include "util/Exception.h"
    6353#include "util/SignalHandler.h"
    64 #include "Clock.h"
    65 #include "CommandLine.h"
     54#include "PathConfig.h"
     55#include "CommandLineParser.h"
    6656#include "ConfigFileManager.h"
    6757#include "ConfigValueIncludes.h"
    6858#include "CoreIncludes.h"
    6959#include "DynLibManager.h"
    70 #include "Factory.h"
    7160#include "Identifier.h"
    7261#include "Language.h"
    7362#include "LuaState.h"
    74 
    75 // Boost 1.36 has some issues with deprecated functions that have been omitted
    76 #if (BOOST_VERSION == 103600)
    77 #  define BOOST_LEAF_FUNCTION filename
    78 #else
    79 #  define BOOST_LEAF_FUNCTION leaf
    80 #endif
    8163
    8264namespace orxonox
     
    8567    Core* Core::singletonPtr_s  = 0;
    8668
    87     SetCommandLineArgument(externalDataPath, "").information("Path to the external data files");
    88     SetCommandLineOnlyArgument(writingPathSuffix, "").information("Additional subfolder for config and log files");
    8969    SetCommandLineArgument(settingsFile, "orxonox.ini").information("THE configuration file");
    9070#ifdef ORXONOX_PLATFORM_WINDOWS
     
    195175        std::string language_;                          //!< The language
    196176        bool bInitializeRandomNumberGenerator_;         //!< If true, srand(time(0)) is called
    197 
    198         //! Path to the parent directory of the ones above if program was installed with relativ pahts
    199         boost::filesystem::path rootPath_;
    200         boost::filesystem::path executablePath_;        //!< Path to the executable
    201         boost::filesystem::path modulePath_;            //!< Path to the modules
    202         boost::filesystem::path dataPath_;              //!< Path to the data file folder
    203         boost::filesystem::path configPath_;            //!< Path to the config file folder
    204         boost::filesystem::path logPath_;               //!< Path to the log file folder
    205177    };
    206178
     
    210182        : identifierDestroyer_(Identifier::destroyAllIdentifiers)
    211183        , configuration_(new CoreConfiguration()) // Don't yet create config values!
    212         , bDevRun_(false)
    213184    {
    214185        // Set the hard coded fixed paths
    215         this->setFixedPaths();
     186        this->pathConfig_.reset(new PathConfig());
    216187
    217188        // Create a new dynamic library manager
     
    219190
    220191        // Load modules
    221         try
    222         {
    223             // We search for helper files with the following extension
    224             std::string moduleextension = specialConfig::moduleExtension;
    225             size_t moduleextensionlength = moduleextension.size();
    226 
    227             // Search in the directory of our executable
    228             boost::filesystem::path searchpath = this->configuration_->modulePath_;
    229 
    230             // Add that path to the PATH variable in case a module depends on another one
    231             std::string pathVariable = getenv("PATH");
    232             putenv(const_cast<char*>(("PATH=" + pathVariable + ";" + configuration_->modulePath_.string()).c_str()));
    233 
    234             boost::filesystem::directory_iterator file(searchpath);
    235             boost::filesystem::directory_iterator end;
    236 
    237             // Iterate through all files
    238             while (file != end)
     192        const std::vector<std::string>& modulePaths = this->pathConfig_->getModulePaths();
     193        for (std::vector<std::string>::const_iterator it = modulePaths.begin(); it != modulePaths.end(); ++it)
     194        {
     195            try
    239196            {
    240                 std::string filename = file->BOOST_LEAF_FUNCTION();
    241 
    242                 // Check if the file ends with the exension in question
    243                 if (filename.size() > moduleextensionlength)
    244                 {
    245                     if (filename.substr(filename.size() - moduleextensionlength) == moduleextension)
    246                     {
    247                         // We've found a helper file - now load the library with the same name
    248                         std::string library = filename.substr(0, filename.size() - moduleextensionlength);
    249                         boost::filesystem::path librarypath = searchpath / library;
    250 
    251                         try
    252                         {
    253                             DynLibManager::getInstance().load(librarypath.string());
    254                         }
    255                         catch (...)
    256                         {
    257                             COUT(1) << "Couldn't load module \"" << librarypath.string() << "\": " << Exception::handleMessage() << std::endl;
    258                         }
    259                     }
    260                 }
    261 
    262                 ++file;
     197                this->dynLibManager_->load(*it);
    263198            }
    264         }
    265         catch (...)
    266         {
    267             COUT(1) << "An error occurred while loading modules: " << Exception::handleMessage() << std::endl;
     199            catch (...)
     200            {
     201                COUT(1) << "Couldn't load module \"" << *it << "\": " << Exception::handleMessage() << std::endl;
     202            }
    268203        }
    269204
    270205        // Parse command line arguments AFTER the modules have been loaded (static code!)
    271         CommandLine::parseCommandLine(cmdLine);
     206        CommandLineParser::parseCommandLine(cmdLine);
    272207
    273208        // Set configurable paths like log, config and media
    274         this->setConfigurablePaths();
     209        this->pathConfig_->setConfigurablePaths();
    275210
    276211        // create a signal handler (only active for linux)
    277212        // This call is placed as soon as possible, but after the directories are set
    278213        this->signalHandler_.reset(new SignalHandler());
    279         this->signalHandler_->doCatch(configuration_->executablePath_.string(), Core::getLogPathString() + "orxonox_crash.log");
     214        this->signalHandler_->doCatch(PathConfig::getExecutablePathString(), PathConfig::getLogPathString() + "orxonox_crash.log");
    280215
    281216        // Set the correct log path. Before this call, /tmp (Unix) or %TEMP% was used
    282         OutputHandler::getOutStream().setLogPath(Core::getLogPathString());
     217        OutputHandler::getOutStream().setLogPath(PathConfig::getLogPathString());
    283218
    284219        // Parse additional options file now that we know its path
    285         CommandLine::parseFile();
     220        CommandLineParser::parseFile();
    286221
    287222#ifdef ORXONOX_PLATFORM_WINDOWS
     
    289224        // do this after ogre has initialised. Somehow Ogre changes the settings again (not through
    290225        // the timer though).
    291         int limitToCPU = CommandLine::getValue("limitToCPU");
     226        int limitToCPU = CommandLineParser::getValue("limitToCPU");
    292227        if (limitToCPU > 0)
    293228            setThreadAffinity(static_cast<unsigned int>(limitToCPU));
     
    297232        this->configFileManager_.reset(new ConfigFileManager());
    298233        this->configFileManager_->setFilename(ConfigFileType::Settings,
    299             CommandLine::getValue("settingsFile").getString());
     234            CommandLineParser::getValue("settingsFile").getString());
    300235
    301236        // Required as well for the config values
     
    303238
    304239        // creates the class hierarchy for all classes with factories
    305         Factory::createClassHierarchy();
     240        Identifier::createClassHierarchy();
    306241
    307242        // Do this soon after the ConfigFileManager has been created to open up the
     
    376311    }
    377312
    378     /*static*/ const boost::filesystem::path& Core::getDataPath()
    379     {
    380         return getInstance().configuration_->dataPath_;
    381     }
    382     /*static*/ std::string Core::getDataPathString()
    383     {
    384         return getInstance().configuration_->dataPath_.string() + '/';
    385     }
    386 
    387     /*static*/ const boost::filesystem::path& Core::getConfigPath()
    388     {
    389         return getInstance().configuration_->configPath_;
    390     }
    391     /*static*/ std::string Core::getConfigPathString()
    392     {
    393         return getInstance().configuration_->configPath_.string() + '/';
    394     }
    395 
    396     /*static*/ const boost::filesystem::path& Core::getLogPath()
    397     {
    398         return getInstance().configuration_->logPath_;
    399     }
    400     /*static*/ std::string Core::getLogPathString()
    401     {
    402         return getInstance().configuration_->logPath_.string() + '/';
    403     }
    404 
    405     /*static*/ const boost::filesystem::path& Core::getRootPath()
    406     {
    407         return getInstance().configuration_->rootPath_;
    408     }
    409     /*static*/ std::string Core::getRootPathString()
    410     {
    411         return getInstance().configuration_->rootPath_.string() + '/';
    412     }
    413 
    414313    /**
    415314    @note
     
    458357    }
    459358
    460     /**
    461     @brief
    462         Retrievs the executable path and sets all hard coded fixed path (currently only the module path)
    463         Also checks for "orxonox_dev_build.keep_me" in the executable diretory.
    464         If found it means that this is not an installed run, hence we
    465         don't write the logs and config files to ~/.orxonox
    466     @throw
    467         GeneralException
    468     */
    469     void Core::setFixedPaths()
    470     {
    471         //////////////////////////
    472         // FIND EXECUTABLE PATH //
    473         //////////////////////////
    474 
    475 #ifdef ORXONOX_PLATFORM_WINDOWS
    476         // get executable module
    477         TCHAR buffer[1024];
    478         if (GetModuleFileName(NULL, buffer, 1024) == 0)
    479             ThrowException(General, "Could not retrieve executable path.");
    480 
    481 #elif defined(ORXONOX_PLATFORM_APPLE)
    482         char buffer[1024];
    483         unsigned long path_len = 1023;
    484         if (_NSGetExecutablePath(buffer, &path_len))
    485             ThrowException(General, "Could not retrieve executable path.");
    486 
    487 #else /* Linux */
    488         /* written by Nicolai Haehnle <prefect_@gmx.net> */
    489 
    490         /* Get our PID and build the name of the link in /proc */
    491         char linkname[64]; /* /proc/<pid>/exe */
    492         if (snprintf(linkname, sizeof(linkname), "/proc/%i/exe", getpid()) < 0)
    493         {
    494             /* This should only happen on large word systems. I'm not sure
    495                what the proper response is here.
    496                Since it really is an assert-like condition, aborting the
    497                program seems to be in order. */
    498             assert(false);
    499         }
    500 
    501         /* Now read the symbolic link */
    502         char buffer[1024];
    503         int ret;
    504         ret = readlink(linkname, buffer, 1024);
    505         /* In case of an error, leave the handling up to the caller */
    506         if (ret == -1)
    507             ThrowException(General, "Could not retrieve executable path.");
    508 
    509         /* Ensure proper NUL termination */
    510         buffer[ret] = 0;
    511 #endif
    512 
    513         configuration_->executablePath_ = boost::filesystem::path(buffer);
    514 #ifndef ORXONOX_PLATFORM_APPLE
    515         configuration_->executablePath_ = configuration_->executablePath_.branch_path(); // remove executable name
    516 #endif
    517 
    518         /////////////////////
    519         // SET MODULE PATH //
    520         /////////////////////
    521 
    522         if (boost::filesystem::exists(configuration_->executablePath_ / "orxonox_dev_build.keep_me"))
    523         {
    524             COUT(1) << "Running from the build tree." << std::endl;
    525             Core::bDevRun_ = true;
    526             configuration_->modulePath_ = specialConfig::moduleDevDirectory;
    527         }
    528         else
    529         {
    530 
    531 #ifdef INSTALL_COPYABLE // --> relative paths
    532 
    533             // Also set the root path
    534             boost::filesystem::path relativeExecutablePath(specialConfig::defaultRuntimePath);
    535             configuration_->rootPath_ = configuration_->executablePath_;
    536             while (!boost::filesystem::equivalent(configuration_->rootPath_ / relativeExecutablePath, configuration_->executablePath_)
    537                    && !configuration_->rootPath_.empty())
    538                 configuration_->rootPath_ = configuration_->rootPath_.branch_path();
    539             if (configuration_->rootPath_.empty())
    540                 ThrowException(General, "Could not derive a root directory. Might the binary installation directory contain '..' when taken relative to the installation prefix path?");
    541 
    542             // Module path is fixed as well
    543             configuration_->modulePath_ = configuration_->rootPath_ / specialConfig::defaultModulePath;
    544 
    545 #else
    546 
    547             // There is no root path, so don't set it at all
    548             // Module path is fixed as well
    549             configuration_->modulePath_ = specialConfig::moduleInstallDirectory;
    550 
    551 #endif
    552         }
    553     }
    554 
    555     /**
    556     @brief
    557         Sets config, log and media path and creates folders if necessary.
    558     @throws
    559         GeneralException
    560     */
    561     void Core::setConfigurablePaths()
    562     {
    563         if (Core::isDevelopmentRun())
    564         {
    565             configuration_->dataPath_  = specialConfig::dataDevDirectory;
    566             configuration_->configPath_ = specialConfig::configDevDirectory;
    567             configuration_->logPath_    = specialConfig::logDevDirectory;
    568         }
    569         else
    570         {
    571 
    572 #ifdef INSTALL_COPYABLE // --> relative paths
    573 
    574             // Using paths relative to the install prefix, complete them
    575             configuration_->dataPath_   = configuration_->rootPath_ / specialConfig::defaultDataPath;
    576             configuration_->configPath_ = configuration_->rootPath_ / specialConfig::defaultConfigPath;
    577             configuration_->logPath_    = configuration_->rootPath_ / specialConfig::defaultLogPath;
    578 
    579 #else
    580 
    581             configuration_->dataPath_  = specialConfig::dataInstallDirectory;
    582 
    583             // Get user directory
    584 #  ifdef ORXONOX_PLATFORM_UNIX /* Apple? */
    585             char* userDataPathPtr(getenv("HOME"));
    586 #  else
    587             char* userDataPathPtr(getenv("APPDATA"));
    588 #  endif
    589             if (userDataPathPtr == NULL)
    590                 ThrowException(General, "Could not retrieve user data path.");
    591             boost::filesystem::path userDataPath(userDataPathPtr);
    592             userDataPath /= ".orxonox";
    593 
    594             configuration_->configPath_ = userDataPath / specialConfig::defaultConfigPath;
    595             configuration_->logPath_    = userDataPath / specialConfig::defaultLogPath;
    596 
    597 #endif
    598 
    599         }
    600 
    601         // Option to put all the config and log files in a separate folder
    602         if (!CommandLine::getArgument("writingPathSuffix")->hasDefaultValue())
    603         {
    604             std::string directory(CommandLine::getValue("writingPathSuffix").getString());
    605             configuration_->configPath_ = configuration_->configPath_ / directory;
    606             configuration_->logPath_    = configuration_->logPath_    / directory;
    607         }
    608 
    609         // Create directories to avoid problems when opening files in non existent folders.
    610         std::vector<std::pair<boost::filesystem::path, std::string> > directories;
    611         directories.push_back(std::make_pair(boost::filesystem::path(configuration_->configPath_), "config"));
    612         directories.push_back(std::make_pair(boost::filesystem::path(configuration_->logPath_), "log"));
    613 
    614         for (std::vector<std::pair<boost::filesystem::path, std::string> >::iterator it = directories.begin();
    615             it != directories.end(); ++it)
    616         {
    617             if (boost::filesystem::exists(it->first) && !boost::filesystem::is_directory(it->first))
    618             {
    619                 ThrowException(General, std::string("The ") + it->second + " directory has been preoccupied by a file! \
    620                                          Please remove " + it->first.string());
    621             }
    622             if (boost::filesystem::create_directories(it->first)) // function may not return true at all (bug?)
    623             {
    624                 COUT(4) << "Created " << it->second << " directory" << std::endl;
    625             }
    626         }
    627     }
    628 
    629359    void Core::preUpdate(const Clock& time)
    630360    {
Note: See TracChangeset for help on using the changeset viewer.