void TopicImpl::update(const SubscriberRecordSeq& records) { IceUtil::Mutex::Lock sync(_subscribersMutex); // We do this with two scans. The first runs through the subscribers // that we have and removes those not in the init list. The second // runs through the init list and add the ones that don't // exist. { vector<SubscriberPtr>::iterator p = _subscribers.begin(); while(p != _subscribers.end()) { SubscriberRecordSeq::const_iterator q; for(q = records.begin(); q != records.end(); ++q) { if((*p)->id() == q->id) { break; } } // The subscriber doesn't exist in the incoming subscriber // set so destroy it. if(q == records.end()) { (*p)->destroy(); p = _subscribers.erase(p); } else { // Otherwise reset the reaped status if necessary. (*p)->resetIfReaped(); ++p; } } } for(SubscriberRecordSeq::const_iterator p = records.begin(); p != records.end(); ++p) { vector<SubscriberPtr>::iterator q; for(q = _subscribers.begin(); q != _subscribers.end(); ++q) { if((*q)->id() == p->id) { break; } } if(q == _subscribers.end()) { SubscriberPtr subscriber = Subscriber::create(_instance, *p); _subscribers.push_back(subscriber); } } }
TopicImpl::TopicImpl( const InstancePtr& instance, const string& name, const Ice::Identity& id, const SubscriberRecordSeq& subscribers) : _instance(instance), _name(name), _id(id), _connectionPool(instance->connectionPool()), _destroyed(false) { try { __setNoDelete(true); // TODO: If we want to improve the performance of the // non-replicated case we could allocate a null-topic impl here. _servant = new TopicI(this, instance); // // Create a servant per topic to receive event data. If the // category is empty then we are in backwards compatibility // mode. In this case the servant's identity is // category=<topicname>, name=publish, otherwise the name is // <instancename>/<topicname>.publish. The same applies to the // link proxy. // // Activate the object and save a reference to give to publishers. // Ice::Identity pubid; Ice::Identity linkid; if(id.category.empty()) { pubid.category = _name; pubid.name = "publish"; linkid.category = _name; linkid.name = "link"; } else { pubid.category = id.category; pubid.name = _name + ".publish"; linkid.category = id.category; linkid.name = _name + ".link"; } _publisherPrx = _instance->publishAdapter()->add(new PublisherI(this, instance), pubid); _linkPrx = TopicLinkPrx::uncheckedCast( _instance->publishAdapter()->add(new TopicLinkI(this, instance), linkid)); // // Re-establish subscribers. // for(SubscriberRecordSeq::const_iterator p = subscribers.begin(); p != subscribers.end(); ++p) { Ice::Identity id = p->obj->ice_getIdentity(); TraceLevelsPtr traceLevels = _instance->traceLevels(); if(traceLevels->topic > 0) { Ice::Trace out(traceLevels->logger, traceLevels->topicCat); out << _name << " recreate " << _instance->communicator()->identityToString(id); if(traceLevels->topic > 1) { out << " endpoints: " << IceStormInternal::describeEndpoints(p->obj); } } try { // // Create the subscriber object add it to the set of // subscribers. // SubscriberPtr subscriber = Subscriber::create(_instance, *p); _subscribers.push_back(subscriber); } catch(const Ice::Exception& ex) { Ice::Warning out(traceLevels->logger); out << _name << " recreate " << _instance->communicator()->identityToString(id); if(traceLevels->topic > 1) { out << " endpoints: " << IceStormInternal::describeEndpoints(p->obj); } out << " failed: " << ex; } } if(_instance->observer()) { _observer.attach(_instance->observer()->getTopicObserver(_instance->serviceName(), _name, 0)); } } catch(...) { shutdown(); __setNoDelete(false); throw; } __setNoDelete(false); }