PCMApplication.cpp

Go to the documentation of this file.
00001 //
00002 // This source file is a part of ParCompMark
00003 // Parallel Compositing Benchmark Framework
00004 //
00005 // for latest info see http://parcompmark.sourceforge.net
00006 
00007 //
00008 // Copyright (C) 2006 IT2 ParCompMark Dev. Team
00009 // 
00010 // This program is free software; you can redistribute it and/or
00011 // modify it under the terms of the GNU General Public License
00012 // as published by the Free Software Foundation; either version 2
00013 // of the License, or (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 General Public License for more details.
00019 // 
00020 // You should have received a copy of the GNU General Public License
00021 // along with this program; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00023 
00024 //
00025 // Inner includes
00026 //
00027 
00028 #include "../include/PCMApplication.h"
00029 
00030 #include "../include/PCMStringConverter.h"
00031 
00032 //
00033 // Outer includes
00034 //
00035 
00036 #include <getopt.h>
00037 #include <iostream>
00038 #include <fstream>
00039 #include <signal.h>
00040 
00041 namespace ParCompMark
00042 {
00043 
00044   // Inherited static attribute initialization
00045   template <> Application * Singleton < Application >::mInstance = 0;
00046 
00047   //
00048   // Class constants
00049   //
00050 
00051   const std::string Application::PCAPINUT = "scripts/framework/pcapi.nut";
00052   const std::string Application::PARCOMPMARKNUT = "scripts/framework/parcompmark.nut";
00053   const std::string Application::UTILSNUT = "scripts/framework/utils.nut";
00054   const std::string Application::ABBREVIATIONSNUT = "scripts/framework/abbreviations.nut";
00055   const std::string Application::DYNAMICINITNUT = "scripts/framework/dynamic-init.nut";
00056   const std::string Application::UIINITNUT = "scripts/framework/ui-init.nut";
00057   const std::string Application::COMMANDDIRECTORY = "scripts/commands/";
00058   const std::string Application::HELPNUT = "scripts/commands/help.nut";
00059   const std::string Application::PCIMPLEMENTATIONS[] = {
00060         "libpcapi.so", "libparcomp.so"
00061   };
00062 
00063   const Application::CommandLineOption Application::mCommandLineOptions[] = {
00064         {'h', "help", " ........... : show help", false, Application::showHelp}
00065         ,
00066         {'v', "version", " ........ : show version", false, Application::showVersion}
00067         ,
00068         {'c', "commander", " ...... : enable commander mode", false, Application::setCommanderOn}
00069         ,
00070         //{'g', "enable-gui", " ..... : enable GUI", false, Application::setGUIOn},
00071         //{'C', "cluster", " ........ : set cluster description", true, Application::setCluster},
00072         //{'l', "enable-lowlevel", ". : indicate the input script is a low-level script", false, Application::setLowLevelOn},
00073         //{'p', "parameters", " ..... : set input parameters from file", true, Application::setParameters},
00074         {'l', "low-level", " ...... : set low-level script file", true, Application::setLowLevelScriptFile}
00075         ,
00076         {'d', "dynamic", " ........ : set cluster dynamic script file", true, Application::setDynamicScriptFile}
00077         ,
00078         {'s', "scenario", " ....... : set scenario script file", true, Application::setScenarioScriptFile}
00079         ,
00080         {'i', "input", " .......... : set intput script file", true, Application::setInput}
00081         ,
00082         {'o', "output", " ......... : set output filename", true, Application::setOutput}
00083         ,
00084         {'H', "hostcount", " ...... : set expected number of rendering hosts", true, Application::setExpectedHostCount}
00085         ,
00086         {'u', "ui", " ............. : set user interface (none|console)", true, Application::setUserInterface}
00087   };
00088 
00089   const u32 Application::mCommandLineOptionCount = sizeof(mCommandLineOptions) / sizeof(mCommandLineOptions[0]);
00090   const std::string Application::mUsageString = "ParCompMark [ options ]";
00091 
00092   //
00093   // Class variables
00094   //
00095 
00096   std::string Application::mLibrarySearchPath = "/usr/lib";
00097   bool Application::mCommanderMode = false;
00098   bool Application::mGUIMode = false;
00099   bool Application::mManualClusterDescription = false;
00100   std::string Application::mClusterDescription;
00101   bool Application::mLowLevelMode = false;
00102   bool Application::mInteractiveParameters = true;
00103 
00104   std::string Application::mParameters;
00105   // '-' means stdin
00106   std::string Application::mInput = "-";
00107   std::string Application::mOutput = "-";
00108   int Application::mExpectedHostCount = 0;
00109 
00110   Application::UserInterface Application::mUserInterface = CONSOLE;
00111 
00112   //
00113   // Constructors & destructor
00114   //
00115 
00116   Application::Application()
00117         // You have to initialize the following attributes:
00118         // - mLibrarySearchPath
00119         // - mHostInfo
00120         // - mInitialized
00121         // - mPostCommand
00122         // - mQuiting
00123         // - mOutputIsDone
00124         // - mOutputDocument
00125         // - mCurrentExecutionOutputDocument
00126         // - mExecutionIndex
00127         // - mConfigOptions
00128         // - mLowLevelScript
00129         // - mDynamicScript
00130         // - mScenarioScript
00131         // - mSquirrelCommandList
00132         // - mDynamicScriptCompiled
00133         // - mServer
00134         // - mClient
00135         // - mCommanderMode
00136         // - mGUIMode
00137         // - mManualClusterDescription
00138         // - mClusterDescription
00139         // - mLowLevelMode
00140         // - mInteractiveParameters
00141         // - mParameters
00142         // - mInput
00143         // - mOutput
00144         // - mExpectedHostCount
00145         // - mUserInterface
00146         // - mCompRun
00147         // - mDynamicScriptSqVM
00148         // - mUserInterfaceSqVM
00149         // - mDynamicScriptParameters
00150   {
00151         mInitialized = false;
00152         mPostCommand = NOTHING;
00153         mQuiting = false;
00154         mOutputIsDone = true;
00155 
00156         mServer = 0;
00157         mClient = 0;
00158 
00159         mCompRun = false;
00160 
00161         // Initialize the application
00162         initialize();
00163 
00164         Logger::getInstance()->log(Logger::NOTICE, "PCM Application has been created.");
00165   }
00166 
00167  /*----------------------------------------------------------------------*/
00168 
00169   Application::~Application()
00170   {
00171         // Finalize the application
00172         if(mInitialized)
00173          finalize();
00174 
00175   }
00176 
00177  /*----------------------------------------------------------------------*/
00178 
00179   //
00180   // Class methods
00181   //
00182 
00183   int Application::complement(int first, int second)
00184   {
00185         //printf("Not implemented yet:)\n");
00186 
00187         return 0;
00188 
00189   }
00190 
00191  /*----------------------------------------------------------------------*/
00192 
00193   void Application::parseCommandLine(const u32 & argc, const char **&argv)
00194   {
00195         // Create getopts structure
00196         struct option long_options[mCommandLineOptionCount + 1];
00197 
00198         for(u32 i = 0; i < mCommandLineOptionCount; i++)
00199         {
00200          long_options[i].name = mCommandLineOptions[i].longName.c_str();
00201          long_options[i].has_arg = mCommandLineOptions[i].hasArgument ? required_argument : no_argument;
00202          long_options[i].flag = 0;
00203          long_options[i].val = (int) mCommandLineOptions[i].shortName;
00204         }
00205         long_options[mCommandLineOptionCount].name = 0;
00206         long_options[mCommandLineOptionCount].has_arg = 0;
00207         long_options[mCommandLineOptionCount].flag = 0;
00208         long_options[mCommandLineOptionCount].val = 0;
00209 
00210         // Create getopts string
00211         char *optionString = new char[2 * mCommandLineOptionCount + 1],
00212          *_optionString = optionString;
00213 
00214         for(u32 i = 0; i < mCommandLineOptionCount; i++)
00215         {
00216          *_optionString = mCommandLineOptions[i].shortName;
00217          _optionString++;
00218          if(mCommandLineOptions[i].hasArgument)
00219          {
00220                 *_optionString = ':';
00221                 _optionString++;
00222          }
00223         }
00224 
00225         // Parse aruments
00226         std::string _dummy;
00227         for(;;)
00228         {
00229 
00230          // getopt_long stores the option index here.
00231          int option_index = 0;
00232 
00233          int c = getopt_long(argc, (char *const *) argv, optionString, long_options, &option_index);
00234 
00235          // Parse argument
00236          if(c == -1)
00237                 break;
00238          for(u32 i = 0; i < mCommandLineOptionCount; i++)
00239                 if(c == mCommandLineOptions[i].shortName && mCommandLineOptions[i].handler)
00240                  mCommandLineOptions[i].handler(mCommandLineOptions[i].hasArgument ? std::string(optarg) : _dummy);
00241         }
00242 
00243         delete[]optionString;
00244   }
00245 
00246  /*----------------------------------------------------------------------*/
00247 
00248   void Application::showHelp(const std::string & strarg)
00249   {
00250         // Show program information
00251         std::cout << getInstance()->getProgramInfo() << std::endl;
00252 
00253         // Show usage
00254         std::cout << "usage: " << mUsageString << std::endl;
00255 
00256         // Show options
00257         std::cout << std::endl << "Options:" << std::endl;
00258         for(u32 i = 0; i < mCommandLineOptionCount; i++)
00259          std::cout << "\t-" << mCommandLineOptions[i].shortName << "\t--" << mCommandLineOptions[i].
00260                 longName << mCommandLineOptions[i].description << std::endl;
00261 
00262         // Bug report information
00263         std::cout << std::endl << "Report bugs to <" << PACKAGE_BUGREPORT << ">" << std::endl;
00264 
00265         // Quit from application
00266         Application::getInstance()->_quit();
00267         exit(0);
00268 
00269   }
00270 
00271  /*----------------------------------------------------------------------*/
00272 
00273   void Application::showVersion(const std::string & strarg)
00274   {
00275         std::cout << PACKAGE_VERSION << std::endl;
00276 
00277         Application::getInstance()->_quit();
00278         exit(0);
00279   }
00280 
00281  /*----------------------------------------------------------------------*/
00282 
00283   void Application::setCommanderOn(const std::string & strarg)
00284   {
00285         mCommanderMode = true;
00286   }
00287 
00288  /*----------------------------------------------------------------------*/
00289 
00290   void Application::setGUIOn(const std::string & strarg)
00291   {
00292         mGUIMode = true;
00293   }
00294 
00295  /*----------------------------------------------------------------------*/
00296 
00297   void Application::setLowLevelOn(const std::string & strarg)
00298   {
00299         mLowLevelMode = true;
00300   }
00301 
00302  /*----------------------------------------------------------------------*/
00303 
00304   void Application::setLowLevelScriptFile(const std::string & strarg)
00305   {
00306         Application::getInstance()->getConfigOptions()->setString("lowLevelScriptFile", "scripts/low-level/" + strarg);
00307   }
00308 
00309  /*----------------------------------------------------------------------*/
00310 
00311   void Application::setDynamicScriptFile(const std::string & strarg)
00312   {
00313         Application::getInstance()->getConfigOptions()->setString("dynamicScriptFile", "scripts/dynamic/" + strarg);
00314   }
00315 
00316  /*----------------------------------------------------------------------*/
00317 
00318   void Application::setScenarioScriptFile(const std::string & strarg)
00319   {
00320         Application::getInstance()->getConfigOptions()->setString("scenarioScriptFile", "scripts/scenario/" + strarg);
00321   }
00322 
00323  /*----------------------------------------------------------------------*/
00324 
00325   void Application::setCluster(const std::string & strarg)
00326   {
00327         mManualClusterDescription = true;
00328         mClusterDescription = strarg;
00329   }
00330 
00331  /*----------------------------------------------------------------------*/
00332 
00333   void Application::setParameters(const std::string & strarg)
00334   {
00335         mInteractiveParameters = false;
00336         mParameters = strarg;
00337   }
00338 
00339  /*----------------------------------------------------------------------*/
00340 
00341   void Application::setInput(const std::string & strarg)
00342   {
00343         mInput = strarg;
00344   }
00345 
00346  /*----------------------------------------------------------------------*/
00347 
00348   void Application::setOutput(const std::string & strarg)
00349   {
00350         mOutput = strarg;
00351   }
00352 
00353  /*----------------------------------------------------------------------*/
00354 
00355   void Application::setExpectedHostCount(const std::string & hostCount)
00356   {
00357         if(hostCount.length())
00358          mExpectedHostCount = StringConverter::toU32(hostCount);
00359         else
00360          mExpectedHostCount = 0;
00361   }
00362 
00363  /*----------------------------------------------------------------------*/
00364 
00365   void Application::setUserInterface(const std::string & strUI)
00366   {
00367         if(strUI == "none")
00368         {
00369          mUserInterface = NONE;
00370         } else if(strUI == "console")
00371         {
00372          mUserInterface = CONSOLE;
00373         } else
00374          Except(INVALID_ENUM_ERROR, "Application::setUserInterface()", strUI + " is not valid user interface.");
00375   }
00376 
00377  /*----------------------------------------------------------------------*/
00378 
00379   bool Application::hasEnvironmentVariable(const std::string & name)
00380   {
00381         char *buffer;
00382 
00383         buffer = getenv(name.c_str());
00384         return buffer;
00385   }
00386 
00387  /*----------------------------------------------------------------------*/
00388 
00389   std::string Application::getEnvironmentVariable(const std::string & name)
00390   {
00391         char *buffer;
00392 
00393         buffer = getenv(name.c_str());
00394         Assert(buffer, INVALID_NAME_ERROR, "Application::getEnvironmentVariable()");
00395         return buffer;
00396   }
00397 
00398  /*----------------------------------------------------------------------*/
00399 
00400   void Application::terminateHandler()
00401   {
00402         // Set NOP termination hander to avoid infinite loops
00403         std::set_terminate(Application::terminateHandlerNOP);
00404 
00405         if(Logger::getInstance())
00406         {
00407          Logger::getInstance()->log(Logger::FATAL, "Uncaught exception !!!");
00408          Logger::getInstance()->log(*Exception::getLastException());
00409         } else
00410         {
00411          std::cerr << "Uncaught exception !!!" << std::endl;
00412          std::cerr << Logger::translateException(*Exception::getLastException()) << std::endl;
00413         }
00414 
00415         // Try to finalize the application
00416         Application::getInstance()->finalize();
00417   }
00418 
00419  /*----------------------------------------------------------------------*/
00420 
00421   void Application::terminateHandlerNOP()
00422   {
00423         // Do nothing, this method is called when an exception is thrown during the terminateHandler()
00424   }
00425 
00426  /*----------------------------------------------------------------------*/
00427 
00428   void Application::unexpectedHandler()
00429   {
00430         Application::terminateHandler();
00431   }
00432 
00433  /*----------------------------------------------------------------------*/
00434 
00435   void Application::segfaultHandler(int value)
00436   {
00437         //asm volatile ("incl 0x44(%ebp)");
00438         //Timer::sleep(0.5);
00439   }
00440 
00441  /*----------------------------------------------------------------------*/
00442 
00443   void Application::interruptHandler(int value)
00444   {
00445         if(Logger::getInstance())
00446         {
00447          Logger::getInstance()->log(Logger::NOTICE, "Interrupt signal caught.");
00448         } else
00449         {
00450          std::cerr << "Interrupt signal caught." << std::endl;
00451         }
00452 
00453         // Quit from application
00454         Application::getInstance()->_quit();
00455         exit(0);
00456   }
00457 
00458  /*----------------------------------------------------------------------*/
00459 
00460   Application *Application::getInstance()
00461   {
00462         return Singleton < Application >::getInstance();
00463   }
00464 
00465  /*----------------------------------------------------------------------*/
00466 
00467   //
00468   // Methods
00469   //
00470 
00471   void Application::setupHandlers() const
00472   {
00473         std::set_terminate(Application::terminateHandler);
00474         std::set_unexpected(Application::unexpectedHandler);
00475 
00476         ::signal(SIGINT, Application::interruptHandler);
00477 
00478         // TODO: later will be implemented
00479         //::signal(SIGSEGV, Application::segfaultHandler);
00480   }
00481 
00482  /*----------------------------------------------------------------------*/
00483 
00484   void Application::initialize()
00485   {
00486         Assert(!mInitialized, INVALID_OPERATION_ERROR, "Application::initialize()");
00487 
00488         // Reset timer correction
00489         Timer::setTimeCorrection(0.0);
00490 
00491         // Setup handlers
00492         setupHandlers();
00493 
00494         // Initialize file system manager
00495         FileSystemManager::createInstance();
00496         FileSystemManager::getInstance()->initialize();
00497 
00498         // Initialize logger to be able to log in constructors
00499         Logger::createInstance();
00500         Logger::getInstance()->initialize();
00501 
00502         // Create root of output document with namespace definitions
00503         mOutputDocument = new OutputNode("results", OutputNode::INFORMATION);
00504         mOutputDocument->setAttribute("xmlns:def", "http://www.it2.bme.hu");
00505         mOutputDocument->setAttribute("xmlns:info", "http://www.it2.bme.hu");
00506         mOutputDocument->setAttribute("xmlns:ref", "http://www.it2.bme.hu");
00507         mOutputDocument->setAttribute("xmlns:stat", "http://www.it2.bme.hu");
00508         mCurrentExecutionOutputDocument = 0;
00509         mExecutionIndex = 0;
00510 
00511         mCollectClusterDescription = new OutputNode("cluster", OutputNode::INFORMATION);
00512 
00513         // Create configuration options
00514         mConfigOptions = new ConfigOptions();
00515         mConfigOptions->initialize();
00516 
00517         // Create ini file if needed
00518         if(!FileSystemManager::getInstance()->existsAppFile(FileSystemManager::getInstance()->getIniFile()))
00519         {
00520          // Default config options
00521          mConfigOptions->setString("dataDirectory", FileSystemManager::getInstance()->findDataDirectory(),
00522                                   "Path of application data directory");
00523 
00524          mConfigOptions->setString("frameletIcon", "true", "Disable or enable framelet icon on rendering windows");
00525 
00526          mConfigOptions->setString("broadcastPort", "1235", "Broadcast port used by parcompmark");
00527 
00528          mConfigOptions->setString("communicationPort", "1234", "Communication port used by parcompmark");
00529 
00530          // Search for PC library
00531          std::vector < std::string > additionalPaths =
00532                 Application::getInstance()->
00533                 hasEnvironmentVariable("PC_LIBRARY_PATH") ? StringConverter::tokenize(Application::getInstance()->
00534                                                                                   getEnvironmentVariable
00535                                                                                   ("PC_LIBRARY_PATH"),
00536                                                                                   ":") : std::vector < std::string >
00537                 ();
00538 
00539          // Place exotic library search paths
00540          additionalPaths.push_back("/opt/paracomp/lib/");
00541          additionalPaths.push_back("/opt/paracomp/lib64/");
00542 
00543          u32 pcImplCount = sizeof(PCIMPLEMENTATIONS) / sizeof(PCIMPLEMENTATIONS[0]);
00544 
00545          for(u32 i = 0; i < pcImplCount; i++)
00546                 if(FileSystemManager::getInstance()->existsLibrary(PCIMPLEMENTATIONS[i], additionalPaths))
00547                  mConfigOptions->setString("pcLibraryPath",
00548                                           FileSystemManager::getInstance()->findLibraryPath(PCIMPLEMENTATIONS[i],
00549                                                                                                 additionalPaths),
00550                                           "PC library path");
00551 
00552          if(!mConfigOptions->hasOption("pcLibraryPath"))
00553                 Logger::getInstance()->log(Logger::WARNING,
00554                                          "PC library path not found. You should specify it, probably you will get an error.");
00555 
00556          mConfigOptions->saveToIniFile(FileSystemManager::getInstance()->getIniFile());
00557         }
00558         // Load ini file
00559         else
00560         {
00561          mConfigOptions->loadFromIniFile(FileSystemManager::getInstance()->getIniFile());
00562         }
00563 
00564         // Call application-wide setters
00565         setFromConfigOptions();
00566 
00567         // Create plugin manager
00568         PluginManager::createInstance();
00569         PluginManager::getInstance()->initialize();
00570 
00571         // Initialize PC
00572         if(PCerr err = pcSystemInitialize((const PCstring) mLibrarySearchPath.c_str()) != PC_NO_ERROR)
00573          Except(INTERNAL_ERROR, "Application::initialize()", pcGetErrorString(err));
00574 
00575         if(PCerr err = pcSessionCreate(0) != PC_NO_ERROR)
00576          Except(INTERNAL_ERROR, "Application::initialize()", pcGetErrorString(err));
00577 
00578         rl_command_func_t *func;
00579 
00580         func = complement;
00581 
00582         rl_bind_key('\t', func);
00583 
00584         mInitialized = true;
00585 
00586         Logger::getInstance()->log(Logger::DEBUG, "PCM Application has been initialized.");
00587 
00588   }
00589 
00590  /*----------------------------------------------------------------------*/
00591 
00592   void Application::finalize()
00593   {
00594         Assert(mInitialized, INVALID_OPERATION_ERROR, "Application::finalize()");
00595 
00596         // Specific finalization code
00597         // (Finalize soldier first)
00598 
00599         finalizeSoldier();
00600         if(mCommanderMode)
00601          finalizeCommander();
00602 
00603         if(PCerr err = pcSessionDestroy() != PC_NO_ERROR)
00604          Except(INTERNAL_ERROR, "Host::finalize()", pcGetErrorString(err));
00605 
00606         if(mDynamicScriptSqVM.isNotNull())
00607          mDynamicScriptSqVM.kill();
00608 
00609         if(mUserInterfaceSqVM.isNotNull())
00610          mUserInterfaceSqVM.kill();
00611 
00612         if(PluginManager::getInstance())
00613          PluginManager::destroyInstance();
00614 
00615         if(FileSystemManager::getInstance())
00616          FileSystemManager::destroyInstance();
00617 
00618         if(mConfigOptions.isNotNull())
00619          mConfigOptions.kill();
00620 
00621         if(mOutputDocument.isNotNull())
00622          mOutputDocument.kill();
00623 
00624         if(Logger::getInstance())
00625         {
00626          Logger::getInstance()->log(Logger::DEBUG, "PCM Application has been finalized.");
00627          Logger::destroyInstance();
00628         }
00629 
00630         mInitialized = false;
00631   }
00632 
00633  /*----------------------------------------------------------------------*/
00634 
00635   void Application::finalizeCommander()
00636   {
00637         Cluster::destroyInstance();
00638         delete mServer;
00639   }
00640 
00641  /*----------------------------------------------------------------------*/
00642 
00643   void Application::finalizeSoldier()
00644   {
00645         // Kill the soldier host
00646         if(Host::getInstance())
00647         {
00648          Host::getInstance()->closeXDisplays();
00649          Host::destroyInstance();
00650         }
00651 
00652         if(mClient)
00653          delete mClient;
00654   }
00655 
00656  /*----------------------------------------------------------------------*/
00657 
00658   void Application::setFromConfigOptions()
00659   {
00660         FileSystemManager::getInstance()->setDataDirectory(mConfigOptions->getString("dataDirectory"));
00661         if(mConfigOptions->hasOption("communicationPort"))
00662         {
00663          Network::setCommunicationPort((unsigned short) StringConverter::
00664                                         toU32(mConfigOptions->getString("communicationPort")));
00665         }
00666 
00667         if(mConfigOptions->hasOption("broadcastPort"))
00668         {
00669          Network::setBroadcastPort((unsigned short) StringConverter::
00670                                   toU32(mConfigOptions->getString("broadcastPort")));
00671         }
00672 
00673         if(mConfigOptions->hasOption("pcLibraryPath"))
00674         {
00675          setLibrarySearchPath(mConfigOptions->getString("pcLibraryPath"));
00676         }
00677         Logger::getInstance()->log(Logger::DEBUG,
00678                                  "Application-wide setters has been called on configuration options (parcompmark.ini).");
00679 
00680   }
00681 
00682  /*----------------------------------------------------------------------*/
00683 
00684   void Application::createVirtualMachines()
00685   {
00686         // Create virtual machine for dynamic script exection
00687         mUserInterfaceSqVM = new SqVM("UserInterface-VM");
00688 
00689         // Load PC API, ParCompMark API, and utils
00690         mUserInterfaceSqVM.lock();
00691         mUserInterfaceSqVM->runScriptFromFile(FileSystemManager::getInstance()->getPathDataFile(PCAPINUT),
00692                                           SqVM::NOMAINMETHOD);
00693         mUserInterfaceSqVM->runScriptFromFile(FileSystemManager::getInstance()->getPathDataFile(PARCOMPMARKNUT),
00694                                           SqVM::NOMAINMETHOD);
00695         mUserInterfaceSqVM->runScriptFromFile(FileSystemManager::getInstance()->getPathDataFile(UTILSNUT),
00696                                           SqVM::NOMAINMETHOD);
00697         mUserInterfaceSqVM->runScriptFromFile(FileSystemManager::getInstance()->getPathDataFile(ABBREVIATIONSNUT),
00698                                           SqVM::NOMAINMETHOD);
00699         mUserInterfaceSqVM.unlock();
00700 
00701         // Load user commands
00702         std::list < std::string > files = FileSystemManager::getInstance()->listDataDirectory(COMMANDDIRECTORY);
00703         mUserInterfaceSqVM.lock();
00704 
00705         // Save current script output, and switch to console output 
00706         SqVM::ScriptOutput lastOutput = SqVM::getScriptOutput();
00707         SqVM::setScriptOutput(SqVM::STD);
00708 
00709         // Load help.nut first
00710         mUserInterfaceSqVM->runScriptFromFile(FileSystemManager::getInstance()->getPathDataFile(HELPNUT),
00711                                           SqVM::NOMAINMETHOD);
00712 
00713         // Load commands
00714         for(std::list < std::string >::iterator i = files.begin(); i != files.end(); i++)
00715          // Take only the .nut files
00716          if((*i).substr((*i).length() - 4) == ".nut")
00717                 mUserInterfaceSqVM->runScriptFromFile(FileSystemManager::getInstance()->getPathDataFile(*i),
00718                                                   SqVM::NOMAINMETHOD);
00719 
00720         SqVM::setScriptOutput(lastOutput);
00721         mUserInterfaceSqVM.unlock();
00722 
00723         // Load dynamic script initialization code
00724         mDynamicScriptSqVM = mUserInterfaceSqVM;
00725         mDynamicScriptSqVM.lock();
00726         mDynamicScriptSqVM->runScriptFromFile(FileSystemManager::getInstance()->getPathDataFile(DYNAMICINITNUT),
00727                                           SqVM::NOMAINMETHOD);
00728         mDynamicScriptSqVM.unlock();
00729   }
00730 
00731  /*----------------------------------------------------------------------*/
00732 
00733   bool Application::startOperation()
00734   {
00735         Logger::getInstance()->log(Logger::NOTICE, "PCM Application starts its operation.");
00736 
00737         // Return codes
00738         bool retC = false,
00739          retS = false,
00740          retUI = false;
00741 
00742         // Commander mode (= commander + soldier + user interface)
00743         if(mCommanderMode)
00744         {
00745 
00746          // Start a commander
00747          retS = soldierOperation();
00748 
00749          // And a soldier too
00750          if(!retS)
00751                 retC = commanderOperation();
00752 
00753          // Start user interface
00754          if(!retS && !retC)
00755          {
00756                 switch (mUserInterface)
00757                 {
00758                  case CONSOLE:
00759                         retUI = textUserInterface();
00760                         break;
00761                  default:
00762                         retUI = noUserInterface();
00763                 }
00764          }
00765          // Wait for output document
00766          waitForOutput();
00767 
00768         }
00769         // Soldier mode (= soldier only)
00770         else
00771         {
00772          // Start only a soldier
00773          retS = soldierOperation();
00774 
00775          // Wait for thread exit
00776          mClient->joinThread();
00777         }
00778 
00779         Logger::getInstance()->log(Logger::NOTICE, "PCM Application has finished its operation.");
00780 
00781         // Return true is either operation has error
00782         return retC || retS || retUI;
00783   }
00784 
00785  /*----------------------------------------------------------------------*/
00786 
00787   void Application::writeOutput()
00788   {
00789         mOutputDocument.lock();
00790 
00791         // Put the cluster description into the output document
00792         mCollectClusterDescription.lock();
00793         mOutputDocument->createChildNode(mCollectClusterDescription->serialize2XML());
00794         mCollectClusterDescription.unlock();
00795 
00796         // Compose xml document
00797         std::ostringstream xmlSourceStream;
00798         //std::ostringstream ccd;
00799         xmlSourceStream << "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>" << std::endl;
00800         xmlSourceStream << mOutputDocument->serialize2XML() << std::endl;
00801         
00802         // Write output to std out
00803         if(mOutput == "-")
00804         {
00805          std::cout << xmlSourceStream.str() << std::endl;
00806 
00807          Logger::getInstance()->log(Logger::NOTICE, "Benchmark output has been written to standard output.");
00808         }
00809         // Write output to file
00810         else
00811         {
00812          std::fstream file_op(mOutput.c_str(), std::ios::out);
00813          file_op << xmlSourceStream.str();
00814          //file_op << ccd.str();
00815          file_op.close();
00816 
00817          Logger::getInstance()->log(Logger::NOTICE, "Benchmark output has been written to `" + mOutput + "\'");
00818         }
00819 
00820         mOutputDocument.unlock();
00821 
00822         // The output document is written now. It is safe to quit
00823         mOutputIsDone = true;
00824   }
00825 
00826  /*----------------------------------------------------------------------*/
00827 
00828   void Application::waitForOutput()
00829   {
00830         while(!mOutputIsDone)
00831         {
00832          Timer::sleep(0.5);
00833          Thread::yield();
00834         }
00835   }
00836 
00837  /*----------------------------------------------------------------------*/
00838 
00839   void Application::quit()
00840   {
00841         mPostCommand = (mPostCommand == STOP || mPostCommand == STOP_QUIT ? STOP_QUIT : QUIT);
00842   }
00843 
00844  /*----------------------------------------------------------------------*/
00845 
00846   void Application::compileDynamic()
00847   {
00848         mPostCommand = (mPostCommand == START || mPostCommand == COMPILE_START ? COMPILE_START : COMPILE);
00849   }
00850 
00851  /*----------------------------------------------------------------------*/
00852 
00853   void Application::start()
00854   {
00855         mPostCommand = (mPostCommand == COMPILE || mPostCommand == COMPILE_START ? COMPILE_START : START);
00856   }
00857 
00858  /*----------------------------------------------------------------------*/
00859 
00860   void Application::stop()
00861   {
00862         mPostCommand = (mPostCommand == QUIT || mPostCommand == STOP_QUIT ? STOP_QUIT : STOP);
00863   }
00864 
00865  /*----------------------------------------------------------------------*/
00866 
00867   void Application::autoDetection()
00868   {
00869         Assert(!mCompRun, INVALID_NAME_ERROR, "Application::autoDetection()");
00870         mServer->buildCluster();
00871 
00872         // New cluster, new low-level script
00873         mDynamicScriptCompiled = false;
00874 
00875         // Refresh cluster description
00876         // TODO: parsing not works
00884         //calculateMessageSendTime();
00885   }
00886 
00887  /*----------------------------------------------------------------------*/
00888 
00889   void Application::cleanup()
00890   {
00891         mOutputDocument->clean();
00892         mCurrentExecutionOutputDocument = 0;
00893   }
00894 
00895  /*----------------------------------------------------------------------*/
00896 
00897   char *Application::getHostListForSquirrel()
00898   {
00899         std::ostringstream osstr;
00900         u32 _i = 0,
00901          _size = Cluster::getInstance()->getHosts()->getSize();
00902 
00903         osstr << '[';
00904         for(Container < HostInfo, Mutex >::Iterator i = Cluster::getInstance()->getHosts()->begin();
00905          i != Cluster::getInstance()->getHosts()->end(); i++, _i++)
00906          osstr << '\"' << i->first << (_i + 1 != _size ? "\"," : "\"");
00907         osstr << ']';
00908 
00909         // TODO: is it deallcated by Squirrel?
00910         return strdup(osstr.str().c_str());
00911   }
00912 
00913  /*----------------------------------------------------------------------*/
00914 
00915   char *Application::getLowLevelScriptForSquirrel()
00916   {
00917         // TODO: is it deallcated by Squirrel?
00918         return (char *) mLowLevelScript.c_str();
00919   }
00920 
00921  /*----------------------------------------------------------------------*/
00922 
00923   char *Application::getDynamicScriptForSquirrel()
00924   {
00925         // TODO: is it deallcated by Squirrel?
00926         return (char *) mDynamicScript.c_str();
00927   }
00928 
00929  /*----------------------------------------------------------------------*/
00930 
00931   bool Application::hasScenarioScript()
00932   {
00933         return mScenarioScript.size() > 0;
00934   }
00935 
00936  /*----------------------------------------------------------------------*/
00937 
00938   char *Application::getDynamicScriptParametersForSquirrel()
00939   {
00940         std::ostringstream osstr;
00941 
00942         osstr << '[' << std::endl;
00943         for(std::list < DynamicScriptParameter * >::iterator i = mDynamicScriptParameters.begin();
00944          i != mDynamicScriptParameters.end(); i++)
00945          osstr << "{name=\"" << (*i)->name << "\"}" << std::endl;
00946         osstr << ']';
00947 
00948         // TODO: is it deallcated by Squirrel?
00949         return strdup(osstr.str().c_str());
00950   }
00951 
00952  /*----------------------------------------------------------------------*/
00953 
00954   char *Application::getProgramInfo()
00955   {
00956         std::ostringstream osstr;
00957         osstr << PACKAGE_STRING << ' ' << PACKAGE_COPYRIGHT;
00958         return strdup(osstr.str().c_str());
00959   }
00960 
00961  /*----------------------------------------------------------------------*/
00962 
00963   void Application::calculateMessageSendTime()
00964   {
00965         mServer->sendBroadcastMessage("TIME", "NONE");
00966   }
00967 
00968  /*----------------------------------------------------------------------*/
00969 
00970   void Application::_pseudoStop()
00971   {
00972 
00973         Assert(mCompRun, INVALID_VALUE_ERROR, "Application::_stop()");
00974 
00975         mServer->sendBroadcastMessage("COLLECTDATA", "NONE");
00976 
00977         //writeOutput();
00978 
00979         mCompRun = false;
00980 
00981   }
00982 
00983  /*----------------------------------------------------------------------*/
00984 
00985   bool Application::commanderOperation()
00986   {
00987         Assert(mCommanderMode, INVALID_OPERATION_ERROR, "Application::commanderOperation()");
00988         Logger::getInstance()->log(Logger::NOTICE, "Starting commander-mode code.");
00989 
00990         try
00991         {
00992          // Create cluster
00993          Cluster::createInstance();
00994 
00995          // Create and initialize virtual machines for dynamic script execution and for user interaction handling
00996          createVirtualMachines();
00997 
00998          // Load low level script if specified
00999          if(mConfigOptions->hasOption("lowLevelScriptFile"))
01000                 loadLowLevelScript(mConfigOptions->getString("lowLevelScriptFile").c_str());
01001 
01002          // Load dynamic script if specified
01003          else if(mConfigOptions->hasOption("dynamicScriptFile"))
01004          {
01005                 loadDynamicScript(mConfigOptions->getString("dynamicScriptFile").c_str());
01006                 doPostCommand();
01007          }
01008          // Load scenario script if specified
01009          else if(mConfigOptions->hasOption("scenarioScriptFile"))
01010          {
01011                 loadScenarioScript(mConfigOptions->getString("scenarioScriptFile").c_str());
01012                 doPostCommand();
01013          }
01014          // Start netserver
01015          mServer = new NetServer("server");
01016          mServer->startThread();
01017 
01018          // Initialize user interface
01019          mUserInterfaceSqVM.lock();
01020          SqVM::ScriptOutput lastOutput = SqVM::getScriptOutput();
01021          SqVM::setScriptOutput(SqVM::STD);
01022          mUserInterfaceSqVM->runScriptFromFile(FileSystemManager::getInstance()->getPathDataFile(UIINITNUT),
01023                                                 SqVM::NOMAINMETHOD);
01024          SqVM::setScriptOutput(lastOutput);
01025          mUserInterfaceSqVM.unlock();
01026 
01027         }
01028         catch(Exception & e)
01029         {
01030          Logger::getInstance()->log(Logger::FATAL,
01031                                    "An exception has been raised during the commander-mode operation!");
01032          Logger::getInstance()->log(e);
01033          return true;
01034         }
01035 
01036         Logger::getInstance()->log(Logger::NOTICE, "Commander-mode code has been finished.");
01037 
01038         return false;
01039   }
01040 
01041  /*----------------------------------------------------------------------*/
01042 
01043   bool Application::soldierOperation()
01044   {
01045         Logger::getInstance()->log(Logger::NOTICE, "Starting soldier-mode code.");
01046 
01047         try
01048         {
01049          mHostInfo = new HostInfo(Network::getHostName(), OutputNode::INFORMATION);
01050          
01051          mHostInfo->refreshData();
01052                 
01053          // Create host
01054 
01055          Host::createInstance();
01056          Host::getInstance()->openXDisplays();
01057          mClient = new NetClient("client");
01058          Host::getInstance()->setNetClient(mClient);
01059          mClient->startThread();
01060         }
01061         catch(Exception & e)
01062         {
01063          Logger::getInstance()->log(Logger::FATAL,
01064                                    "An exception has been raised during the soldier-mode operation!");
01065          Logger::getInstance()->log(e);
01066          return true;
01067         }
01068 
01069         Logger::getInstance()->log(Logger::NOTICE, "Soldier-mode code has been finished.");
01070 
01071         return false;
01072   }
01073 
01074  /*----------------------------------------------------------------------*/
01075 
01076   bool Application::textUserInterface()
01077   {
01078 
01079         for(;;)
01080         {
01081 #if defined(HAVE_READLINE_HISTORY_H) && defined(HAVE_READLINE_READLINE_H)
01082          char *s = 0;
01083 
01084          s = readline("\n: ");
01085 
01086          if(s && *s)
01087                 add_history(s);
01088 #else
01089          char s[1024];
01090 
01091          printf("\n: ");
01092          gets(s);
01093 #endif
01094 
01095          if(executeUserCommand(s))
01096                 return true;
01097 
01098 #if defined(HAVE_READLINE_HISTORY_H) && defined(HAVE_READLINE_READLINE_H)
01099          free(s);
01100 #endif
01101 
01102          // Process post commands
01103          doPostCommand();
01104 
01105         // Process command list
01106         processSquirrelCommandList();
01107 
01108          if(mQuiting)
01109                 break;
01110         }
01111 
01112         return false;
01113   }
01114 
01115  /*----------------------------------------------------------------------*/
01116 
01117   bool Application::noUserInterface()
01118   {
01119         // Wait for a while
01120         Timer::sleep(0.5);
01121 
01122         // Start compositing 
01123         executeUserCommand("start");
01124         doPostCommand();
01125 
01126         // Process command list
01127         processSquirrelCommandList();
01128 
01129         if(!mCompRun)
01130          return true;
01131 
01132         for(;;)
01133         {
01134          Timer::sleep(0.5);
01135 
01136          // Quit when the compositing is done
01137          if(!mCompRun)
01138                 executeUserCommand("quit");
01139 
01140          doPostCommand();
01141 
01142          if(mQuiting)
01143                 break;
01144         }
01145 
01146         // Wait for a while
01147         Timer::sleep(1.0);
01148 
01149         return false;
01150   }
01151 
01152  /*----------------------------------------------------------------------*/
01153 
01154   bool Application::executeUserCommand(const std::string & command)
01155   {
01156         try
01157         {
01158          mUserInterfaceSqVM.lock();
01159 
01160          // Save current script output, and switch to console output 
01161          SqVM::ScriptOutput lastOutput = SqVM::getScriptOutput();
01162          SqVM::setScriptOutput(SqVM::STD);
01163 
01164          // Resolve abbreviation
01165          std::list < std::string > params;
01166          params.push_back(command);
01167          std::string resolved_command =
01168                 mUserInterfaceSqVM->runScriptFromString("", "", "resolve_abbreviation", params, true);
01169 
01170          // Execute user command
01171          mUserInterfaceSqVM->runScriptFromString(resolved_command, "", SqVM::NOMAINMETHOD);
01172 
01173          // Restore original output
01174          SqVM::setScriptOutput(lastOutput);
01175          mUserInterfaceSqVM.unlock();
01176         }
01177         catch(const Exception & e)
01178         {
01179          // Unlock VM
01180          if(mUserInterfaceSqVM.getLocked())
01181                 mUserInterfaceSqVM.unlock();
01182 
01183          // Clear error flag
01184          if(e.getType() == Exception::SCRIPT_ERROR)
01185                 mUserInterfaceSqVM->setError(false);
01186 
01187          // If not script error, throw forward
01188          else
01189                 throw Exception(e);
01190         }
01191 
01192         return false;
01193   }
01194 
01195  /*----------------------------------------------------------------------*/
01196 
01197   bool Application::processSquirrelCommandList()
01198   {
01199         while(mSquirrelCommandList.size()) {
01200 
01201                 // Wait until compositing is running
01202                 while(mCompRun) Timer::sleep(0.5);
01203 
01204                 executeUserCommand(mSquirrelCommandList.front());
01205                 doPostCommand();
01206                 
01207                 mSquirrelCommandList.pop_front();
01208                 std::cout << "There are " << mSquirrelCommandList.size() << " commands in the queue." << std::endl;
01209         } 
01210 
01211         return false;
01212   }
01213 
01214  /*----------------------------------------------------------------------*/
01215 
01216   void Application::doPostCommand()
01217   {
01218         switch (mPostCommand)
01219         {
01220          case LOADSCENARIO:
01221                 _loadScenario();
01222          case LOADDYNAMIC:
01223                 _loadDynamic();
01224                 break;
01225          case COMPILE:
01226                 _compileDynamic();
01227                 break;
01228          case START:
01229                 _start();
01230                 break;
01231          case COMPILE_START:
01232                 _compileDynamic();
01233                 _start();
01234                 break;
01235          case STOP:
01236                 _stop();
01237                 break;
01238          case STOP_QUIT:
01239                 _stop();
01240                 _quit();
01241                 break;
01242          case QUIT:
01243                 _quit();
01244                 break;
01245          default:
01246                 return;
01247         }
01248 
01249         mPostCommand = NOTHING;
01250   }
01251 
01252  /*----------------------------------------------------------------------*/
01253 
01254   void Application::loadLowLevelScript(const char *filename)
01255   {
01256         mLowLevelScript = FileSystemManager::getInstance()->readDataTextFile(filename);
01257   }
01258 
01259  /*----------------------------------------------------------------------*/
01260 
01261   void Application::loadDynamicScript(const char *filename)
01262   {
01263         // New script
01264         mDynamicScript = FileSystemManager::getInstance()->readDataTextFile(filename);
01265 
01266         // Not compiled
01267         mDynamicScriptCompiled = false;
01268 
01269         mPostCommand = LOADDYNAMIC;
01270   }
01271 
01272  /*----------------------------------------------------------------------*/
01273 
01274   void Application::loadScenarioScript(const char *filename)
01275   {
01276         // New script
01277         mScenarioScript = FileSystemManager::getInstance()->readDataTextFile(filename);
01278 
01279         mPostCommand = LOADSCENARIO;
01280   }
01281 
01282  /*----------------------------------------------------------------------*/
01283 
01284   void Application::pushSquirrelCommand(const char *command)
01285   {
01286         mSquirrelCommandList.push_back(command);
01287   }
01288 
01289  /*----------------------------------------------------------------------*/
01290 
01291   void Application::createLowLevelScript(const std::string & clusterDescription)
01292   {
01293         try
01294         {
01295          // Create low level script
01296          mDynamicScriptSqVM.lock();
01297          std::list < std::string > params;
01298          params.push_back(clusterDescription);
01299          mLowLevelScript =
01300                 mDynamicScriptSqVM->runScriptFromString(mDynamicScript, "", "createLowLevelScript", params, true);
01301          mDynamicScriptSqVM.unlock();
01302 
01303          mDynamicScriptCompiled = true;
01304         }
01305         catch(const Exception & e)
01306         {
01307          // Unlock VM
01308          if(mDynamicScriptSqVM.getLocked())
01309                 mDynamicScriptSqVM.unlock();
01310 
01311          // Clear error flag
01312          if(e.getType() == Exception::SCRIPT_ERROR)
01313                 mDynamicScriptSqVM->setError(false);
01314 
01315          // If not script error, throw forward
01316          else
01317                 throw Exception(e);
01318         }
01319   }
01320 
01321  /*----------------------------------------------------------------------*/
01322 
01323   void Application::processScenarioScript()
01324   {
01325         try
01326         {
01327          // Create low level script
01328          mDynamicScriptSqVM.lock();
01329          mDynamicScriptSqVM->runScriptFromString(mScenarioScript, "", "prepareScenario");
01330          mDynamicScriptSqVM.unlock();
01331 
01332          mDynamicScriptCompiled = true;
01333         }
01334         catch(const Exception & e)
01335         {
01336          // Unlock VM
01337          if(mDynamicScriptSqVM.getLocked())
01338                 mDynamicScriptSqVM.unlock();
01339 
01340          // Clear error flag
01341          if(e.getType() == Exception::SCRIPT_ERROR)
01342                 mDynamicScriptSqVM->setError(false);
01343 
01344          // If not script error, throw forward
01345          else
01346                 throw Exception(e);
01347         }
01348   }
01349 
01350  /*----------------------------------------------------------------------*/
01351 
01352   void Application::setEnvironmentVariablesToSquirrel()
01353   {
01354         XDisplay::Pointer commanderDisplay =
01355          Host::getInstance()? Host::getInstance()->getFirstXDisplay() : XDisplay::Pointer();
01356 
01357         // Create environment variables
01358         std::map < std::string, std::string > envVars;
01359         envVars["commanderHost"] = Network::getHostName();
01360         if(commanderDisplay.getPtr())
01361          envVars["screenWidth"] = StringConverter::toString(commanderDisplay->getWidth());
01362         if(commanderDisplay.getPtr())
01363          envVars["screenHeight"] = StringConverter::toString(commanderDisplay->getHeight());
01364         std::ostringstream environmentVariables;
01365         environmentVariables << "{";
01366         for(std::map < std::string, std::string >::iterator i = envVars.begin(); i != envVars.end(); i++)
01367          environmentVariables << i->first << "=\"" << i->second << "\" ";
01368         environmentVariables << "}";
01369 
01370         try
01371         {
01372          // Transmit these parameters to the squirrel
01373          mDynamicScriptSqVM.lock();
01374          std::list < std::string > params;
01375          params.push_back(environmentVariables.str());
01376          mDynamicScriptSqVM->runScriptFromString(mDynamicScript, "", "setEnvironmentVariables", params);
01377          mDynamicScriptSqVM.unlock();
01378         }
01379         catch(const Exception & e)
01380         {
01381          // Unlock VM
01382          if(mDynamicScriptSqVM.getLocked())
01383                 mDynamicScriptSqVM.unlock();
01384 
01385          // Clear error flag
01386          if(e.getType() == Exception::SCRIPT_ERROR)
01387                 mDynamicScriptSqVM->setError(false);
01388 
01389          // If not script error, throw forward
01390          else
01391                 throw Exception(e);
01392         }
01393   }
01394 
01395  /*----------------------------------------------------------------------*/
01396 
01397   void Application::initializeDynamicScriptParameters(const bool & reset)
01398   {
01399         mDynamicScriptSqVM.lock();
01400         std::list < std::string > params;
01401         params.push_back(reset ? "true" : "false");
01402         mDynamicScriptSqVM->runScriptFromString(mDynamicScript, "", "initializeDynamicScriptParameters", params);
01403         mDynamicScriptSqVM.unlock();
01404   }
01405 
01406  /*----------------------------------------------------------------------*/
01407 
01408   void Application::retrieveDynamicScriptParameters()
01409   {
01410         Assert(mDynamicScript.length() > 0, INVALID_OPERATION_ERROR, "Application::retrieveDynamicScriptParameters()");
01411 
01412         try
01413         {
01414          // Get script parameters from dynamic script as XML
01415          mDynamicScriptSqVM.lock();
01416          std::string dScriptParamsXML =
01417                 mDynamicScriptSqVM->runScriptFromString(mDynamicScript, "dynamicScriptParameters", "getParameters",
01418                                                         std::list < std::string > (), true);
01419          mDynamicScriptSqVM.unlock();
01420 
01421          //std::cerr << dScriptParamsXML << std::endl;
01422 
01423          // Drop current parameters
01424          mDynamicScriptParameters.clear();
01425 
01426          // Parse XML (TODO: move this to SqVM) 
01427          TiXmlDocument tiDocument;
01428 
01429          tiDocument.Parse(dScriptParamsXML.c_str());
01430 
01431          TiXmlElement *tiArray = tiDocument.RootElement();
01432 
01433          for(TiXmlElement * tiElement = tiArray->FirstChildElement(); tiElement != 0;
01434                 tiElement = tiElement->NextSiblingElement())
01435          {
01436                 TiXmlElement *tiTable = tiElement->FirstChildElement();
01437 
01438                 if(!tiTable)
01439                  continue;
01440 
01441                 DynamicScriptParameter *dsparam = new DynamicScriptParameter();
01442 
01443                 for(TiXmlElement * tiSlot = tiTable->FirstChildElement(); tiSlot != 0;
01444                  tiSlot = tiSlot->NextSiblingElement())
01445                 {
01446                  const char *name = tiSlot->Attribute("name");
01447                  const char *text = tiSlot->NoChildren()? 0 : tiSlot->GetText();
01448 
01449                  if(!strcmp(name, "name"))
01450                  {
01451                         dsparam->name = text ? text : "";
01452                  } else if(!strcmp(name, "type"))
01453                  {
01454                         Assert(text, NULL_POINTER_ERROR, "Application::retrieveDynamicScriptParameters()");
01455                         if(!strcmp(text, "string"))
01456                          dsparam->type = STRING;
01457                         else if(!strcmp(text, "integer") || !strcmp(text, "int"))
01458                          dsparam->type = INTEGER;
01459                         else if(!strcmp(text, "real") || !strcmp(text, "float"))
01460                          dsparam->type = REAL;
01461                         else if(!strcmp(text, "boolean") || !strcmp(text, "bool"))
01462                          dsparam->type = BOOL;
01463                         else
01464                          Except(INVALID_ENUM_ERROR, "Application::retrieveDynamicScriptParameters()",
01465                                  std::string("Invalid dynamic script type parameter `") + text + "\'");
01466                  } else if(!strcmp(name, "description"))
01467                         dsparam->description = text ? text : "";
01468                  else if(!strcmp(name, "possibleValues"))
01469                  {
01470 
01483                  } else if(!strcmp(name, "defaultValue"))
01484                         dsparam->defaultValue = text ? text : "";
01485                  else
01486                         Except(INVALID_ENUM_ERROR, "Application::retrieveDynamicScriptParameters()",
01487                            std::string("Invalid dynamic script parameter `") + name + "\'");
01488                 }
01489                 mDynamicScriptParameters.push_back(dsparam);
01490                 //std::cerr << dsparam->name << "|" << dsparam->description << "|" << dsparam->defaultValue << "|" << std::endl;
01491          }
01492         }
01493         catch(const Exception & e)
01494         {
01495          // Unlock VM
01496          if(mDynamicScriptSqVM.getLocked())
01497                 mDynamicScriptSqVM.unlock();
01498 
01499          // Clear error flag
01500          if(e.getType() == Exception::SCRIPT_ERROR)
01501                 mDynamicScriptSqVM->setError(false);
01502 
01503          // If not script error, throw forward
01504          else
01505                 throw Exception(e);
01506         }
01507   }
01508 
01509  /*----------------------------------------------------------------------*/
01510 
01511   void Application::_loadScenario()
01512   {
01513         processScenarioScript();
01514   }
01515 
01516  /*----------------------------------------------------------------------*/
01517 
01518   void Application::_loadDynamic()
01519   {
01520         // Set environment variables to Squirrel
01521         setEnvironmentVariablesToSquirrel();
01522 
01523         // Compile dynamic script and initialize dynamic script parameters with reset
01524         initializeDynamicScriptParameters(true);
01525   }
01526 
01527  /*----------------------------------------------------------------------*/
01528 
01529   void Application::_compileDynamic()
01530   {
01531         // If a dynamic script is given, generate low level script
01532         if(mDynamicScript.length())
01533         {
01534          // Get squirrel cluster description
01535          std::string clusterDescription = Cluster::getInstance()->serialize2Squirrel();
01536 
01537          // Create low-level script from dynamic script and cluster description 
01538          createLowLevelScript(clusterDescription);
01539         }
01540   }
01541 
01542  /*----------------------------------------------------------------------*/
01543 
01544   void Application::_start()
01545   {
01546         Assert(!mCompRun, INVALID_NAME_ERROR, "Application::_start()");
01547 
01548         // Verify low level script existence
01549         if(!mLowLevelScript.length())
01550          Except(INVALID_OPERATION_ERROR, "Application::start()",
01551                  "Unable to send low-level scripts to the soldier nodes. You have to specify an explicit low-level script or a dynamic script.");
01552 
01553         // Create new execution node
01554         mCurrentExecutionOutputDocument = mOutputDocument->createChildNode("execution", OutputNode::INFORMATION);
01555         mCurrentExecutionOutputDocument->setAttribute("index", StringConverter::toString(mExecutionIndex++));
01556 
01557         // Get dynamic script parameters from squirrel as XML
01558         std::string dynamicParameters;
01559 
01560         try
01561         {
01562          // Transmit these parameters to the squirrel
01563          mDynamicScriptSqVM.lock();
01564          dynamicParameters =
01565                 mDynamicScriptSqVM->
01566                 runScriptFromString
01567                 ("function main() { return \"<info:parameters>\" + objectToXML(DYNAMICSCRIPTPARAMETERS) + \"</info:parameters>\" }",
01568                  "", "main", std::list < std::string > (), true);
01569          mDynamicScriptSqVM.unlock();
01570         }
01571         catch(const Exception & e)
01572         {
01573          // Unlock VM
01574          if(mDynamicScriptSqVM.getLocked())
01575                 mDynamicScriptSqVM.unlock();
01576 
01577          // Clear error flag
01578          if(e.getType() == Exception::SCRIPT_ERROR)
01579                 mDynamicScriptSqVM->setError(false);
01580 
01581          // If not script error, throw forward
01582          else
01583                 throw Exception(e);
01584         }
01585 
01586         mCurrentExecutionOutputDocument->createChildNode(dynamicParameters);
01587         mCollectClusterDescription->clean();
01588 
01589         mServer->sendBroadcastMessage("INIT",
01590                                   StringConverter::toString(Timer::getUncorrectedSystemTime(),
01591                                                                 StringConverter::DEFAULTFIELDWIDTH, 6));
01592 
01593         // Compositing is running and the output is not written yet
01594         mCompRun = true;
01595         mOutputIsDone = false;
01596   }
01597 
01598  /*----------------------------------------------------------------------*/
01599 
01600   void Application::_stop()
01601   {
01602         Assert(mCompRun, INVALID_NAME_ERROR, "Application::_stop()");
01603 
01604         NetServer::IntPointer frameID;
01605         frameID = mServer->getStopFrameID();
01606         frameID.lock();
01607         *frameID.getPtr() = 0;
01608         frameID.unlock();
01609 
01610         mServer->sendBroadcastMessage("STOP", "NONE");
01611 
01612         mServer->sendBroadcastMessage("FRAMEID", StringConverter::toString(*frameID.getPtr() + 5));
01613 
01614         //writeOutput();        
01615 
01616         mCompRun = false;
01617   }
01618 
01619  /*----------------------------------------------------------------------*/
01620 
01621   void Application::_quit()
01622   {
01623 
01624         if(!mQuiting)
01625         {
01626 
01627          // Do not assert, quiting is quiting
01628          if(mCompRun)
01629                 _stop();
01630 
01631          writeOutput();
01632 
01633          mQuiting = true;
01634          mServer->sendBroadcastMessage("QUIT", "NONE");
01635         }
01636 
01637   }
01638 
01639  /*----------------------------------------------------------------------*/
01640 
01641 }