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