| [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) { | 
|---|
|  | 50 | AsyncOp_ptr ptr(op); // this always prevents memory loss | 
|---|
| [a40c85] | 51 | ptr->signOn(this); | 
|---|
| [92b1d3] | 52 | OperationQueue_t::iterator iter = queue.insert(queue.end(), ptr ); | 
|---|
| [f45c08] | 53 | op = NULL; | 
|---|
| [92b1d3] | 54 | AddressMap.insert( make_pair(*iter, address) ); | 
|---|
|  | 55 | LaunchNextOp(); | 
|---|
| [f45c08] | 56 | } else { | 
|---|
|  | 57 | ELOG(1, "Given operation pointer is NULL."); | 
|---|
|  | 58 | } | 
|---|
|  | 59 | } | 
|---|
|  | 60 |  | 
|---|
| [92b1d3] | 61 | void OperationQueue::LaunchNextOp() | 
|---|
|  | 62 | { | 
|---|
|  | 63 | // connection available? | 
|---|
|  | 64 | if (getNumberOfRunningOps() < max_connections) { | 
|---|
|  | 65 | // only start operation when address is valid | 
|---|
|  | 66 | OperationQueue_t::iterator queueiter = | 
|---|
|  | 67 | std::find_if(queue.begin(), queue.end(), | 
|---|
|  | 68 | boost::bind(&AddressMap_t::count, boost::ref(AddressMap), boost::lambda::_1) ); | 
|---|
|  | 69 | if (queueiter != queue.end()) { | 
|---|
|  | 70 | AddressMap_t::iterator mapiter = AddressMap.find(*queueiter); | 
|---|
|  | 71 | ASSERT( mapiter != AddressMap.end(), | 
|---|
|  | 72 | "OperationQueue::LaunchNextOp() - cannot find connection "+toString((*queueiter)->getName())+" in AddressMap."); | 
|---|
|  | 73 | const WorkerAddress address = mapiter->second; | 
|---|
|  | 74 | AsyncOp_ptr ptr = mapiter->first; | 
|---|
|  | 75 | // always erase the op from the list of ones pending for launch | 
|---|
|  | 76 | AddressMap.erase(mapiter); | 
|---|
|  | 77 | // only launch when not a debug op | 
|---|
|  | 78 | if ((!address.host.empty()) && (!address.service.empty())) { | 
|---|
|  | 79 | LOG(2, "DEBUG: Launching next operation " << ptr->getName() << "."); | 
|---|
|  | 80 | (*ptr)(address.host, address.service); | 
|---|
|  | 81 | } else { | 
|---|
|  | 82 | LOG(3, "DEBUG: Skipping debug operation " << ptr->getName() << " with empty address."); | 
|---|
|  | 83 | } | 
|---|
|  | 84 | } else { | 
|---|
|  | 85 | LOG(2, "DEBUG: All remaining operations are already running."); | 
|---|
|  | 86 | } | 
|---|
|  | 87 | } else { | 
|---|
|  | 88 | LOG(2, "DEBUG: Currently there are no free connections."); | 
|---|
|  | 89 | } | 
|---|
|  | 90 | } | 
|---|
|  | 91 |  | 
|---|
| [f45c08] | 92 | void OperationQueue::remove(AsyncOperation *op, Observer *observer) | 
|---|
|  | 93 | { | 
|---|
|  | 94 | if (op != NULL) { | 
|---|
|  | 95 | OperationQueue_t::iterator iter = findOperation(op); | 
|---|
|  | 96 | if (iter != queue.end()) { | 
|---|
|  | 97 | // sign off and remove op | 
|---|
|  | 98 | if (observer != NULL) | 
|---|
|  | 99 | op->signOff(observer); | 
|---|
|  | 100 | queue.erase(iter); | 
|---|
|  | 101 | } else { | 
|---|
|  | 102 | ELOG(1, "Could not find Operation " << op->getName() << " in operation's queue."); | 
|---|
|  | 103 | } | 
|---|
|  | 104 | } else { | 
|---|
|  | 105 | ELOG(1, "Given operation pointer is NULL."); | 
|---|
|  | 106 | } | 
|---|
|  | 107 | } | 
|---|
| [a40c85] | 108 |  | 
|---|
|  | 109 | void OperationQueue::update(Observable *publisher) | 
|---|
|  | 110 | { | 
|---|
|  | 111 | AsyncOperation *op = static_cast<AsyncOperation *>(publisher); | 
|---|
|  | 112 | if (op != NULL) { | 
|---|
|  | 113 | LOG(1, "INFO: We are note notified that " << op->getName() << " is done, removing ..."); | 
|---|
|  | 114 | // remove from queue | 
|---|
|  | 115 | remove(op, this); | 
|---|
| [92b1d3] | 116 | LaunchNextOp(); | 
|---|
| [a40c85] | 117 | } | 
|---|
|  | 118 | } | 
|---|
|  | 119 |  | 
|---|
|  | 120 | void OperationQueue::recieveNotification(Observable *publisher, Notification_ptr notification) | 
|---|
|  | 121 | {} | 
|---|
|  | 122 |  | 
|---|
|  | 123 | void OperationQueue::subjectKilled(Observable *publisher) | 
|---|
|  | 124 | { | 
|---|
|  | 125 | AsyncOperation *op = static_cast<AsyncOperation *>(publisher); | 
|---|
|  | 126 | if (op != NULL) { | 
|---|
|  | 127 | ELOG(2, "DEBUG: AsyncOperation at " << publisher << " got killed before being done?"); | 
|---|
|  | 128 | // remove from queue | 
|---|
|  | 129 | remove(op, this); | 
|---|
|  | 130 | } | 
|---|
|  | 131 | } | 
|---|
|  | 132 |  | 
|---|