1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4 
5 #include <IceUtil/DisableWarnings.h>
6 #include <Ice/LocatorInfo.h>
7 #include <Ice/Locator.h>
8 #include <Ice/LocalException.h>
9 #include <Ice/Instance.h>
10 #include <Ice/TraceLevels.h>
11 #include <Ice/LoggerUtil.h>
12 #include <Ice/EndpointI.h>
13 #include <Ice/Reference.h>
14 #include <Ice/Functional.h>
15 #include <Ice/Properties.h>
16 #include <Ice/Comparable.h>
17 #include <iterator>
18 
19 using namespace std;
20 using namespace Ice;
21 using namespace IceInternal;
22 
upCast(LocatorManager * p)23 IceUtil::Shared* IceInternal::upCast(LocatorManager* p) { return p; }
upCast(LocatorInfo * p)24 IceUtil::Shared* IceInternal::upCast(LocatorInfo* p) { return p; }
upCast(LocatorTable * p)25 IceUtil::Shared* IceInternal::upCast(LocatorTable* p) { return p; }
26 
27 namespace
28 {
29 
30 class ObjectRequest : public LocatorInfo::Request
31 {
32 public:
33 
ObjectRequest(const LocatorInfoPtr & locatorInfo,const ReferencePtr & ref)34     ObjectRequest(const LocatorInfoPtr& locatorInfo, const ReferencePtr& ref) : LocatorInfo::Request(locatorInfo, ref)
35     {
36         assert(ref->isWellKnown());
37     }
38 
send()39     virtual void send()
40     {
41         try
42         {
43 #ifdef ICE_CPP11_MAPPING
44             LocatorInfo::RequestPtr request = this;
45             _locatorInfo->getLocator()->findObjectByIdAsync(
46                 _reference->getIdentity(),
47                 [request](const ObjectPrxPtr& object)
48                 {
49                     request->response(object);
50                 },
51                 [request](exception_ptr e)
52                 {
53                     try
54                     {
55                         rethrow_exception(e);
56                     }
57                     catch(const Exception& ex)
58                     {
59                         request->exception(ex);
60                     }
61                 });
62 #else
63             _locatorInfo->getLocator()->begin_findObjectById(
64                 _reference->getIdentity(),
65                 newCallback_Locator_findObjectById(static_cast<LocatorInfo::Request*>(this),
66                                                    &LocatorInfo::Request::response,
67                                                    &LocatorInfo::Request::exception));
68 #endif
69         }
70         catch(const Ice::Exception& ex)
71         {
72             exception(ex);
73         }
74     }
75 };
76 
77 class AdapterRequest : public LocatorInfo::Request
78 {
79 public:
80 
AdapterRequest(const LocatorInfoPtr & locatorInfo,const ReferencePtr & ref)81     AdapterRequest(const LocatorInfoPtr& locatorInfo, const ReferencePtr& ref) : LocatorInfo::Request(locatorInfo, ref)
82     {
83         assert(ref->isIndirect() && !ref->isWellKnown());
84     }
85 
send()86     virtual void send()
87     {
88         try
89         {
90 #ifdef ICE_CPP11_MAPPING
91             LocatorInfo::RequestPtr request = this;
92             _locatorInfo->getLocator()->findAdapterByIdAsync(_reference->getAdapterId(),
93                 [request](const shared_ptr<Ice::ObjectPrx>& object)
94                 {
95                     request->response(object);
96                 },
97                 [request](exception_ptr e)
98                 {
99                     try
100                     {
101                         rethrow_exception(e);
102                     }
103                     catch(const Exception& ex)
104                     {
105                         request->exception(ex);
106                     }
107                 });
108 #else
109             _locatorInfo->getLocator()->begin_findAdapterById(
110                 _reference->getAdapterId(),
111                 newCallback_Locator_findAdapterById(static_cast<LocatorInfo::Request*>(this),
112                                                     &LocatorInfo::Request::response,
113                                                     &LocatorInfo::Request::exception));
114 #endif
115         }
116         catch(const Ice::Exception& ex)
117         {
118             exception(ex);
119         }
120     }
121 };
122 
123 }
124 
LocatorManager(const Ice::PropertiesPtr & properties)125 IceInternal::LocatorManager::LocatorManager(const Ice::PropertiesPtr& properties) :
126     _background(properties->getPropertyAsInt("Ice.BackgroundLocatorCacheUpdates") > 0),
127     _tableHint(_table.end())
128 {
129 }
130 
131 void
destroy()132 IceInternal::LocatorManager::destroy()
133 {
134     IceUtil::Mutex::Lock sync(*this);
135 
136 #ifdef ICE_CPP11_MAPPING
137     for_each(_table.begin(), _table.end(), [](pair<shared_ptr<Ice::LocatorPrx>, LocatorInfoPtr> it){ it.second->destroy(); });
138 #else
139     for_each(_table.begin(), _table.end(), Ice::secondVoidMemFun<const LocatorPrx, LocatorInfo>(&LocatorInfo::destroy));
140 #endif
141     _table.clear();
142     _tableHint = _table.end();
143 
144     _locatorTables.clear();
145 }
146 
147 LocatorInfoPtr
get(const LocatorPrxPtr & loc)148 IceInternal::LocatorManager::get(const LocatorPrxPtr& loc)
149 {
150     if(!loc)
151     {
152         return 0;
153     }
154 
155     LocatorPrxPtr locator = loc->ice_locator(0); // The locator can't be located.
156 
157     //
158     // TODO: reap unused locator info objects?
159     //
160 
161     IceUtil::Mutex::Lock sync(*this);
162 
163     LocatorInfoTable::iterator p = _table.end();
164 
165     if(_tableHint != _table.end())
166     {
167         if(targetEqualTo(_tableHint->first, locator))
168         {
169             p = _tableHint;
170         }
171     }
172 
173     if(p == _table.end())
174     {
175         p = _table.find(locator);
176     }
177 
178     if(p == _table.end())
179     {
180         //
181         // Rely on locator identity for the adapter table. We want to
182         // have only one table per locator (not one per locator
183         // proxy).
184         //
185         pair<Identity, EncodingVersion> locatorKey(locator->ice_getIdentity(), locator->ice_getEncodingVersion());
186         map<pair<Identity, EncodingVersion>, LocatorTablePtr>::iterator t = _locatorTables.find(locatorKey);
187         if(t == _locatorTables.end())
188         {
189             t = _locatorTables.insert(_locatorTables.begin(),
190                                       pair<const pair<Identity, EncodingVersion>, LocatorTablePtr>(
191                                           locatorKey, new LocatorTable()));
192         }
193 
194         _tableHint = _table.insert(_tableHint,
195                                    pair<const LocatorPrxPtr, LocatorInfoPtr>(locator,
196                                                                           new LocatorInfo(locator, t->second,
197                                                                                           _background)));
198     }
199     else
200     {
201         _tableHint = p;
202     }
203 
204     return _tableHint->second;
205 }
206 
LocatorTable()207 IceInternal::LocatorTable::LocatorTable()
208 {
209 }
210 
211 void
clear()212 IceInternal::LocatorTable::clear()
213 {
214      IceUtil::Mutex::Lock sync(*this);
215 
216      _adapterEndpointsMap.clear();
217      _objectMap.clear();
218 }
219 
220 bool
getAdapterEndpoints(const string & adapter,int ttl,vector<EndpointIPtr> & endpoints)221 IceInternal::LocatorTable::getAdapterEndpoints(const string& adapter, int ttl, vector<EndpointIPtr>& endpoints)
222 {
223     if(ttl == 0) // No locator cache.
224     {
225         return false;
226     }
227 
228     IceUtil::Mutex::Lock sync(*this);
229 
230     map<string, pair<IceUtil::Time, vector<EndpointIPtr> > >::iterator p = _adapterEndpointsMap.find(adapter);
231 
232     if(p != _adapterEndpointsMap.end())
233     {
234         endpoints = p->second.second;
235         return checkTTL(p->second.first, ttl);
236     }
237     return false;
238 }
239 
240 void
addAdapterEndpoints(const string & adapter,const vector<EndpointIPtr> & endpoints)241 IceInternal::LocatorTable::addAdapterEndpoints(const string& adapter, const vector<EndpointIPtr>& endpoints)
242 {
243     IceUtil::Mutex::Lock sync(*this);
244 
245     map<string, pair<IceUtil::Time, vector<EndpointIPtr> > >::iterator p = _adapterEndpointsMap.find(adapter);
246 
247     if(p != _adapterEndpointsMap.end())
248     {
249         p->second = make_pair(IceUtil::Time::now(IceUtil::Time::Monotonic), endpoints);
250     }
251     else
252     {
253         _adapterEndpointsMap.insert(
254             make_pair(adapter, make_pair(IceUtil::Time::now(IceUtil::Time::Monotonic), endpoints)));
255     }
256 }
257 
258 vector<EndpointIPtr>
removeAdapterEndpoints(const string & adapter)259 IceInternal::LocatorTable::removeAdapterEndpoints(const string& adapter)
260 {
261     IceUtil::Mutex::Lock sync(*this);
262 
263     map<string, pair<IceUtil::Time, vector<EndpointIPtr> > >::iterator p = _adapterEndpointsMap.find(adapter);
264     if(p == _adapterEndpointsMap.end())
265     {
266         return vector<EndpointIPtr>();
267     }
268 
269     vector<EndpointIPtr> endpoints = p->second.second;
270 
271     _adapterEndpointsMap.erase(p);
272 
273     return endpoints;
274 }
275 
276 bool
getObjectReference(const Identity & id,int ttl,ReferencePtr & ref)277 IceInternal::LocatorTable::getObjectReference(const Identity& id, int ttl, ReferencePtr& ref)
278 {
279     if(ttl == 0) // No locator cache
280     {
281         return false;
282     }
283 
284     IceUtil::Mutex::Lock sync(*this);
285 
286     map<Identity, pair<IceUtil::Time, ReferencePtr> >::iterator p = _objectMap.find(id);
287 
288     if(p != _objectMap.end())
289     {
290         ref = p->second.second;
291         return checkTTL(p->second.first, ttl);
292     }
293     return false;
294 }
295 
296 void
addObjectReference(const Identity & id,const ReferencePtr & ref)297 IceInternal::LocatorTable::addObjectReference(const Identity& id, const ReferencePtr& ref)
298 {
299     IceUtil::Mutex::Lock sync(*this);
300 
301     map<Identity, pair<IceUtil::Time, ReferencePtr> >::iterator p = _objectMap.find(id);
302 
303     if(p != _objectMap.end())
304     {
305         p->second = make_pair(IceUtil::Time::now(IceUtil::Time::Monotonic), ref);
306     }
307     else
308     {
309         _objectMap.insert(make_pair(id, make_pair(IceUtil::Time::now(IceUtil::Time::Monotonic), ref)));
310     }
311 }
312 
313 ReferencePtr
removeObjectReference(const Identity & id)314 IceInternal::LocatorTable::removeObjectReference(const Identity& id)
315 {
316     IceUtil::Mutex::Lock sync(*this);
317 
318     map<Identity, pair<IceUtil::Time, ReferencePtr> >::iterator p = _objectMap.find(id);
319     if(p == _objectMap.end())
320     {
321         return 0;
322     }
323 
324     ReferencePtr ref = p->second.second;
325     _objectMap.erase(p);
326     return ref;
327 }
328 
329 bool
checkTTL(const IceUtil::Time & time,int ttl) const330 IceInternal::LocatorTable::checkTTL(const IceUtil::Time& time, int ttl) const
331 {
332     assert(ttl != 0);
333     if (ttl < 0) // TTL = infinite
334     {
335         return true;
336     }
337     else
338     {
339         return IceUtil::Time::now(IceUtil::Time::Monotonic) - time <= IceUtil::Time::seconds(ttl);
340     }
341 }
342 
343 void
response(const LocatorInfoPtr & locatorInfo,const Ice::ObjectPrxPtr & proxy)344 IceInternal::LocatorInfo::RequestCallback::response(const LocatorInfoPtr& locatorInfo, const Ice::ObjectPrxPtr& proxy)
345 {
346     vector<EndpointIPtr> endpoints;
347     if(proxy)
348     {
349         ReferencePtr r = proxy->_getReference();
350         if(_reference->isWellKnown() && !isSupported(_reference->getEncoding(), r->getEncoding()))
351         {
352             //
353             // If a well-known proxy and the returned proxy encoding
354             // isn't supported, we're done: there's no compatible
355             // endpoint we can use.
356             //
357         }
358         else if(!r->isIndirect())
359         {
360             endpoints = r->getEndpoints();
361         }
362         else if(_reference->isWellKnown() && !r->isWellKnown())
363         {
364             //
365             // We're resolving the endpoints of a well-known object and the proxy returned
366             // by the locator is an indirect proxy. We now need to resolve the endpoints
367             // of this indirect proxy.
368             //
369             if(_reference->getInstance()->traceLevels()->location >= 1)
370             {
371                 locatorInfo->trace("retrieved adapter for well-known object from locator, adding to locator cache",
372                                    _reference, r);
373             }
374             locatorInfo->getEndpoints(r, _reference, _ttl, _callback);
375             return;
376         }
377     }
378 
379     if(_reference->getInstance()->traceLevels()->location >= 1)
380     {
381         locatorInfo->getEndpointsTrace(_reference, endpoints, false);
382     }
383     if(_callback)
384     {
385         _callback->setEndpoints(endpoints, false);
386     }
387 }
388 
389 void
exception(const LocatorInfoPtr & locatorInfo,const Ice::Exception & exc)390 IceInternal::LocatorInfo::RequestCallback::exception(const LocatorInfoPtr& locatorInfo, const Ice::Exception& exc)
391 {
392     try
393     {
394         locatorInfo->getEndpointsException(_reference, exc); // This throws.
395     }
396     catch(const Ice::LocalException& ex)
397     {
398         if(_callback)
399         {
400             _callback->setException(ex);
401         }
402     }
403 }
404 
RequestCallback(const ReferencePtr & ref,int ttl,const GetEndpointsCallbackPtr & cb)405 IceInternal::LocatorInfo::RequestCallback::RequestCallback(const ReferencePtr& ref,
406                                                            int ttl,
407                                                            const GetEndpointsCallbackPtr& cb) :
408     _reference(ref),  _ttl(ttl), _callback(cb)
409 {
410 }
411 
412 void
addCallback(const ReferencePtr & ref,const ReferencePtr & wellKnownRef,int ttl,const GetEndpointsCallbackPtr & cb)413 IceInternal::LocatorInfo::Request::addCallback(const ReferencePtr& ref,
414                                                const ReferencePtr& wellKnownRef,
415                                                int ttl,
416                                                const GetEndpointsCallbackPtr& cb)
417 {
418     RequestCallbackPtr callback = new RequestCallback(ref, ttl, cb);
419     {
420         IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
421         if(!_response && !_exception)
422         {
423             _callbacks.push_back(callback);
424             if(wellKnownRef) // This request is to resolve the endpoints of a cached well-known object reference
425             {
426                 _wellKnownRefs.push_back(wellKnownRef);
427             }
428             if(!_sent)
429             {
430                 _sent = true;
431                 sync.release();
432                 send(); // send() might call exception() from this thread so we need to release the mutex.
433             }
434             return;
435         }
436     }
437 
438     if(_response)
439     {
440         callback->response(_locatorInfo, _proxy);
441     }
442     else
443     {
444         assert(_exception);
445         callback->exception(_locatorInfo, *_exception);
446     }
447 }
448 
Request(const LocatorInfoPtr & locatorInfo,const ReferencePtr & ref)449 IceInternal::LocatorInfo::Request::Request(const LocatorInfoPtr& locatorInfo, const ReferencePtr& ref) :
450     _locatorInfo(locatorInfo), _reference(ref), _sent(false), _response(false)
451 {
452 }
453 
454 void
response(const Ice::ObjectPrxPtr & proxy)455 IceInternal::LocatorInfo::Request::response(const Ice::ObjectPrxPtr& proxy)
456 {
457     {
458         IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
459         _locatorInfo->finishRequest(_reference, _wellKnownRefs, proxy, false);
460         _response = true;
461         _proxy = proxy;
462         _monitor.notifyAll();
463     }
464     for(vector<RequestCallbackPtr>::const_iterator p = _callbacks.begin(); p != _callbacks.end(); ++p)
465     {
466         (*p)->response(_locatorInfo, proxy);
467     }
468 }
469 
470 void
exception(const Ice::Exception & ex)471 IceInternal::LocatorInfo::Request::exception(const Ice::Exception& ex)
472 {
473     {
474         IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
475         _locatorInfo->finishRequest(_reference, _wellKnownRefs, 0, dynamic_cast<const Ice::UserException*>(&ex));
476 
477         ICE_SET_EXCEPTION_FROM_CLONE(_exception, ex.ice_clone());
478         _monitor.notifyAll();
479     }
480     for(vector<RequestCallbackPtr>::const_iterator p = _callbacks.begin(); p != _callbacks.end(); ++p)
481     {
482         (*p)->exception(_locatorInfo, ex);
483     }
484 }
485 
LocatorInfo(const LocatorPrxPtr & locator,const LocatorTablePtr & table,bool background)486 IceInternal::LocatorInfo::LocatorInfo(const LocatorPrxPtr& locator, const LocatorTablePtr& table, bool background) :
487     _locator(locator),
488     _table(table),
489     _background(background)
490 {
491     assert(_locator);
492     assert(_table);
493 }
494 
495 void
destroy()496 IceInternal::LocatorInfo::destroy()
497 {
498     IceUtil::Mutex::Lock sync(*this);
499 
500     _locatorRegistry = 0;
501     _table->clear();
502 }
503 
504 bool
operator ==(const LocatorInfo & rhs) const505 IceInternal::LocatorInfo::operator==(const LocatorInfo& rhs) const
506 {
507     return Ice::targetEqualTo(_locator, rhs._locator);
508 }
509 
510 bool
operator <(const LocatorInfo & rhs) const511 IceInternal::LocatorInfo::operator<(const LocatorInfo& rhs) const
512 {
513     return Ice::targetLess(_locator, rhs._locator);
514 }
515 
516 LocatorRegistryPrxPtr
getLocatorRegistry()517 IceInternal::LocatorInfo::getLocatorRegistry()
518 {
519     {
520         IceUtil::Mutex::Lock sync(*this);
521         if(_locatorRegistry)
522         {
523             return _locatorRegistry;
524         }
525     }
526 
527     //
528     // Do not make locator calls from within sync.
529     //
530     LocatorRegistryPrxPtr locatorRegistry = _locator->getRegistry();
531     if(!locatorRegistry)
532     {
533         return 0;
534     }
535 
536     {
537         IceUtil::Mutex::Lock sync(*this);
538 
539         //
540         // The locator registry can't be located. We use ordered
541         // endpoint selection in case the locator returned a proxy
542         // with some endpoints which are prefered to be tried first.
543         //
544         _locatorRegistry = locatorRegistry->ice_locator(0)->ice_endpointSelection(Ice::ICE_ENUM(EndpointSelectionType, Ordered));
545         return _locatorRegistry;
546     }
547 }
548 
549 void
getEndpoints(const ReferencePtr & ref,const ReferencePtr & wellKnownRef,int ttl,const GetEndpointsCallbackPtr & callback)550 IceInternal::LocatorInfo::getEndpoints(const ReferencePtr& ref,
551                                        const ReferencePtr& wellKnownRef,
552                                        int ttl,
553                                        const GetEndpointsCallbackPtr& callback)
554 {
555     assert(ref->isIndirect());
556     vector<EndpointIPtr> endpoints;
557     if(!ref->isWellKnown())
558     {
559         if(!_table->getAdapterEndpoints(ref->getAdapterId(), ttl, endpoints))
560         {
561             if(_background && !endpoints.empty())
562             {
563                 getAdapterRequest(ref)->addCallback(ref, wellKnownRef, ttl, 0);
564             }
565             else
566             {
567                 getAdapterRequest(ref)->addCallback(ref, wellKnownRef, ttl, callback);
568                 return;
569             }
570         }
571     }
572     else
573     {
574         ReferencePtr r;
575         if(!_table->getObjectReference(ref->getIdentity(), ttl, r))
576         {
577             if(_background && r)
578             {
579                 getObjectRequest(ref)->addCallback(ref, 0, ttl, 0);
580             }
581             else
582             {
583                 getObjectRequest(ref)->addCallback(ref, 0, ttl, callback);
584                 return;
585             }
586         }
587 
588         if(!r->isIndirect())
589         {
590             endpoints = r->getEndpoints();
591         }
592         else if(!r->isWellKnown())
593         {
594             if(ref->getInstance()->traceLevels()->location >= 1)
595             {
596                 trace("found adapter for well-known object in locator cache", ref, r);
597             }
598             getEndpoints(r, ref, ttl, callback);
599             return;
600         }
601     }
602 
603     assert(!endpoints.empty());
604     if(ref->getInstance()->traceLevels()->location >= 1)
605     {
606         getEndpointsTrace(ref, endpoints, true);
607     }
608     if(callback)
609     {
610         callback->setEndpoints(endpoints, true);
611     }
612 }
613 
614 void
clearCache(const ReferencePtr & ref)615 IceInternal::LocatorInfo::clearCache(const ReferencePtr& ref)
616 {
617     assert(ref->isIndirect());
618 
619     if(!ref->isWellKnown())
620     {
621         vector<EndpointIPtr> endpoints = _table->removeAdapterEndpoints(ref->getAdapterId());
622 
623         if(!endpoints.empty() && ref->getInstance()->traceLevels()->location >= 2)
624         {
625             trace("removed endpoints for adapter from locator cache", ref, endpoints);
626         }
627     }
628     else
629     {
630         ReferencePtr r = _table->removeObjectReference(ref->getIdentity());
631         if(r)
632         {
633             if(!r->isIndirect())
634             {
635                 if(ref->getInstance()->traceLevels()->location >= 2)
636                 {
637                     trace("removed endpoints for well-known object from locator cache", ref, r->getEndpoints());
638                 }
639             }
640             else if(!r->isWellKnown())
641             {
642                 if(ref->getInstance()->traceLevels()->location >= 2)
643                 {
644                     trace("removed adapter for well-known object from locator cache", ref, r);
645                 }
646                 clearCache(r);
647             }
648         }
649     }
650 }
651 
652 void
getEndpointsException(const ReferencePtr & ref,const Ice::Exception & exc)653 IceInternal::LocatorInfo::getEndpointsException(const ReferencePtr& ref, const Ice::Exception& exc)
654 {
655     assert(ref->isIndirect());
656 
657     try
658     {
659         exc.ice_throw();
660     }
661     catch(const AdapterNotFoundException&)
662     {
663         if(ref->getInstance()->traceLevels()->location >= 1)
664         {
665             Trace out(ref->getInstance()->initializationData().logger,
666                       ref->getInstance()->traceLevels()->locationCat);
667             out << "adapter not found" << "\n";
668             out << "adapter = " << ref->getAdapterId();
669         }
670 
671         throw NotRegisteredException(__FILE__, __LINE__, "object adapter", ref->getAdapterId());
672     }
673     catch(const ObjectNotFoundException&)
674     {
675         if(ref->getInstance()->traceLevels()->location >= 1)
676         {
677             Trace out(ref->getInstance()->initializationData().logger,
678                       ref->getInstance()->traceLevels()->locationCat);
679             out << "object not found" << "\n";
680             out << "object = " << Ice::identityToString(ref->getIdentity(),
681                                                         ref->getInstance()->toStringMode());
682         }
683 
684         throw NotRegisteredException(__FILE__, __LINE__, "object",
685                                      Ice::identityToString(ref->getIdentity(), ref->getInstance()->toStringMode()));
686     }
687     catch(const NotRegisteredException&)
688     {
689         throw;
690     }
691     catch(const LocalException& ex)
692     {
693         if(ref->getInstance()->traceLevels()->location >= 1)
694         {
695             Trace out(ref->getInstance()->initializationData().logger, ref->getInstance()->traceLevels()->locationCat);
696             out << "couldn't contact the locator to retrieve endpoints\n";
697             if(ref->getAdapterId().empty())
698             {
699                 out << "well-known proxy = " << ref->toString() << "\n";
700             }
701             else
702             {
703                 out << "adapter = " << ref->getAdapterId() << "\n";
704             }
705             out << "reason = " << ex;
706         }
707         throw;
708     }
709 }
710 
711 void
getEndpointsTrace(const ReferencePtr & ref,const vector<EndpointIPtr> & endpoints,bool cached)712 IceInternal::LocatorInfo::getEndpointsTrace(const ReferencePtr& ref,
713                                             const vector<EndpointIPtr>& endpoints,
714                                             bool cached)
715 {
716     if(!endpoints.empty())
717     {
718         if(cached)
719         {
720             if(ref->isWellKnown())
721             {
722                 trace("found endpoints for well-known proxy in locator cache", ref, endpoints);
723             }
724             else
725             {
726                 trace("found endpoints for adapter in locator cache", ref, endpoints);
727             }
728         }
729         else
730         {
731             if(ref->isWellKnown())
732             {
733                 trace("retrieved endpoints for well-known proxy from locator, adding to locator cache", ref, endpoints);
734             }
735             else
736             {
737                 trace("retrieved endpoints for adapter from locator, adding to locator cache", ref, endpoints);
738             }
739         }
740     }
741     else
742     {
743         Trace out(ref->getInstance()->initializationData().logger, ref->getInstance()->traceLevels()->locationCat);
744         out << "no endpoints configured for ";
745         if(ref->getAdapterId().empty())
746         {
747             out << "well-known object\n";
748             out << "well-known proxy = " << ref->toString();
749         }
750         else
751         {
752             out << "adapter\n";
753             out << "adapter = " << ref->getAdapterId();
754         }
755     }
756 }
757 
758 void
trace(const string & msg,const ReferencePtr & ref,const vector<EndpointIPtr> & endpoints)759 IceInternal::LocatorInfo::trace(const string& msg, const ReferencePtr& ref, const vector<EndpointIPtr>& endpoints)
760 {
761     assert(ref->isIndirect());
762 
763     Trace out(ref->getInstance()->initializationData().logger, ref->getInstance()->traceLevels()->locationCat);
764     out << msg << '\n';
765     if(!ref->isWellKnown())
766     {
767         out << "adapter = "  << ref->getAdapterId() << '\n';
768     }
769     else
770     {
771         out << "well-known proxy = "  << ref->toString() << '\n';
772     }
773 
774     const char* sep = endpoints.size() > 1 ? ":" : "";
775     ostringstream o;
776 #ifdef ICE_CPP11_MAPPING
777     transform(endpoints.begin(), endpoints.end(), ostream_iterator<string>(o, sep),
778               [](const EndpointPtr& endpoint)
779               {
780                   return endpoint->toString();
781               });
782 #else
783     transform(endpoints.begin(), endpoints.end(), ostream_iterator<string>(o, sep),
784               Ice::constMemFun(&Endpoint::toString));
785 #endif
786     out << "endpoints = " << o.str();
787 }
788 
789 void
trace(const string & msg,const ReferencePtr & ref,const ReferencePtr & resolved)790 IceInternal::LocatorInfo::trace(const string& msg, const ReferencePtr& ref, const ReferencePtr& resolved)
791 {
792     assert(ref->isWellKnown());
793 
794     Trace out(ref->getInstance()->initializationData().logger, ref->getInstance()->traceLevels()->locationCat);
795     out << msg << '\n';
796     out << "well-known proxy = "  << ref->toString() << '\n';
797     out << "adapter = " << resolved->getAdapterId();
798 }
799 
800 IceInternal::LocatorInfo::RequestPtr
getAdapterRequest(const ReferencePtr & ref)801 IceInternal::LocatorInfo::getAdapterRequest(const ReferencePtr& ref)
802 {
803     IceUtil::Mutex::Lock sync(*this);
804     if(ref->getInstance()->traceLevels()->location >= 1)
805     {
806         Trace out(ref->getInstance()->initializationData().logger, ref->getInstance()->traceLevels()->locationCat);
807         out << "searching for adapter by id\nadapter = " << ref->getAdapterId();
808     }
809 
810     map<string, RequestPtr>::const_iterator p = _adapterRequests.find(ref->getAdapterId());
811     if(p != _adapterRequests.end())
812     {
813         return p->second;
814     }
815 
816     RequestPtr request = new AdapterRequest(this, ref);
817     _adapterRequests.insert(make_pair(ref->getAdapterId(), request));
818     return request;
819 }
820 
821 IceInternal::LocatorInfo::RequestPtr
getObjectRequest(const ReferencePtr & ref)822 IceInternal::LocatorInfo::getObjectRequest(const ReferencePtr& ref)
823 {
824     IceUtil::Mutex::Lock sync(*this);
825     if(ref->getInstance()->traceLevels()->location >= 1)
826     {
827         Trace out(ref->getInstance()->initializationData().logger, ref->getInstance()->traceLevels()->locationCat);
828         out << "searching for well-known object\nwell-known proxy = " << ref->toString();
829     }
830 
831     map<Ice::Identity, RequestPtr>::const_iterator p = _objectRequests.find(ref->getIdentity());
832     if(p != _objectRequests.end())
833     {
834         return p->second;
835     }
836     RequestPtr request = new ObjectRequest(this, ref);
837     _objectRequests.insert(make_pair(ref->getIdentity(), request));
838     return request;
839 }
840 
841 void
finishRequest(const ReferencePtr & ref,const vector<ReferencePtr> & wellKnownRefs,const Ice::ObjectPrxPtr & proxy,bool notRegistered)842 IceInternal::LocatorInfo::finishRequest(const ReferencePtr& ref,
843                                         const vector<ReferencePtr>& wellKnownRefs,
844                                         const Ice::ObjectPrxPtr& proxy,
845                                         bool notRegistered)
846 {
847     if(!proxy || proxy->_getReference()->isIndirect())
848     {
849         //
850         // Remove the cached references of well-known objects for which we tried
851         // to resolved the endpoints if these endpoints are empty.
852         //
853         for(vector<ReferencePtr>::const_iterator q = wellKnownRefs.begin(); q != wellKnownRefs.end(); ++q)
854         {
855             _table->removeObjectReference((*q)->getIdentity());
856         }
857     }
858 
859     if(!ref->isWellKnown())
860     {
861         if(proxy && !proxy->_getReference()->isIndirect()) // Cache the adapter endpoints.
862         {
863             _table->addAdapterEndpoints(ref->getAdapterId(), proxy->_getReference()->getEndpoints());
864         }
865         else if(notRegistered) // If the adapter isn't registered anymore, remove it from the cache.
866         {
867             _table->removeAdapterEndpoints(ref->getAdapterId());
868         }
869 
870         IceUtil::Mutex::Lock sync(*this);
871         assert(_adapterRequests.find(ref->getAdapterId()) != _adapterRequests.end());
872         _adapterRequests.erase(ref->getAdapterId());
873     }
874     else
875     {
876         if(proxy && !proxy->_getReference()->isWellKnown()) // Cache the well-known object reference.
877         {
878             _table->addObjectReference(ref->getIdentity(), proxy->_getReference());
879         }
880         else if(notRegistered) // If the well-known object isn't registered anymore, remove it from the cache.
881         {
882             _table->removeObjectReference(ref->getIdentity());
883         }
884 
885         IceUtil::Mutex::Lock sync(*this);
886         assert(_objectRequests.find(ref->getIdentity()) != _objectRequests.end());
887         _objectRequests.erase(ref->getIdentity());
888     }
889 }
890