source: src/controller.cpp@ 685e28

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults AddingActions_SaveParseParticleParameters Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_ParticleName_to_Atom Adding_StructOpt_integration_tests AtomFragments Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.5.4 Candidate_v1.6.0 Candidate_v1.6.1 Candidate_v1.7.0 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator CombiningParticlePotentialParsing Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_BoundInBox_CenterInBox_MoleculeActions Fix_ChargeSampling_PBC Fix_ChronosMutex Fix_FitPartialCharges Fix_FitPotential_needs_atomicnumbers Fix_ForceAnnealing Fix_IndependentFragmentGrids Fix_ParseParticles Fix_ParseParticles_split_forward_backward_Actions Fix_PopActions Fix_QtFragmentList_sorted_selection Fix_Restrictedkeyset_FragmentMolecule Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns Fix_fitting_potentials Fixes ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion FragmentAction_writes_AtomFragments FragmentMolecule_checks_bonddegrees GeometryObjects Gui_Fixes Gui_displays_atomic_force_velocity ImplicitCharges IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix MoreRobust_FragmentAutomation ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PdbParser_setsAtomName PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks Rewrite_FitPartialCharges RotateToPrincipalAxisSystem_UndoRedo SaturateAtoms_findBestMatching SaturateAtoms_singleDegree StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg Switchable_LogView ThirdParty_MPQC_rebuilt_buildsystem TrajectoryDependenant_MaxOrder TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps TremoloParser_setsAtomName Ubuntu_1604_changes stable
Last change on this file since 685e28 was 685e28, checked in by Frederik Heber <heber@…>, 13 years ago

Removed the lot of switch statements in controller's main(), replaced by deque's of bound functions.

  • This will eventually allow the use to simply add another command by furnishing it with its own queue of bound functions.
  • Property mode set to 100644
