示例#1
0
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);
        }
    }
}
示例#2
0
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);
}
示例#3
0
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);
}
示例#4
0
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);
}