/* * Project: MoleCuilder * Description: creates and alters molecular systems * Copyright (C) 2011 University of Bonn. All rights reserved. * Please see the LICENSE file or "Copyright notice" in builder.cpp for details. */ /* * \file FragmentWorker.cpp * * This file strongly follows the Serialization example from the boost::asio * library (see client.cpp). * * Created on: Nov 18, 2011 * Author: heber */ // include config.h #ifdef HAVE_CONFIG_H #include #endif // boost asio needs specific operator new #include #include "CodePatterns/MemDebug.hpp" #include #include #include #include "Connection.hpp" // Must come before boost/serialization headers. #include #include "CodePatterns/Info.hpp" #include "CodePatterns/Log.hpp" #include "Jobs/FragmentJob.hpp" #include "FragmentResult.hpp" #include "FragmentWorker.hpp" FragmentResult FragmentWorker::EmptyResult(JobId::NoJob, std::string("EmptyResult")); /// Constructor starts the asynchronous connect operation. FragmentWorker::FragmentWorker( boost::asio::io_service& io_service, const std::string& host, const std::string& service) : connection_(io_service), result(JobId::IllegalJob), Exitflag(OkFlag) { Info info(__FUNCTION__); // Resolve the host name into an IP address. boost::asio::ip::tcp::resolver resolver(io_service); boost::asio::ip::tcp::resolver::query query(host, service); boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); boost::asio::ip::tcp::endpoint endpoint = *endpoint_iterator; // Start an asynchronous connect operation. std::cout << "Connecting to endpoint " << endpoint << std::endl; connection_.socket().async_connect(endpoint, boost::bind(&FragmentWorker::handle_connect, this, boost::asio::placeholders::error, ++endpoint_iterator)); } /// Handle completion of a connect operation. void FragmentWorker::handle_connect(const boost::system::error_code& e, boost::asio::ip::tcp::resolver::iterator endpoint_iterator) { Info info(__FUNCTION__); if (!e) { // Successfully established connection. Start operation to read the list // of jobs. The connection::async_read() function will automatically // decode the data that is read from the underlying socket. LOG(1, "INFO: Receiving a job ..."); connection_.async_read(job, boost::bind(&FragmentWorker::handle_ReceiveJob, this, boost::asio::placeholders::error)); } else if (endpoint_iterator != boost::asio::ip::tcp::resolver::iterator()) { // Try the next endpoint. connection_.socket().close(); boost::asio::ip::tcp::endpoint endpoint = *endpoint_iterator; connection_.socket().async_connect(endpoint, boost::bind(&FragmentWorker::handle_connect, this, boost::asio::placeholders::error, ++endpoint_iterator)); } else { // An error occurred. Log it and return. Since we are not starting a new // operation the io_service will run out of work to do and the client will // exit. Exitflag = ErrorFlag; ELOG(1, e.message()); } } /// Callback function when job has been received. void FragmentWorker::handle_ReceiveJob(const boost::system::error_code& e) { Info info(__FUNCTION__); if (!e) { LOG(1, "INFO: Received job #" << job->getId() << "."); if (job->getId() != JobId::NoJob) { // Print out the data that was received. std::cout << "Job output: " << job->outputfile << "\n"; std::cout << "Job id: " << job->getId() << "\n"; // do something .. right now: wait LOG(1, "INFO: Calculating job #" << job->getId() << " ..."); FragmentResult result(job->Work()); // write the result to the server LOG(1, "INFO: Sending result for job #" << job->getId() << " ..."); connection_.async_write(result, boost::bind(&FragmentWorker::handle_SendResult, this, boost::asio::placeholders::error)); } else { std::cout << "The server has no job for me." << std::endl; // send out empty result LOG(1, "INFO: Sending empty result ..."); connection_.async_write(EmptyResult, boost::bind(&FragmentWorker::handle_SendResult, this, boost::asio::placeholders::error)); Exitflag = NoJobFlag; } } else { // An error occurred. Exitflag = ErrorFlag; ELOG(1, e.message()); } // Since we are not starting a new operation the io_service will run out of // work to do and the client will exit. } /// Callback function when result has been sent. void FragmentWorker::handle_SendResult(const boost::system::error_code& e) { Info info(__FUNCTION__); // Nothing to do. LOG(1, "INFO: Job #" << job->getId() << " calculated and sent."); // erase job job = FragmentJob::ptr(new FragmentJob()); }