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 }