| [72eaf7f] | 1 | /* | 
|---|
| [cd4a6e] | 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 FragmentScheduler.cpp | 
|---|
|  | 10 | * | 
|---|
|  | 11 | * This file strongly follows the Serialization example from the boost::asio | 
|---|
|  | 12 | * library (see server.cpp) | 
|---|
| [72eaf7f] | 13 | * | 
|---|
| [cd4a6e] | 14 | *  Created on: Oct 19, 2011 | 
|---|
| [72eaf7f] | 15 | *      Author: heber | 
|---|
|  | 16 | */ | 
|---|
|  | 17 |  | 
|---|
| [f93842] | 18 | // include config.h | 
|---|
|  | 19 | #ifdef HAVE_CONFIG_H | 
|---|
|  | 20 | #include <config.h> | 
|---|
|  | 21 | #endif | 
|---|
|  | 22 |  | 
|---|
| [c6bcd0] | 23 | // boost asio needs specific operator new | 
|---|
| [72eaf7f] | 24 | #include <boost/asio.hpp> | 
|---|
| [c6bcd0] | 25 |  | 
|---|
|  | 26 | #include "CodePatterns/MemDebug.hpp" | 
|---|
|  | 27 |  | 
|---|
| [72eaf7f] | 28 | #include <boost/bind.hpp> | 
|---|
|  | 29 | #include <boost/lexical_cast.hpp> | 
|---|
|  | 30 | #include <iostream> | 
|---|
|  | 31 | #include <vector> | 
|---|
| [af3aed] | 32 | #include "Connection.hpp" // Must come before boost/serialization headers. | 
|---|
| [72eaf7f] | 33 | #include <boost/serialization/vector.hpp> | 
|---|
| [af3aed] | 34 | #include "CodePatterns/Info.hpp" | 
|---|
| [b0b64c] | 35 | #include "CodePatterns/Log.hpp" | 
|---|
| [31ca5f] | 36 | #include "FragmentJob.hpp" | 
|---|
| [ef2767] | 37 | #include "JobId.hpp" | 
|---|
| [72eaf7f] | 38 |  | 
|---|
| [cd4a6e] | 39 | #include "FragmentScheduler.hpp" | 
|---|
| [72eaf7f] | 40 |  | 
|---|
| [c7deca] | 41 | FragmentJob FragmentScheduler::NoJob(std::string("NoJob"), JobId::NoJob); | 
|---|
|  | 42 |  | 
|---|
| [926a49] | 43 | FragmentScheduler::FragmentScheduler(boost::asio::io_service& io_service, unsigned short port) : | 
|---|
| [ed2c5b] | 44 | acceptor_(io_service, | 
|---|
|  | 45 | boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port) | 
|---|
| [ef2767] | 46 | ), | 
|---|
|  | 47 | result(JobId::NoJob) | 
|---|
| [ed2c5b] | 48 | { | 
|---|
| [b0b64c] | 49 | Info info(__FUNCTION__); | 
|---|
| [31ca5f] | 50 | FragmentJob s(std::string("test"), 1); | 
|---|
| [b0b64c] | 51 | JobsQueue.pushJob(s); | 
|---|
| [72eaf7f] | 52 |  | 
|---|
| [ed2c5b] | 53 | // Start an accept operation for a new connection. | 
|---|
| [af3aed] | 54 | connection_ptr new_conn(new Connection(acceptor_.get_io_service())); | 
|---|
| [ed2c5b] | 55 | acceptor_.async_accept(new_conn->socket(), | 
|---|
| [926a49] | 56 | boost::bind(&FragmentScheduler::handle_accept, this, | 
|---|
| [ed2c5b] | 57 | boost::asio::placeholders::error, new_conn)); | 
|---|
|  | 58 | } | 
|---|
| [72eaf7f] | 59 |  | 
|---|
| [cd4a6e] | 60 | /// Handle completion of a accept operation. | 
|---|
| [926a49] | 61 | void FragmentScheduler::handle_accept(const boost::system::error_code& e, connection_ptr conn) | 
|---|
| [ed2c5b] | 62 | { | 
|---|
| [cd4a6e] | 63 | Info info(__FUNCTION__); | 
|---|
| [ed2c5b] | 64 | if (!e) | 
|---|
| [72eaf7f] | 65 | { | 
|---|
| [b0b64c] | 66 | // Successfully accepted a new connection. | 
|---|
|  | 67 | // Check whether there are jobs in the queue | 
|---|
|  | 68 | if (JobsQueue.isJobPresent()) { | 
|---|
|  | 69 | // pop a job and send it to the client. | 
|---|
| [ef2767] | 70 | FragmentJob job(JobsQueue.popJob()); | 
|---|
| [b0b64c] | 71 | // The connection::async_write() function will automatically | 
|---|
|  | 72 | // serialize the data structure for us. | 
|---|
| [ef2767] | 73 | LOG(1, "INFO: Sending job #" << job.getId() << "."); | 
|---|
|  | 74 | conn->async_write(job, | 
|---|
| [083490] | 75 | boost::bind(&FragmentScheduler::handle_SendJob, this, | 
|---|
| [b0b64c] | 76 | boost::asio::placeholders::error, conn)); | 
|---|
| [0bdd51b] | 77 |  | 
|---|
|  | 78 | // Start an accept operation for a new Connection only when there | 
|---|
|  | 79 | // are still jobs present otherwise we quit. | 
|---|
|  | 80 | connection_ptr new_conn(new Connection(acceptor_.get_io_service())); | 
|---|
|  | 81 | acceptor_.async_accept(new_conn->socket(), | 
|---|
|  | 82 | boost::bind(&FragmentScheduler::handle_accept, this, | 
|---|
|  | 83 | boost::asio::placeholders::error, new_conn)); | 
|---|
| [b0b64c] | 84 | } else { | 
|---|
| [c7deca] | 85 | // send the static NoJob | 
|---|
|  | 86 | conn->async_write(NoJob, | 
|---|
| [083490] | 87 | boost::bind(&FragmentScheduler::handle_SendJob, this, | 
|---|
| [c7deca] | 88 | boost::asio::placeholders::error, conn)); | 
|---|
|  | 89 |  | 
|---|
| [ef2767] | 90 | // then there must be no read necesary | 
|---|
|  | 91 |  | 
|---|
| [b0b64c] | 92 | ELOG(2, "There is currently no job present in the queue."); | 
|---|
|  | 93 | } | 
|---|
| [cd4a6e] | 94 | } | 
|---|
|  | 95 | else | 
|---|
|  | 96 | { | 
|---|
|  | 97 | // An error occurred. Log it and return. Since we are not starting a new | 
|---|
|  | 98 | // accept operation the io_service will run out of work to do and the | 
|---|
|  | 99 | // server will exit. | 
|---|
| [b0b64c] | 100 | ELOG(0, e.message()); | 
|---|
| [cd4a6e] | 101 | } | 
|---|
| [ed2c5b] | 102 | } | 
|---|
| [72eaf7f] | 103 |  | 
|---|
| [083490] | 104 | /// Callback function when job has been sent. | 
|---|
|  | 105 | void FragmentScheduler::handle_SendJob(const boost::system::error_code& e, connection_ptr conn) | 
|---|
| [ed2c5b] | 106 | { | 
|---|
| [af3aed] | 107 | Info info(__FUNCTION__); | 
|---|
| [ef2767] | 108 | LOG(1, "INFO: Job sent."); | 
|---|
|  | 109 | // obtain result | 
|---|
|  | 110 | LOG(1, "INFO: Receiving result for a job ..."); | 
|---|
|  | 111 | conn->async_read(result, | 
|---|
| [083490] | 112 | boost::bind(&FragmentScheduler::handle_ReceiveResult, this, | 
|---|
| [ef2767] | 113 | boost::asio::placeholders::error, conn)); | 
|---|
|  | 114 | } | 
|---|
|  | 115 |  | 
|---|
| [083490] | 116 | /// Callback function when result has been received. | 
|---|
|  | 117 | void FragmentScheduler::handle_ReceiveResult(const boost::system::error_code& e, connection_ptr conn) | 
|---|
| [ef2767] | 118 | { | 
|---|
|  | 119 | Info info(__FUNCTION__); | 
|---|
|  | 120 | // nothing to do | 
|---|
|  | 121 | LOG(1, "INFO: Received result for job #" << result.getId() << " ..."); | 
|---|
|  | 122 | // and push into queue | 
|---|
|  | 123 | ASSERT(result.getId() != JobId::NoJob, | 
|---|
|  | 124 | "FragmentScheduler::handle_write() - result received has NoJob id."); | 
|---|
|  | 125 | ASSERT(result.getId() != JobId::IllegalJob, | 
|---|
|  | 126 | "FragmentScheduler::handle_write() - result received has IllegalJob id."); | 
|---|
|  | 127 | if ((result.getId() != JobId::NoJob) && (result.getId() != JobId::IllegalJob)) | 
|---|
|  | 128 | JobsQueue.pushResult(result); | 
|---|
|  | 129 | // erase result | 
|---|
|  | 130 | result = FragmentResult(JobId::NoJob); | 
|---|
| [ed2c5b] | 131 | } | 
|---|
| [cd4a6e] | 132 |  | 
|---|