void TopicImpl::removeSubscribers(const Ice::IdentitySeq& ids) { // First update the database LogUpdate llu; bool found = false; try { IceDB::ReadWriteTxn txn(_instance->dbEnv()); for(Ice::IdentitySeq::const_iterator id = ids.begin(); id != ids.end(); ++id) { SubscriberRecordKey key; key.topic = _id; key.id = *id; if(_subscriberMap.del(txn, key)) { found = true; } } if(found) { llu = getIncrementedLLU(txn, _lluMap); txn.commit(); } else { txn.rollback(); } } catch(const IceDB::LMDBException& ex) { logError(_instance->communicator(), ex); throw; // will become UnknownException in caller } if(found) { // Then remove the subscriber from the subscribers list. Its // possible that some of these subscribers have already been // removed (consider, for example, a concurrent reap call from two // replicas on the same subscriber). To avoid sending unnecessary // observer updates keep track of the observers that are actually // removed. for(Ice::IdentitySeq::const_iterator id = ids.begin(); id != ids.end(); ++id) { vector<SubscriberPtr>::iterator p = find(_subscribers.begin(), _subscribers.end(), *id); if(p != _subscribers.end()) { (*p)->destroy(); _subscribers.erase(p); } } _instance->observers()->removeSubscriber(llu, _name, ids); } }
void TopicImpl::observerRemoveSubscriber(const LogUpdate& llu, const Ice::IdentitySeq& ids) { TraceLevelsPtr traceLevels = _instance->traceLevels(); if(traceLevels->topic > 0) { Ice::Trace out(traceLevels->logger, traceLevels->topicCat); out << _name << ": remove replica observer: "; for(Ice::IdentitySeq::const_iterator id = ids.begin(); id != ids.end(); ++id) { if(id != ids.begin()) { out << ","; } out << _instance->communicator()->identityToString(*id); } out << " llu: " << llu.generation << "/" << llu.iteration; } IceUtil::Mutex::Lock sync(_subscribersMutex); // First remove from the database. try { IceDB::ReadWriteTxn txn(_instance->dbEnv()); for(Ice::IdentitySeq::const_iterator id = ids.begin(); id != ids.end(); ++id) { SubscriberRecordKey key; key.topic = _id; key.id = *id; _subscriberMap.del(txn, key); } _lluMap.put(txn, lluDbKey, llu); txn.commit(); } catch(const IceDB::LMDBException& ex) { logError(_instance->communicator(), ex); throw; // will become UnknownException in caller } // Then remove the subscriber from the subscribers list. If the // subscriber had a local failure and was removed from the // subscriber list it could already be gone. That's not a problem. for(Ice::IdentitySeq::const_iterator id = ids.begin(); id != ids.end(); ++id) { vector<SubscriberPtr>::iterator p = find(_subscribers.begin(), _subscribers.end(), *id); if(p != _subscribers.end()) { (*p)->destroy(); _subscribers.erase(p); } } }
void TopicImpl::removeSubscribers(const Ice::IdentitySeq& ids) { Ice::IdentitySeq removed; // First remove the subscriber from the subscribers list. Its // possible that some of these subscribers have already been // removed (consider, for example, a concurrent reap call from two // replicas on the same subscriber). To avoid sending unnecessary // observer updates keep track of the observers that are actually // removed. for(Ice::IdentitySeq::const_iterator id = ids.begin(); id != ids.end(); ++id) { vector<SubscriberPtr>::iterator p = find(_subscribers.begin(), _subscribers.end(), *id); if(p != _subscribers.end()) { (*p)->destroy(); _subscribers.erase(p); removed.push_back(*id); } } // If there is no further work to do we are done. if(removed.empty()) { return; } // Next update the database and send the notification to any // slaves. LogUpdate llu; try { IceDB::ReadWriteTxn txn(_instance->dbEnv()); for(Ice::IdentitySeq::const_iterator id = ids.begin(); id != ids.end(); ++id) { SubscriberRecordKey key; key.topic = _id; key.id = *id; _subscriberMap.del(txn, key); } llu = getIncrementedLLU(txn, _lluMap); txn.commit(); } catch(const IceDB::LMDBException& ex) { halt(_instance->communicator(), ex); } _instance->observers()->removeSubscriber(llu, _name, ids); }
void TopicImpl::reap(const Ice::IdentitySeq& ids) { IceUtil::Mutex::Lock sync(_subscribersMutex); TraceLevelsPtr traceLevels = _instance->traceLevels(); if(traceLevels->topic > 0) { Ice::Trace out(traceLevels->logger, traceLevels->topicCat); out << _name << ": reap "; for(Ice::IdentitySeq::const_iterator p = ids.begin(); p != ids.end() ; ++p) { if(p != ids.begin()) { out << ","; } out << _instance->communicator()->identityToString(*p); } } removeSubscribers(ids); }
void TopicImpl::removeSubscribers(const Ice::IdentitySeq& ids) { Ice::IdentitySeq removed; // First remove the subscriber from the subscribers list. Its // possible that some of these subscribers have already been // removed (consider, for example, a concurrent reap call from two // replicas on the same subscriber). To avoid sending unnecessary // observer updates keep track of the observers that are actually // removed. for(Ice::IdentitySeq::const_iterator id = ids.begin(); id != ids.end(); ++id) { vector<SubscriberPtr>::iterator p = find(_subscribers.begin(), _subscribers.end(), *id); if(p != _subscribers.end()) { (*p)->destroy(); _subscribers.erase(p); removed.push_back(*id); } } // If there is no further work to do we are done. if(removed.empty()) { return; } // Next update the database and send the notification to any // slaves. LogUpdate llu; for(;;) { try { DatabaseConnectionPtr connection = _connectionPool->newConnection(); TransactionHolder txn(connection); for(Ice::IdentitySeq::const_iterator id = ids.begin(); id != ids.end(); ++id) { SubscriberRecordKey key; key.topic = _id; key.id = *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); } } _instance->observers()->removeSubscriber(llu, _name, ids); }
void TopicImpl::observerRemoveSubscriber(const LogUpdate& llu, const Ice::IdentitySeq& ids) { TraceLevelsPtr traceLevels = _instance->traceLevels(); if(traceLevels->topic > 0) { Ice::Trace out(traceLevels->logger, traceLevels->topicCat); out << _name << ": remove replica observer: "; for(Ice::IdentitySeq::const_iterator id = ids.begin(); id != ids.end(); ++id) { if(id != ids.begin()) { out << ","; } out << _instance->communicator()->identityToString(*id); } out << " llu: " << llu.generation << "/" << llu.iteration; } IceUtil::Mutex::Lock sync(_subscribersMutex); // Remove the subscriber from the subscribers list. If the // subscriber had a local failure and was removed from the // subscriber list it could already be gone. That's not a problem. for(Ice::IdentitySeq::const_iterator id = ids.begin(); id != ids.end(); ++id) { vector<SubscriberPtr>::iterator p = find(_subscribers.begin(), _subscribers.end(), *id); if(p != _subscribers.end()) { (*p)->destroy(); _subscribers.erase(p); } } // Next remove from the database. for(;;) { try { DatabaseConnectionPtr connection = _connectionPool->newConnection(); TransactionHolder txn(connection); for(Ice::IdentitySeq::const_iterator id = ids.begin(); id != ids.end(); ++id) { SubscriberRecordKey key; key.topic = _id; key.id = *id; SubscribersWrapperPtr subscribersWrapper = _connectionPool->getSubscribers(connection); subscribersWrapper->erase(key); } LLUWrapperPtr lluWrapper = _connectionPool->getLLU(connection); lluWrapper->put(llu); txn.commit(); break; } catch(const DeadlockException&) { continue; } catch(const DatabaseException& ex) { halt(_instance->communicator(), ex); } } }