source: src/controller.cpp@ 0aaf84

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 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 0aaf84 was 0aaf84, checked in by Frederik Heber <heber@…>, 13 years ago

Added DefaultOptions, containing help and verbosity from ControllerOptions.

  • same options are required for Server and PoolWorker.
  • Property mode set to 100644
File size: 20.5 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 DefaultOptions
290{
291 int parseHelp(boost::program_options::variables_map &vm, const boost::program_options::options_description &desc) {
292 if (vm.count("help")) {
293 std::cout << desc << "\n";
294 return 1;
295 }
296 return 0;
297 }
298 int parseVerbosity(boost::program_options::variables_map &vm) {
299 if (vm.count("verbosity")) {
300 LOG(0, "STATUS: Verbosity level was set to " << vm["verbosity"].as<size_t>() << ".");
301 setVerbosity(vm["verbosity"].as<size_t>());
302 } else {
303 LOG(0, "STATUS: Verbosity level was not set, defaulting to 5.");
304 setVerbosity(5);
305 }
306 return 0;
307 }
308};
309
310struct ControllerOptions : public DefaultOptions
311{
312 int parseServerPort(boost::program_options::variables_map &vm) {
313 if (vm.count("server")) {
314 server = vm["server"].as< std::string >();
315 serverport = server.substr(server.find_last_of(':')+1, std::string::npos);
316 server = server.substr(0, server.find_last_of(':'));
317 try {
318 boost::lexical_cast<size_t>(serverport);
319 } catch (boost::bad_lexical_cast &) {
320 ELOG(1, "Could not interpret " << serverport << " as server:port.");
321 return 255;
322 }
323 LOG(1, "INFO: Using " << server << ":" << serverport << " as server's address.");
324 } else {
325 ELOG(1, "Requiring server's address (host:port) to connect to.");
326 return 255;
327 }
328 return 0;
329 }
330
331 int parseCommand(boost::program_options::variables_map &vm, const std::vector<std::string> &Commands) {
332 if (!vm.count("command")) {
333 ELOG(1, "Controller requires one of the following commands: "+toString(Commands));
334 return 255;
335 }
336 command = vm["command"].as< std::string >();
337 return 0;
338 }
339
340 std::string command;
341 std::string server;
342 std::string serverport;
343
344};
345
346struct ControllerOptions_SystemCommandJob : public ControllerOptions
347{
348 int parseExecutable(boost::program_options::variables_map &vm) {
349 if ((command == "createjobs") || (command == "addjobs")) {
350 if (!vm.count("executable")) {
351 ELOG(1, "'"+command+"' requires two options: [executable] [jobcommand].");
352 return 255;
353 }
354 executable = vm["executable"].as< std::string >();
355 }
356 return 0;
357 }
358
359 int parseJobCommand(boost::program_options::variables_map &vm) {
360 if (command == "createjobs") {
361 if (!vm.count("jobcommand")) {
362 ELOG(1, "'"+command+"' requires two options: [executable] [jobcommand].");
363 return 255;
364 }
365 jobcommand = vm["jobcommand"].as< std::string >();
366 }
367 return 0;
368 }
369
370 std::string executable;
371 std::string jobcommand;
372};
373
374struct ControllerOptions_MPQCCommandJob : public ControllerOptions_SystemCommandJob
375{
376 int parseFragmentpath(boost::program_options::variables_map &vm) {
377 if (command == "receivempqc") {
378 if (!vm.count("fragment-path")) {
379 ELOG(1, "'"+command+"' requires two options: [fragment-path].");
380 return 255;
381 }
382 fragmentpath = vm["fragment-path"].as< std::string >();
383 }
384 return 0;
385 }
386
387 int parseJobfiles(boost::program_options::variables_map &vm) {
388 if (command == "addjobs") {
389 if (!vm.count("jobfiles")) {
390 ELOG(1, "'"+command+"' requires two options: [executable] [jobfiles].");
391 return 255;
392 }
393 jobfiles = vm["jobfiles"].as< std::vector<std::string> >();
394 }
395 return 0;
396 }
397
398 std::string fragmentpath;
399 std::vector<std::string> jobfiles;
400};
401
402void creatingJob(FragmentController &controller, const ControllerOptions_SystemCommandJob &ControllerInfo)
403{
404 const JobId_t next_id = controller.getAvailableId();
405 std::vector<FragmentJob::ptr> jobs;
406 createjobs(jobs, ControllerInfo.executable, ControllerInfo.jobcommand, next_id);
407 controller.addJobs(jobs);
408 controller.sendJobs(ControllerInfo.server, ControllerInfo.serverport);
409}
410
411/** Creates a MPQCCommandJob out of give \a command with \a argument.
412 *
413 * @param controller reference to controller to add jobs
414 * @param ControllerInfo information on the job
415 */
416void AddJobs(FragmentController &controller, const ControllerOptions_MPQCCommandJob &ControllerInfo)
417{
418 std::vector<FragmentJob::ptr> jobs;
419 for (std::vector< std::string >::const_iterator iter = ControllerInfo.jobfiles.begin();
420 iter != ControllerInfo.jobfiles.end(); ++iter) {
421 const JobId_t next_id = controller.getAvailableId();
422 const std::string &filename = *iter;
423 LOG(1, "INFO: Creating MPQCCommandJob with filename '"
424 +filename+"', and id "+toString(next_id)+".");
425 parsejob(jobs, ControllerInfo.executable, filename, next_id);
426 }
427 controller.addJobs(jobs);
428 controller.sendJobs(ControllerInfo.server, ControllerInfo.serverport);
429}
430
431int main(int argc, char* argv[])
432{
433 // from this moment on, we need to be sure to deeinitialize in the correct order
434 // this is handled by the cleanup function
435 atexit(cleanUp);
436
437 size_t Exitflag = 0;
438
439 ControllerOptions_MPQCCommandJob ControllerInfo;
440 boost::asio::io_service io_service;
441 FragmentController controller(io_service);
442 boost::program_options::variables_map vm;
443
444 typedef boost::function<void ()> ControllerCommand;
445 typedef std::map<std::string, std::deque<ControllerCommand> > CommandsMap_t;
446 CommandsMap_t CommandsMap;
447
448 // prepare the command queues for each ControllerCommand
449 // note: we need "< ControllerCommand >" because parseExecutable(),... return int
450 // in contrast to other functions that return void
451 std::deque<ControllerCommand> addjobsQueue = boost::assign::list_of< ControllerCommand >
452 (boost::bind(&FragmentController::requestIds,
453 boost::ref(controller), boost::cref(ControllerInfo.server), boost::cref(ControllerInfo.serverport),
454 boost::bind(&std::vector<std::string>::size, boost::cref(ControllerInfo.jobfiles))))
455 (boost::bind(&AddJobs, boost::ref(controller), boost::cref(ControllerInfo)))
456 ;
457 std::deque<ControllerCommand> createjobsQueue = boost::assign::list_of< ControllerCommand >
458 (boost::bind(&FragmentController::requestIds,
459 boost::ref(controller), boost::cref(ControllerInfo.server), boost::cref(ControllerInfo.serverport), 1))
460 (boost::bind(&creatingJob, boost::ref(controller), boost::cref(ControllerInfo)))
461 ;
462 std::deque<ControllerCommand> checkresultsQueue = boost::assign::list_of< ControllerCommand >
463 (boost::bind(&FragmentController::checkResults,
464 boost::ref(controller), boost::cref(ControllerInfo.server), boost::cref(ControllerInfo.serverport)))
465 (boost::bind(&printJobStatus,
466 boost::bind(&FragmentController::getJobStatus, boost::ref(controller))))
467 ;
468 std::deque<ControllerCommand> receiveresultsQueue = boost::assign::list_of< ControllerCommand >
469 (boost::bind(&FragmentController::receiveResults,
470 boost::ref(controller), boost::cref(ControllerInfo.server), boost::cref(ControllerInfo.serverport)))
471 (boost::bind(&printReceivedResults,
472 boost::bind(&FragmentController::getReceivedResults, boost::ref(controller))))
473 ;
474 std::deque<ControllerCommand> receivempqcresultsQueue = boost::assign::list_of< ControllerCommand >
475 (boost::bind(&FragmentController::receiveResults,
476 boost::ref(controller), boost::cref(ControllerInfo.server), boost::cref(ControllerInfo.serverport)))
477 (boost::bind(&printReceivedMPQCResults,
478 boost::bind(&FragmentController::getReceivedResults, boost::ref(controller)),
479 boost::cref(ControllerInfo.fragmentpath),
480 boost::bind(&getNoAtomsFromAdjacencyFile, boost::cref(ControllerInfo.fragmentpath))))
481 ;
482 std::deque<ControllerCommand> removeallQueue = boost::assign::list_of< ControllerCommand >
483 (boost::bind(&FragmentController::removeall,
484 boost::ref(controller), boost::cref(ControllerInfo.server), boost::cref(ControllerInfo.serverport)))
485 ;
486 std::deque<ControllerCommand> shutdownQueue = boost::assign::list_of< ControllerCommand >
487 (boost::bind(&FragmentController::shutdown,
488 boost::ref(controller), boost::cref(ControllerInfo.server), boost::cref(ControllerInfo.serverport)))
489 ;
490 CommandsMap.insert( std::make_pair("addjobs", addjobsQueue) );
491 CommandsMap.insert( std::make_pair("createjobs", createjobsQueue) );
492 CommandsMap.insert( std::make_pair("checkresults", checkresultsQueue) );
493 CommandsMap.insert( std::make_pair("receiveresults", receiveresultsQueue) );
494 CommandsMap.insert( std::make_pair("receivempqc", receivempqcresultsQueue) );
495 CommandsMap.insert( std::make_pair("removeall", removeallQueue) );
496 CommandsMap.insert( std::make_pair("shutdown", shutdownQueue) );
497 std::vector<std::string> Commands;
498 for (CommandsMap_t::const_iterator iter = CommandsMap.begin(); iter != CommandsMap.end(); ++iter)
499 Commands.push_back(iter->first);
500
501 // Declare the supported options.
502 boost::program_options::options_description desc("Allowed options");
503 desc.add_options()
504 ("help,h", "produce help message")
505 ("verbosity,v", boost::program_options::value<size_t>(), "set verbosity level")
506 ("server", boost::program_options::value< std::string >(), "connect to server at this address (host:port)")
507 ("command", boost::program_options::value< std::string >(), (std::string("command to send to server: ")+toString(Commands)).c_str())
508 ("executable", boost::program_options::value< std::string >(), "executable for commands 'addjobs' and 'createjobs'")
509 ("fragment-path", boost::program_options::value< std::string >(), "path to fragment files for 'receivempqc'")
510 ("jobcommand", boost::program_options::value< std::string >(), "command argument for executable for 'createjobs'")
511 ("jobfiles", boost::program_options::value< std::vector< std::string > >()->multitoken(), "list of files as single argument to executable for 'addjobs'")
512 ;
513
514 // parse command line
515 boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm);
516 boost::program_options::notify(vm);
517
518 // set controller information
519 ControllerInfo.parseHelp(vm, desc);
520 ControllerInfo.parseVerbosity(vm);
521 ControllerInfo.parseServerPort(vm);
522 ControllerInfo.parseCommand(vm, Commands);
523
524 // all later parse functions depend on parsed command
525 ControllerInfo.parseExecutable(vm);
526
527 ControllerInfo.parseJobCommand(vm);
528
529 ControllerInfo.parseFragmentpath(vm);
530
531 ControllerInfo.parseJobfiles(vm);
532
533 // parse given ControllerCommand
534 if( CommandsMap.count(ControllerInfo.command) == 0) {
535 ELOG(1, "Unrecognized command '"+toString(ControllerInfo.command)+"'.");
536 return 255;
537 }
538 std::deque<ControllerCommand> &commands = CommandsMap[ControllerInfo.command];
539 try
540 {
541 // execute each command in the queue synchronously
542 size_t phase = 1;
543 while (!commands.empty()) {
544 ControllerCommand command = commands.front();
545 commands.pop_front();
546 command();
547 {
548 io_service.reset();
549 Info info((std::string("io_service: ")+toString(phase)).c_str());
550 io_service.run();
551 }
552 }
553 Exitflag = controller.getExitflag();
554 }
555 catch (std::exception& e)
556 {
557 std::cerr << e.what() << std::endl;
558 }
559
560 return Exitflag;
561}
562
Note: See TracBrowser for help on using the repository browser.