// ********************************************************************** // // Copyright (c) 2003-2016 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. // // ********************************************************************** namespace IceDiscovery { using System; using System.Collections.Generic; class Request { protected Request(LookupI lookup, T id, int retryCount) { lookup_ = lookup; nRetry_ = retryCount; _id = id; } public T getId() { return _id; } public bool addCallback(AmdCB cb) { callbacks_.Add(cb); return callbacks_.Count == 1; } public virtual bool retry() { return --nRetry_ >= 0; } protected LookupI lookup_; protected int nRetry_; protected List callbacks_ = new List(); private T _id; }; class AdapterRequest : Request, IceInternal.TimerTask { public AdapterRequest(LookupI lookup, string id, int retryCount) : base(lookup, id, retryCount) { _start = System.DateTime.Now.Ticks; } public override bool retry() { return _proxies.Count == 0 && --nRetry_ >= 0; } public bool response(Ice.ObjectPrx proxy, bool isReplicaGroup) { if(isReplicaGroup) { _proxies.Add(proxy); if(_latency == 0) { _latency = (long)((System.DateTime.Now.Ticks - _start) * lookup_.latencyMultiplier() / 10000.0); if(_latency == 0) { _latency = 1; // 1ms } lookup_.timer().cancel(this); lookup_.timer().schedule(this, _latency); } return false; } finished(proxy); return true; } public void finished(Ice.ObjectPrx proxy) { if(proxy != null || _proxies.Count == 0) { sendResponse(proxy); return; } else if(_proxies.Count == 1) { sendResponse(_proxies[0]); return; } List endpoints = new List(); Ice.ObjectPrx result = null; foreach(Ice.ObjectPrx prx in _proxies) { if(result == null) { result = prx; } endpoints.AddRange(prx.ice_getEndpoints()); } sendResponse(result.ice_endpoints(endpoints.ToArray())); } public void runTimerTask() { lookup_.adapterRequestTimedOut(this); } private void sendResponse(Ice.ObjectPrx proxy) { foreach(Ice.AMD_Locator_findAdapterById cb in callbacks_) { cb.ice_response(proxy); } callbacks_.Clear(); } private List _proxies = new List(); private long _start; private long _latency; }; class ObjectRequest : Request, IceInternal.TimerTask { public ObjectRequest(LookupI lookup, Ice.Identity id, int retryCount) : base(lookup, id, retryCount) { } public void response(Ice.ObjectPrx proxy) { finished(proxy); } public void finished(Ice.ObjectPrx proxy) { foreach(Ice.AMD_Locator_findObjectById cb in callbacks_) { cb.ice_response(proxy); } callbacks_.Clear(); } public void runTimerTask() { lookup_.objectRequestTimedOut(this); } }; class LookupI : LookupDisp_ { public LookupI(LocatorRegistryI registry, LookupPrx lookup, Ice.Properties properties) { _registry = registry; _lookup = lookup; _timeout = properties.getPropertyAsIntWithDefault("IceDiscovery.Timeout", 300); _retryCount = properties.getPropertyAsIntWithDefault("IceDiscovery.RetryCount", 3); _latencyMultiplier = properties.getPropertyAsIntWithDefault("IceDiscovery.LatencyMultiplier", 1); _domainId = properties.getProperty("IceDiscovery.DomainId"); _timer = IceInternal.Util.getInstance(lookup.ice_getCommunicator()).timer(); } public void setLookupReply(LookupReplyPrx lookupReply) { _lookupReply = lookupReply; } public override void findObjectById(string domainId, Ice.Identity id, IceDiscovery.LookupReplyPrx reply, Ice.Current c) { if(!domainId.Equals(_domainId)) { return; // Ignore } Ice.ObjectPrx proxy = _registry.findObject(id); if(proxy != null) { // // Reply to the mulicast request using the given proxy. // try { reply.begin_foundObjectById(id, proxy); } catch(Ice.LocalException) { // Ignore. } } } public override void findAdapterById(string domainId, string adapterId, IceDiscovery.LookupReplyPrx reply, Ice.Current c) { if(!domainId.Equals(_domainId)) { return; // Ignore } bool isReplicaGroup; Ice.ObjectPrx proxy = _registry.findAdapter(adapterId, out isReplicaGroup); if(proxy != null) { // // Reply to the multicast request using the given proxy. // try { reply.begin_foundAdapterById(adapterId, proxy, isReplicaGroup); } catch(Ice.LocalException) { // Ignore. } } } internal void findObject(Ice.AMD_Locator_findObjectById cb, Ice.Identity id) { lock(this) { ObjectRequest request; if(!_objectRequests.TryGetValue(id, out request)) { request = new ObjectRequest(this, id, _retryCount); _objectRequests.Add(id, request); } if(request.addCallback(cb)) { try { _lookup.begin_findObjectById(_domainId, id, _lookupReply); _timer.schedule(request, _timeout); } catch(Ice.LocalException) { request.finished(null); _objectRequests.Remove(id); } } } } internal void findAdapter(Ice.AMD_Locator_findAdapterById cb, string adapterId) { lock(this) { AdapterRequest request; if(!_adapterRequests.TryGetValue(adapterId, out request)) { request = new AdapterRequest(this, adapterId, _retryCount); _adapterRequests.Add(adapterId, request); } if(request.addCallback(cb)) { try { _lookup.begin_findAdapterById(_domainId, adapterId, _lookupReply); _timer.schedule(request, _timeout); } catch(Ice.LocalException) { request.finished(null); _adapterRequests.Remove(adapterId); } } } } internal void foundObject(Ice.Identity id, Ice.ObjectPrx proxy) { lock(this) { ObjectRequest request; if(!_objectRequests.TryGetValue(id, out request)) { return; } request.response(proxy); _timer.cancel(request); _objectRequests.Remove(id); } } internal void foundAdapter(string adapterId, Ice.ObjectPrx proxy, bool isReplicaGroup) { lock(this) { AdapterRequest request; if(!_adapterRequests.TryGetValue(adapterId, out request)) { return; } if(request.response(proxy, isReplicaGroup)) { _timer.cancel(request); _adapterRequests.Remove(request.getId()); } } } internal void objectRequestTimedOut(ObjectRequest request) { lock(this) { ObjectRequest r; if(!_objectRequests.TryGetValue(request.getId(), out r) || r != request) { return; } if(request.retry()) { try { _lookup.begin_findObjectById(_domainId, request.getId(), _lookupReply); _timer.schedule(request, _timeout); return; } catch(Ice.LocalException) { } } request.finished(null); _objectRequests.Remove(request.getId()); _timer.cancel(request); } } internal void adapterRequestTimedOut(AdapterRequest request) { lock(this) { AdapterRequest r; if(!_adapterRequests.TryGetValue(request.getId(), out r) || r != request) { return; } if(request.retry()) { try { _lookup.begin_findAdapterById(_domainId, request.getId(), _lookupReply); _timer.schedule(request, _timeout); return; } catch(Ice.LocalException) { } } request.finished(null); _adapterRequests.Remove(request.getId()); _timer.cancel(request); } } internal IceInternal.Timer timer() { return _timer; } internal int latencyMultiplier() { return _latencyMultiplier; } private LocatorRegistryI _registry; private readonly LookupPrx _lookup; private LookupReplyPrx _lookupReply; private readonly int _timeout; private readonly int _retryCount; private readonly int _latencyMultiplier; private readonly string _domainId; private IceInternal.Timer _timer; private Dictionary _objectRequests = new Dictionary(); private Dictionary _adapterRequests = new Dictionary(); }; class LookupReplyI : LookupReplyDisp_ { public LookupReplyI(LookupI lookup) { _lookup = lookup; } public override void foundObjectById(Ice.Identity id, Ice.ObjectPrx proxy, Ice.Current c) { _lookup.foundObject(id, proxy); } public override void foundAdapterById(string adapterId, Ice.ObjectPrx proxy, bool isReplicaGroup, Ice.Current c) { _lookup.foundAdapter(adapterId, proxy, isReplicaGroup); } private LookupI _lookup; }; }