source: src/Fragmentation/Automation/Controller/FragmentController.cpp@ 73d6fc

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

Shifted all Controller stuff into own subfolder, extract class Operation.

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