Esempio n. 1
0
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
TransientTopicImpl::subscribe(const QoS& origQoS, 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();
    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 << ']';
            }
        }
    }

    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();
        }
    }

    Lock sync(*this);
    SubscriberRecord record;
    record.id = id;
    record.obj = newObj;
    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())
    {
        // If we already have this subscriber remove it from our
        // subscriber list and remove it from the database.
        (*p)->destroy();
        _subscribers.erase(p);
    }

    SubscriberPtr subscriber = Subscriber::create(_instance, record);
    _subscribers.push_back(subscriber);
}