1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4 
5 package IceInternal;
6 
7 public final class LocatorInfo
8 {
9     interface GetEndpointsCallback
10     {
setEndpoints(EndpointI[] endpoints, boolean cached)11         void setEndpoints(EndpointI[] endpoints, boolean cached);
setException(Ice.LocalException ex)12         void setException(Ice.LocalException ex);
13     }
14 
15     private static class RequestCallback
16     {
17         public void
response(LocatorInfo locatorInfo, Ice.ObjectPrx proxy)18         response(LocatorInfo locatorInfo, Ice.ObjectPrx proxy)
19         {
20             EndpointI[] endpoints = null;
21             if(proxy != null)
22             {
23                 Reference r = ((Ice.ObjectPrxHelperBase)proxy)._getReference();
24                 if(_ref.isWellKnown() && !Protocol.isSupported(_ref.getEncoding(), r.getEncoding()))
25                 {
26                     //
27                     // If a well-known proxy and the returned proxy
28                     // encoding isn't supported, we're done: there's
29                     // no compatible endpoint we can use.
30                     //
31                 }
32                 else if(!r.isIndirect())
33                 {
34                     endpoints = r.getEndpoints();
35                 }
36                 else if(_ref.isWellKnown() && !r.isWellKnown())
37                 {
38                     //
39                     // We're resolving the endpoints of a well-known object and the proxy returned
40                     // by the locator is an indirect proxy. We now need to resolve the endpoints
41                     // of this indirect proxy.
42                     //
43                     if(_ref.getInstance().traceLevels().location >= 1)
44                     {
45                         locatorInfo.trace("retrieved adapter for well-known object from locator, " +
46                                           "adding to locator cache", _ref, r);
47                     }
48                     locatorInfo.getEndpoints(r, _ref, _ttl, _callback);
49                     return;
50                 }
51             }
52 
53             if(_ref.getInstance().traceLevels().location >= 1)
54             {
55                 locatorInfo.getEndpointsTrace(_ref, endpoints, false);
56             }
57             if(_callback != null)
58             {
59                 _callback.setEndpoints(endpoints == null ? new EndpointI[0] : endpoints, false);
60             }
61         }
62 
63         public void
exception(LocatorInfo locatorInfo, Exception exc)64         exception(LocatorInfo locatorInfo, Exception exc)
65         {
66             try
67             {
68                 locatorInfo.getEndpointsException(_ref, exc); // This throws.
69             }
70             catch(Ice.LocalException ex)
71             {
72                 if(_callback != null)
73                 {
74                     _callback.setException(ex);
75                 }
76             }
77         }
78 
RequestCallback(Reference ref, int ttl, GetEndpointsCallback cb)79         RequestCallback(Reference ref, int ttl, GetEndpointsCallback cb)
80         {
81             _ref = ref;
82             _ttl = ttl;
83             _callback = cb;
84         }
85 
86         final Reference _ref;
87         final int _ttl;
88         final GetEndpointsCallback _callback;
89     }
90 
91     private abstract class Request
92     {
93         public void
addCallback(Reference ref, Reference wellKnownRef, int ttl, GetEndpointsCallback cb)94         addCallback(Reference ref, Reference wellKnownRef, int ttl, GetEndpointsCallback cb)
95         {
96             RequestCallback callback = new RequestCallback(ref, ttl, cb);
97             synchronized(this)
98             {
99                 if(!_response && _exception == null)
100                 {
101                     _callbacks.add(callback);
102                     if(wellKnownRef != null) // This request is to resolve the endpoints of a cached well-known object ref
103                     {
104                         _wellKnownRefs.add(wellKnownRef);
105                     }
106                     if(!_sent)
107                     {
108                         _sent = true;
109                         send();
110                     }
111                     return;
112                 }
113             }
114 
115             if(_response)
116             {
117                 callback.response(_locatorInfo, _proxy);
118             }
119             else
120             {
121                 assert(_exception != null);
122                 callback.exception(_locatorInfo, _exception);
123             }
124         }
125 
Request(LocatorInfo locatorInfo, Reference ref)126         Request(LocatorInfo locatorInfo, Reference ref)
127         {
128             _locatorInfo = locatorInfo;
129             _ref = ref;
130             _sent = false;
131             _response = false;
132         }
133 
134         protected void
response(Ice.ObjectPrx proxy)135         response(Ice.ObjectPrx proxy)
136         {
137             synchronized(this)
138             {
139                 _locatorInfo.finishRequest(_ref, _wellKnownRefs, proxy, false);
140                 _response = true;
141                 _proxy = proxy;
142                 notifyAll();
143             }
144             for(RequestCallback callback : _callbacks)
145             {
146                 callback.response(_locatorInfo, proxy);
147             }
148         }
149 
150         protected void
exception(Exception ex)151         exception(Exception ex)
152         {
153             synchronized(this)
154             {
155                 _locatorInfo.finishRequest(_ref, _wellKnownRefs, null, ex instanceof Ice.UserException);
156                 _exception = ex;
157                 notifyAll();
158             }
159             for(RequestCallback callback : _callbacks)
160             {
161                 callback.exception(_locatorInfo, ex);
162             }
163         }
164 
send()165         protected abstract void send();
166 
167         final protected LocatorInfo _locatorInfo;
168         final protected Reference _ref;
169 
170         private java.util.List<RequestCallback> _callbacks = new java.util.ArrayList<RequestCallback>();
171         private java.util.List<Reference> _wellKnownRefs = new java.util.ArrayList<Reference>();
172         private boolean _sent;
173         private boolean _response;
174         private Ice.ObjectPrx _proxy;
175         private Exception _exception;
176     }
177 
178     private class ObjectRequest extends Request
179     {
ObjectRequest(LocatorInfo locatorInfo, Reference reference)180         public ObjectRequest(LocatorInfo locatorInfo, Reference reference)
181         {
182             super(locatorInfo, reference);
183             assert(reference.isWellKnown());
184         }
185 
186         @Override
187         protected void
send()188         send()
189         {
190             try
191             {
192                 _locatorInfo.getLocator().begin_findObjectById(
193                     _ref.getIdentity(),
194                     new Ice.Callback_Locator_findObjectById()
195                     {
196                         @Override
197                         public void
198                         response(Ice.ObjectPrx proxy)
199                         {
200                             ObjectRequest.this.response(proxy);
201                         }
202 
203                         @Override
204                         public void
205                         exception(Ice.UserException ex)
206                         {
207                             ObjectRequest.this.exception(ex);
208                         }
209 
210                         @Override
211                         public void
212                         exception(Ice.LocalException ex)
213                         {
214                             ObjectRequest.this.exception(ex);
215                         }
216                     });
217             }
218             catch(Exception ex)
219             {
220                 exception(ex);
221             }
222         }
223     }
224 
225     private class AdapterRequest extends Request
226     {
AdapterRequest(LocatorInfo locatorInfo, Reference reference)227         public AdapterRequest(LocatorInfo locatorInfo, Reference reference)
228         {
229             super(locatorInfo, reference);
230             assert(reference.isIndirect());
231         }
232 
233         @Override
234         protected void
send()235         send()
236         {
237             try
238             {
239                 _locatorInfo.getLocator().begin_findAdapterById(
240                     _ref.getAdapterId(),
241                     new Ice.Callback_Locator_findAdapterById()
242                     {
243                         @Override
244                         public void
245                         response(Ice.ObjectPrx proxy)
246                         {
247                             AdapterRequest.this.response(proxy);
248                         }
249 
250                         @Override
251                         public void
252                         exception(Ice.UserException ex)
253                         {
254                             AdapterRequest.this.exception(ex);
255                         }
256 
257                         @Override
258                         public void
259                         exception(Ice.LocalException ex)
260                         {
261                             AdapterRequest.this.exception(ex);
262                         }
263                     });
264             }
265             catch(Exception ex)
266             {
267                 exception(ex);
268             }
269         }
270     }
271 
LocatorInfo(Ice.LocatorPrx locator, LocatorTable table, boolean background)272     LocatorInfo(Ice.LocatorPrx locator, LocatorTable table, boolean background)
273     {
274         _locator = locator;
275         _table = table;
276         _background = background;
277     }
278 
279     synchronized public void
destroy()280     destroy()
281     {
282         _locatorRegistry = null;
283         _table.clear();
284     }
285 
286     @Override
287     public boolean
equals(java.lang.Object obj)288     equals(java.lang.Object obj)
289     {
290         if(this == obj)
291         {
292             return true;
293         }
294 
295         if(obj instanceof LocatorInfo)
296         {
297             return _locator.equals(((LocatorInfo)obj)._locator);
298         }
299 
300         return false;
301     }
302 
303     @Override
304     public int
hashCode()305     hashCode()
306     {
307          return _locator.hashCode();
308     }
309 
310     public Ice.LocatorPrx
getLocator()311     getLocator()
312     {
313         //
314         // No synchronization necessary, _locator is immutable.
315         //
316         return _locator;
317     }
318 
319     public Ice.LocatorRegistryPrx
getLocatorRegistry()320     getLocatorRegistry()
321     {
322         synchronized(this)
323         {
324             if(_locatorRegistry != null)
325             {
326                 return _locatorRegistry;
327             }
328         }
329 
330         //
331         // Do not make locator calls from within sync.
332         //
333         Ice.LocatorRegistryPrx locatorRegistry = _locator.getRegistry();
334         if(locatorRegistry == null)
335         {
336             return null;
337         }
338 
339         synchronized(this)
340         {
341             //
342             // The locator registry can't be located. We use ordered
343             // endpoint selection in case the locator returned a proxy
344             // with some endpoints which are prefered to be tried first.
345             //
346             _locatorRegistry = (Ice.LocatorRegistryPrx)locatorRegistry.ice_locator(null).ice_endpointSelection(
347                 Ice.EndpointSelectionType.Ordered);
348             return _locatorRegistry;
349         }
350     }
351 
352     public void
getEndpoints(Reference ref, int ttl, GetEndpointsCallback callback)353     getEndpoints(Reference ref, int ttl, GetEndpointsCallback callback)
354     {
355         getEndpoints(ref, null, ttl, callback);
356     }
357 
358     public void
getEndpoints(Reference ref, Reference wellKnownRef, int ttl, GetEndpointsCallback callback)359     getEndpoints(Reference ref, Reference wellKnownRef, int ttl, GetEndpointsCallback callback)
360     {
361         assert(ref.isIndirect());
362         EndpointI[] endpoints = null;
363         Ice.Holder<Boolean> cached = new Ice.Holder<Boolean>();
364         if(!ref.isWellKnown())
365         {
366             endpoints = _table.getAdapterEndpoints(ref.getAdapterId(), ttl, cached);
367             if(!cached.value)
368             {
369                 if(_background && endpoints != null)
370                 {
371                     getAdapterRequest(ref).addCallback(ref, wellKnownRef, ttl, null);
372                 }
373                 else
374                 {
375                     getAdapterRequest(ref).addCallback(ref, wellKnownRef, ttl, callback);
376                     return;
377                 }
378             }
379         }
380         else
381         {
382             Reference r = _table.getObjectReference(ref.getIdentity(), ttl, cached);
383             if(!cached.value)
384             {
385                 if(_background && r != null)
386                 {
387                     getObjectRequest(ref).addCallback(ref, null, ttl, null);
388                 }
389                 else
390                 {
391                     getObjectRequest(ref).addCallback(ref, null, ttl, callback);
392                     return;
393                 }
394             }
395 
396             if(!r.isIndirect())
397             {
398                 endpoints = r.getEndpoints();
399             }
400             else if(!r.isWellKnown())
401             {
402                 if(ref.getInstance().traceLevels().location >= 1)
403                 {
404                     trace("found adapter for well-known object in locator cache", ref, r);
405                 }
406                 getEndpoints(r, ref, ttl, callback);
407                 return;
408             }
409         }
410 
411         assert(endpoints != null);
412         if(ref.getInstance().traceLevels().location >= 1)
413         {
414             getEndpointsTrace(ref, endpoints, true);
415         }
416         if(callback != null)
417         {
418             callback.setEndpoints(endpoints, true);
419         }
420     }
421 
422     public void
clearCache(Reference ref)423     clearCache(Reference ref)
424     {
425         assert(ref.isIndirect());
426 
427         if(!ref.isWellKnown())
428         {
429             EndpointI[] endpoints = _table.removeAdapterEndpoints(ref.getAdapterId());
430 
431             if(endpoints != null && ref.getInstance().traceLevels().location >= 2)
432             {
433                 trace("removed endpoints for adapter from locator cache", ref, endpoints);
434             }
435         }
436         else
437         {
438             Reference r = _table.removeObjectReference(ref.getIdentity());
439             if(r != null)
440             {
441                 if(!r.isIndirect())
442                 {
443                     if(ref.getInstance().traceLevels().location >= 2)
444                     {
445                         trace("removed endpoints for well-known object from locator cache", ref, r.getEndpoints());
446                     }
447                 }
448                 else if(!r.isWellKnown())
449                 {
450                     if(ref.getInstance().traceLevels().location >= 2)
451                     {
452                         trace("removed adapter for well-known object from locator cache", ref, r);
453                     }
454                     clearCache(r);
455                 }
456             }
457         }
458     }
459 
460     private void
trace(String msg, Reference ref, EndpointI[] endpoints)461     trace(String msg, Reference ref, EndpointI[] endpoints)
462     {
463         assert(ref.isIndirect());
464 
465         StringBuilder s = new StringBuilder(128);
466         s.append(msg);
467         s.append("\n");
468         if(!ref.isWellKnown())
469         {
470             s.append("adapter = ");
471             s.append(ref.getAdapterId());
472             s.append("\n");
473         }
474         else
475         {
476             s.append("well-known proxy = ");
477             s.append(ref.toString());
478             s.append("\n");
479         }
480 
481         s.append("endpoints = ");
482         final int sz = endpoints.length;
483         for(int i = 0; i < sz; i++)
484         {
485             s.append(endpoints[i].toString());
486             if(i + 1 < sz)
487             {
488                 s.append(":");
489             }
490         }
491 
492         ref.getInstance().initializationData().logger.trace(ref.getInstance().traceLevels().locationCat, s.toString());
493     }
494 
495     private void
trace(String msg, Reference ref, Reference resolved)496     trace(String msg, Reference ref, Reference resolved)
497     {
498         assert(ref.isWellKnown());
499 
500         StringBuilder s = new StringBuilder(128);
501         s.append(msg);
502         s.append("\n");
503         s.append("well-known proxy = ");
504         s.append(ref.toString());
505         s.append("\n");
506         s.append("adapter = ");
507         s.append(resolved.getAdapterId());
508 
509         ref.getInstance().initializationData().logger.trace(ref.getInstance().traceLevels().locationCat, s.toString());
510     }
511 
512     private void
getEndpointsException(Reference ref, Exception exc)513     getEndpointsException(Reference ref, Exception exc)
514     {
515         assert(ref.isIndirect());
516 
517         try
518         {
519             throw exc;
520         }
521         catch(Ice.AdapterNotFoundException ex)
522         {
523             final Instance instance = ref.getInstance();
524             if(instance.traceLevels().location >= 1)
525             {
526                 StringBuilder s = new StringBuilder(128);
527                 s.append("adapter not found\n");
528                 s.append("adapter = ");
529                 s.append(ref.getAdapterId());
530                 instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.toString());
531             }
532 
533             Ice.NotRegisteredException e = new Ice.NotRegisteredException();
534             e.kindOfObject = "object adapter";
535             e.id = ref.getAdapterId();
536             throw e;
537         }
538         catch(Ice.ObjectNotFoundException ex)
539         {
540             final Instance instance = ref.getInstance();
541             if(instance.traceLevels().location >= 1)
542             {
543                 StringBuilder s = new StringBuilder(128);
544                 s.append("object not found\n");
545                 s.append("object = ");
546                 s.append(Ice.Util.identityToString(ref.getIdentity(), instance.toStringMode()));
547                 instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.toString());
548             }
549 
550             Ice.NotRegisteredException e = new Ice.NotRegisteredException();
551             e.kindOfObject = "object";
552             e.id = Ice.Util.identityToString(ref.getIdentity(), instance.toStringMode());
553             throw e;
554         }
555         catch(Ice.NotRegisteredException ex)
556         {
557             throw ex;
558         }
559         catch(Ice.LocalException ex)
560         {
561             final Instance instance = ref.getInstance();
562             if(instance.traceLevels().location >= 1)
563             {
564                 StringBuilder s = new StringBuilder(128);
565                 s.append("couldn't contact the locator to retrieve endpoints\n");
566                 if(ref.getAdapterId().length() > 0)
567                 {
568                     s.append("adapter = ");
569                     s.append(ref.getAdapterId());
570                     s.append("\n");
571                 }
572                 else
573                 {
574                     s.append("well-known proxy = ");
575                     s.append(ref.toString());
576                     s.append("\n");
577                 }
578                 s.append("reason = " + ex);
579                 instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.toString());
580             }
581             throw ex;
582         }
583         catch(Exception ex)
584         {
585             assert(false);
586         }
587     }
588 
589     private void
getEndpointsTrace(Reference ref, EndpointI[] endpoints, boolean cached)590     getEndpointsTrace(Reference ref, EndpointI[] endpoints, boolean cached)
591     {
592         if(endpoints != null && endpoints.length > 0)
593         {
594             if(cached)
595             {
596                 if(ref.isWellKnown())
597                 {
598                     trace("found endpoints for well-known proxy in locator cache", ref, endpoints);
599                 }
600                 else
601                 {
602                     trace("found endpoints for adapter in locator cache", ref, endpoints);
603                 }
604             }
605             else
606             {
607                 if(ref.isWellKnown())
608                 {
609                     trace("retrieved endpoints for well-known proxy from locator, adding to locator cache",
610                           ref, endpoints);
611                 }
612                 else
613                 {
614                     trace("retrieved endpoints for adapter from locator, adding to locator cache",
615                           ref, endpoints);
616                 }
617             }
618         }
619         else
620         {
621             final Instance instance = ref.getInstance();
622             StringBuilder s = new StringBuilder(128);
623             s.append("no endpoints configured for ");
624             if(ref.getAdapterId().length() > 0)
625             {
626                 s.append("adapter\n");
627                 s.append("adapter = ");
628                 s.append(ref.getAdapterId());
629                 s.append("\n");
630             }
631             else
632             {
633                 s.append("well-known object\n");
634                 s.append("well-known proxy = ");
635                 s.append(ref.toString());
636                 s.append("\n");
637             }
638             instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.toString());
639         }
640     }
641 
642     synchronized private Request
getAdapterRequest(Reference ref)643     getAdapterRequest(Reference ref)
644     {
645         if(ref.getInstance().traceLevels().location >= 1)
646         {
647             Instance instance = ref.getInstance();
648             StringBuilder s = new StringBuilder(128);
649             s.append("searching for adapter by id\n");
650             s.append("adapter = ");
651             s.append(ref.getAdapterId());
652             instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.toString());
653         }
654 
655         Request request = _adapterRequests.get(ref.getAdapterId());
656         if(request != null)
657         {
658             return request;
659         }
660         request = new AdapterRequest(this, ref);
661         _adapterRequests.put(ref.getAdapterId(), request);
662         return request;
663     }
664 
665     synchronized private Request
getObjectRequest(Reference ref)666     getObjectRequest(Reference ref)
667     {
668         if(ref.getInstance().traceLevels().location >= 1)
669         {
670             Instance instance = ref.getInstance();
671             StringBuilder s = new StringBuilder(128);
672             s.append("searching for well-known object\n");
673             s.append("well-known proxy = ");
674             s.append(ref.toString());
675             instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.toString());
676         }
677 
678         Request request = _objectRequests.get(ref.getIdentity());
679         if(request != null)
680         {
681             return request;
682         }
683         request = new ObjectRequest(this, ref);
684         _objectRequests.put(ref.getIdentity(), request);
685         return request;
686     }
687 
688     private void
finishRequest(Reference ref, java.util.List<Reference> wellKnownRefs, Ice.ObjectPrx proxy, boolean notRegistered)689     finishRequest(Reference ref, java.util.List<Reference> wellKnownRefs, Ice.ObjectPrx proxy, boolean notRegistered)
690     {
691         if(proxy == null || ((Ice.ObjectPrxHelperBase)proxy)._getReference().isIndirect())
692         {
693             //
694             // Remove the cached references of well-known objects for which we tried
695             // to resolved the endpoints if these endpoints are empty.
696             //
697             for(Reference r : wellKnownRefs)
698             {
699                 _table.removeObjectReference(r.getIdentity());
700             }
701         }
702 
703         if(!ref.isWellKnown())
704         {
705             if(proxy != null && !((Ice.ObjectPrxHelperBase)proxy)._getReference().isIndirect())
706             {
707                 // Cache the adapter endpoints.
708                 _table.addAdapterEndpoints(ref.getAdapterId(),
709                                            ((Ice.ObjectPrxHelperBase)proxy)._getReference().getEndpoints());
710             }
711             else if(notRegistered) // If the adapter isn't registered anymore, remove it from the cache.
712             {
713                 _table.removeAdapterEndpoints(ref.getAdapterId());
714             }
715 
716             synchronized(this)
717             {
718                 assert(_adapterRequests.get(ref.getAdapterId()) != null);
719                 _adapterRequests.remove(ref.getAdapterId());
720             }
721         }
722         else
723         {
724             if(proxy != null && !((Ice.ObjectPrxHelperBase)proxy)._getReference().isWellKnown())
725             {
726                 // Cache the well-known object reference.
727                 _table.addObjectReference(ref.getIdentity(), ((Ice.ObjectPrxHelperBase)proxy)._getReference());
728             }
729             else if(notRegistered) // If the well-known object isn't registered anymore, remove it from the cache.
730             {
731                 _table.removeObjectReference(ref.getIdentity());
732             }
733 
734             synchronized(this)
735             {
736                 assert(_objectRequests.get(ref.getIdentity()) != null);
737                 _objectRequests.remove(ref.getIdentity());
738             }
739         }
740     }
741 
742     private final Ice.LocatorPrx _locator;
743     private Ice.LocatorRegistryPrx _locatorRegistry;
744     private final LocatorTable _table;
745     private final boolean _background;
746 
747     private java.util.Map<String, Request> _adapterRequests = new java.util.HashMap<String, Request>();
748     private java.util.Map<Ice.Identity, Request> _objectRequests = new java.util.HashMap<Ice.Identity, Request>();
749 }
750