Exemple #1
0
void
ConnectRequestHandler::flushRequests()
{
    {
        Lock sync(*this);
        assert(_connection && !_initialized);

        //
        // We set the _flushing flag to true to prevent any additional queuing. Callers
        // might block for a little while as the queued requests are being sent but this
        // shouldn't be an issue as the request sends are non-blocking.
        //
        _flushing = true;
    }

#ifdef ICE_CPP11_MAPPING
    std::exception_ptr exception;
#else
    IceUtil::UniquePtr<Ice::LocalException> exception;
#endif
    while(!_requests.empty()) // _requests is immutable when _flushing = true
    {
        Request& req = _requests.front();
        try
        {
            if(req.out)
            {
                req.out->invokeRemote(_connection, _compress, _response);
            }
            else if(req.outAsync->invokeRemote(_connection, _compress, _response) & AsyncStatusInvokeSentCallback)
            {
                req.outAsync->invokeSentAsync();
            }
        }
        catch(const RetryException& ex)
        {
#ifdef ICE_CPP11_MAPPING
            exception = ex.get();
            try
            {
                rethrow_exception(exception);
            }
            catch(const Ice::LocalException& ee)
            {
                // Remove the request handler before retrying.
                _reference->getInstance()->requestHandlerFactory()->removeRequestHandler(_reference, shared_from_this());

                if(req.out)
                {
                    req.out->retryException(ee);
                }
                else
                {
                    req.outAsync->retryException(ee);
                }
            }
#else
            exception.reset(ex.get()->ice_clone());
            // Remove the request handler before retrying.
            _reference->getInstance()->requestHandlerFactory()->removeRequestHandler(_reference, this);

            if(req.out)
            {
                req.out->retryException(*ex.get());
            }
            else
            {
                req.outAsync->retryException(*ex.get());
            }
#endif
        }
        catch(const Ice::LocalException& ex)
        {
#ifdef ICE_CPP11_MAPPING
            exception = ex.ice_clone();
#else
            exception.reset(ex.ice_clone());
#endif
            if(req.out)
            {
                req.out->completed(ex);
            }
            else if(req.outAsync->completed(ex))
            {
                req.outAsync->invokeCompletedAsync();
            }
        }
        _requests.pop_front();
    }

    //
    // If we aren't caching the connection, don't bother creating a
    // connection request handler. Otherwise, update the proxies
    // request handler to use the more efficient connection request
    // handler.
    //
    if(_reference->getCacheConnection() && !ICE_EXCEPTION_GET(exception))
    {
        _requestHandler = ICE_MAKE_SHARED(ConnectionRequestHandler, _reference, _connection, _compress);
        for(set<Ice::ObjectPrxPtr>::const_iterator p = _proxies.begin(); p != _proxies.end(); ++p)
        {
            (*p)->__updateRequestHandler(ICE_SHARED_FROM_THIS, _requestHandler);
        }
    }

    {
        Lock sync(*this);
        assert(!_initialized);
#ifdef ICE_CPP11_MAPPING
        swap(_exception, exception);
#else
        _exception.swap(exception);
#endif
        _initialized = !ICE_EXCEPTION_GET(_exception);
        _flushing = false;

        //
        // Only remove once all the requests are flushed to
        // guarantee serialization.
        //
        _reference->getInstance()->requestHandlerFactory()->removeRequestHandler(_reference, ICE_SHARED_FROM_THIS);

        _proxies.clear();
        _proxy = ICE_NULLPTR; // Break cyclic reference count.
        notifyAll();
    }
}
ConnectionIPtr
IceInternal::OutgoingConnectionFactory::create(const vector<EndpointIPtr>& endpts, bool hasMore,
        Ice::EndpointSelectionType selType, bool& compress)
{
    assert(!endpts.empty());

    //
    // Apply the overrides.
    //
    vector<EndpointIPtr> endpoints = applyOverrides(endpts);

    //
    // Try to find a connection to one of the given endpoints.
    //
    Ice::ConnectionIPtr connection = findConnection(endpoints, compress);
    if(connection)
    {
        return connection;
    }

    IceUtil::UniquePtr<Ice::LocalException> exception;

    //
    // If we didn't find a connection with the endpoints, we create the connectors
    // for the endpoints.
    //
    vector<ConnectorInfo> connectors;
    for(vector<EndpointIPtr>::const_iterator p = endpoints.begin(); p != endpoints.end(); ++p)
    {
        //
        // Create connectors for the endpoint.
        //
        try
        {
            vector<ConnectorPtr> cons = (*p)->connectors(selType);
            assert(!cons.empty());
            for(vector<ConnectorPtr>::const_iterator r = cons.begin(); r != cons.end(); ++r)
            {
                assert(*r);
                connectors.push_back(ConnectorInfo(*r, *p));
            }
        }
        catch(const Ice::LocalException& ex)
        {
            exception.reset(ex.ice_clone());
            handleException(ex, hasMore || p != endpoints.end() - 1);
        }
    }

    if(connectors.empty())
    {
        assert(exception.get());
        exception->ice_throw();
    }

    //
    // Try to get a connection to one of the connectors. A null result indicates that no
    // connection was found and that we should try to establish the connection (and that
    // the connectors were added to _pending to prevent other threads from establishing
    // the connection).
    //
    connection = getConnection(connectors, 0, compress);
    if(connection)
    {
        return connection;
    }

    //
    // Try to establish the connection to the connectors.
    //
    DefaultsAndOverridesPtr defaultsAndOverrides = _instance->defaultsAndOverrides();
    const CommunicatorObserverPtr& obsv = _instance->getObserver();
    vector<ConnectorInfo>::const_iterator q;
    for(q = connectors.begin(); q != connectors.end(); ++q)
    {
        ObserverPtr observer;
        if(obsv)
        {
            observer = obsv->getConnectionEstablishmentObserver(q->endpoint, q->connector->toString());
            if(observer)
            {
                observer->attach();
            }
        }

        try
        {
            connection = createConnection(q->connector->connect(), *q);
            connection->start(0);

            if(observer)
            {
                observer->detach();
            }

            if(defaultsAndOverrides->overrideCompress)
            {
                compress = defaultsAndOverrides->overrideCompressValue;
            }
            else
            {
                compress = q->endpoint->compress();
            }

            connection->activate();
            break;
        }
        catch(const Ice::CommunicatorDestroyedException& ex)
        {
            if(observer)
            {
                observer->failed(ex.ice_name());
                observer->detach();
            }
            exception.reset(ex.ice_clone());
            handleConnectionException(*exception.get(), hasMore || q != connectors.end() - 1);
            connection = 0;
            break; // No need to continue
        }
        catch(const Ice::LocalException& ex)
        {
            if(observer)
            {
                observer->failed(ex.ice_name());
                observer->detach();
            }
            exception.reset(ex.ice_clone());
            handleConnectionException(*exception.get(), hasMore || q != connectors.end() - 1);
            connection = 0;
        }
    }

    //
    // Finish creating the connection (this removes the connectors from the _pending
    // list and notifies any waiting threads).
    //
    if(connection)
    {
        finishGetConnection(connectors, *q, connection, 0);
    }
    else
    {
        finishGetConnection(connectors, *exception.get(), 0);
    }

    if(!connection)
    {
        assert(exception.get());
        exception->ice_throw();
    }

    return connection;
}
Exemple #3
0
bool
OutgoingAsync::completed()
{
    //
    // NOTE: this method is called from ConnectionI.parseMessage
    // with the connection locked. Therefore, it must not invoke
    // any user callbacks.
    //
    assert(_proxy->ice_isTwoway()); // Can only be called for twoways.

    if(_childObserver)
    {
        _childObserver->reply(static_cast<Int>(_is.b.size() - headerSize - 4));
        _childObserver.detach();
    }

    Byte replyStatus;
    try
    {
        _is.read(replyStatus);

        switch(replyStatus)
        {
            case replyOK:
            {
                break;
            }
            case replyUserException:
            {
                _observer.userException();
                break;
            }

            case replyObjectNotExist:
            case replyFacetNotExist:
            case replyOperationNotExist:
            {
                Identity ident;
                _is.read(ident);

                //
                // For compatibility with the old FacetPath.
                //
                vector<string> facetPath;
                _is.read(facetPath);
                string facet;
                if(!facetPath.empty())
                {
                    if(facetPath.size() > 1)
                    {
                        throw MarshalException(__FILE__, __LINE__);
                    }
                    facet.swap(facetPath[0]);
                }

                string operation;
                _is.read(operation, false);

                IceUtil::UniquePtr<RequestFailedException> ex;
                switch(replyStatus)
                {
                    case replyObjectNotExist:
                    {
                        ex.reset(new ObjectNotExistException(__FILE__, __LINE__));
                        break;
                    }

                    case replyFacetNotExist:
                    {
                        ex.reset(new FacetNotExistException(__FILE__, __LINE__));
                        break;
                    }

                    case replyOperationNotExist:
                    {
                        ex.reset(new OperationNotExistException(__FILE__, __LINE__));
                        break;
                    }

                    default:
                    {
                        assert(false);
                        break;
                    }
                }

                ex->id = ident;
                ex->facet = facet;
                ex->operation = operation;
                ex->ice_throw();
            }

            case replyUnknownException:
            case replyUnknownLocalException:
            case replyUnknownUserException:
            {
                string unknown;
                _is.read(unknown, false);

                IceUtil::UniquePtr<UnknownException> ex;
                switch(replyStatus)
                {
                    case replyUnknownException:
                    {
                        ex.reset(new UnknownException(__FILE__, __LINE__));
                        break;
                    }

                    case replyUnknownLocalException:
                    {
                        ex.reset(new UnknownLocalException(__FILE__, __LINE__));
                        break;
                    }

                    case replyUnknownUserException:
                    {
                        ex.reset(new UnknownUserException(__FILE__, __LINE__));
                        break;
                    }

                    default:
                    {
                        assert(false);
                        break;
                    }
                }

                ex->unknown = unknown;
                ex->ice_throw();
            }

            default:
            {
                throw UnknownReplyStatusException(__FILE__, __LINE__);
            }
        }

        return finished(replyStatus == replyOK);
    }
    catch(const Exception& ex)
    {
        return completed(ex);
    }
}
Exemple #4
0
Freeze::MapDb::MapDb(const ConnectionIPtr& connection, 
                     const string& dbName,
                     const string& key,
                     const string& value,
                     const KeyCompareBasePtr& keyCompare,
                     const vector<MapIndexBasePtr>& indices,
                     bool createDb) :
    Db(connection->dbEnv()->getEnv(), 0),
    _communicator(connection->communicator()),
    _encoding(connection->encoding()),
    _dbName(dbName),
    _trace(connection->trace()),
    _keyCompare(keyCompare)
{
    if(_trace >= 1)
    {
        Trace out(_communicator->getLogger(), "Freeze.Map");
        out << "opening Db \"" << _dbName << "\"";
    }

    Catalog catalog(connection, _catalogName);
   
    TransactionPtr tx = connection->currentTransaction();
    bool ownTx = (tx == 0);

    for(;;)
    {
        try
        {
            if(ownTx)
            {
                tx = 0;
                tx = connection->beginTransaction();
            }

            Catalog::iterator ci = catalog.find(_dbName);
        
            if(ci != catalog.end())
            {
                if(ci->second.evictor)
                {
                    throw DatabaseException(__FILE__, __LINE__, _dbName + " is an evictor database");
                }
                
                _key = ci->second.key;
                _value = ci->second.value;
                checkTypes(key, value);
            }
            else
            {
                _key = key;
                _value = value;
            }
    
            set_app_private(this);
            if(_keyCompare->compareEnabled())
            {
                set_bt_compare(&customCompare);
            }
            
            PropertiesPtr properties = _communicator->getProperties();
            string propPrefix = "Freeze.Map." + _dbName + ".";
            
            int btreeMinKey = properties->getPropertyAsInt(propPrefix + "BtreeMinKey");
            if(btreeMinKey > 2)
            {
                if(_trace >= 1)
                {
                    Trace out(_communicator->getLogger(), "Freeze.Map");
                    out << "Setting \"" << _dbName << "\"'s btree minkey to " << btreeMinKey;
                }
                set_bt_minkey(btreeMinKey);
            }
            
            bool checksum = properties->getPropertyAsInt(propPrefix + "Checksum") > 0;
            if(checksum)
            {
                if(_trace >= 1)
                {
                    Trace out(_communicator->getLogger(), "Freeze.Map");
                    out << "Turning checksum on for \"" << _dbName << "\"";
                }
                
                set_flags(DB_CHKSUM);
            }
            
            int pageSize = properties->getPropertyAsInt(propPrefix + "PageSize");
            if(pageSize > 0)
            {
                if(_trace >= 1)
                {
                    Trace out(_communicator->getLogger(), "Freeze.Map");
                    out << "Setting \"" << _dbName << "\"'s pagesize to " << pageSize;
                }
                set_pagesize(pageSize);
            }
            

            DbTxn* txn = getTxn(tx);
            
            u_int32_t flags = DB_THREAD;
            if(createDb)
            {
                flags |= DB_CREATE;
            }

            //
            // Berkeley DB expects file paths to be UTF8 encoded.
            //
            open(txn, nativeToUTF8(_dbName, getProcessStringConverter()).c_str(), 0, DB_BTREE,
                 flags, FREEZE_DB_MODE);
            
            StringSeq oldIndices;
            StringSeq newIndices;
            size_t oldSize = 0;
            CatalogIndexList catalogIndexList(connection, _catalogIndexListName);
            
            if(createDb)
            {
                CatalogIndexList::iterator cil = catalogIndexList.find(_dbName);
                if(cil != catalogIndexList.end())
                {
                    oldIndices = cil->second;
                    oldSize = oldIndices.size();
                }
            } 
            
            for(vector<MapIndexBasePtr>::const_iterator p = indices.begin();
                p != indices.end(); ++p)
            {
                const MapIndexBasePtr& indexBase = *p; 
                assert(indexBase->_impl == 0);
                assert(indexBase->_communicator == 0);
                indexBase->_communicator = connection->communicator();
                indexBase->_encoding = connection->encoding();
                
                IceUtil::UniquePtr<MapIndexI> indexI;

                try
                {
                    indexI.reset(new MapIndexI(connection, *this, txn, createDb, indexBase));
                }
                catch(const DbDeadlockException&)
                {
                    throw;
                }
                catch(const DbException& dx)
                {
                    string message = "Error while opening index \"" + _dbName +
                        "." + indexBase->name() + "\": " + dx.what();

                    throw DatabaseException(__FILE__, __LINE__, message);
                }
                
#ifdef NDEBUG
                _indices.insert(IndexMap::value_type(indexBase->name(), indexI.get()));
#else
                bool inserted = 
                    _indices.insert(IndexMap::value_type(indexBase->name(), indexI.get())).second;
                assert(inserted);
#endif
                
                indexBase->_impl = indexI.release();
                
                if(createDb)
                {
                    newIndices.push_back(indexBase->name());
                    oldIndices.erase(std::remove(oldIndices.begin(), oldIndices.end(), indexBase->name()), oldIndices.end());
                }
            }
            
            if(ci == catalog.end())
            {
                CatalogData catalogData;
                catalogData.evictor = false;
                catalogData.key = key;
                catalogData.value = value;
                catalog.put(Catalog::value_type(_dbName, catalogData));
            }
            
            if(createDb)
            {
                //
                // Remove old indices and write the new ones
                //
                bool indexRemoved = false;

                for(StringSeq::const_iterator q = oldIndices.begin(); q != oldIndices.end(); ++q)
                {
                    const string& index = *q;
                    
                    if(_trace >= 1)
                    {
                        Trace out(_communicator->getLogger(), "Freeze.Map");
                        out << "removing old index \"" << index << "\" on Db \"" << _dbName << "\"";
                    }
                    
                    try
                    {
                        connection->removeMapIndex(_dbName, *q);
                        indexRemoved = true;
                    }
                    catch(const IndexNotFoundException&)
                    {
                        // Ignored
                        
                        if(_trace >= 1)
                        {
                            Trace out(_communicator->getLogger(), "Freeze.Map");
                            out << "index \"" << index << "\" on Db \"" << _dbName << "\" does not exist";
                        }
                    }
                }
                
                if(indexRemoved || oldSize != newIndices.size())
                {
                    if(newIndices.size() == 0)
                    {
                        catalogIndexList.erase(_dbName);
                        if(_trace >= 1)
                        {
                            Trace out(_communicator->getLogger(), "Freeze.Map");
                            out << "Removed catalogIndexList entry for Db \"" << _dbName << "\"";
                        }
                        
                    }
                    else
                    {
                        catalogIndexList.put(CatalogIndexList::value_type(_dbName, newIndices));
                        if(_trace >= 1)
                        {
                            Trace out(_communicator->getLogger(), "Freeze.Map");
                            out << "Updated catalogIndexList entry for Db \"" << _dbName << "\"";
                        }
                    }
                }
            }

            if(ownTx)
            {
                tx->commit();
            }
            break; // for(;;)
        }
        catch(const DbDeadlockException& dx)
        {
            if(ownTx)
            {
                if(connection->deadlockWarning())
                {
                    Warning out(connection->communicator()->getLogger());
                    out << "Deadlock in Freeze::MapDb::MapDb on Map \"" 
                        << _dbName << "\"; retrying ...";
                }

                //
                // Ignored, try again
                //
            }
            else
            {
                throw DeadlockException(__FILE__, __LINE__, dx.what(), tx);
            }
        }
        catch(const DbException& dx)
        {
            if(ownTx)
            {
                try
                {
                    tx->rollback();
                }
                catch(...)
                {
                }
            }
                
            string message = "Error while opening Db \"" + _dbName +
                "\": " + dx.what();

            throw DatabaseException(__FILE__, __LINE__, message);
        }
        catch(...)
        {
            if(ownTx && tx != 0)
            {   
                try
                {
                    tx->rollback();
                }
                catch(...)
                {
                }
            }
            throw;
        }
    }
}