[f45c08] | 1 | /*
|
---|
| 2 | * Project: MoleCuilder
|
---|
| 3 | * Description: creates and alters molecular systems
|
---|
| 4 | * Copyright (C) 2012 University of Bonn. All rights reserved.
|
---|
| 5 | * Please see the LICENSE file or "Copyright notice" in builder.cpp for details.
|
---|
| 6 | */
|
---|
| 7 |
|
---|
| 8 | /*
|
---|
| 9 | * OperationQueue.cpp
|
---|
| 10 | *
|
---|
| 11 | * Created on: Apr 24, 2012
|
---|
| 12 | * Author: heber
|
---|
| 13 | */
|
---|
| 14 |
|
---|
| 15 |
|
---|
| 16 | // include config.h
|
---|
| 17 | #ifdef HAVE_CONFIG_H
|
---|
| 18 | #include <config.h>
|
---|
| 19 | #endif
|
---|
| 20 |
|
---|
| 21 | // boost asio needs specific operator new
|
---|
| 22 | #include <boost/asio.hpp>
|
---|
| 23 |
|
---|
| 24 | #include "CodePatterns/MemDebug.hpp"
|
---|
| 25 |
|
---|
| 26 | #include <boost/bind.hpp>
|
---|
| 27 | #include <boost/lambda/lambda.hpp>
|
---|
| 28 | #include <string>
|
---|
| 29 |
|
---|
| 30 | #include "CodePatterns/Log.hpp"
|
---|
| 31 | #include "CodePatterns/Observer/Observer.hpp"
|
---|
| 32 |
|
---|
| 33 | #include "Operations/AsyncOperation.hpp"
|
---|
| 34 | #include "Operations/OperationQueue.hpp"
|
---|
| 35 | #include "WorkerAddress.hpp"
|
---|
| 36 |
|
---|
[92b1d3] | 37 | size_t OperationQueue::max_connections = 1;
|
---|
| 38 |
|
---|
[f45c08] | 39 | OperationQueue::OperationQueue_t::iterator OperationQueue::findOperation(AsyncOperation *op)
|
---|
| 40 | {
|
---|
| 41 | OperationQueue_t::iterator iter =
|
---|
| 42 | std::find_if(queue.begin(), queue.end(),
|
---|
| 43 | boost::bind(&AsyncOp_ptr::get, boost::lambda::_1) == op);
|
---|
| 44 | return iter;
|
---|
| 45 | }
|
---|
| 46 |
|
---|
| 47 | void OperationQueue::push_back(AsyncOperation *&op, const WorkerAddress &address)
|
---|
| 48 | {
|
---|
| 49 | if (op != NULL) {
|
---|
[30438f] | 50 | if (!IsBlockedFlag) {
|
---|
| 51 | AsyncOp_ptr ptr(op); // this always prevents memory loss
|
---|
| 52 | ptr->signOn(this);
|
---|
| 53 | OperationQueue_t::iterator iter = queue.insert(queue.end(), ptr );
|
---|
| 54 | op = NULL;
|
---|
| 55 | AddressMap.insert( make_pair(*iter, address) );
|
---|
| 56 | LaunchNextOp();
|
---|
| 57 | } else {
|
---|
| 58 | ELOG(1, "Queue is currently blocked, dropping operation "+op->getName()+".");
|
---|
| 59 | delete op;
|
---|
| 60 | op = NULL;
|
---|
| 61 | }
|
---|
[f45c08] | 62 | } else {
|
---|
| 63 | ELOG(1, "Given operation pointer is NULL.");
|
---|
| 64 | }
|
---|
| 65 | }
|
---|
| 66 |
|
---|
[92b1d3] | 67 | void OperationQueue::LaunchNextOp()
|
---|
| 68 | {
|
---|
| 69 | // connection available?
|
---|
| 70 | if (getNumberOfRunningOps() < max_connections) {
|
---|
| 71 | // only start operation when address is valid
|
---|
| 72 | OperationQueue_t::iterator queueiter =
|
---|
| 73 | std::find_if(queue.begin(), queue.end(),
|
---|
| 74 | boost::bind(&AddressMap_t::count, boost::ref(AddressMap), boost::lambda::_1) );
|
---|
| 75 | if (queueiter != queue.end()) {
|
---|
| 76 | AddressMap_t::iterator mapiter = AddressMap.find(*queueiter);
|
---|
| 77 | ASSERT( mapiter != AddressMap.end(),
|
---|
| 78 | "OperationQueue::LaunchNextOp() - cannot find connection "+toString((*queueiter)->getName())+" in AddressMap.");
|
---|
| 79 | const WorkerAddress address = mapiter->second;
|
---|
| 80 | AsyncOp_ptr ptr = mapiter->first;
|
---|
| 81 | // always erase the op from the list of ones pending for launch
|
---|
| 82 | AddressMap.erase(mapiter);
|
---|
| 83 | // only launch when not a debug op
|
---|
| 84 | if ((!address.host.empty()) && (!address.service.empty())) {
|
---|
| 85 | LOG(2, "DEBUG: Launching next operation " << ptr->getName() << ".");
|
---|
| 86 | (*ptr)(address.host, address.service);
|
---|
| 87 | } else {
|
---|
| 88 | LOG(3, "DEBUG: Skipping debug operation " << ptr->getName() << " with empty address.");
|
---|
| 89 | }
|
---|
| 90 | } else {
|
---|
| 91 | LOG(2, "DEBUG: All remaining operations are already running.");
|
---|
| 92 | }
|
---|
| 93 | } else {
|
---|
| 94 | LOG(2, "DEBUG: Currently there are no free connections.");
|
---|
| 95 | }
|
---|
| 96 | }
|
---|
| 97 |
|
---|
[f45c08] | 98 | void OperationQueue::remove(AsyncOperation *op, Observer *observer)
|
---|
| 99 | {
|
---|
| 100 | if (op != NULL) {
|
---|
| 101 | OperationQueue_t::iterator iter = findOperation(op);
|
---|
| 102 | if (iter != queue.end()) {
|
---|
| 103 | // sign off and remove op
|
---|
| 104 | if (observer != NULL)
|
---|
| 105 | op->signOff(observer);
|
---|
| 106 | queue.erase(iter);
|
---|
| 107 | } else {
|
---|
| 108 | ELOG(1, "Could not find Operation " << op->getName() << " in operation's queue.");
|
---|
| 109 | }
|
---|
| 110 | } else {
|
---|
| 111 | ELOG(1, "Given operation pointer is NULL.");
|
---|
| 112 | }
|
---|
| 113 | }
|
---|
[a40c85] | 114 |
|
---|
| 115 | void OperationQueue::update(Observable *publisher)
|
---|
| 116 | {
|
---|
| 117 | AsyncOperation *op = static_cast<AsyncOperation *>(publisher);
|
---|
| 118 | if (op != NULL) {
|
---|
| 119 | LOG(1, "INFO: We are note notified that " << op->getName() << " is done, removing ...");
|
---|
| 120 | // remove from queue
|
---|
| 121 | remove(op, this);
|
---|
[92b1d3] | 122 | LaunchNextOp();
|
---|
[a40c85] | 123 | }
|
---|
| 124 | }
|
---|
| 125 |
|
---|
| 126 | void OperationQueue::recieveNotification(Observable *publisher, Notification_ptr notification)
|
---|
| 127 | {}
|
---|
| 128 |
|
---|
| 129 | void OperationQueue::subjectKilled(Observable *publisher)
|
---|
| 130 | {
|
---|
| 131 | AsyncOperation *op = static_cast<AsyncOperation *>(publisher);
|
---|
| 132 | if (op != NULL) {
|
---|
| 133 | ELOG(2, "DEBUG: AsyncOperation at " << publisher << " got killed before being done?");
|
---|
| 134 | // remove from queue
|
---|
| 135 | remove(op, this);
|
---|
| 136 | }
|
---|
| 137 | }
|
---|
| 138 |
|
---|