File size: 20.4 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2011 University of Bonn. All rights reserved.
5 * Please see the LICENSE file or "Copyright notice" in builder.cpp for details.
6 */
7
8/*
9 * \file controller.cpp
10 *
11 * This file strongly follows the Serialization example from the boost::asio
12 * library (see client.cpp)
13 *
14 * Created on: Nov 27, 2011
15 * Author: heber
16 */
17
18
19// include config.h
20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
23
24// boost asio needs specific operator new
25#include <boost/asio.hpp>
26
27#include "CodePatterns/MemDebug.hpp"
28
29#include <boost/assign.hpp>
30#include <boost/program_options.hpp>
31#include <deque>
32#include <fstream>
33#include <iostream>
34#include <map>
35#include <sstream>
36#include <streambuf>
37#include <vector>
38
39#include "Fragmentation/Automation/atexit.hpp"
40#include "CodePatterns/Info.hpp"
41#include "CodePatterns/Log.hpp"
42#include "Fragmentation/EnergyMatrix.hpp"
43#include "Fragmentation/ForceMatrix.hpp"
44#include "Fragmentation/KeySetsContainer.hpp"
45#include "FragmentController.hpp"
46#include "Helpers/defs.hpp"
47#include "Jobs/MPQCCommandJob.hpp"
48#include "Jobs/MPQCCommandJob_MPQCData.hpp"
49#include "Fragmentation/Automation/Jobs/SystemCommandJob.hpp"
50#include "Fragmentation/Automation/Results/FragmentResult.hpp"
51
52/** Print the status of scheduled and done jobs.
53 *
54 * @param status pair of number of schedule and done jobs
55 */
56void printJobStatus(const std::pair<size_t, size_t> &JobStatus)
57{
58 LOG(1, "INFO: #" << JobStatus.first << " are waiting in the queue and #"
59 << JobStatus.second << " jobs are calculated so far.");
60}
61
62/** Creates a SystemCommandJob out of give \a command with \a argument.
63 *
64 * @param jobs created job is added to this vector
65 * @param command command to execute for SystemCommandJob
66 * @param argument argument for command to execute
67 * @param nextid id for this job
68 */
69void createjobs(
70 std::vector<FragmentJob::ptr> &jobs,
71 const std::string &command,
72 const std::string &argument,
73 const JobId_t nextid)
74{
75 FragmentJob::ptr testJob( new SystemCommandJob(command, argument, nextid) );
76 jobs.push_back(testJob);
77 LOG(1, "INFO: Added one SystemCommandJob.");
78}
79
80/** Creates a MPQCCommandJob with argument \a filename.
81 *
82 * @param jobs created job is added to this vector
83 * @param command mpqc command to execute
84 * @param filename filename being argument to job
85 * @param nextid id for this job
86 */
87void parsejob(
88 std::vector<FragmentJob::ptr> &jobs,
89 const std::string &command,
90 const std::string &filename,
91 const JobId_t nextid)
92{
93 std::ifstream file;
94 file.open(filename.c_str());
95 ASSERT( file.good(), "parsejob() - file "+filename+" does not exist.");
96 std::string output((std::istreambuf_iterator<char>(file)),
97 std::istreambuf_iterator<char>());
98 FragmentJob::ptr testJob( new MPQCCommandJob(output, nextid, command) );
99 jobs.push_back(testJob);
100 file.close();
101 LOG(1, "INFO: Added MPQCCommandJob from file "+filename+".");
102}
103
104/** Print received results.
105 *
106 * @param results received results to print
107 */
108void printReceivedResults(const std::vector<FragmentResult::ptr> &results)
109{
110 for (std::vector<FragmentResult::ptr>::const_iterator iter = results.begin();
111 iter != results.end(); ++iter)
112 LOG(1, "RESULT: job #"+toString((*iter)->getId())+": "+toString((*iter)->result));
113}
114
115/** Print MPQCData from received results.
116 *
117 * @param results received results to extract MPQCData from
118 * @param KeySetFilename filename with keysets to associate forces correctly
119 * @param NoAtoms total number of atoms
120 */
121bool printReceivedMPQCResults(
122 const std::vector<FragmentResult::ptr> &results,
123 const std::string &KeySetFilename,
124 size_t NoAtoms)
125{
126 EnergyMatrix Energy;
127 EnergyMatrix EnergyFragments;
128 ForceMatrix Force;
129 ForceMatrix ForceFragments;
130 KeySetsContainer KeySet;
131
132 // align fragments
133 std::map< JobId_t, size_t > MatrixNrLookup;
134 size_t FragmentCounter = 0;
135 {
136 // bring ids in order ...
137 typedef std::map< JobId_t, FragmentResult::ptr> IdResultMap_t;
138 IdResultMap_t IdResultMap;
139 for (std::vector<FragmentResult::ptr>::const_iterator iter = results.begin();
140 iter != results.end(); ++iter) {
141 #ifndef NDEBUG
142 std::pair< IdResultMap_t::iterator, bool> inserter =
143 #endif
144 IdResultMap.insert( make_pair((*iter)->getId(), *iter) );
145 ASSERT( inserter.second,
146 "printReceivedMPQCResults() - two results have same id "
147 +toString((*iter)->getId())+".");
148 }
149 // ... and fill lookup
150 for(IdResultMap_t::const_iterator iter = IdResultMap.begin();
151 iter != IdResultMap.end(); ++iter)
152 MatrixNrLookup.insert( make_pair(iter->first, FragmentCounter++) );
153 }
154 LOG(1, "INFO: There are " << FragmentCounter << " fragments.");
155
156 // extract results
157 std::vector<MPQCData> fragmentData(results.size());
158 MPQCData combinedData;
159
160 LOG(2, "DEBUG: Parsing now through " << results.size() << " results.");
161 for (std::vector<FragmentResult::ptr>::const_iterator iter = results.begin();
162 iter != results.end(); ++iter) {
163 LOG(1, "RESULT: job #"+toString((*iter)->getId())+": "+toString((*iter)->result));
164 MPQCData extractedData;
165 std::stringstream inputstream((*iter)->result);
166 LOG(2, "DEBUG: First 50 characters FragmentResult's string: "+(*iter)->result.substr(0, 50));
167 boost::archive::text_iarchive ia(inputstream);
168 ia >> extractedData;
169 LOG(1, "INFO: extracted data is " << extractedData << ".");
170
171 // place results into EnergyMatrix ...
172 {
173 MatrixContainer::MatrixArray matrix;
174 matrix.resize(1);
175 matrix[0].resize(1, extractedData.energy);
176 if (!Energy.AddMatrix(
177 std::string("MPQCJob ")+toString((*iter)->getId()),
178 matrix,
179 MatrixNrLookup[(*iter)->getId()])) {
180 ELOG(1, "Adding energy matrix failed.");
181 return false;
182 }
183 }
184 // ... and ForceMatrix (with two empty columns in front)
185 {
186 MatrixContainer::MatrixArray matrix;
187 const size_t rows = extractedData.forces.size();
188 matrix.resize(rows);
189 for (size_t i=0;i<rows;++i) {
190 const size_t columns = 2+extractedData.forces[i].size();
191 matrix[i].resize(columns, 0.);
192 // for (size_t j=0;j<2;++j)
193 // matrix[i][j] = 0.;
194 for (size_t j=2;j<columns;++j)
195 matrix[i][j] = extractedData.forces[i][j-2];
196 }
197 if (!Force.AddMatrix(
198 std::string("MPQCJob ")+toString((*iter)->getId()),
199 matrix,
200 MatrixNrLookup[(*iter)->getId()])) {
201 ELOG(1, "Adding force matrix failed.");
202 return false;
203 }
204 }
205 }
206 // add one more matrix (not required for energy)
207 MatrixContainer::MatrixArray matrix;
208 matrix.resize(1);
209 matrix[0].resize(1, 0.);
210 if (!Energy.AddMatrix(std::string("MPQCJob total"), matrix, FragmentCounter))
211 return false;
212 // but for energy because we need to know total number of atoms
213 matrix.resize(NoAtoms);
214 for (size_t i = 0; i< NoAtoms; ++i)
215 matrix[i].resize(2+NDIM, 0.);
216 if (!Force.AddMatrix(std::string("MPQCJob total"), matrix, FragmentCounter))
217 return false;
218
219
220 // combine all found data
221 if (!Energy.InitialiseIndices()) return false;
222
223 if (!Force.ParseIndices(KeySetFilename.c_str())) return false;
224
225 if (!KeySet.ParseKeySets(KeySetFilename.c_str(), Force.RowCounter, Force.MatrixCounter)) return false;
226
227 if (!KeySet.ParseManyBodyTerms()) return false;
228
229 if (!EnergyFragments.AllocateMatrix(Energy.Header, Energy.MatrixCounter, Energy.RowCounter, Energy.ColumnCounter)) return false;
230 if (!ForceFragments.AllocateMatrix(Force.Header, Force.MatrixCounter, Force.RowCounter, Force.ColumnCounter)) return false;
231
232 if(!Energy.SetLastMatrix(0., 0)) return false;
233 if(!Force.SetLastMatrix(0., 2)) return false;
234
235 for (int BondOrder=0;BondOrder<KeySet.Order;BondOrder++) {
236 // --------- sum up energy --------------------
237 LOG(1, "INFO: Summing energy of order " << BondOrder+1 << " ...");
238 if (!EnergyFragments.SumSubManyBodyTerms(Energy, KeySet, BondOrder)) return false;
239 if (!Energy.SumSubEnergy(EnergyFragments, NULL, KeySet, BondOrder, 1.)) return false;
240
241 // --------- sum up Forces --------------------
242 LOG(1, "INFO: Summing forces of order " << BondOrder+1 << " ...");
243 if (!ForceFragments.SumSubManyBodyTerms(Force, KeySet, BondOrder)) return false;
244 if (!Force.SumSubForces(ForceFragments, KeySet, BondOrder, 1.)) return false;
245 }
246
247 // for debugging print resulting energy and forces
248 LOG(1, "INFO: Resulting energy is " << Energy.Matrix[ FragmentCounter ][0][0]);
249 std::stringstream output;
250 for (int i=0; i< Force.RowCounter[FragmentCounter]; ++i) {
251 for (int j=0; j< Force.ColumnCounter[FragmentCounter]; ++j)
252 output << Force.Matrix[ FragmentCounter ][i][j] << " ";
253 output << "\n";
254 }
255 LOG(1, "INFO: Resulting forces are " << std::endl << output.str());
256
257 return true;
258}
259
260/** Helper function to get number of atoms somehow.
261 *
262 * Here, we just parse the number of lines in the adjacency file as
263 * it should correspond to the number of atoms, except when some atoms
264 * are not bonded, but then fragmentation makes no sense.
265 *
266 * @param path path to the adjacency file
267 */
268size_t getNoAtomsFromAdjacencyFile(const std::string &path)
269{
270 size_t NoAtoms = 0;
271
272 // parse in special file to get atom count (from line count)
273 std::string filename(path);
274 filename += FRAGMENTPREFIX;
275 filename += ADJACENCYFILE;
276 std::ifstream adjacency(filename.c_str());
277 if (adjacency.fail()) {
278 LOG(0, endl << "getNoAtomsFromAdjacencyFile() - Unable to open " << filename << ", is the directory correct?");
279 return false;
280 }
281 std::string buffer;
282 while (getline(adjacency, buffer))
283 NoAtoms++;
284 LOG(1, "INFO: There are " << NoAtoms << " atoms.");
285
286 return NoAtoms;
287}
288
289struct ControllerOptions
290{
291
292 int parseHelp(boost::program_options::variables_map &vm, const boost::program_options::options_description &desc) {
293 if (vm.count("help")) {
294 std::cout << desc << "\n";
295 return 1;
296 }
297 return 0;
298 }
299 int parseVerbosity(boost::program_options::variables_map &vm) {
300 if (vm.count("verbosity")) {
301 LOG(0, "STATUS: Verbosity level was set to " << vm["verbosity"].as<size_t>() << ".");
302 setVerbosity(vm["verbosity"].as<size_t>());
303 } else {
304 LOG(0, "STATUS: Verbosity level was not set, defaulting to 5.");
305 setVerbosity(5);
306 }
307 return 0;
308 }
309
310 int parseServerPort(boost::program_options::variables_map &vm) {
311 if (vm.count("server")) {
312 server = vm["server"].as< std::string >();
313 serverport = server.substr(server.find_last_of(':')+1, std::string::npos);
314 server = server.substr(0, server.find_last_of(':'));
315 try {
316 boost::lexical_cast<size_t>(serverport);
317 } catch (boost::bad_lexical_cast &) {
318 ELOG(1, "Could not interpret " << serverport << " as server:port.");
319 return 255;
320 }
321 LOG(1, "INFO: Using " << server << ":" << serverport << " as server's address.");
322 } else {
323 ELOG(1, "Requiring server's address (host:port) to connect to.");
324 return 255;
325 }
326 return 0;
327 }
328
329 int parseCommand(boost::program_options::variables_map &vm, const std::vector<std::string> &Commands) {
330 if (!vm.count("command")) {
331 ELOG(1, "Controller requires one of the following commands: "+toString(Commands));
332 return 255;
333 }
334 command = vm["command"].as< std::string >();
335 return 0;
336 }
337
338 std::string command;
339 std::string server;
340 std::string serverport;
341
342};
343
344struct ControllerOptions_SystemCommandJob : public ControllerOptions
345{
346 int parseExecutable(boost::program_options::variables_map &vm) {
347 if ((command == "createjobs") || (command == "addjobs")) {
348 if (!vm.count("executable")) {
349 ELOG(1, "'"+command+"' requires two options: [executable] [jobcommand].");
350 return 255;
351 }
352 executable = vm["executable"].as< std::string >();
353 }
354 return 0;
355 }
356
357 int parseJobCommand(boost::program_options::variables_map &vm) {
358 if (command == "createjobs") {
359 if (!vm.count("jobcommand")) {
360 ELOG(1, "'"+command+"' requires two options: [executable] [jobcommand].");
361 return 255;
362 }
363 jobcommand = vm["jobcommand"].as< std::string >();
364 }
365 return 0;
366 }
367
368 std::string executable;
369 std::string jobcommand;
370};
371
372struct ControllerOptions_MPQCCommandJob : public ControllerOptions_SystemCommandJob
373{
374 int parseFragmentpath(boost::program_options::variables_map &vm) {
375 if (command == "receivempqc") {
376 if (!vm.count("fragment-path")) {
377 ELOG(1, "'"+command+"' requires two options: [fragment-path].");
378 return 255;
379 }
380 fragmentpath = vm["fragment-path"].as< std::string >();
381 }
382 return 0;
383 }
384
385 int parseJobfiles(boost::program_options::variables_map &vm) {
386 if (command == "addjobs") {
387 if (!vm.count("jobfiles")) {
388 ELOG(1, "'"+command+"' requires two options: [executable] [jobfiles].");
389 return 255;
390 }
391 jobfiles = vm["jobfiles"].as< std::vector<std::string> >();
392 }
393 return 0;
394 }
395
396 std::string fragmentpath;
397 std::vector<std::string> jobfiles;
398};
399
400void creatingJob(FragmentController &controller, const ControllerOptions_SystemCommandJob &ControllerInfo)
401{
402 const JobId_t next_id = controller.getAvailableId();
403 std::vector<FragmentJob::ptr> jobs;
404 createjobs(jobs, ControllerInfo.executable, ControllerInfo.jobcommand, next_id);
405 controller.addJobs(jobs);
406 controller.sendJobs(ControllerInfo.server, ControllerInfo.serverport);
407}
408
409/** Creates a MPQCCommandJob out of give \a command with \a argument.
410 *
411 * @param controller reference to controller to add jobs
412 * @param ControllerInfo information on the job
413 */
414void AddJobs(FragmentController &controller, const ControllerOptions_MPQCCommandJob &ControllerInfo)
415{
416 std::vector<FragmentJob::ptr> jobs;
417 for (std::vector< std::string >::const_iterator iter = ControllerInfo.jobfiles.begin();
418 iter != ControllerInfo.jobfiles.end(); ++iter) {
419 const JobId_t next_id = controller.getAvailableId();
420 const std::string &filename = *iter;
421 LOG(1, "INFO: Creating MPQCCommandJob with filename '"
422 +filename+"', and id "+toString(next_id)+".");
423 parsejob(jobs, ControllerInfo.executable, filename, next_id);
424 }
425 controller.addJobs(jobs);
426 controller.sendJobs(ControllerInfo.server, ControllerInfo.serverport);
427}
428
429int main(int argc, char* argv[])
430{
431 // from this moment on, we need to be sure to deeinitialize in the correct order
432 // this is handled by the cleanup function
433 atexit(cleanUp);
434
435 size_t Exitflag = 0;
436
437 ControllerOptions_MPQCCommandJob ControllerInfo;
438 boost::asio::io_service io_service;
439 FragmentController controller(io_service);
440 boost::program_options::variables_map vm;
441
442 typedef boost::function<void ()> ControllerCommand;
443 typedef std::map<std::string, std::deque<ControllerCommand> > CommandsMap_t;
444 CommandsMap_t CommandsMap;
445
446 // prepare the command queues for each ControllerCommand
447 // note: we need "< ControllerCommand >" because parseExecutable(),... return int
448 // in contrast to other functions that return void
449 std::deque<ControllerCommand> addjobsQueue = boost::assign::list_of< ControllerCommand >
450 (boost::bind(&FragmentController::requestIds,
451 boost::ref(controller), boost::cref(ControllerInfo.server), boost::cref(ControllerInfo.serverport),
452 boost::bind(&std::vector<std::string>::size, boost::cref(ControllerInfo.jobfiles))))
453 (boost::bind(&AddJobs, boost::ref(controller), boost::cref(ControllerInfo)))
454 ;
455 std::deque<ControllerCommand> createjobsQueue = boost::assign::list_of< ControllerCommand >
456 (boost::bind(&FragmentController::requestIds,
457 boost::ref(controller), boost::cref(ControllerInfo.server), boost::cref(ControllerInfo.serverport), 1))
458 (boost::bind(&creatingJob, boost::ref(controller), boost::cref(ControllerInfo)))
459 ;
460 std::deque<ControllerCommand> checkresultsQueue = boost::assign::list_of< ControllerCommand >
461 (boost::bind(&FragmentController::checkResults,
462 boost::ref(controller), boost::cref(ControllerInfo.server), boost::cref(ControllerInfo.serverport)))
463 (boost::bind(&printJobStatus,
464 boost::bind(&FragmentController::getJobStatus, boost::ref(controller))))
465 ;
466 std::deque<ControllerCommand> receiveresultsQueue = boost::assign::list_of< ControllerCommand >
467 (boost::bind(&FragmentController::receiveResults,
468 boost::ref(controller), boost::cref(ControllerInfo.server), boost::cref(ControllerInfo.serverport)))
469 (boost::bind(&printReceivedResults,
470 boost::bind(&FragmentController::getReceivedResults, boost::ref(controller))))
471 ;
472 std::deque<ControllerCommand> receivempqcresultsQueue = boost::assign::list_of< ControllerCommand >
473 (boost::bind(&FragmentController::receiveResults,
474 boost::ref(controller), boost::cref(ControllerInfo.server), boost::cref(ControllerInfo.serverport)))
475 (boost::bind(&printReceivedMPQCResults,
476 boost::bind(&FragmentController::getReceivedResults, boost::ref(controller)),
477 boost::cref(ControllerInfo.fragmentpath),
478 boost::bind(&getNoAtomsFromAdjacencyFile, boost::cref(ControllerInfo.fragmentpath))))
479 ;
480 std::deque<ControllerCommand> removeallQueue = boost::assign::list_of< ControllerCommand >
481 (boost::bind(&FragmentController::removeall,
482 boost::ref(controller), boost::cref(ControllerInfo.server), boost::cref(ControllerInfo.serverport)))
483 ;
484 std::deque<ControllerCommand> shutdownQueue = boost::assign::list_of< ControllerCommand >
485 (boost::bind(&FragmentController::shutdown,
486 boost::ref(controller), boost::cref(ControllerInfo.server), boost::cref(ControllerInfo.serverport)))
487 ;
488 CommandsMap.insert( std::make_pair("addjobs", addjobsQueue) );
489 CommandsMap.insert( std::make_pair("createjobs", createjobsQueue) );
490 CommandsMap.insert( std::make_pair("checkresults", checkresultsQueue) );
491 CommandsMap.insert( std::make_pair("receiveresults", receiveresultsQueue) );
492 CommandsMap.insert( std::make_pair("receivempqc", receivempqcresultsQueue) );
493 CommandsMap.insert( std::make_pair("removeall", removeallQueue) );
494 CommandsMap.insert( std::make_pair("shutdown", shutdownQueue) );
495 std::vector<std::string> Commands;
496 for (CommandsMap_t::const_iterator iter = CommandsMap.begin(); iter != CommandsMap.end(); ++iter)
497 Commands.push_back(iter->first);
498
499 // Declare the supported options.
500 boost::program_options::options_description desc("Allowed options");
501 desc.add_options()
502 ("help,h", "produce help message")
503 ("verbosity,v", boost::program_options::value<size_t>(), "set verbosity level")
504 ("server", boost::program_options::value< std::string >(), "connect to server at this address (host:port)")
505 ("command", boost::program_options::value< std::string >(), (std::string("command to send to server: ")+toString(Commands)).c_str())
506 ("executable", boost::program_options::value< std::string >(), "executable for commands 'addjobs' and 'createjobs'")
507 ("fragment-path", boost::program_options::value< std::string >(), "path to fragment files for 'receivempqc'")
508 ("jobcommand", boost::program_options::value< std::string >(), "command argument for executable for 'createjobs'")
509 ("jobfiles", boost::program_options::value< std::vector< std::string > >()->multitoken(), "list of files as single argument to executable for 'addjobs'")
510 ;
511
512 // parse command line
513 boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm);
514 boost::program_options::notify(vm);
515
516 // set controller information
517 ControllerInfo.parseHelp(vm, desc);
518 ControllerInfo.parseVerbosity(vm);
519 ControllerInfo.parseServerPort(vm);
520 ControllerInfo.parseCommand(vm, Commands);
521
522 // all later parse functions depend on parsed command
523 ControllerInfo.parseExecutable(vm);
524
525 ControllerInfo.parseJobCommand(vm);
526
527 ControllerInfo.parseFragmentpath(vm);
528
529 ControllerInfo.parseJobfiles(vm);
530
531 // parse given ControllerCommand
532 if( CommandsMap.count(ControllerInfo.command) == 0) {
533 ELOG(1, "Unrecognized command '"+toString(ControllerInfo.command)+"'.");
534 return 255;
535 }
536 std::deque<ControllerCommand> &commands = CommandsMap[ControllerInfo.command];
537 try
538 {
539 // execute each command in the queue synchronously
540 size_t phase = 1;
541 while (!commands.empty()) {
542 ControllerCommand command = commands.front();
543 commands.pop_front();
544 command();
545 {
546 io_service.reset();
547 Info info((std::string("io_service: ")+toString(phase)).c_str());
548 io_service.run();
549 }
550 }
551 Exitflag = controller.getExitflag();
552 }
553 catch (std::exception& e)
554 {
555 std::cerr << e.what() << std::endl;
556 }
557
558 return Exitflag;
559}
560
Note: See TracBrowser for help on using the repository browser.