source: src/Fragmentation/Automation/controller.cpp@ 50d095

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

Moved Controller/Commands to Operations/ folder and split into Controllers, Servers, Workers.

  • each will eventually go into its own Registry.
  • also changed all include occurences in all files.
  • fixed some includes in the definition where path was used (header always resides in same folder as definition).
  • Property mode set to 100644
File size: 14.3 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/archive/text_oarchive.hpp>
30#include <boost/archive/text_iarchive.hpp>
31#include <fstream>
32#include <iostream>
33#include <map>
34#include <sstream>
35#include <streambuf>
36#include <vector>
37
38#include "atexit.hpp"
39#include "CodePatterns/Info.hpp"
40#include "CodePatterns/Log.hpp"
41#include "Controller/FragmentController.hpp"
42#include "Operations/Controllers/CheckResultsOperation.hpp"
43#include "Operations/Controllers/GetNextJobIdOperation.hpp"
44#include "Operations/Controllers/ReceiveResultsOperation.hpp"
45#include "Operations/Controllers/SendJobsOperation.hpp"
46#include "Operations/Controllers/ShutdownOperation.hpp"
47#include "Jobs/MPQCCommandJob.hpp"
48#include "Jobs/MPQCCommandJob_MPQCData.hpp"
49#include "Jobs/SystemCommandJob.hpp"
50#include "Results/FragmentResult.hpp"
51
52enum CommandIndices {
53 UnknownCommandIndex = 0,
54 AddJobsIndex = 1,
55 CreateJobsIndex = 2,
56 CheckResultsIndex = 3,
57 ReceiveResultsIndex = 4,
58 ReceiveMPQCIndex = 5,
59 ShutdownIndex = 6,
60};
61
62/** Requests an available id from server
63 *
64 * @param controller FragmentController with CommandRegistry
65 * @param host address of server
66 * @param service port/service of server
67 */
68void requestid(
69 FragmentController &controller,
70 const std::string &host,
71 const std::string &service)
72{
73 GetNextJobIdOperation *getnextid = static_cast<GetNextJobIdOperation *>(
74 controller.Commands.getByName("getnextjobid"));
75 (*getnextid)(host,service);
76}
77
78/** Returns another available id from a finished GetNextJobIdOperation.
79 *
80 * @param controller FragmentController with CommandRegistry
81 * @return next available id
82 */
83JobId_t getavailableid(FragmentController &controller)
84{
85 GetNextJobIdOperation *getnextid = static_cast<GetNextJobIdOperation *>(
86 controller.Commands.getByName("getnextjobid"));
87 const JobId_t nextid = getnextid->getNextId();
88 LOG(1, "INFO: Next available id is " << nextid << ".");
89 return nextid;
90}
91
92void createjobs(
93 std::vector<FragmentJob::ptr> &jobs,
94 const std::string &command,
95 const std::string &argument,
96 const JobId_t nextid)
97{
98 FragmentJob::ptr testJob( new SystemCommandJob(command, argument, nextid) );
99 jobs.push_back(testJob);
100 LOG(1, "INFO: Added one SystemCommandJob.");
101}
102
103/** Creates a MPQCCommandJob with argument \a filename.
104 *
105 * @param jobs created job is added to this vector
106 * @param filename filename being argument to job
107 * @param nextid id for this job
108 */
109void parsejob(
110 std::vector<FragmentJob::ptr> &jobs,
111 const std::string &filename,
112 const JobId_t nextid)
113{
114 std::ifstream file;
115 file.open(filename.c_str());
116 ASSERT( file.good(), "parsejob() - file "+filename+" does not exist.");
117 std::string output((std::istreambuf_iterator<char>(file)),
118 std::istreambuf_iterator<char>());
119 FragmentJob::ptr testJob( new MPQCCommandJob(output, nextid) );
120 jobs.push_back(testJob);
121 file.close();
122 LOG(1, "INFO: Added MPQCCommandJob from file "+filename+".");
123}
124
125/** Adds a vector of jobs to the send operation.
126 *
127 * @param controller FragmentController with CommandRegistry
128 * @param jobs jobs to add
129 */
130void addjobs(
131 FragmentController &controller,
132 std::vector<FragmentJob::ptr> &jobs)
133{
134 SendJobsOperation *sendjobs = static_cast<SendJobsOperation *>(
135 controller.Commands.getByName("sendjobs"));
136 sendjobs->addJobs(jobs);
137 const size_t presentJobs = sendjobs->getPresentJobs();
138 LOG(1, "INFO: #" << presentJobs << " jobs are now waiting to be transmitted.");
139}
140
141/** Sends contained jobs in operation to server
142 *
143 * @param controller FragmentController with CommandRegistry
144 * @param host address of server
145 * @param service port/service of server
146 */
147void sendjobs(
148 FragmentController &controller,
149 const std::string &host,
150 const std::string &service)
151{
152 SendJobsOperation *sendjobs = static_cast<SendJobsOperation *>(
153 controller.Commands.getByName("sendjobs"));
154 const size_t presentJobs = sendjobs->getPresentJobs();
155 LOG(1, "INFO: #" << presentJobs << " jobs are being sent to the server.");
156 (*sendjobs)(host, service);
157}
158
159/** Obtains scheduled and done jobs from server
160 *
161 * @param controller FragmentController with CommandRegistry
162 * @param host address of server
163 * @param service port/service of server
164 */
165void checkresults(
166 FragmentController &controller,
167 const std::string &host,
168 const std::string &service)
169{
170 CheckResultsOperation *checkres = static_cast<CheckResultsOperation *>(
171 controller.Commands.getByName("checkresults"));
172 (*checkres)(host, service);
173}
174
175/** Prints scheduled and done jobs.
176 *
177 * @param controller FragmentController with CommandRegistry
178 */
179void printdonejobs(FragmentController &controller)
180{
181 CheckResultsOperation *checkres = static_cast<CheckResultsOperation *>(
182 controller.Commands.getByName("checkresults"));
183 const size_t doneJobs = checkres->getDoneJobs();
184 const size_t presentJobs = checkres->getPresentJobs();
185 LOG(1, "INFO: #" << presentJobs << " are waiting in the queue and #" << doneJobs << " jobs are calculated so far.");
186}
187
188/** Obtains results from done jobs from server.
189 *
190 * @param controller FragmentController with CommandRegistry
191 * @param host address of server
192 * @param service port/service of server
193 */
194void receiveresults(
195 FragmentController &controller,
196 const std::string &host,
197 const std::string &service)
198{
199 ReceiveResultsOperation *receiveres = static_cast<ReceiveResultsOperation *>(
200 controller.Commands.getByName("receiveresults"));
201 (*receiveres)(host, service);
202}
203
204/** Print received results.
205 *
206 * @param controller FragmentController with CommandRegistry
207 */
208void printreceivedresults(FragmentController &controller)
209{
210 ReceiveResultsOperation *receiveres = static_cast<ReceiveResultsOperation *>(
211 controller.Commands.getByName("receiveresults"));
212 std::vector<FragmentResult::ptr> results = receiveres->getResults();
213 for (std::vector<FragmentResult::ptr>::const_iterator iter = results.begin();
214 iter != results.end(); ++iter)
215 LOG(1, "RESULT: job #"+toString((*iter)->getId())+": "+toString((*iter)->result));
216}
217
218/** Print received results.
219 *
220 * @param controller FragmentController with CommandRegistry
221 */
222void printreceivedmpqcresults(FragmentController &controller, const std::string &KeySetFilename)
223{
224 ReceiveResultsOperation *receiveres = static_cast<ReceiveResultsOperation *>(
225 controller.Commands.getByName("receiveresults"));
226 std::vector<FragmentResult::ptr> results = receiveres->getResults();
227
228 // parse in KeySetfile
229// const size_t MAXBUFFER = 256;
230 std::ifstream inputfile;
231 inputfile.open(KeySetFilename.c_str());
232// while (inputfile.getline(buffer, MAXBUFFER)) {
233//
234// }
235 inputfile.close();
236
237 // combine all found data
238 std::vector<MPQCData> fragmentData(results.size());
239 MPQCData combinedData;
240
241 LOG(2, "DEBUG: Parsing now through " << results.size() << " results.");
242 for (std::vector<FragmentResult::ptr>::const_iterator iter = results.begin();
243 iter != results.end(); ++iter) {
244 LOG(1, "RESULT: job #"+toString((*iter)->getId())+": "+toString((*iter)->result));
245 MPQCData extractedData;
246 std::stringstream inputstream((*iter)->result);
247 boost::archive::text_iarchive ia(inputstream);
248 ia >> extractedData;
249 LOG(1, "INFO: extracted data is " << extractedData << ".");
250 }
251}
252
253/** Sends shutdown signal to server
254 *
255 * @param controller FragmentController with CommandRegistry
256 * @param host address of server
257 * @param service port/service of server
258 */
259void shutdown(
260 FragmentController &controller,
261 const std::string &host,
262 const std::string &service)
263{
264 ShutdownOperation *shutdown = static_cast<ShutdownOperation *>(
265 controller.Commands.getByName("shutdown"));
266 (*shutdown)(host, service);
267}
268
269/** Returns a unique index for every command to allow switching over it.
270 *
271 * \param &commandmap map with command strings
272 * \param &cmd command string
273 * \return index from CommandIndices: UnkownCommandIndex - unknown command, else - command index
274 */
275CommandIndices getCommandIndex(std::map<std::string, CommandIndices> &commandmap, const std::string &cmd)
276{
277 std::map<std::string, CommandIndices>::const_iterator iter = commandmap.find(cmd);
278 if (iter != commandmap.end())
279 return iter->second;
280 else
281 return UnknownCommandIndex;
282}
283
284
285int main(int argc, char* argv[])
286{
287 // from this moment on, we need to be sure to deeinitialize in the correct order
288 // this is handled by the cleanup function
289 atexit(cleanUp);
290
291 setVerbosity(3);
292
293 size_t Exitflag = 0;
294 typedef std::map<std::string, CommandIndices> CommandsMap_t;
295 CommandsMap_t CommandsMap;
296 CommandsMap.insert( std::make_pair("addjobs", AddJobsIndex) );
297 CommandsMap.insert( std::make_pair("createjobs", CreateJobsIndex) );
298 CommandsMap.insert( std::make_pair("checkresults", CheckResultsIndex) );
299 CommandsMap.insert( std::make_pair("receiveresults", ReceiveResultsIndex) );
300 CommandsMap.insert( std::make_pair("receivempqc", ReceiveMPQCIndex) );
301 CommandsMap.insert( std::make_pair("shutdown", ShutdownIndex) );
302 try
303 {
304 // Check command line arguments.
305 if (argc < 4)
306 {
307 std::cerr << "Usage: " << argv[0] << " <host> <port> <command> [options to command]" << std::endl;
308 std::cerr << "List of available commands:" << std::endl;
309 for(CommandsMap_t::const_iterator iter = CommandsMap.begin();
310 iter != CommandsMap.end(); ++iter) {
311 std::cerr << "\t" << iter->first << std::endl;
312 }
313 return 1;
314 }
315
316 boost::asio::io_service io_service;
317 FragmentController controller(io_service);
318
319 // Initial phase: information gathering from server
320
321 switch(getCommandIndex(CommandsMap, argv[3])) {
322 case AddJobsIndex:
323 {
324 if (argc < 5) {
325 ELOG(1, "Please add a filename for the MPQCCommandJob.");
326 } else {
327 // get an id for every filename
328 for (int argcount = 4; argcount < argc; ++argcount) {
329 requestid(controller, argv[1], argv[2]);
330 }
331 }
332 break;
333 }
334 case CreateJobsIndex:
335 {
336 std::vector<FragmentJob::ptr> jobs;
337 if (argc < 6) {
338 ELOG(1, "'createjobs' requires two options: [command] [argument].");
339 } else {
340 requestid(controller, argv[1], argv[2]);
341 }
342 break;
343 }
344 case CheckResultsIndex:
345 break;
346 case ReceiveResultsIndex:
347 break;
348 case ReceiveMPQCIndex:
349 break;
350 case ShutdownIndex:
351 break;
352 case UnknownCommandIndex:
353 default:
354 ELOG(1, "Unrecognized command '"+toString(argv[3])+"'.");
355 break;
356 }
357
358 {
359 io_service.reset();
360 Info info("io_service: Phase One");
361 io_service.run();
362 }
363
364 // Second phase: Building jobs and sending information to server
365
366 switch(getCommandIndex(CommandsMap, argv[3])) {
367 case AddJobsIndex:
368 {
369 std::vector<FragmentJob::ptr> jobs;
370 if (argc < 5) {
371 ELOG(1, "Please add a filename for the MPQCCommandJob.");
372 } else {
373 for (int argcount = 4; argcount < argc; ++argcount) {
374 const JobId_t next_id = getavailableid(controller);
375 const std::string filename(argv[argcount]);
376 LOG(1, "INFO: Creating MPQCCommandJob with filename'"
377 +filename+"', and id "+toString(next_id)+".");
378 parsejob(jobs, filename, next_id);
379 }
380 addjobs(controller, jobs);
381 sendjobs(controller, argv[1], argv[2]);
382 }
383 break;
384 }
385 case CreateJobsIndex:
386 {
387 std::vector<FragmentJob::ptr> jobs;
388 if (argc < 6) {
389 ELOG(1, "'createjobs' requires two options: [command] [argument].");
390 } else {
391 const JobId_t next_id = getavailableid(controller);
392 const std::string command(argv[4]);
393 const std::string argument(argv[5]);
394 LOG(1, "INFO: Creating SystemCommandJob with command '"
395 +command+"', argument '"+argument+"', and id "+toString(next_id)+".");
396 createjobs(jobs, command, argument, next_id);
397 }
398 addjobs(controller, jobs);
399 sendjobs(controller, argv[1], argv[2]);
400 break;
401 }
402 case CheckResultsIndex:
403 {
404 checkresults(controller, argv[1], argv[2]);
405 break;
406 }
407 case ReceiveResultsIndex:
408 {
409 receiveresults(controller, argv[1], argv[2]);
410 break;
411 }
412 case ReceiveMPQCIndex:
413 {
414 receiveresults(controller, argv[1], argv[2]);
415 break;
416 }
417 case ShutdownIndex:
418 {
419 shutdown(controller, argv[1], argv[2]);
420 break;
421 }
422 case UnknownCommandIndex:
423 default:
424 ELOG(0, "Unrecognized command '"+toString(argv[3])+"'.");
425 break;
426 }
427
428 {
429 io_service.reset();
430 Info info("io_service: Phase Two");
431 io_service.run();
432 }
433
434 // Final phase: Print result of command
435
436 switch(getCommandIndex(CommandsMap, argv[3])) {
437 case AddJobsIndex:
438 case CreateJobsIndex:
439 break;
440 case CheckResultsIndex:
441 {
442 printdonejobs(controller);
443 break;
444 }
445 case ReceiveResultsIndex:
446 {
447 printreceivedresults(controller);
448 break;
449 }
450 case ReceiveMPQCIndex:
451 {
452 if (argc == 4) {
453 ELOG(1, "'receivempqc' requires one option: [KeySetFilename].");
454 } else {
455 const std::string KeySetFilename = argv[4];
456 LOG(1, "INFO: Parsing id associations from " << KeySetFilename << ".");
457 printreceivedmpqcresults(controller, KeySetFilename);
458 }
459 break;
460 }
461 case ShutdownIndex:
462 break;
463 case UnknownCommandIndex:
464 default:
465 ELOG(0, "Unrecognized command '"+toString(argv[3])+"'.");
466 break;
467 }
468 Exitflag = controller.getExitflag();
469 }
470 catch (std::exception& e)
471 {
472 std::cerr << e.what() << std::endl;
473 }
474
475 return Exitflag;
476}
Note: See TracBrowser for help on using the repository browser.