示例#1
0
void
FlushBatch::invoke()
{
    assert(_proxy || _connection);

    if(_connection)
    {
        if(_connection->flushBatchRequests(this))
        {
            return;
        }

        Monitor<Mutex>::Lock sync(_monitor);
        while(!_exception.get() && !_sent)
        {
            _monitor.wait();
        }
        if(_exception.get())
        {
            _exception->ice_throw();
        }
        return;
    }

    RequestHandlerPtr handler;
    try
    {
        handler = _proxy->__getRequestHandler();
        if(handler->sendRequest(this))
        {
            return;
        }

        bool timedOut = false;
        {
            Monitor<Mutex>::Lock sync(_monitor);
            int timeout = _proxy->__reference()->getInvocationTimeout();
            if(timeout > 0)
            {
                Time now = Time::now(Time::Monotonic);
                Time deadline = now + Time::milliSeconds(timeout);
                while(!_exception.get() && !_sent && !timedOut)
                {
                    _monitor.timedWait(deadline - now);                
                    if(!_exception.get() && !_sent)
                    {
                        now = Time::now(Time::Monotonic);
                        timedOut = now >= deadline;
                    }
                }
            }
            else
            {
                while(!_exception.get() && !_sent)
                {
                    _monitor.wait();
                }
            }
        }

        if(timedOut)
        {
            Ice::InvocationTimeoutException ex(__FILE__, __LINE__);
            handler->requestCanceled(this, ex);

            //
            // Wait for the exception to propagate. It's possible the request handler ignores
            // the timeout if there was a failure shortly before requestTimedOut got called. 
            // In this case, the exception should be set on the Outgoing.
            //
            Monitor<Mutex>::Lock sync(_monitor);
            while(!_exception.get() && !_sent)
            {
                _monitor.wait();
            }
        }
    
        if(_exception.get())
        {
            _exception->ice_throw();
        }
    }
    catch(const RetryException& ex)
    {
        _proxy->__setRequestHandler(handler, 0); // Clear request handler
        ex.get()->ice_throw(); // Throw to notify the user that batch requests were potentially lost.
    }
    catch(const Ice::Exception& ex)
    {
        _proxy->__setRequestHandler(handler, 0); // Clear request handler
        _observer.failed(ex.ice_name());
        throw; // Throw to notify the user that batch requests were potentially lost.
    }
}