// ********************************************************************** // // Copyright (c) 2003-2015 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace Ice; using namespace IceInternal; #ifndef ICE_CPP11_MAPPING IceUtil::Shared* IceInternal::upCast(IncomingAsync* p) { return p; } IceUtil::Shared* Ice::upCast(AMD_Object_ice_invoke* p) { return p; } #endif namespace { IceUtil::Mutex* globalMutex = 0; class Init { public: Init() { globalMutex = new IceUtil::Mutex; } ~Init() { delete globalMutex; globalMutex = 0; } }; Init init; } IceInternal::IncomingAsync::IncomingAsync(Incoming& in) : IncomingBase(in), _instanceCopy(_os.instance()), _responseHandlerCopy(_responseHandler->shared_from_this()), // Acquire reference on response handler _retriable(in.isRetriable()), _active(true) { #ifndef ICE_CPP11_MAPPING if(_retriable) { in.setActive(this); } #endif } #ifdef ICE_CPP11_MAPPING IncomingAsyncPtr IceInternal::IncomingAsync::create(Incoming& in) { IncomingAsyncPtr self = make_shared(in); if(in.isRetriable()) { in.setActive(self->shared_from_this()); } return self; } #endif void IceInternal::IncomingAsync::__deactivate(Incoming& in) { assert(_retriable); { IceUtilInternal::MutexPtrLock lock(globalMutex); if(!_active) { // // Since _deactivate can only be called on an active object, // this means the response has already been sent (see __validateXXX below) // throw ResponseSentException(__FILE__, __LINE__); } _active = false; } in.__adopt(*this); } void IceInternal::IncomingAsync::ice_exception(const ::std::exception& ex) { // // Only call __exception if this incoming is not retriable or if // all the interceptors return true and no response has been sent // yet. // if(_retriable) { try { for(deque::iterator p = _interceptorAsyncCallbackQueue.begin(); p != _interceptorAsyncCallbackQueue.end(); ++p) { if((*p)->exception(ex) == false) { return; } } } catch(...) { return; } IceUtilInternal::MutexPtrLock lock(globalMutex); if(!_active) { return; } _active = false; } if(_responseHandler) { __exception(ex); } else { // // Response has already been sent. // if(_os.instance()->initializationData().properties->getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 0) { __warning(ex.what()); } } } void IceInternal::IncomingAsync::ice_exception() { // // Only call __exception if this incoming is not retriable or if // all the interceptors return true and no response has been sent // yet. // if(_retriable) { try { for(deque::iterator p = _interceptorAsyncCallbackQueue.begin(); p != _interceptorAsyncCallbackQueue.end(); ++p) { if((*p)->exception() == false) { return; } } } catch(...) { return; } IceUtilInternal::MutexPtrLock lock(globalMutex); if(!_active) { return; } _active = false; } if(_responseHandler) { __exception(); } else { // // Response has already been sent. // if(_os.instance()->initializationData().properties->getPropertyAsIntWithDefault("Ice.Warn.Dispatch", 1) > 0) { __warning("unknown exception"); } } } void IceInternal::IncomingAsync::__response() { try { if(_locator && !__servantLocatorFinished(true)) { return; } assert(_responseHandler); if(_response) { _observer.reply(static_cast(_os.b.size() - headerSize - 4)); _responseHandler->sendResponse(_current.requestId, &_os, _compress, true); } else { _responseHandler->sendNoResponse(); } _observer.detach(); _responseHandler = 0; } catch(const LocalException& ex) { _responseHandler->invokeException(_current.requestId, ex, 1, true); // Fatal invocation exception } } void IceInternal::IncomingAsync::__exception(const std::exception& exc) { try { if(_locator && !__servantLocatorFinished(true)) { return; } __handleException(exc, true); } catch(const LocalException& ex) { _responseHandler->invokeException(_current.requestId, ex, 1, true); // Fatal invocation exception } } void IceInternal::IncomingAsync::__exception() { try { if(_locator && !__servantLocatorFinished(true)) { return; } __handleException(true); } catch(const LocalException& ex) { _responseHandler->invokeException(_current.requestId, ex, 1, true); // Fatal invocation exception } } bool IceInternal::IncomingAsync::__validateResponse(bool ok) { // // Only returns true if this incoming is not retriable or if all // the interceptors return true and no response has been sent // yet. Upon getting a true return value, the caller should send // the response. // if(_retriable) { try { for(deque::iterator p = _interceptorAsyncCallbackQueue.begin(); p != _interceptorAsyncCallbackQueue.end(); ++p) { if((*p)->response(ok) == false) { return false; } } } catch(...) { return false; } IceUtilInternal::MutexPtrLock lock(globalMutex); if(!_active) { return false; } _active = false; } return true; } #ifndef ICE_CPP11_MAPPING IceAsync::Ice::AMD_Object_ice_invoke::AMD_Object_ice_invoke(Incoming& in) : IncomingAsync(in) { } void IceAsync::Ice::AMD_Object_ice_invoke::ice_response(bool ok, const vector& outEncaps) { if(__validateResponse(ok)) { try { if(outEncaps.empty()) { __writeParamEncaps(0, 0, ok); } else { __writeParamEncaps(&outEncaps[0], static_cast< ::Ice::Int>(outEncaps.size()), ok); } } catch(const LocalException& ex) { __exception(ex); return; } __response(); } } void IceAsync::Ice::AMD_Object_ice_invoke::ice_response(bool ok, const pair& outEncaps) { if(__validateResponse(ok)) { try { __writeParamEncaps(outEncaps.first, static_cast(outEncaps.second - outEncaps.first), ok); } catch(const LocalException& ex) { __exception(ex); return; } __response(); } } #endif