void IceInternal::LocatorInfo::clearCache(const ReferencePtr& ref) { assert(ref->isIndirect()); if(!ref->isWellKnown()) { vector<EndpointIPtr> endpoints = _table->removeAdapterEndpoints(ref->getAdapterId()); if(!endpoints.empty() && ref->getInstance()->traceLevels()->location >= 2) { trace("removed endpoints from locator table", ref, endpoints); } } else { ReferencePtr r = _table->removeObjectReference(ref->getIdentity()); if(r) { if(!r->isIndirect()) { if(ref->getInstance()->traceLevels()->location >= 2) { trace("removed endpoints from locator table", ref, r->getEndpoints()); } } else if(!r->isWellKnown()) { clearCache(r); } } } }
void IceInternal::LocatorInfo::getEndpoints(const ReferencePtr& ref, const ReferencePtr& wellKnownRef, int ttl, const GetEndpointsCallbackPtr& callback) { assert(ref->isIndirect()); vector<EndpointIPtr> endpoints; if(!ref->isWellKnown()) { if(!_table->getAdapterEndpoints(ref->getAdapterId(), ttl, endpoints)) { if(_background && !endpoints.empty()) { getAdapterRequest(ref)->addCallback(ref, wellKnownRef, ttl, 0); } else { getAdapterRequest(ref)->addCallback(ref, wellKnownRef, ttl, callback); return; } } } else { ReferencePtr r; if(!_table->getObjectReference(ref->getIdentity(), ttl, r)) { if(_background && r) { getObjectRequest(ref)->addCallback(ref, 0, ttl, 0); } else { getObjectRequest(ref)->addCallback(ref, 0, ttl, callback); return; } } if(!r->isIndirect()) { endpoints = r->getEndpoints(); } else if(!r->isWellKnown()) { getEndpoints(r, ref, ttl, callback); return; } } assert(!endpoints.empty()); if(ref->getInstance()->traceLevels()->location >= 1) { getEndpointsTrace(ref, endpoints, true); } if(callback) { callback->setEndpoints(endpoints, true); } }
vector<EndpointIPtr> IceInternal::LocatorInfo::Request::getEndpoints(const ReferencePtr& ref, const ReferencePtr& wellKnownRef, int ttl, bool& cached) { IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor); if(!_response || _exception.get()) { if(wellKnownRef) // This request is to resolve the endpoints of a cached well-known object reference { _wellKnownRefs.push_back(wellKnownRef); } if(!_sent) { _sent = true; sync.release(); send(); // send() might call exception() from this thread so we need to release the mutex. sync.acquire(); } while(!_response && !_exception.get()) { _monitor.wait(); } } if(_exception.get()) { _locatorInfo->getEndpointsException(ref, *_exception.get()); // This throws. } assert(_response); vector<EndpointIPtr> endpoints; if(_proxy) { ReferencePtr r = _proxy->__reference(); if(!r->isIndirect()) { endpoints = r->getEndpoints(); } else if(ref->isWellKnown() && !r->isWellKnown()) { // // We're resolving the endpoints of a well-known object and the proxy returned // by the locator is an indirect proxy. We now need to resolve the endpoints // of this indirect proxy. // return _locatorInfo->getEndpoints(r, ref, ttl, cached); } } cached = false; if(_ref->getInstance()->traceLevels()->location >= 1) { _locatorInfo->getEndpointsTrace(ref, endpoints, false); } return endpoints; }
void IceInternal::LocatorInfo::finishRequest(const ReferencePtr& ref, const vector<ReferencePtr>& wellKnownRefs, const Ice::ObjectPrx& proxy, bool notRegistered) { if(!proxy || proxy->__reference()->isIndirect()) { // // Remove the cached references of well-known objects for which we tried // to resolved the endpoints if these endpoints are empty. // for(vector<ReferencePtr>::const_iterator q = wellKnownRefs.begin(); q != wellKnownRefs.end(); ++q) { _table->removeObjectReference((*q)->getIdentity()); } } if(!ref->isWellKnown()) { if(proxy && !proxy->__reference()->isIndirect()) // Cache the adapter endpoints. { _table->addAdapterEndpoints(ref->getAdapterId(), proxy->__reference()->getEndpoints()); } else if(notRegistered) // If the adapter isn't registered anymore, remove it from the cache. { _table->removeAdapterEndpoints(ref->getAdapterId()); } IceUtil::Mutex::Lock sync(*this); assert(_adapterRequests.find(ref->getAdapterId()) != _adapterRequests.end()); _adapterRequests.erase(ref->getAdapterId()); } else { if(proxy && !proxy->__reference()->isWellKnown()) // Cache the well-known object reference. { _table->addObjectReference(ref->getIdentity(), proxy->__reference()); } else if(notRegistered) // If the well-known object isn't registered anymore, remove it from the cache. { _table->removeObjectReference(ref->getIdentity()); } IceUtil::Mutex::Lock sync(*this); assert(_objectRequests.find(ref->getIdentity()) != _objectRequests.end()); _objectRequests.erase(ref->getIdentity()); } }
void IceInternal::LocatorInfo::RequestCallback::response(const LocatorInfoPtr& locatorInfo, const Ice::ObjectPrx& proxy) { vector<EndpointIPtr> endpoints; if(proxy) { ReferencePtr r = proxy->__reference(); if(_ref->isWellKnown() && !isSupported(_ref->getEncoding(), r->getEncoding())) { // // If a well-known proxy and the returned proxy encoding // isn't supported, we're done: there's no compatible // endpoint we can use. // } else if(!r->isIndirect()) { endpoints = r->getEndpoints(); } else if(_ref->isWellKnown() && !r->isWellKnown()) { // // We're resolving the endpoints of a well-known object and the proxy returned // by the locator is an indirect proxy. We now need to resolve the endpoints // of this indirect proxy. // locatorInfo->getEndpoints(r, _ref, _ttl, _callback); return; } } if(_ref->getInstance()->traceLevels()->location >= 1) { locatorInfo->getEndpointsTrace(_ref, endpoints, false); } if(_callback) { _callback->setEndpoints(endpoints, false); } }
void IceInternal::LocatorInfo::trace(const string& msg, const ReferencePtr& ref, const vector<EndpointIPtr>& endpoints) { assert(ref->isIndirect()); Trace out(ref->getInstance()->initializationData().logger, ref->getInstance()->traceLevels()->locationCat); out << msg << '\n'; if(!ref->isWellKnown()) { out << "adapter = " << ref->getAdapterId() << '\n'; } else { out << "object = " << ref->getInstance()->identityToString(ref->getIdentity()) << '\n'; } const char* sep = endpoints.size() > 1 ? ":" : ""; ostringstream o; transform(endpoints.begin(), endpoints.end(), ostream_iterator<string>(o, sep), Ice::constMemFun(&Endpoint::toString)); out << "endpoints = " << o.str(); }
bool Ice::ObjectAdapterI::isLocal(const ObjectPrx& proxy) const { // // NOTE: it's important that isLocal() doesn't perform any blocking operations as // it can be called for AMI invocations if the proxy has no delegate set yet. // ReferencePtr ref = proxy->__reference(); if(ref->isWellKnown()) { // // Check the active servant map to see if the well-known // proxy is for a local object. // return _servantManager->hasServant(ref->getIdentity()); } else if(ref->isIndirect()) { // // Proxy is local if the reference adapter id matches this // adapter id or replica group id. // return ref->getAdapterId() == _id || ref->getAdapterId() == _replicaGroupId; } else { vector<EndpointIPtr> endpoints = ref->getEndpoints(); IceUtil::Monitor<IceUtil::RecMutex>::Lock sync(*this); checkForDeactivation(); // // Proxies which have at least one endpoint in common with the // endpoints used by this object adapter are considered local. // for(vector<EndpointIPtr>::const_iterator p = endpoints.begin(); p != endpoints.end(); ++p) { for(vector<IncomingConnectionFactoryPtr>::const_iterator q = _incomingConnectionFactories.begin(); q != _incomingConnectionFactories.end(); ++q) { if((*p)->equivalent((*q)->endpoint())) { return true; } } for(vector<EndpointIPtr>::const_iterator r = _publishedEndpoints.begin(); r != _publishedEndpoints.end(); ++r) { if((*p)->equivalent(*r)) { return true; } } } // // Proxies which have at least one endpoint in common with the // router's server proxy endpoints (if any), are also considered // local. // if(_routerInfo && _routerInfo->getRouter() == proxy->ice_getRouter()) { for(vector<EndpointIPtr>::const_iterator p = endpoints.begin(); p != endpoints.end(); ++p) { for(vector<EndpointIPtr>::const_iterator r = _routerEndpoints.begin(); r != _routerEndpoints.end(); ++r) { if((*p)->equivalent(*r)) { return true; } } } } } return false; }
int IceInternal::ProxyFactory::checkRetryAfterException(const LocalException& ex, const ReferencePtr& ref, bool sleep, int& cnt) const { TraceLevelsPtr traceLevels = _instance->traceLevels(); LoggerPtr logger = _instance->initializationData().logger; // // We don't retry batch requests because the exception might have caused // the all the requests batched with the connection to be aborted and we // want the application to be notified. // if(ref->getMode() == Reference::ModeBatchOneway || ref->getMode() == Reference::ModeBatchDatagram) { ex.ice_throw(); } const ObjectNotExistException* one = dynamic_cast<const ObjectNotExistException*>(&ex); if(one) { if(ref->getRouterInfo() && one->operation == "ice_add_proxy") { // // If we have a router, an ObjectNotExistException with an // operation name "ice_add_proxy" indicates to the client // that the router isn't aware of the proxy (for example, // because it was evicted by the router). In this case, we // must *always* retry, so that the missing proxy is added // to the router. // ref->getRouterInfo()->clearCache(ref); if(traceLevels->retry >= 1) { Trace out(logger, traceLevels->retryCat); out << "retrying operation call to add proxy to router\n" << ex; } return 0; // We must always retry, so we don't look at the retry count. } else if(ref->isIndirect()) { // // We retry ObjectNotExistException if the reference is // indirect. // if(ref->isWellKnown()) { LocatorInfoPtr li = ref->getLocatorInfo(); if(li) { li->clearCache(ref); } } } else { // // For all other cases, we don't retry // ObjectNotExistException. // ex.ice_throw(); } } else if(dynamic_cast<const RequestFailedException*>(&ex)) { // // We don't retry other *NotExistException, which are all // derived from RequestFailedException. // ex.ice_throw(); } // // There is no point in retrying an operation that resulted in a // MarshalException. This must have been raised locally (because // if it happened in a server it would result in an // UnknownLocalException instead), which means there was a problem // in this process that will not change if we try again. // // The most likely cause for a MarshalException is exceeding the // maximum message size, which is represented by the subclass // MemoryLimitException. For example, a client can attempt to send // a message that exceeds the maximum memory size, or accumulate // enough batch requests without flushing that the maximum size is // reached. // // This latter case is especially problematic, because if we were // to retry a batch request after a MarshalException, we would in // fact silently discard the accumulated requests and allow new // batch requests to accumulate. If the subsequent batched // requests do not exceed the maximum message size, it appears to // the client that all of the batched requests were accepted, when // in reality only the last few are actually sent. // if(dynamic_cast<const MarshalException*>(&ex)) { ex.ice_throw(); } ++cnt; assert(cnt > 0); int interval = -1; if(cnt == static_cast<int>(_retryIntervals.size() + 1) && dynamic_cast<const CloseConnectionException*>(&ex)) { // // A close connection exception is always retried at least once, even if the retry // limit is reached. // interval = 0; } else if(cnt > static_cast<int>(_retryIntervals.size())) { if(traceLevels->retry >= 1) { Trace out(logger, traceLevels->retryCat); out << "cannot retry operation call because retry limit has been exceeded\n" << ex; } ex.ice_throw(); } else { interval = _retryIntervals[cnt - 1]; } if(traceLevels->retry >= 1) { Trace out(logger, traceLevels->retryCat); out << "retrying operation call"; if(interval > 0) { out << " in " << interval << "ms"; } out << " because of exception\n" << ex; } if(sleep && interval > 0) { // // Sleep before retrying. // IceUtil::ThreadControl::sleep(IceUtil::Time::milliSeconds(interval)); } return interval; }