source: src/Fragmentation/Automation/controller.cpp@ d1dbfc

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

New GetNextJobIdOperation for obtaining next available JobId from server.

  • as JobId is required to create the job, we now need two, separate communication phases: gathering info (ids) and sending info (jobs).
  • new SchedulderState GetNextJobId along with handlers.
  • new GetNextJobIdOperation that requests another id which is internally stored into a list, along with a getter that extracts them one by one.
  • controller's createjobs() and parsejobs() each take an nextid parameter now.
  • Property mode set to 100644
File size: 11.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 <fstream>
30#include <iostream>
31#include <map>
32#include <sstream>
33#include <streambuf>
34#include <vector>
35
36#include "atexit.hpp"
37#include "CodePatterns/Info.hpp"
38#include "CodePatterns/Log.hpp"
39#include "Controller/FragmentController.hpp"
40#include "Controller/Commands/CheckResultsOperation.hpp"
41#include "Controller/Commands/GetNextJobIdOperation.hpp"
42#include "Controller/Commands/ReceiveJobsOperation.hpp"
43#include "Controller/Commands/SendResultsOperation.hpp"
44#include "Controller/Commands/ShutdownOperation.hpp"
45#include "Jobs/MPQCCommandJob.hpp"
46#include "Jobs/SystemCommandJob.hpp"
47#include "Results/FragmentResult.hpp"
48
49enum CommandIndices {
50 UnknownCommandIndex = 0,
51 AddJobsIndex = 1,
52 CreateJobsIndex = 2,
53 CheckResultsIndex = 3,
54 ReceiveResultsIndex = 4,
55 ShutdownIndex = 5
56};
57
58/** Requests an available id from server
59 *
60 * @param controller FragmentController with CommandRegistry
61 * @param host address of server
62 * @param service port/service of server
63 */
64void requestid(
65 FragmentController &controller,
66 const std::string &host,
67 const std::string &service)
68{
69 GetNextJobIdOperation *getnextid = static_cast<GetNextJobIdOperation *>(
70 controller.Commands.getByName("getnextjobid"));
71 (*getnextid)(host,service);
72}
73
74/** Returns another available id from a finished GetNextJobIdOperation.
75 *
76 * @param controller FragmentController with CommandRegistry
77 * @return next available id
78 */
79JobId_t getavailableid(FragmentController &controller)
80{
81 GetNextJobIdOperation *getnextid = static_cast<GetNextJobIdOperation *>(
82 controller.Commands.getByName("getnextjobid"));
83 const JobId_t nextid = getnextid->getNextId();
84 LOG(1, "INFO: Next available id is " << nextid << ".");
85 return nextid;
86}
87
88void createjobs(std::vector<FragmentJob::ptr> &jobs, const JobId_t nextid)
89{
90 FragmentJob::ptr testJob( new SystemCommandJob( std::string("cat"), std::string("Nothing"), nextid) );
91 jobs.push_back(testJob);
92 LOG(1, "INFO: Added one empty SystemCommandJob's.");
93}
94
95/** Creates a MPQCCommandJob with argument \a filename.
96 *
97 * @param jobs created job is added to this vector
98 * @param filename filename being argument to job
99 * @param nextid id for this job
100 */
101void parsejob(
102 std::vector<FragmentJob::ptr> &jobs,
103 const std::string &filename,
104 const JobId_t nextid)
105{
106 std::ifstream file;
107 file.open(filename.c_str());
108 ASSERT( file.good(), "parsejob() - file "+filename+" does not exist.");
109 std::string output((std::istreambuf_iterator<char>(file)),
110 std::istreambuf_iterator<char>());
111 FragmentJob::ptr testJob( new MPQCCommandJob(output, nextid) );
112 jobs.push_back(testJob);
113 file.close();
114 LOG(1, "INFO: Added MPQCCommandJob from file "+filename+".");
115}
116
117/** Adds a vector of jobs to the send operation.
118 *
119 * @param controller FragmentController with CommandRegistry
120 * @param jobs jobs to add
121 */
122void addjobs(
123 FragmentController &controller,
124 std::vector<FragmentJob::ptr> &jobs)
125{
126 ReceiveJobsOperation *recjobs = static_cast<ReceiveJobsOperation *>(
127 controller.Commands.getByName("receivejobs"));
128 recjobs->addJobs(jobs);
129}
130
131/** Sends contained jobs in operation to server
132 *
133 * @param controller FragmentController with CommandRegistry
134 * @param host address of server
135 * @param service port/service of server
136 */
137void sendjobs(
138 FragmentController &controller,
139 const std::string &host,
140 const std::string &service)
141{
142 ReceiveJobsOperation *recjobs = static_cast<ReceiveJobsOperation *>(
143 controller.Commands.getByName("receivejobs"));
144 (*recjobs)(host, service);
145}
146
147/** Obtains scheduled and done jobs from server
148 *
149 * @param controller FragmentController with CommandRegistry
150 * @param host address of server
151 * @param service port/service of server
152 */
153void checkresults(
154 FragmentController &controller,
155 const std::string &host,
156 const std::string &service)
157{
158 CheckResultsOperation *checkres = static_cast<CheckResultsOperation *>(
159 controller.Commands.getByName("checkresults"));
160 (*checkres)(host, service);
161}
162
163/** Prints scheduled and done jobs.
164 *
165 * @param controller FragmentController with CommandRegistry
166 */
167void printdonejobs(FragmentController &controller)
168{
169 CheckResultsOperation *checkres = static_cast<CheckResultsOperation *>(
170 controller.Commands.getByName("checkresults"));
171 const size_t doneJobs = checkres->getDoneJobs();
172 const size_t presentJobs = checkres->getPresentJobs();
173 LOG(1, "INFO: #" << presentJobs << " are waiting in the queue and #" << doneJobs << " jobs are calculated so far.");
174}
175
176/** Obtains results from done jobs from server.
177 *
178 * @param controller FragmentController with CommandRegistry
179 * @param host address of server
180 * @param service port/service of server
181 */
182void receiveresults(
183 FragmentController &controller,
184 const std::string &host,
185 const std::string &service)
186{
187 SendResultsOperation *sendres = static_cast<SendResultsOperation *>(
188 controller.Commands.getByName("sendresults"));
189 (*sendres)(host, service);
190}
191
192/** Print received results.
193 *
194 * @param controller FragmentController with CommandRegistry
195 */
196void printreceivedresults(FragmentController &controller)
197{
198 SendResultsOperation *sendres = static_cast<SendResultsOperation *>(
199 controller.Commands.getByName("sendresults"));
200 std::vector<FragmentResult::ptr> results = sendres->getResults();
201 for (std::vector<FragmentResult::ptr>::const_iterator iter = results.begin();
202 iter != results.end(); ++iter)
203 LOG(1, "RESULT: job #"+toString((*iter)->getId())+": "+toString((*iter)->result));
204}
205
206/** Sends shutdown signal to server
207 *
208 * @param controller FragmentController with CommandRegistry
209 * @param host address of server
210 * @param service port/service of server
211 */
212void shutdown(
213 FragmentController &controller,
214 const std::string &host,
215 const std::string &service)
216{
217 ShutdownOperation *shutdown = static_cast<ShutdownOperation *>(
218 controller.Commands.getByName("shutdown"));
219 (*shutdown)(host, service);
220}
221
222/** Returns a unique index for every command to allow switching over it.
223 *
224 * \param &commandmap map with command strings
225 * \param &cmd command string
226 * \return index from CommandIndices: UnkownCommandIndex - unknown command, else - command index
227 */
228CommandIndices getCommandIndex(std::map<std::string, CommandIndices> &commandmap, const std::string &cmd)
229{
230 std::map<std::string, CommandIndices>::const_iterator iter = commandmap.find(cmd);
231 if (iter != commandmap.end())
232 return iter->second;
233 else
234 return UnknownCommandIndex;
235}
236
237
238int main(int argc, char* argv[])
239{
240 // from this moment on, we need to be sure to deeinitialize in the correct order
241 // this is handled by the cleanup function
242 atexit(cleanUp);
243
244 setVerbosity(3);
245
246 size_t Exitflag = 0;
247 typedef std::map<std::string, CommandIndices> CommandsMap_t;
248 CommandsMap_t CommandsMap;
249 CommandsMap.insert( std::make_pair("addjobs", AddJobsIndex) );
250 CommandsMap.insert( std::make_pair("createjobs", CreateJobsIndex) );
251 CommandsMap.insert( std::make_pair("checkresults", CheckResultsIndex) );
252 CommandsMap.insert( std::make_pair("receiveresults", ReceiveResultsIndex) );
253 CommandsMap.insert( std::make_pair("shutdown", ShutdownIndex) );
254 try
255 {
256 // Check command line arguments.
257 if (argc < 4)
258 {
259 std::cerr << "Usage: " << argv[0] << " <host> <port> <command> [options to command]" << std::endl;
260 std::cerr << "List of available commands:" << std::endl;
261 for(CommandsMap_t::const_iterator iter = CommandsMap.begin();
262 iter != CommandsMap.end(); ++iter) {
263 std::cerr << "\t" << iter->first << std::endl;
264 }
265 return 1;
266 }
267
268 boost::asio::io_service io_service;
269 FragmentController controller(io_service);
270
271 // Initial phase: information gathering from server
272
273 switch(getCommandIndex(CommandsMap, argv[3])) {
274 case AddJobsIndex:
275 {
276 if (argc < 5) {
277 ELOG(1, "Please add a filename for the MPQCCommandJob.");
278 } else {
279 // get an id for every filename
280 for (int argcount = 4; argcount < argc; ++argcount) {
281 requestid(controller, argv[1], argv[2]);
282 }
283 }
284 break;
285 }
286 case CreateJobsIndex:
287 {
288 requestid(controller, argv[1], argv[2]);
289 break;
290 }
291 case CheckResultsIndex:
292 break;
293 case ReceiveResultsIndex:
294 break;
295 case ShutdownIndex:
296 break;
297 case UnknownCommandIndex:
298 default:
299 ELOG(1, "Unrecognized command '"+toString(argv[3])+"'.");
300 break;
301 }
302
303 {
304 io_service.reset();
305 Info info("io_service: Phase One");
306 io_service.run();
307 }
308
309 // Second phase: Building jobs and sending information to server
310
311 switch(getCommandIndex(CommandsMap, argv[3])) {
312 case AddJobsIndex:
313 {
314 std::vector<FragmentJob::ptr> jobs;
315 if (argc < 5) {
316 ELOG(1, "Please add a filename for the MPQCCommandJob.");
317 } else {
318 for (int argcount = 4; argcount < argc; ++argcount) {
319 const JobId_t next_id = getavailableid(controller);
320 const std::string filename(argv[argcount]);
321 LOG(1, "INFO: Creating MPQCCommandJob with filename'"
322 +filename+"', and id "+toString(next_id)+".");
323 parsejob(jobs, filename, next_id);
324 }
325 addjobs(controller, jobs);
326 sendjobs(controller, argv[1], argv[2]);
327 }
328 break;
329 }
330 case CreateJobsIndex:
331 {
332 std::vector<FragmentJob::ptr> jobs;
333 const JobId_t next_id = getavailableid(controller);
334 createjobs(jobs, next_id);
335 addjobs(controller, jobs);
336 sendjobs(controller, argv[1], argv[2]);
337 break;
338 }
339 case CheckResultsIndex:
340 {
341 checkresults(controller, argv[1], argv[2]);
342 break;
343 }
344 case ReceiveResultsIndex:
345 {
346 receiveresults(controller, argv[1], argv[2]);
347 break;
348 }
349 case ShutdownIndex:
350 {
351 shutdown(controller, argv[1], argv[2]);
352 break;
353 }
354 case UnknownCommandIndex:
355 default:
356 ELOG(0, "Unrecognized command '"+toString(argv[3])+"'.");
357 break;
358 }
359
360 {
361 io_service.reset();
362 Info info("io_service: Phase Two");
363 io_service.run();
364 }
365
366 // Final phase: Print result of command
367
368 switch(getCommandIndex(CommandsMap, argv[3])) {
369 case AddJobsIndex:
370 case CreateJobsIndex:
371 break;
372 case CheckResultsIndex:
373 {
374 printdonejobs(controller);
375 break;
376 }
377 case ReceiveResultsIndex:
378 {
379 printreceivedresults(controller);
380 break;
381 }
382 case ShutdownIndex:
383 break;
384 case UnknownCommandIndex:
385 default:
386 ELOG(0, "Unrecognized command '"+toString(argv[3])+"'.");
387 break;
388 }
389 Exitflag = controller.getExitflag();
390 }
391 catch (std::exception& e)
392 {
393 std::cerr << e.what() << std::endl;
394 }
395
396 return Exitflag;
397}
Note: See TracBrowser for help on using the repository browser.