From 0b27c37fe95c6aced613d51a3624f8930a96ad3f Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Thu, 4 Jun 2009 22:23:07 +0200 Subject: RequestHandler-Interface ?berarbeitet --- src/Common/RequestManager.cpp | 117 +++++++++++++++++++++++++++++------------- 1 file changed, 80 insertions(+), 37 deletions(-) (limited to 'src/Common/RequestManager.cpp') 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 info) { - if(!insert(std::make_pair(id, info)).second) +void RequestManager::RequestMap::unregisterConnection(Connection *connection) { + std::map::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 request) { + std::map::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 RequestManager::RequestMap::findRequest(boost::uint16_t id) { - iterator it = find(id); - if(it == end()) +boost::shared_ptr RequestManager::RequestMap::findRequest(Connection *con, boost::uint16_t id) { + std::map::iterator idMap = connectionMap.find(con); + if(idMap == connectionMap.end()) + return boost::shared_ptr(); + + IdMap::iterator it = idMap->second.find(id); + if(it == idMap->second.end()) return boost::shared_ptr(); 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::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 RequestManager::RequestMap::getRequestInfo(const RequestHandler *requestHandler) { + HandlerMap::iterator it = handlerMap.find(requestHandler); + if(it == handlerMap.end()) + return std::pair(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 packet, boost::uint16_t requestId) { boost::upgrade_lock lock(mutex); - std::map >::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 request = requestMap.findRequest(connection, requestId); + if(request) { + lock.unlock(); + request->callHandlePacket(packet); return; } - boost::shared_ptr requestMap = it->second; - boost::shared_ptr 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 >::iterator factoryIt = requestHandlerFactories.find(packet.getType()); + std::map >::iterator factoryIt = requestHandlerFactories.find(packet->getType()); if(factoryIt != requestHandlerFactories.end()) { { boost::upgrade_to_unique_lock 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::_getUnusedRequestId(Connection *connection, boost::uint16_t *requestId) { - std::map >::iterator it = requestMaps.find(connection); +// XXX Error handling! +bool RequestManager::sendRequest(Connection *connection, boost::shared_ptr request) { + boost::unique_lock 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(); + return false; } - boost::shared_ptr 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 lock(mutex); - requestMaps.insert(std::make_pair(connection, new RequestMap())); - + requestMap.registerConnection(connection); connection->connectSignalReceive(boost::bind(&RequestManager::receiveHandler, this, connection, _1, _2)); } -- cgit v1.2.3