00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 #include "../include/PCMApplication.h"
00029 
00030 #include "../include/PCMStringConverter.h"
00031 
00032 
00033 
00034 
00035 
00036 #include <getopt.h>
00037 #include <iostream>
00038 #include <fstream>
00039 #include <signal.h>
00040 
00041 namespace ParCompMark
00042 {
00043 
00044   
00045   template <> Application * Singleton < Application >::mInstance = 0;
00046 
00047   
00048   
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         
00071         
00072         
00073         
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   
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   
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   
00114   
00115 
00116   Application::Application()
00117         
00118         
00119         
00120         
00121         
00122         
00123         
00124         
00125         
00126         
00127         
00128         
00129         
00130         
00131         
00132         
00133         
00134         
00135         
00136         
00137         
00138         
00139         
00140         
00141         
00142         
00143         
00144         
00145         
00146         
00147         
00148         
00149         
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         
00162         initialize();
00163 
00164         Logger::getInstance()->log(Logger::NOTICE, "PCM Application has been created.");
00165   }
00166 
00167  
00168 
00169   Application::~Application()
00170   {
00171         
00172         if(mInitialized)
00173          finalize();
00174 
00175   }
00176 
00177  
00178 
00179   
00180   
00181   
00182 
00183   int Application::complement(int first, int second)
00184   {
00185         
00186 
00187         return 0;
00188 
00189   }
00190 
00191  
00192 
00193   void Application::parseCommandLine(const u32 & argc, const char **&argv)
00194   {
00195         
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         
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         
00226         std::string _dummy;
00227         for(;;)
00228         {
00229 
00230          
00231          int option_index = 0;
00232 
00233          int c = getopt_long(argc, (char *const *) argv, optionString, long_options, &option_index);
00234 
00235          
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         
00251         std::cout << getInstance()->getProgramInfo() << std::endl;
00252 
00253         
00254         std::cout << "usage: " << mUsageString << std::endl;
00255 
00256         
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         
00263         std::cout << std::endl << "Report bugs to <" << PACKAGE_BUGREPORT << ">" << std::endl;
00264 
00265         
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         
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         
00416         Application::getInstance()->finalize();
00417   }
00418 
00419  
00420 
00421   void Application::terminateHandlerNOP()
00422   {
00423         
00424   }
00425 
00426  
00427 
00428   void Application::unexpectedHandler()
00429   {
00430         Application::terminateHandler();
00431   }
00432 
00433  
00434 
00435   void Application::segfaultHandler(int value)
00436   {
00437         
00438         
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         
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   
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         
00479         
00480   }
00481 
00482  
00483 
00484   void Application::initialize()
00485   {
00486         Assert(!mInitialized, INVALID_OPERATION_ERROR, "Application::initialize()");
00487 
00488         
00489         Timer::setTimeCorrection(0.0);
00490 
00491         
00492         setupHandlers();
00493 
00494         
00495         FileSystemManager::createInstance();
00496         FileSystemManager::getInstance()->initialize();
00497 
00498         
00499         Logger::createInstance();
00500         Logger::getInstance()->initialize();
00501 
00502         
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         
00514         mConfigOptions = new ConfigOptions();
00515         mConfigOptions->initialize();
00516 
00517         
00518         if(!FileSystemManager::getInstance()->existsAppFile(FileSystemManager::getInstance()->getIniFile()))
00519         {
00520          
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          
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          
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         
00559         else
00560         {
00561          mConfigOptions->loadFromIniFile(FileSystemManager::getInstance()->getIniFile());
00562         }
00563 
00564         
00565         setFromConfigOptions();
00566 
00567         
00568         PluginManager::createInstance();
00569         PluginManager::getInstance()->initialize();
00570 
00571         
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         
00597         
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         
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         
00687         mUserInterfaceSqVM = new SqVM("UserInterface-VM");
00688 
00689         
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         
00702         std::list < std::string > files = FileSystemManager::getInstance()->listDataDirectory(COMMANDDIRECTORY);
00703         mUserInterfaceSqVM.lock();
00704 
00705         
00706         SqVM::ScriptOutput lastOutput = SqVM::getScriptOutput();
00707         SqVM::setScriptOutput(SqVM::STD);
00708 
00709         
00710         mUserInterfaceSqVM->runScriptFromFile(FileSystemManager::getInstance()->getPathDataFile(HELPNUT),
00711                                           SqVM::NOMAINMETHOD);
00712 
00713         
00714         for(std::list < std::string >::iterator i = files.begin(); i != files.end(); i++)
00715          
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         
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         
00738         bool retC = false,
00739          retS = false,
00740          retUI = false;
00741 
00742         
00743         if(mCommanderMode)
00744         {
00745 
00746          
00747          retS = soldierOperation();
00748 
00749          
00750          if(!retS)
00751                 retC = commanderOperation();
00752 
00753          
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          
00766          waitForOutput();
00767 
00768         }
00769         
00770         else
00771         {
00772          
00773          retS = soldierOperation();
00774 
00775          
00776          mClient->joinThread();
00777         }
00778 
00779         Logger::getInstance()->log(Logger::NOTICE, "PCM Application has finished its operation.");
00780 
00781         
00782         return retC || retS || retUI;
00783   }
00784 
00785  
00786 
00787   void Application::writeOutput()
00788   {
00789         mOutputDocument.lock();
00790 
00791         
00792         mCollectClusterDescription.lock();
00793         mOutputDocument->createChildNode(mCollectClusterDescription->serialize2XML());
00794         mCollectClusterDescription.unlock();
00795 
00796         
00797         std::ostringstream xmlSourceStream;
00798         
00799         xmlSourceStream << "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>" << std::endl;
00800         xmlSourceStream << mOutputDocument->serialize2XML() << std::endl;
00801         
00802         
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         
00810         else
00811         {
00812          std::fstream file_op(mOutput.c_str(), std::ios::out);
00813          file_op << xmlSourceStream.str();
00814          
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         
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         
00873         mDynamicScriptCompiled = false;
00874 
00875         
00876         
00884         
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         
00910         return strdup(osstr.str().c_str());
00911   }
00912 
00913  
00914 
00915   char *Application::getLowLevelScriptForSquirrel()
00916   {
00917         
00918         return (char *) mLowLevelScript.c_str();
00919   }
00920 
00921  
00922 
00923   char *Application::getDynamicScriptForSquirrel()
00924   {
00925         
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         
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         
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          
00993          Cluster::createInstance();
00994 
00995          
00996          createVirtualMachines();
00997 
00998          
00999          if(mConfigOptions->hasOption("lowLevelScriptFile"))
01000                 loadLowLevelScript(mConfigOptions->getString("lowLevelScriptFile").c_str());
01001 
01002          
01003          else if(mConfigOptions->hasOption("dynamicScriptFile"))
01004          {
01005                 loadDynamicScript(mConfigOptions->getString("dynamicScriptFile").c_str());
01006                 doPostCommand();
01007          }
01008          
01009          else if(mConfigOptions->hasOption("scenarioScriptFile"))
01010          {
01011                 loadScenarioScript(mConfigOptions->getString("scenarioScriptFile").c_str());
01012                 doPostCommand();
01013          }
01014          
01015          mServer = new NetServer("server");
01016          mServer->startThread();
01017 
01018          
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          
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          
01103          doPostCommand();
01104 
01105         
01106         processSquirrelCommandList();
01107 
01108          if(mQuiting)
01109                 break;
01110         }
01111 
01112         return false;
01113   }
01114 
01115  
01116 
01117   bool Application::noUserInterface()
01118   {
01119         
01120         Timer::sleep(0.5);
01121 
01122         
01123         executeUserCommand("start");
01124         doPostCommand();
01125 
01126         
01127         processSquirrelCommandList();
01128 
01129         if(!mCompRun)
01130          return true;
01131 
01132         for(;;)
01133         {
01134          Timer::sleep(0.5);
01135 
01136          
01137          if(!mCompRun)
01138                 executeUserCommand("quit");
01139 
01140          doPostCommand();
01141 
01142          if(mQuiting)
01143                 break;
01144         }
01145 
01146         
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          
01161          SqVM::ScriptOutput lastOutput = SqVM::getScriptOutput();
01162          SqVM::setScriptOutput(SqVM::STD);
01163 
01164          
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          
01171          mUserInterfaceSqVM->runScriptFromString(resolved_command, "", SqVM::NOMAINMETHOD);
01172 
01173          
01174          SqVM::setScriptOutput(lastOutput);
01175          mUserInterfaceSqVM.unlock();
01176         }
01177         catch(const Exception & e)
01178         {
01179          
01180          if(mUserInterfaceSqVM.getLocked())
01181                 mUserInterfaceSqVM.unlock();
01182 
01183          
01184          if(e.getType() == Exception::SCRIPT_ERROR)
01185                 mUserInterfaceSqVM->setError(false);
01186 
01187          
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                 
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         
01264         mDynamicScript = FileSystemManager::getInstance()->readDataTextFile(filename);
01265 
01266         
01267         mDynamicScriptCompiled = false;
01268 
01269         mPostCommand = LOADDYNAMIC;
01270   }
01271 
01272  
01273 
01274   void Application::loadScenarioScript(const char *filename)
01275   {
01276         
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          
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          
01308          if(mDynamicScriptSqVM.getLocked())
01309                 mDynamicScriptSqVM.unlock();
01310 
01311          
01312          if(e.getType() == Exception::SCRIPT_ERROR)
01313                 mDynamicScriptSqVM->setError(false);
01314 
01315          
01316          else
01317                 throw Exception(e);
01318         }
01319   }
01320 
01321  
01322 
01323   void Application::processScenarioScript()
01324   {
01325         try
01326         {
01327          
01328          mDynamicScriptSqVM.lock();
01329          mDynamicScriptSqVM->runScriptFromString(mScenarioScript, "", "prepareScenario");
01330          mDynamicScriptSqVM.unlock();
01331 
01332          mDynamicScriptCompiled = true;
01333         }
01334         catch(const Exception & e)
01335         {
01336          
01337          if(mDynamicScriptSqVM.getLocked())
01338                 mDynamicScriptSqVM.unlock();
01339 
01340          
01341          if(e.getType() == Exception::SCRIPT_ERROR)
01342                 mDynamicScriptSqVM->setError(false);
01343 
01344          
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         
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          
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          
01382          if(mDynamicScriptSqVM.getLocked())
01383                 mDynamicScriptSqVM.unlock();
01384 
01385          
01386          if(e.getType() == Exception::SCRIPT_ERROR)
01387                 mDynamicScriptSqVM->setError(false);
01388 
01389          
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          
01415          mDynamicScriptSqVM.lock();
01416          std::string dScriptParamsXML =
01417                 mDynamicScriptSqVM->runScriptFromString(mDynamicScript, "dynamicScriptParameters", "getParameters",
01418                                                         std::list < std::string > (), true);
01419          mDynamicScriptSqVM.unlock();
01420 
01421          
01422 
01423          
01424          mDynamicScriptParameters.clear();
01425 
01426          
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                 
01491          }
01492         }
01493         catch(const Exception & e)
01494         {
01495          
01496          if(mDynamicScriptSqVM.getLocked())
01497                 mDynamicScriptSqVM.unlock();
01498 
01499          
01500          if(e.getType() == Exception::SCRIPT_ERROR)
01501                 mDynamicScriptSqVM->setError(false);
01502 
01503          
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         
01521         setEnvironmentVariablesToSquirrel();
01522 
01523         
01524         initializeDynamicScriptParameters(true);
01525   }
01526 
01527  
01528 
01529   void Application::_compileDynamic()
01530   {
01531         
01532         if(mDynamicScript.length())
01533         {
01534          
01535          std::string clusterDescription = Cluster::getInstance()->serialize2Squirrel();
01536 
01537          
01538          createLowLevelScript(clusterDescription);
01539         }
01540   }
01541 
01542  
01543 
01544   void Application::_start()
01545   {
01546         Assert(!mCompRun, INVALID_NAME_ERROR, "Application::_start()");
01547 
01548         
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         
01554         mCurrentExecutionOutputDocument = mOutputDocument->createChildNode("execution", OutputNode::INFORMATION);
01555         mCurrentExecutionOutputDocument->setAttribute("index", StringConverter::toString(mExecutionIndex++));
01556 
01557         
01558         std::string dynamicParameters;
01559 
01560         try
01561         {
01562          
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          
01574          if(mDynamicScriptSqVM.getLocked())
01575                 mDynamicScriptSqVM.unlock();
01576 
01577          
01578          if(e.getType() == Exception::SCRIPT_ERROR)
01579                 mDynamicScriptSqVM->setError(false);
01580 
01581          
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         
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         
01615 
01616         mCompRun = false;
01617   }
01618 
01619  
01620 
01621   void Application::_quit()
01622   {
01623 
01624         if(!mQuiting)
01625         {
01626 
01627          
01628          if(mCompRun)
01629                 _stop();
01630 
01631          writeOutput();
01632 
01633          mQuiting = true;
01634          mServer->sendBroadcastMessage("QUIT", "NONE");
01635         }
01636 
01637   }
01638 
01639  
01640 
01641 }