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