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); }
TopicManagerImpl::TopicManagerImpl(const InstancePtr& instance) : _instance(instance), _connectionPool(instance->connectionPool()) { try { __setNoDelete(true); if(_instance->observer()) { _instance->observer()->setObserverUpdater(this); } // TODO: If we want to improve the performance of the // non-replicated case we could allocate a null-topic manager impl // here. _managerImpl = new TopicManagerI(instance, this); Ice::PropertiesPtr properties = _instance->communicator()->getProperties(); // If there is no node adapter we don't need to start the // observer, nor sync since we're not replicating. if(_instance->nodeAdapter()) { _observerImpl = new ReplicaObserverI(instance, this); _observer = _instance->nodeAdapter()->addWithUUID(_observerImpl); _syncImpl = new TopicManagerSyncI(this); _sync = _instance->nodeAdapter()->addWithUUID(_syncImpl); } DatabaseConnectionPtr connection = _connectionPool->newConnection(); // Ensure that the llu counter is present in the log. LLUWrapperPtr lluWrapper = _connectionPool->getLLU(connection); LogUpdate empty = {0, 0}; lluWrapper->put(empty); // Recreate each of the topics. SubscribersWrapperPtr subscribersWrapper = _connectionPool->getSubscribers(connection); map<SubscriberRecordKey, SubscriberRecord> subscriberMap = subscribersWrapper->getMap(); map<SubscriberRecordKey, SubscriberRecord>::const_iterator p = subscriberMap.begin(); while(p != subscriberMap.end()) { // This record has to be a place holder record, otherwise // there is a database bug. assert(p->first.id.name.empty() && p->first.id.category.empty()); Ice::Identity topic = p->first.topic; // Skip the place holder. ++p; SubscriberRecordSeq content; while(p != subscriberMap.end() && p->first.topic == topic) { content.push_back(p->second); ++p; } string name = identityToTopicName(topic); installTopic(name, topic, false, content); } } catch(...) { shutdown(); __setNoDelete(false); throw; } __setNoDelete(false); }
TopicManagerImpl::TopicManagerImpl(const PersistentInstancePtr& instance) : _instance(instance), _lluMap(instance->lluMap()), _subscriberMap(instance->subscriberMap()) { try { __setNoDelete(true); if(_instance->observer()) { _instance->observer()->setObserverUpdater(this); } // TODO: If we want to improve the performance of the // non-replicated case we could allocate a null-topic manager impl // here. _managerImpl = new TopicManagerI(instance, this); // If there is no node adapter we don't need to start the // observer, nor sync since we're not replicating. if(_instance->nodeAdapter()) { _observerImpl = new ReplicaObserverI(instance, this); _observer = _instance->nodeAdapter()->addWithUUID(_observerImpl); _syncImpl = new TopicManagerSyncI(this); _sync = _instance->nodeAdapter()->addWithUUID(_syncImpl); } { IceDB::ReadWriteTxn txn(_instance->dbEnv()); // Ensure that the llu counter is present in the log. LogUpdate empty = {0, 0}; _instance->lluMap().put(txn, lluDbKey, empty); // Recreate each of the topics. SubscriberRecordKey k; SubscriberRecord v; SubscriberMapRWCursor cursor(_subscriberMap, txn); if(cursor.get(k, v, MDB_FIRST)) { bool moreTopics = false; do { // This record has to be a place holder record, otherwise // there is a database bug. assert(k.id.name.empty() && k.id.category.empty()); Ice::Identity topic = k.topic; bool moreTopics; SubscriberRecordSeq content; while((moreTopics = cursor.get(k, v, MDB_NEXT)) && k.topic == topic) { content.push_back(v); } string name = identityToTopicName(topic); installTopic(name, topic, false, content); } while(moreTopics); } txn.commit(); } } catch(...) { shutdown(); __setNoDelete(false); throw; } __setNoDelete(false); }