source: src/Fragmentation/Automation/FragmentController.cpp@ 1dc209

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

Factored out Operation and derived all operations from it.

  • a number of subclass of FragmentController that encapsulate each operation.
  • Operation contains getEndpointIterator(), handle_FinishOperation() and disconnect().
  • Operation now also contains Exitflag that was formerly in FragmentController.
  • new derived Operations: ReceiveJobsOperation(), CheckResultsOperation(), SendResultsOperation(), ShutdownOperation() that each contain the connect_..., handle_... functions.
  • functions to initiate operation have been placed into these Operation- derived classes as implemented virtual operator().
  • most of the required member variables have also been associated with the class that needs them. Getters and Setters have been relayed for the moment.
  • each Operation as of now needs ref to connection, host and service. This should be changed and the stuff around getEndpointIterator() refactored along with it.
  • Property mode set to 100644
File size: 15.9 KB
RevLine 
[db03d9]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 * FragmentController.cpp
10 *
11 * Created on: Nov 27, 2011
12 * Author: heber
13 */
14
15// include config.h
16#ifdef HAVE_CONFIG_H
17#include <config.h>
18#endif
19
20// boost asio needs specific operator new
21#include <boost/asio.hpp>
22
23#include "CodePatterns/MemDebug.hpp"
24
25#include <boost/bind.hpp>
[778abb]26#include <boost/foreach.hpp>
[db03d9]27#include <iostream>
28#include <vector>
29#include "Connection.hpp" // Must come before boost/serialization headers.
30#include <boost/serialization/vector.hpp>
31#include "CodePatterns/Info.hpp"
32#include "CodePatterns/Log.hpp"
33#include "FragmentJob.hpp"
34#include "FragmentResult.hpp"
[778abb]35#include "ControllerChoices.hpp"
[db03d9]36
37#include "FragmentController.hpp"
38
39/** Constructor of class FragmentController.
40 *
41 * \param io_service io_service for the asynchronous operations
42 * \param _host hostname of server that accepts jobs
43 * \param _service of server
44 */
45FragmentController::FragmentController(
46 boost::asio::io_service& io_service,
47 const std::string& _host,
48 const std::string& _service) :
49 connection_(io_service),
50 host(_host),
51 service(_service),
[5adb84]52 recjobs(connection_, _host, _service),
53 checkres(connection_, _host, _service),
54 sendres(connection_, _host, _service),
55 shutdown(connection_, _host, _service)
[db03d9]56{
57 Info info(__FUNCTION__);
58}
59
60/** Destructor of class FragmentController.
61 *
62 */
63FragmentController::~FragmentController()
64{}
65
[5adb84]66/** Constructor for class Operation.
67 *
68 * \param _connection connection to operate on
69 */
70FragmentController::Operation::Operation(Connection &_connection, const std::string& _host, const std::string& _service) :
71 connection_(_connection),
72 host(_host),
73 service(_service),
74 Exitflag(OkFlag)
75{}
76
77/** Destructor for class Operation.
78 *
79 */
80FragmentController::Operation::~Operation()
81{}
82
83/** Handle connect operation to receive jobs from controller
[db03d9]84 *
85 * \param e error code if something went wrong
86 * \param endpoint_iterator endpoint of the connection
87 */
[5adb84]88void FragmentController::ReceiveJobsOperation::handle_connect_calc(const boost::system::error_code& e,
[db03d9]89 boost::asio::ip::tcp::resolver::iterator endpoint_iterator)
90{
91 Info info(__FUNCTION__);
92 if (!e)
93 {
[778abb]94 // Successfully established connection. Give choice.
95 enum ControllerChoices choice = ReceiveJobs;
96 connection_.async_write(choice,
[5adb84]97 boost::bind(&FragmentController::ReceiveJobsOperation::handle_SendJobs, this,
[db03d9]98 boost::asio::placeholders::error));
99 } else if (endpoint_iterator != boost::asio::ip::tcp::resolver::iterator()) {
100 // Try the next endpoint.
101 connection_.socket().close();
102 boost::asio::ip::tcp::endpoint endpoint = *endpoint_iterator;
103 connection_.socket().async_connect(endpoint,
[5adb84]104 boost::bind(&FragmentController::ReceiveJobsOperation::handle_connect_calc, this,
[db03d9]105 boost::asio::placeholders::error, ++endpoint_iterator));
106 } else {
107 // An error occurred. Log it and return. Since we are not starting a new
108 // operation the io_service will run out of work to do and the client will
109 // exit.
110 Exitflag = ErrorFlag;
111 ELOG(1, e.message());
112 }
113}
114
[5adb84]115/** Callback function when an operation has been completed.
116 *
117 * \param e error code if something went wrong
118 */
119void FragmentController::ReceiveJobsOperation::handle_FinishOperation(const boost::system::error_code& e)
120{
121 Info info(__FUNCTION__);
122
123 LOG(1, "INFO: Jobs have been sent. Clearing.");
124 jobs.clear();
125
126 Operation::handle_FinishOperation(e);
127}
128
129
130/** Handle connect operation to send number of done jobs.
[3c4a5e]131 *
132 * \param e error code if something went wrong
133 * \param endpoint_iterator endpoint of the connection
134 */
[5adb84]135void FragmentController::CheckResultsOperation::handle_connect_check(const boost::system::error_code& e,
[3c4a5e]136 boost::asio::ip::tcp::resolver::iterator endpoint_iterator)
137{
138 Info info(__FUNCTION__);
139 if (!e)
140 {
[778abb]141 // Successfully established connection. Give choice.
142 enum ControllerChoices choice = CheckState;
143 connection_.async_write(choice,
[5adb84]144 boost::bind(&FragmentController::CheckResultsOperation::handle_ReceiveDoneJobs, this,
[3c4a5e]145 boost::asio::placeholders::error));
146 } else if (endpoint_iterator != boost::asio::ip::tcp::resolver::iterator()) {
147 // Try the next endpoint.
148 connection_.socket().close();
149 boost::asio::ip::tcp::endpoint endpoint = *endpoint_iterator;
150 connection_.socket().async_connect(endpoint,
[5adb84]151 boost::bind(&FragmentController::CheckResultsOperation::handle_connect_check, this,
[3c4a5e]152 boost::asio::placeholders::error, ++endpoint_iterator));
153 } else {
154 // An error occurred. Log it and return. Since we are not starting a new
155 // operation the io_service will run out of work to do and the client will
156 // exit.
157 Exitflag = ErrorFlag;
158 ELOG(1, e.message());
159 }
160}
161
[5adb84]162/** Handle connect operation to send results.
[778abb]163 *
164 * \param e error code if something went wrong
165 * \param endpoint_iterator endpoint of the connection
166 */
[5adb84]167void FragmentController::SendResultsOperation::handle_connect_get(const boost::system::error_code& e,
[778abb]168 boost::asio::ip::tcp::resolver::iterator endpoint_iterator)
169{
170 Info info(__FUNCTION__);
171 if (!e)
172 {
173 // Successfully established connection. Give choice.
174 enum ControllerChoices choice = SendResults;
175 connection_.async_write(choice,
[5adb84]176 boost::bind(&FragmentController::SendResultsOperation::handle_ReceivingResults, this,
[778abb]177 boost::asio::placeholders::error));
178 } else if (endpoint_iterator != boost::asio::ip::tcp::resolver::iterator()) {
179 // Try the next endpoint.
180 connection_.socket().close();
181 boost::asio::ip::tcp::endpoint endpoint = *endpoint_iterator;
182 connection_.socket().async_connect(endpoint,
[5adb84]183 boost::bind(&FragmentController::SendResultsOperation::handle_connect_get, this,
[778abb]184 boost::asio::placeholders::error, ++endpoint_iterator));
185 } else {
186 // An error occurred. Log it and return. Since we are not starting a new
187 // operation the io_service will run out of work to do and the client will
188 // exit.
189 Exitflag = ErrorFlag;
190 ELOG(1, e.message());
191 }
192}
193
[5adb84]194/** Handle connect operation to shutdown scheduler.
[0196c6]195 *
196 * \param e error code if something went wrong
197 * \param endpoint_iterator endpoint of the connection
198 */
[5adb84]199void FragmentController::ShutdownOperation::handle_connect_shutdown(const boost::system::error_code& e,
[0196c6]200 boost::asio::ip::tcp::resolver::iterator endpoint_iterator)
201{
202 Info info(__FUNCTION__);
203 if (!e)
204 {
205 // Successfully established connection. Give choice.
206 enum ControllerChoices choice = Shutdown;
207 connection_.async_write(choice,
[5adb84]208 boost::bind(&FragmentController::ShutdownOperation::handle_FinishOperation, this,
[0196c6]209 boost::asio::placeholders::error));
210 } else if (endpoint_iterator != boost::asio::ip::tcp::resolver::iterator()) {
211 // Try the next endpoint.
212 connection_.socket().close();
213 boost::asio::ip::tcp::endpoint endpoint = *endpoint_iterator;
214 connection_.socket().async_connect(endpoint,
[5adb84]215 boost::bind(&FragmentController::ShutdownOperation::handle_connect_shutdown, this,
[0196c6]216 boost::asio::placeholders::error, ++endpoint_iterator));
217 } else {
218 // An error occurred. Log it and return. Since we are not starting a new
219 // operation the io_service will run out of work to do and the client will
220 // exit.
221 Exitflag = ErrorFlag;
222 ELOG(1, e.message());
223 }
224}
225
[5adb84]226/** Callback function when an operation has been completed.
[778abb]227 *
228 * \param e error code if something went wrong
229 */
[5adb84]230void FragmentController::Operation::handle_FinishOperation(const boost::system::error_code& e)
[778abb]231{
232 Info info(__FUNCTION__);
233 if (!e)
234 {
235 LOG(1, "INFO: Operation completed.");
236 }
237 else
238 {
239 // An error occurred.
240 Exitflag = ErrorFlag;
241 ELOG(1, e.message());
242 }
243
244 // Since we are not starting a new operation the io_service will run out of
245 // work to do and the client will exit.
246}
247
[db03d9]248/** Callback function when jobs have been sent.
249 *
250 * \param e error code if something went wrong
251 */
[5adb84]252void FragmentController::ReceiveJobsOperation::handle_SendJobs(const boost::system::error_code& e)
[db03d9]253{
254 Info info(__FUNCTION__);
[3c4a5e]255 if (!e)
256 {
[778abb]257 // Successfully established connection. Start operation to read the vector
258 // of jobs. The connection::async_write() function will automatically
259 // encode the data that is written to the underlying socket.
260 LOG(1, "INFO: Sending "+toString(jobs.size())+" jobs ...");
261 connection_.async_write(jobs,
[5adb84]262 boost::bind(&FragmentController::ReceiveJobsOperation::handle_FinishOperation, this,
[778abb]263 boost::asio::placeholders::error));
264 }
265 else
266 {
267 // An error occurred.
268 Exitflag = ErrorFlag;
269 ELOG(1, e.message());
270 }
271
272 // Since we are not starting a new operation the io_service will run out of
273 // work to do and the client will exit.
274}
275
276/** Callback function when results have been received.
277 *
278 * \param e error code if something went wrong
279 */
[5adb84]280void FragmentController::SendResultsOperation::handle_ReceivingResults(const boost::system::error_code& e)
[778abb]281{
282 Info info(__FUNCTION__);
283 if (!e)
284 {
285 // The connection::async_read() function will automatically
286 // decode the data that is written to the underlying socket.
287 connection_.async_read(results,
[5adb84]288 boost::bind(&FragmentController::SendResultsOperation::handle_ReceivedResults, this,
[778abb]289 boost::asio::placeholders::error));
[3c4a5e]290 }
291 else
292 {
293 // An error occurred.
294 Exitflag = ErrorFlag;
295 ELOG(1, e.message());
296 }
297
298 // Since we are not starting a new operation the io_service will run out of
299 // work to do and the client will exit.
300}
301
[778abb]302/** Callback function when doneJobs have been received.
303 *
304 * \param e error code if something went wrong
305 */
[5adb84]306void FragmentController::SendResultsOperation::handle_ReceivedResults(const boost::system::error_code& e)
[778abb]307{
308 Info info(__FUNCTION__);
309
310 LOG(1, "INFO: Received "+toString(results.size())+" results ...");
311
312 handle_FinishOperation(e);
313}
314
[3c4a5e]315/** Callback function when doneJobs have been received.
316 *
317 * \param e error code if something went wrong
318 */
[5adb84]319void FragmentController::CheckResultsOperation::handle_ReceiveDoneJobs(const boost::system::error_code& e)
[3c4a5e]320{
321 Info info(__FUNCTION__);
[778abb]322 if (!e)
323 {
324 // The connection::async_read() function will automatically
325 // decode the data that is written to the underlying socket.
326 LOG(1, "INFO: Checking number of done jobs ...");
327 connection_.async_read(doneJobs,
[5adb84]328 boost::bind(&FragmentController::Operation::handle_FinishOperation, this,
[778abb]329 boost::asio::placeholders::error));
330 }
331 else
332 {
333 // An error occurred.
334 Exitflag = ErrorFlag;
335 ELOG(1, e.message());
336 }
[db03d9]337}
338
339/** Internal function to resolve all possible connection endpoints.
340 *
341 * \return endpoint iterator of connection
342 */
[5adb84]343boost::asio::ip::tcp::resolver::iterator FragmentController::Operation::getEndpointIterator()
[db03d9]344{
345 // Resolve the host name into an IP address.
346 boost::asio::ip::tcp::resolver resolver(connection_.socket().get_io_service());
347 boost::asio::ip::tcp::resolver::query query(host, service);
348 boost::asio::ip::tcp::resolver::iterator endpoint_iterator =
349 resolver.resolve(query);
350
351 return endpoint_iterator;
352}
353
354/** Internal function to connect to the endpoint of the server asynchronuously.
355 *
356 * We require internal connetion_ and host and service to be set up for this.
357 */
[5adb84]358void FragmentController::ReceiveJobsOperation::connect_calc()
[db03d9]359{
360 Info info(__FUNCTION__);
361 // Resolve the host name into an IP address.
362 boost::asio::ip::tcp::resolver::iterator endpoint_iterator = getEndpointIterator();
363 boost::asio::ip::tcp::endpoint endpoint = *endpoint_iterator;
364
365 // Start an asynchronous connect operation.
366 std::cout << "Connecting to endpoint " << endpoint << " to calc " << std::endl;
367 connection_.socket().async_connect(endpoint,
[5adb84]368 boost::bind(&FragmentController::ReceiveJobsOperation::handle_connect_calc, this,
[db03d9]369 boost::asio::placeholders::error, ++endpoint_iterator));
370}
371
[3c4a5e]372/** Internal function to connect to the endpoint of the server asynchronuously.
373 *
374 * We require internal connetion_ and host and service to be set up for this.
375 */
[5adb84]376void FragmentController::CheckResultsOperation::connect_check()
[3c4a5e]377{
378 Info info(__FUNCTION__);
379 // Resolve the host name into an IP address.
380 boost::asio::ip::tcp::resolver::iterator endpoint_iterator = getEndpointIterator();
381 boost::asio::ip::tcp::endpoint endpoint = *endpoint_iterator;
382
383 // Start an asynchronous connect operation.
384 std::cout << "Connecting to endpoint " << endpoint << " to check " << std::endl;
385 connection_.socket().async_connect(endpoint,
[5adb84]386 boost::bind(&FragmentController::CheckResultsOperation::handle_connect_check, this,
[3c4a5e]387 boost::asio::placeholders::error, ++endpoint_iterator));
388}
389
[778abb]390/** Internal function to connect to the endpoint of the server asynchronuously.
391 *
392 * We require internal connetion_ and host and service to be set up for this.
393 */
[5adb84]394void FragmentController::SendResultsOperation::connect_get()
[778abb]395{
396 Info info(__FUNCTION__);
397 // Resolve the host name into an IP address.
398 boost::asio::ip::tcp::resolver::iterator endpoint_iterator = getEndpointIterator();
399 boost::asio::ip::tcp::endpoint endpoint = *endpoint_iterator;
400
401 // Start an asynchronous connect operation.
402 std::cout << "Connecting to endpoint " << endpoint << " to get results " << std::endl;
403 connection_.socket().async_connect(endpoint,
[5adb84]404 boost::bind(&FragmentController::SendResultsOperation::handle_connect_get, this,
[778abb]405 boost::asio::placeholders::error, ++endpoint_iterator));
406}
407
[0196c6]408/** Internal function to connect to the endpoint of the server asynchronuously.
409 *
410 * We require internal connetion_ and host and service to be set up for this.
411 */
[5adb84]412void FragmentController::ShutdownOperation::connect_shutdown()
[0196c6]413{
414 Info info(__FUNCTION__);
415 // Resolve the host name into an IP address.
416 boost::asio::ip::tcp::resolver::iterator endpoint_iterator = getEndpointIterator();
417 boost::asio::ip::tcp::endpoint endpoint = *endpoint_iterator;
418
419 // Start an asynchronous connect operation.
420 std::cout << "Connecting to endpoint " << endpoint << " to get results " << std::endl;
421 connection_.socket().async_connect(endpoint,
[5adb84]422 boost::bind(&FragmentController::ShutdownOperation::handle_connect_shutdown, this,
[0196c6]423 boost::asio::placeholders::error, ++endpoint_iterator));
424}
425
[db03d9]426/** Internal function to disconnect connection_ correctly.
427 *
428 */
[5adb84]429void FragmentController::Operation::disconnect()
[db03d9]430{
431 //connection_.socket().close();
432}
433
434/** Place number of jobs into this controller.
435 *
436 * \param _jobs jobs to add
437 */
[5adb84]438void FragmentController::ReceiveJobsOperation::addJobs(const std::vector<FragmentJob> &_jobs)
[db03d9]439{
[778abb]440 jobs.reserve(jobs.size()+_jobs.size());
441 BOOST_FOREACH(FragmentJob job, _jobs) {
442 jobs.push_back(job);
443 }
[db03d9]444}
445
446/** Prepares the calculation of the results for the current jobs.
447 */
[5adb84]448void FragmentController::ReceiveJobsOperation::operator()()
[db03d9]449{
450 Info info(__FUNCTION__);
451 // connect
452 connect_calc();
453 //disconnect
454 disconnect();
455}
456
[3c4a5e]457/** Prepares the calculation of the results for the current jobs.
458 */
[5adb84]459void FragmentController::CheckResultsOperation::operator()()
[3c4a5e]460{
461 Info info(__FUNCTION__);
462 // connect
463 connect_check();
464 //disconnect
465 disconnect();
466}
467
[778abb]468/** Getter for results.
469 *
470 * \return vector of results for the added jobs (\sa addJobs()).
471 */
[5adb84]472std::vector<FragmentResult> FragmentController::SendResultsOperation::getResults()
[778abb]473{
474 Info info(__FUNCTION__);
475 return results;
476}
477
478/** Function to initiate receival of results.
479 *
480 */
[5adb84]481void FragmentController::SendResultsOperation::operator()()
[778abb]482{
483 // connect
484 connect_get();
485 //disconnect
486 disconnect();
487}
488
[0196c6]489/** Function to initiate shutdown of server.
490 *
491 */
[5adb84]492void FragmentController::ShutdownOperation::operator()()
[0196c6]493{
494 // connect
495 connect_shutdown();
496 //disconnect
497 disconnect();
498}
499
[3c4a5e]500/** Getter for doneJobs.
501 *
502 * \sa checkResults()
503 * \param doneJobs
504 */
[5adb84]505size_t FragmentController::CheckResultsOperation::getDoneJobs() const
[3c4a5e]506{
507 return doneJobs;
508}
[dba6d1]509
510/** Getter for number of jobs present in the queue.
511 *
512 * \return jobs.size()
513 */
[5adb84]514size_t FragmentController::ReceiveJobsOperation::getPresentJobs() const
[dba6d1]515{
516 return jobs.size();
517}
Note: See TracBrowser for help on using the repository browser.