/** * Find local service matching filter. */ std::set<ServiceDescription> ServiceManager::findLocal(const ServiceFilter& svcFilter) { std::set<ServiceDescription> foundSvcs; std::map<intptr_t, ServiceDescription>::iterator svcDescIter = _localSvcDesc.begin(); while(svcDescIter != _localSvcDesc.end()) { if (svcFilter.matches(svcDescIter->second)) { foundSvcs.insert(svcDescIter->second); UM_LOG_INFO("we have a match for %s", svcFilter.getServiceName().c_str()); } svcDescIter++; } return foundSvcs; }
void ServiceManager::stopQuery(const ServiceFilter& filter) { RScopeLock lock(_mutex); if (_localQueries.find(filter) != _localQueries.end()) { Message* unqueryMsg = filter.toMessage(); unqueryMsg->putMeta("um.rpc.type", "stopDiscovery"); unqueryMsg->putMeta("um.rpc.mgrId", _svcSub->getUUID()); _svcPub->send(unqueryMsg); delete unqueryMsg; _localQueries.erase(filter); } }
/** * Start a query for a service. * * Remember service filter and send query to all connected ServiceManagers. */ void ServiceManager::startQuery(const ServiceFilter& filter, ResultSet<ServiceDescription>* listener) { RScopeLock lock(_mutex); _localQueries[filter] = listener; Message* queryMsg = filter.toMessage(); queryMsg->putMeta("um.rpc.type", "startDiscovery"); queryMsg->putMeta("um.rpc.mgrId", _svcSub->getUUID()); _svcPub->send(queryMsg); UM_LOG_INFO("Sending new query to %d ServiceManagers", _svcPub->waitForSubscribers(0)); delete queryMsg; }
ServiceDescription ServiceManager::find(const ServiceFilter& svcFilter, int timeout) { if(_svcPub->waitForSubscribers(1, timeout) < 1) { // there is no other ServiceManager yet UM_LOG_INFO("Failed to find another ServiceManager"); return ServiceDescription(); } Message* findMsg = svcFilter.toMessage(); std::string reqId = UUID::getUUID(); findMsg->putMeta("um.rpc.type", "discover"); findMsg->putMeta("um.rpc.reqId", reqId.c_str()); findMsg->putMeta("um.rpc.mgrId", _svcSub->getUUID()); // Thread::sleepMs(1000); if(_findRequests.find(reqId) != _findRequests.end()) UM_LOG_WARN("Find request %s already received", reqId.c_str()); _findRequests[reqId] = new Monitor(); _svcPub->send(findMsg); delete findMsg; RScopeLock lock(_mutex); _findRequests[reqId]->wait(_mutex, timeout); delete _findRequests[reqId]; _findRequests.erase(reqId); if (_findResponses.find(reqId) == _findResponses.end()) { UM_LOG_INFO("Failed to find %s", svcFilter.getServiceName().c_str()); return ServiceDescription(); } // TODO: Remove other replies as they come in! Message* foundMsg = _findResponses[reqId]; assert(foundMsg != NULL); ServiceDescription svcDesc(foundMsg); svcDesc._svcManager = this; _findResponses.erase(reqId); delete foundMsg; return svcDesc; }
/* @brief Do mutual connections */ bool SendHugeData::SearchAndConnectToAnotherOne() { // Store pointer to the filter object ServiceFilter * MySearch = And(NameIs("SendHugeData"),Not(PeerIdIs(MyAssociatedService->GetPeerId()))); // Search for a SendHugeData service that is not me ServiceProxy * TheOtherSendHugeData = MyAssociatedService->FindService( MySearch ); // Free the ServiceFilter. As it is a simple one, call to Empty is not mandatory MySearch->Empty(); delete MySearch; if ( TheOtherSendHugeData == (ServiceProxy *)NULL ) { OmiscidError( "Could not find another SendHugeData service.\n" ); return false; } MyAssociatedService->ConnectTo( "SendData", TheOtherSendHugeData, "ReceiveData" ); return true; }
void ServiceManager::receive(Message* msg) { ScopeLock lock(&_mutex); // is this a response for one of our requests? if (msg->getMeta().find("respId") != msg->getMeta().end()) { string respId = msg->getMeta("respId"); if (_findRequests.find(respId) != _findRequests.end()) { _findResponses[respId] = new Message(*msg); _findRequests[respId].signal(); } } // is someone asking for a service? if (msg->getMeta().find("type") != msg->getMeta().end() && msg->getMeta("type").compare("serviceDisc") == 0) { ServiceFilter* filter = new ServiceFilter(msg); std::set<ServiceDescription*> foundSvcs = findLocal(filter); delete filter; if (foundSvcs.size() > 0) { ServiceDescription* svcDesc = (*(foundSvcs.begin())); Message* foundMsg = svcDesc->toMessage(); foundMsg->setMeta("respId", msg->getMeta("reqId")); foundMsg->setMeta("desc:channel", svcDesc->getChannelName()); _svcPub->send(foundMsg); delete foundMsg; } } // is this the start of a continuous query? if (msg->getMeta().find("type") != msg->getMeta().end() && msg->getMeta("type").compare("serviceDiscStart") == 0) { ServiceFilter* filter = new ServiceFilter(msg); _remoteQueries[filter->_uuid] = filter; // do we have such a service? std::set<ServiceDescription*> foundSvcs = findLocal(filter); std::set<ServiceDescription*>::iterator svcDescIter = foundSvcs.begin(); while(svcDescIter != foundSvcs.end()) { if (filter->matches(*svcDescIter)) { Message* foundMsg = (*svcDescIter)->toMessage(); foundMsg->setMeta("filterId", filter->_uuid); foundMsg->setMeta("type", "serviceDiscFound"); foundMsg->setMeta("desc:channel", (*svcDescIter)->getChannelName()); _svcPub->send(foundMsg); delete foundMsg; } svcDescIter++; } } // is this the end of a continuous query? if (msg->getMeta().find("type") != msg->getMeta().end() && msg->getMeta("type").compare("serviceDiscStop") == 0) { ServiceFilter* filter = new ServiceFilter(msg); if (_remoteQueries.find(filter->_uuid) != _remoteQueries.end()) { delete _remoteQueries[filter->_uuid]; _remoteQueries.erase(filter->_uuid); } delete filter; } // is this a reply to a continuous service query? if (msg->getMeta().find("type") != msg->getMeta().end() && (msg->getMeta("type").compare("serviceDiscFound") == 0 || msg->getMeta("type").compare("serviceDiscRemoved") == 0)) { // _svcQueries comparator uses filter uuid ServiceFilter* keyFilter = new ServiceFilter(""); keyFilter->_uuid = msg->getMeta("filterId"); if (_localQueries.find(keyFilter) != _localQueries.end()) { ResultSet<ServiceDescription>* listener = _localQueries[keyFilter]; assert(msg->getMeta("desc:channel").size() > 0); if (_remoteSvcDesc.find(msg->getMeta("desc:channel")) == _remoteSvcDesc.end()) _remoteSvcDesc[msg->getMeta("desc:channel")] = shared_ptr<ServiceDescription>(new ServiceDescription(msg)); if (msg->getMeta("type").compare("serviceDiscFound") == 0) { listener->added(_remoteSvcDesc[msg->getMeta("desc:channel")]); } else { listener->removed(_remoteSvcDesc[msg->getMeta("desc:channel")]); _remoteSvcDesc.erase(msg->getMeta("desc:channel")); } } delete keyFilter; } }