Ice::ObjectPrx TransientTopicImpl::subscribeAndGetPublisher(const QoS& qos, const Ice::ObjectPrx& obj, const Ice::Current&) { if(!obj) { TraceLevelsPtr traceLevels = _instance->traceLevels(); if(traceLevels->topic > 0) { Ice::Trace out(traceLevels->logger, traceLevels->topicCat); out << _name << ": subscribe: null proxy"; } throw InvalidSubscriber("subscriber is a null proxy"); } Ice::Identity id = obj->ice_getIdentity(); TraceLevelsPtr traceLevels = _instance->traceLevels(); if(traceLevels->topic > 0) { Ice::Trace out(traceLevels->logger, traceLevels->topicCat); out << _name << ": subscribeAndGetPublisher: " << _instance->communicator()->identityToString(id); if(traceLevels->topic > 1) { out << " endpoints: " << IceStormInternal::describeEndpoints(obj) << " QoS: "; for(QoS::const_iterator p = qos.begin(); p != qos.end() ; ++p) { if(p != qos.begin()) { out << ','; } } } } Lock sync(*this); SubscriberRecord record; record.id = id; record.obj = obj; record.theQoS = qos; record.topicName = _name; record.link = false; record.cost = 0; vector<SubscriberPtr>::iterator p = find(_subscribers.begin(), _subscribers.end(), record.id); if(p != _subscribers.end()) { throw AlreadySubscribed(); } SubscriberPtr subscriber = Subscriber::create(_instance, record); _subscribers.push_back(subscriber); return subscriber->proxy(); }
void generic_subscribe(Callback handle_message, SubscriberPtr message_subscribe) { // Subscribing must be immediate. We cannot switch thread contexts if (stopped_) handle_message(error::service_stopped, Message()); else message_subscribe->subscribe(handle_message); }
Ice::ObjectPrx TopicImpl::subscribeAndGetPublisher(const QoS& qos, const Ice::ObjectPrx& obj) { Ice::Identity id = obj->ice_getIdentity(); TraceLevelsPtr traceLevels = _instance->traceLevels(); if(traceLevels->topic > 0) { Ice::Trace out(traceLevels->logger, traceLevels->topicCat); out << _name << ": subscribeAndGetPublisher: " << _instance->communicator()->identityToString(id); if(traceLevels->topic > 1) { out << " endpoints: " << IceStormInternal::describeEndpoints(obj) << " QoS: "; for(QoS::const_iterator p = qos.begin(); p != qos.end() ; ++p) { if(p != qos.begin()) { out << ','; } } out << " subscriptions: "; trace(out, _instance, _subscribers); } } IceUtil::Mutex::Lock sync(_subscribersMutex); SubscriberRecord record; record.id = id; record.obj = obj; record.theQoS = qos; record.topicName = _name; record.link = false; record.cost = 0; vector<SubscriberPtr>::iterator p = find(_subscribers.begin(), _subscribers.end(), record.id); if(p != _subscribers.end()) { throw AlreadySubscribed(); } LogUpdate llu; SubscriberPtr subscriber = Subscriber::create(_instance, record); for(;;) { try { DatabaseConnectionPtr connection = _connectionPool->newConnection(); TransactionHolder txn(connection); SubscriberRecordKey key; key.topic = _id; key.id = subscriber->id(); SubscribersWrapperPtr subscribersWrapper = _connectionPool->getSubscribers(connection); subscribersWrapper->put(key, record); LLUWrapperPtr lluWrapper = _connectionPool->getLLU(connection); llu = lluWrapper->get(); llu.iteration++; lluWrapper->put(llu); txn.commit(); break; } catch(const DeadlockException&) { continue; } catch(const DatabaseException& ex) { halt(_instance->communicator(), ex); } } _subscribers.push_back(subscriber); _instance->observers()->addSubscriber(llu, _name, record); return subscriber->proxy(); }
void TopicImpl::subscribe(const QoS& origQoS, const Ice::ObjectPrx& obj) { Ice::Identity id = obj->ice_getIdentity(); TraceLevelsPtr traceLevels = _instance->traceLevels(); QoS qos = origQoS; if(traceLevels->topic > 0) { Ice::Trace out(traceLevels->logger, traceLevels->topicCat); out << _name << ": subscribe: " << _instance->communicator()->identityToString(id); if(traceLevels->topic > 1) { out << " endpoints: " << IceStormInternal::describeEndpoints(obj) << " QoS: "; for(QoS::const_iterator p = qos.begin(); p != qos.end() ; ++p) { if(p != qos.begin()) { out << ','; } out << '[' << p->first << "," << p->second << ']'; } out << " subscriptions: "; trace(out, _instance, _subscribers); } } string reliability = "oneway"; { QoS::iterator p = qos.find("reliability"); if(p != qos.end()) { reliability = p->second; qos.erase(p); } } Ice::ObjectPrx newObj = obj; if(reliability == "batch") { if(newObj->ice_isDatagram()) { newObj = newObj->ice_batchDatagram(); } else { newObj = newObj->ice_batchOneway(); } } else if(reliability == "twoway") { newObj = newObj->ice_twoway(); } else if(reliability == "twoway ordered") { qos["reliability"] = "ordered"; newObj = newObj->ice_twoway(); } else // reliability == "oneway" { if(reliability != "oneway" && traceLevels->subscriber > 0) { Ice::Trace out(traceLevels->logger, traceLevels->subscriberCat); out << reliability <<" mode not understood."; } if(!newObj->ice_isDatagram()) { newObj = newObj->ice_oneway(); } } IceUtil::Mutex::Lock sync(_subscribersMutex); SubscriberRecord record; record.id = id; record.obj = newObj; record.theQoS = qos; record.topicName = _name; record.link = false; record.cost = 0; LogUpdate llu; vector<SubscriberPtr>::iterator p = find(_subscribers.begin(), _subscribers.end(), record.id); if(p != _subscribers.end()) { // If we already have this subscriber remove it from our // subscriber list and remove it from the database. (*p)->destroy(); _subscribers.erase(p); for(;;) { try { DatabaseConnectionPtr connection = _connectionPool->newConnection(); TransactionHolder txn(connection); SubscriberRecordKey key; key.topic = _id; key.id = record.id; SubscribersWrapperPtr subscribersWrapper = _connectionPool->getSubscribers(connection); subscribersWrapper->erase(key); LLUWrapperPtr lluWrapper = _connectionPool->getLLU(connection); llu = lluWrapper->get(); llu.iteration++; lluWrapper->put(llu); txn.commit(); break; } catch(const DeadlockException&) { continue; } catch(const DatabaseException& ex) { halt(_instance->communicator(), ex); } } Ice::IdentitySeq ids; ids.push_back(id); _instance->observers()->removeSubscriber(llu, _name, ids); } SubscriberPtr subscriber = Subscriber::create(_instance, record); for(;;) { try { DatabaseConnectionPtr connection = _connectionPool->newConnection(); TransactionHolder txn(connection); SubscriberRecordKey key; key.topic = _id; key.id = subscriber->id(); SubscribersWrapperPtr subscribersWrapper = _connectionPool->getSubscribers(connection); subscribersWrapper->put(key, record); // Update the LLU. LLUWrapperPtr lluWrapper = _connectionPool->getLLU(connection); llu = lluWrapper->get(); llu.iteration++; lluWrapper->put(llu); txn.commit(); break; } catch(const DeadlockException&) { continue; } catch(const DatabaseException& ex) { halt(_instance->communicator(), ex); } } _subscribers.push_back(subscriber); _instance->observers()->addSubscriber(llu, _name, record); }
void TopicImpl::observerAddSubscriber(const LogUpdate& llu, const SubscriberRecord& record) { IceUtil::Mutex::Lock sync(_subscribersMutex); TraceLevelsPtr traceLevels = _instance->traceLevels(); if(traceLevels->topic > 0) { Ice::Trace out(traceLevels->logger, traceLevels->topicCat); out << _name << ": add replica observer: " << _instance->communicator()->identityToString(record.id); if(traceLevels->topic > 1) { out << " endpoints: " << IceStormInternal::describeEndpoints(record.obj) << " QoS: "; for(QoS::const_iterator p = record.theQoS.begin(); p != record.theQoS.end() ; ++p) { if(p != record.theQoS.begin()) { out << ','; } out << '[' << p->first << "," << p->second << ']'; } } out << " llu: " << llu.generation << "/" << llu.iteration; } vector<SubscriberPtr>::iterator p = find(_subscribers.begin(), _subscribers.end(), record.id); if(p != _subscribers.end()) { // If the subscriber is already in the database display a // diagnostic. TraceLevelsPtr traceLevels = _instance->traceLevels(); if(traceLevels->topic > 0) { Ice::Trace out(traceLevels->logger, traceLevels->topicCat); out << _instance->communicator()->identityToString(record.id) << ": already subscribed"; } return; } SubscriberPtr subscriber = Subscriber::create(_instance, record); for(;;) { try { DatabaseConnectionPtr connection = _connectionPool->newConnection(); TransactionHolder txn(connection); SubscriberRecordKey key; key.topic = _id; key.id = subscriber->id(); SubscribersWrapperPtr subscribersWrapper = _connectionPool->getSubscribers(connection); subscribersWrapper->put(key, record); // Update the LLU. LLUWrapperPtr lluWrapper = _connectionPool->getLLU(connection); lluWrapper->put(llu); txn.commit(); break; } catch(const DeadlockException&) { continue; } catch(const DatabaseException& ex) { halt(_instance->communicator(), ex); } } _subscribers.push_back(subscriber); }
bool IceStorm::operator==(const SubscriberPtr& subscriber, const Ice::Identity& id) { return subscriber->id() == id; }
Ice::ObjectPrx TopicImpl::subscribeAndGetPublisher(const QoS& qos, const Ice::ObjectPrx& obj) { if(!obj) { TraceLevelsPtr traceLevels = _instance->traceLevels(); if(traceLevels->topic > 0) { Ice::Trace out(traceLevels->logger, traceLevels->topicCat); out << _name << ": subscribeAndGetPublisher: null proxy"; } throw InvalidSubscriber("subscriber is a null proxy"); } Ice::Identity id = obj->ice_getIdentity(); TraceLevelsPtr traceLevels = _instance->traceLevels(); if(traceLevels->topic > 0) { Ice::Trace out(traceLevels->logger, traceLevels->topicCat); out << _name << ": subscribeAndGetPublisher: " << _instance->communicator()->identityToString(id); if(traceLevels->topic > 1) { out << " endpoints: " << IceStormInternal::describeEndpoints(obj) << " QoS: "; for(QoS::const_iterator p = qos.begin(); p != qos.end() ; ++p) { if(p != qos.begin()) { out << ','; } } out << " subscriptions: "; trace(out, _instance, _subscribers); } } IceUtil::Mutex::Lock sync(_subscribersMutex); SubscriberRecord record; record.id = id; record.obj = obj; record.theQoS = qos; record.topicName = _name; record.link = false; record.cost = 0; vector<SubscriberPtr>::iterator p = find(_subscribers.begin(), _subscribers.end(), record.id); if(p != _subscribers.end()) { throw AlreadySubscribed(); } LogUpdate llu; SubscriberPtr subscriber = Subscriber::create(_instance, record); try { IceDB::ReadWriteTxn txn(_instance->dbEnv()); SubscriberRecordKey key; key.topic = _id; key.id = subscriber->id(); _subscriberMap.put(txn, key, record); llu = getIncrementedLLU(txn, _lluMap); txn.commit(); } catch(const IceDB::LMDBException& ex) { logError(_instance->communicator(), ex); throw; // will become UnknownException in caller } _subscribers.push_back(subscriber); _instance->observers()->addSubscriber(llu, _name, record); return subscriber->proxy(); }
void TopicImpl::observerAddSubscriber(const LogUpdate& llu, const SubscriberRecord& record) { IceUtil::Mutex::Lock sync(_subscribersMutex); TraceLevelsPtr traceLevels = _instance->traceLevels(); if(traceLevels->topic > 0) { Ice::Trace out(traceLevels->logger, traceLevels->topicCat); out << _name << ": add replica observer: " << _instance->communicator()->identityToString(record.id); if(traceLevels->topic > 1) { out << " endpoints: " << IceStormInternal::describeEndpoints(record.obj) << " QoS: "; for(QoS::const_iterator p = record.theQoS.begin(); p != record.theQoS.end() ; ++p) { if(p != record.theQoS.begin()) { out << ','; } out << '[' << p->first << "," << p->second << ']'; } } out << " llu: " << llu.generation << "/" << llu.iteration; } vector<SubscriberPtr>::iterator p = find(_subscribers.begin(), _subscribers.end(), record.id); if(p != _subscribers.end()) { // If the subscriber is already in the database display a // diagnostic. TraceLevelsPtr traceLevels = _instance->traceLevels(); if(traceLevels->topic > 0) { Ice::Trace out(traceLevels->logger, traceLevels->topicCat); out << _instance->communicator()->identityToString(record.id) << ": already subscribed"; } return; } SubscriberPtr subscriber = Subscriber::create(_instance, record); try { IceDB::ReadWriteTxn txn(_instance->dbEnv()); SubscriberRecordKey key; key.topic = _id; key.id = subscriber->id(); _subscriberMap.put(txn, key, record); // Update the LLU. _lluMap.put(txn, lluDbKey, llu); txn.commit(); } catch(const IceDB::LMDBException& ex) { logError(_instance->communicator(), ex); throw; // will become UnknownException in caller } _subscribers.push_back(subscriber); }
void TransientTopicImpl::publish(bool forwarded, const EventDataSeq& events) { // // Copy of the subscriber list so that event publishing can occur // in parallel. // vector<SubscriberPtr> copy; { Lock sync(*this); copy = _subscribers; } // // Queue each event, gathering a list of those subscribers that // must be reaped. // vector<Ice::Identity> e; for(vector<SubscriberPtr>::const_iterator p = copy.begin(); p != copy.end(); ++p) { if(!(*p)->queue(forwarded, events) && (*p)->reap()) { e.push_back((*p)->id()); } } // // Run through the error list removing those subscribers that are // in error from the subscriber list. // if(!e.empty()) { Lock sync(*this); for(vector<Ice::Identity>::const_iterator ep = e.begin(); ep != e.end(); ++ep) { // // Its possible for the subscriber to already have been // removed since the copy is iterated over outside of // mutex protection. // // Note that although this could be quicker if we used a // map, the most optimal case should be pushing around // events not searching for a particular subscriber. // // The subscriber is immediately destroyed & removed from // the _subscribers list. Add the subscriber to a list of // error'd subscribers and remove it from the database on // the next reap. // vector<SubscriberPtr>::iterator q = find(_subscribers.begin(), _subscribers.end(), *ep); if(q != _subscribers.end()) { SubscriberPtr subscriber = *q; // // Destroy the subscriber. // subscriber->destroy(); _subscribers.erase(q); } } } }