diff options
Diffstat (limited to 'src/Common/RequestManager.cpp')
-rw-r--r-- | src/Common/RequestManager.cpp | 117 |
1 files changed, 80 insertions, 37 deletions
diff --git a/src/Common/RequestManager.cpp b/src/Common/RequestManager.cpp index da9979a..3817ff5 100644 --- a/src/Common/RequestManager.cpp +++ b/src/Common/RequestManager.cpp @@ -29,71 +29,105 @@ namespace Common { RequestManager RequestManager::requestManager; -bool RequestManager::RequestMap::addRequest(boost::uint16_t id, boost::shared_ptr<RequestHandler> info) { - if(!insert(std::make_pair(id, info)).second) +void RequestManager::RequestMap::unregisterConnection(Connection *connection) { + std::map<Connection*, IdMap>::iterator idMap = connectionMap.find(connection); + if(idMap == connectionMap.end()) + return; + + for(IdMap::iterator request = idMap->second.begin(); request != idMap->second.end(); ++request) + handlerMap.erase(request->second.get()); + + connectionMap.erase(idMap); +} + +bool RequestManager::RequestMap::addRequest(Connection *con, boost::uint16_t id, boost::shared_ptr<RequestHandler> request) { + std::map<Connection*, IdMap>::iterator idMap = connectionMap.find(con); + if(idMap == connectionMap.end()) + return false; + + if(!idMap->second.insert(std::make_pair(id, request)).second) return false; - info->connectSignalFinished(boost::bind(&RequestManager::RequestMap::deleteRequest, this, id)); + if(!handlerMap.insert(std::make_pair(request.get(), std::make_pair(con, id))).second) { + idMap->second.erase(id); + return false; + } return true; } -boost::shared_ptr<RequestHandler> RequestManager::RequestMap::findRequest(boost::uint16_t id) { - iterator it = find(id); - if(it == end()) +boost::shared_ptr<RequestHandler> RequestManager::RequestMap::findRequest(Connection *con, boost::uint16_t id) { + std::map<Connection*, IdMap>::iterator idMap = connectionMap.find(con); + if(idMap == connectionMap.end()) + return boost::shared_ptr<RequestHandler>(); + + IdMap::iterator it = idMap->second.find(id); + if(it == idMap->second.end()) return boost::shared_ptr<RequestHandler>(); return it->second; } -void RequestManager::RequestMap::deleteRequest(boost::uint16_t id) { - Net::ThreadManager::get()->pushWork(boost::bind(&RequestMap::doDeleteRequest, this, id)); +void RequestManager::RequestMap::deleteRequest(Connection *con, boost::uint16_t id) { + std::map<Connection*, IdMap>::iterator idMap = connectionMap.find(con); + if(idMap == connectionMap.end()) + return; + + IdMap::iterator it = idMap->second.find(id); + if(it == idMap->second.end()) + return; + + handlerMap.erase(it->second.get()); + idMap->second.erase(it); } -void RequestManager::RequestMap::doDeleteRequest(boost::uint16_t id) { - erase(id); +std::pair<Connection*, boost::uint16_t> RequestManager::RequestMap::getRequestInfo(const RequestHandler *requestHandler) { + HandlerMap::iterator it = handlerMap.find(requestHandler); + if(it == handlerMap.end()) + return std::pair<Connection*, boost::uint16_t>(0, 0); + else + return it->second; } -void RequestManager::receiveHandler(Connection *connection, const XmlPacket &packet, boost::uint16_t requestId) { +void RequestManager::receiveHandler(Connection *connection, boost::shared_ptr<const XmlPacket> packet, boost::uint16_t requestId) { boost::upgrade_lock<boost::shared_mutex> lock(mutex); - std::map<Connection*, boost::shared_ptr<RequestMap> >::iterator it = requestMaps.find(connection); - if(it == requestMaps.end()) { - // TODO: Error - Logger::log(Logger::ERROR, "Received a packet from an unregistered connection."); + boost::shared_ptr<RequestHandler> request = requestMap.findRequest(connection, requestId); + if(request) { + lock.unlock(); + request->callHandlePacket(packet); return; } - boost::shared_ptr<RequestMap> requestMap = it->second; - boost::shared_ptr<RequestHandler> request = requestMap->findRequest(requestId); - - if(request) { - lock.unlock(); - request->handlePacket(packet); + if(!requestMap.isConnectionRegistered(connection)) { + // TODO: Error + Logger::log(Logger::ERROR, "Received a packet from an unregistered connection."); return; } - std::map<std::string, boost::shared_ptr<RequestHandlerFactory> >::iterator factoryIt = requestHandlerFactories.find(packet.getType()); + std::map<std::string, boost::shared_ptr<RequestHandlerFactory> >::iterator factoryIt = requestHandlerFactories.find(packet->getType()); if(factoryIt != requestHandlerFactories.end()) { { boost::upgrade_to_unique_lock<boost::shared_mutex> upgradeLock(lock); - request = factoryIt->second->createRequestHandler(connection, requestId); - requestMap->addRequest(requestId, request); + request = factoryIt->second->createRequestHandler(); + requestMap.addRequest(connection, requestId, request); + request->connectSignalFinished(boost::bind(&RequestManager::handleRequestFinished, this, connection, requestId)); + } lock.unlock(); - request->handlePacket(packet); + request->callHandlePacket(packet); return; } lock.unlock(); - Logger::logf(Logger::ERROR, "Received an unexpected packet with type '%s'.", packet.getType().c_str()); + Logger::logf(Logger::ERROR, "Received an unexpected packet with type '%s'.", packet->getType().c_str()); XmlPacket ret; ret.setType("Error"); @@ -102,28 +136,37 @@ void RequestManager::receiveHandler(Connection *connection, const XmlPacket &pac connection->sendPacket(ret, requestId); } -boost::shared_ptr<RequestManager::RequestMap> RequestManager::_getUnusedRequestId(Connection *connection, boost::uint16_t *requestId) { - std::map<Connection*, boost::shared_ptr<RequestMap> >::iterator it = requestMaps.find(connection); +// XXX Error handling! +bool RequestManager::sendRequest(Connection *connection, boost::shared_ptr<Request> request) { + boost::unique_lock<boost::shared_mutex> lock(mutex); - if(it == requestMaps.end()) { + if(!requestMap.isConnectionRegistered(connection)) { Logger::log(Logger::CRITICAL, "Trying to send a request over an unregistered connecion."); - return boost::shared_ptr<RequestMap>(); + return false; } - boost::shared_ptr<RequestMap> requestMap = it->second; + uint16_t requestId = _getUnusedRequestId(connection); + requestMap.addRequest(connection, requestId, request); + request->connectSignalFinished(boost::bind(&RequestManager::handleRequestFinished, this, connection, requestId)); + lock.unlock(); + + Net::ThreadManager::get()->pushWork(boost::bind(&Request::sendRequest, request)); - do { - *requestId = _getRequestId(); - } while(requestMap->findRequest(*requestId)); + return true; +} - return requestMap; +boost::uint16_t RequestManager::_getUnusedRequestId(Connection *connection) { + while(true) { + boost::uint16_t requestId = _getRequestId(); + if(!requestMap.findRequest(connection, requestId)) + return requestId; + } } void RequestManager::registerConnection(Connection *connection) { boost::lock_guard<boost::shared_mutex> lock(mutex); - requestMaps.insert(std::make_pair(connection, new RequestMap())); - + requestMap.registerConnection(connection); connection->connectSignalReceive(boost::bind(&RequestManager::receiveHandler, this, connection, _1, _2)); } |