1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4 
5 namespace Ice
6 {
7     using System;
8     using System.Collections.Generic;
9     using System.Diagnostics;
10     using System.Text;
11 
12     using IceInternal;
13 
14     public sealed class ObjectAdapterI : ObjectAdapter
15     {
getName()16         public string getName()
17         {
18             //
19             // No mutex lock necessary, _name is immutable.
20             //
21             return _noConfig ? "" : _name;
22         }
23 
getCommunicator()24         public Communicator getCommunicator()
25         {
26             return _communicator;
27         }
28 
activate()29         public void activate()
30         {
31             LocatorInfo locatorInfo = null;
32             bool printAdapterReady = false;
33 
34             lock(this)
35             {
36                 checkForDeactivation();
37 
38                 //
39                 // If we've previously been initialized we just need to activate the
40                 // incoming connection factories and we're done.
41                 //
42                 if(_state != StateUninitialized)
43                 {
44                     foreach(IncomingConnectionFactory icf in _incomingConnectionFactories)
45                     {
46                         icf.activate();
47                     }
48                     return;
49                 }
50 
51                 //
52                 // One off initializations of the adapter: update the
53                 // locator registry and print the "adapter ready"
54                 // message. We set set state to StateActivating to prevent
55                 // deactivation from other threads while these one off
56                 // initializations are done.
57                 //
58                 _state = StateActivating;
59 
60                 locatorInfo = _locatorInfo;
61                 if(!_noConfig)
62                 {
63                     Properties properties = _instance.initializationData().properties;
64                     printAdapterReady = properties.getPropertyAsInt("Ice.PrintAdapterReady") > 0;
65                 }
66             }
67 
68             try
69             {
70                 Identity dummy = new Identity();
71                 dummy.name = "dummy";
72                 updateLocatorRegistry(locatorInfo, createDirectProxy(dummy));
73             }
74             catch(LocalException)
75             {
76                 //
77                 // If we couldn't update the locator registry, we let the
78                 // exception go through and don't activate the adapter to
79                 // allow to user code to retry activating the adapter
80                 // later.
81                 //
82                 lock(this)
83                 {
84                     _state = StateUninitialized;
85                     System.Threading.Monitor.PulseAll(this);
86                 }
87                 throw;
88             }
89 
90             if(printAdapterReady)
91             {
92                 Console.Out.WriteLine(_name + " ready");
93             }
94 
95             lock(this)
96             {
97                 Debug.Assert(_state == StateActivating);
98 
99                 foreach(IncomingConnectionFactory icf in _incomingConnectionFactories)
100                 {
101                     icf.activate();
102                 }
103 
104                 _state = StateActive;
105                 System.Threading.Monitor.PulseAll(this);
106             }
107         }
108 
hold()109         public void hold()
110         {
111             lock(this)
112             {
113                 checkForDeactivation();
114                 _state = StateHeld;
115                 foreach(IncomingConnectionFactory factory in _incomingConnectionFactories)
116                 {
117                     factory.hold();
118                 }
119             }
120         }
121 
waitForHold()122         public void waitForHold()
123         {
124             List<IncomingConnectionFactory> incomingConnectionFactories;
125             lock(this)
126             {
127                 checkForDeactivation();
128 
129                 incomingConnectionFactories = new List<IncomingConnectionFactory>(_incomingConnectionFactories);
130             }
131 
132             foreach(IncomingConnectionFactory factory in incomingConnectionFactories)
133             {
134                 factory.waitUntilHolding();
135             }
136         }
137 
deactivate()138         public void deactivate()
139         {
140             lock(this)
141             {
142                 //
143                 //
144                 // Wait for activation to complete. This is necessary to not
145                 // get out of order locator updates.
146                 //
147                 while(_state == StateActivating || _state == StateDeactivating)
148                 {
149                     System.Threading.Monitor.Wait(this);
150                 }
151                 if(_state > StateDeactivating)
152                 {
153                     return;
154                 }
155                 _state = StateDeactivating;
156             }
157 
158             //
159             // NOTE: the router/locator infos and incoming connection
160             // factory list are immutable at this point.
161             //
162 
163             try
164             {
165                 if(_routerInfo != null)
166                 {
167                     //
168                     // Remove entry from the router manager.
169                     //
170                     _instance.routerManager().erase(_routerInfo.getRouter());
171 
172                     //
173                     // Clear this object adapter with the router.
174                     //
175                     _routerInfo.setAdapter(null);
176                 }
177 
178                 updateLocatorRegistry(_locatorInfo, null);
179             }
180             catch(LocalException)
181             {
182                 //
183                 // We can't throw exceptions in deactivate so we ignore
184                 // failures to update the locator registry.
185                 //
186             }
187 
188             foreach(IncomingConnectionFactory factory in _incomingConnectionFactories)
189             {
190                 factory.destroy();
191             }
192 
193             _instance.outgoingConnectionFactory().removeAdapter(this);
194 
195             lock(this)
196             {
197                 Debug.Assert(_state == StateDeactivating);
198                 _state = StateDeactivated;
199                 System.Threading.Monitor.PulseAll(this);
200             }
201         }
202 
waitForDeactivate()203         public void waitForDeactivate()
204         {
205             IncomingConnectionFactory[] incomingConnectionFactories = null;
206             lock(this)
207             {
208                 //
209                 // Wait for deactivation of the adapter itself, and
210                 // for the return of all direct method calls using this
211                 // adapter.
212                 //
213                 while((_state < StateDeactivated) || _directCount > 0)
214                 {
215                     System.Threading.Monitor.Wait(this);
216                 }
217                 if(_state > StateDeactivated)
218                 {
219                     return;
220                 }
221 
222                 incomingConnectionFactories = _incomingConnectionFactories.ToArray();
223             }
224 
225             //
226             // Now we wait for until all incoming connection factories are
227             // finished.
228             //
229             foreach(IncomingConnectionFactory factory in incomingConnectionFactories)
230             {
231                 factory.waitUntilFinished();
232             }
233         }
234 
isDeactivated()235         public bool isDeactivated()
236         {
237             lock(this)
238             {
239                 return _state >= StateDeactivated;
240             }
241         }
242 
destroy()243         public void destroy()
244         {
245             //
246             // Deactivate and wait for completion.
247             //
248             deactivate();
249             waitForDeactivate();
250 
251             lock(this)
252             {
253                 //
254                 // Only a single thread is allowed to destroy the object
255                 // adapter. Other threads wait for the destruction to be
256                 // completed.
257                 //
258                 while(_state == StateDestroying)
259                 {
260                     System.Threading.Monitor.Wait(this);
261                 }
262                 if(_state == StateDestroyed)
263                 {
264                     return;
265                 }
266                 _state = StateDestroying;
267             }
268 
269             //
270             // Now it's also time to clean up our servants and servant
271             // locators.
272             //
273             _servantManager.destroy();
274 
275             //
276             // Destroy the thread pool.
277             //
278             if(_threadPool != null)
279             {
280                 _threadPool.destroy();
281                 _threadPool.joinWithAllThreads();
282             }
283 
284             if(_objectAdapterFactory != null)
285             {
286                 _objectAdapterFactory.removeObjectAdapter(this);
287             }
288 
289             lock(this)
290             {
291                 //
292                 // We're done, now we can throw away all incoming connection
293                 // factories.
294                 //
295                 _incomingConnectionFactories.Clear();
296 
297                 //
298                 // Remove object references (some of them cyclic).
299                 //
300                 _instance = null;
301                 _threadPool = null;
302                 _routerInfo = null;
303                 _publishedEndpoints = new EndpointI[0];
304                 _locatorInfo = null;
305                 _reference = null;
306                 _objectAdapterFactory = null;
307 
308                 _state = StateDestroyed;
309                 System.Threading.Monitor.PulseAll(this);
310             }
311         }
312 
add(Object obj, Identity ident)313         public ObjectPrx add(Object obj, Identity ident)
314         {
315             return addFacet(obj, ident, "");
316         }
317 
addFacet(Object obj, Identity ident, string facet)318         public ObjectPrx addFacet(Object obj, Identity ident, string facet)
319         {
320             lock(this)
321             {
322                 checkForDeactivation();
323                 checkIdentity(ident);
324                 checkServant(obj);
325 
326                 //
327                 // Create a copy of the Identity argument, in case the caller
328                 // reuses it.
329                 //
330                 Identity id = new Identity();
331                 id.category = ident.category;
332                 id.name = ident.name;
333 
334                 _servantManager.addServant(obj, id, facet);
335 
336                 return newProxy(id, facet);
337             }
338         }
339 
addWithUUID(Object obj)340         public ObjectPrx addWithUUID(Object obj)
341         {
342             return addFacetWithUUID(obj, "");
343         }
344 
addFacetWithUUID(Object obj, string facet)345         public ObjectPrx addFacetWithUUID(Object obj, string facet)
346         {
347             Identity ident = new Identity();
348             ident.category = "";
349             ident.name = Guid.NewGuid().ToString();
350 
351             return addFacet(obj, ident, facet);
352         }
353 
addDefaultServant(Ice.Object servant, string category)354         public void addDefaultServant(Ice.Object servant, string category)
355         {
356             checkServant(servant);
357 
358             lock(this)
359             {
360                 checkForDeactivation();
361 
362                 _servantManager.addDefaultServant(servant, category);
363             }
364         }
365 
remove(Identity ident)366         public Object remove(Identity ident)
367         {
368             return removeFacet(ident, "");
369         }
370 
removeFacet(Identity ident, string facet)371         public Object removeFacet(Identity ident, string facet)
372         {
373             lock(this)
374             {
375                 checkForDeactivation();
376                 checkIdentity(ident);
377 
378                 return _servantManager.removeServant(ident, facet);
379             }
380         }
381 
removeAllFacets(Identity ident)382         public Dictionary<string, Object> removeAllFacets(Identity ident)
383         {
384             lock(this)
385             {
386                 checkForDeactivation();
387                 checkIdentity(ident);
388 
389                 return _servantManager.removeAllFacets(ident);
390             }
391         }
392 
removeDefaultServant(string category)393         public Object removeDefaultServant(string category)
394         {
395             lock(this)
396             {
397                 checkForDeactivation();
398 
399                 return _servantManager.removeDefaultServant(category);
400             }
401         }
402 
find(Identity ident)403         public Object find(Identity ident)
404         {
405             return findFacet(ident, "");
406         }
407 
findFacet(Identity ident, string facet)408         public Object findFacet(Identity ident, string facet)
409         {
410             lock(this)
411             {
412                 checkForDeactivation();
413                 checkIdentity(ident);
414 
415                 return _servantManager.findServant(ident, facet);
416             }
417         }
418 
findAllFacets(Identity ident)419         public Dictionary<string, Object> findAllFacets(Identity ident)
420         {
421             lock(this)
422             {
423                 checkForDeactivation();
424                 checkIdentity(ident);
425 
426                 return _servantManager.findAllFacets(ident);
427             }
428         }
429 
findByProxy(ObjectPrx proxy)430         public Object findByProxy(ObjectPrx proxy)
431         {
432             lock(this)
433             {
434                 checkForDeactivation();
435 
436                 Reference @ref = ((ObjectPrxHelperBase)proxy).iceReference();
437                 return findFacet(@ref.getIdentity(), @ref.getFacet());
438             }
439         }
440 
findDefaultServant(string category)441         public Object findDefaultServant(string category)
442         {
443             lock(this)
444             {
445                 checkForDeactivation();
446 
447                 return _servantManager.findDefaultServant(category);
448             }
449         }
450 
addServantLocator(ServantLocator locator, string prefix)451         public void addServantLocator(ServantLocator locator, string prefix)
452         {
453             lock(this)
454             {
455                 checkForDeactivation();
456 
457                 _servantManager.addServantLocator(locator, prefix);
458             }
459         }
460 
removeServantLocator(string prefix)461         public ServantLocator removeServantLocator(string prefix)
462         {
463             lock(this)
464             {
465                 checkForDeactivation();
466 
467                 return _servantManager.removeServantLocator(prefix);
468             }
469         }
470 
findServantLocator(string prefix)471         public ServantLocator findServantLocator(string prefix)
472         {
473             lock(this)
474             {
475                 checkForDeactivation();
476 
477                 return _servantManager.findServantLocator(prefix);
478             }
479         }
480 
createProxy(Identity ident)481         public ObjectPrx createProxy(Identity ident)
482         {
483             lock(this)
484             {
485                 checkForDeactivation();
486                 checkIdentity(ident);
487 
488                 return newProxy(ident, "");
489             }
490         }
491 
createDirectProxy(Identity ident)492         public ObjectPrx createDirectProxy(Identity ident)
493         {
494             lock(this)
495             {
496                 checkForDeactivation();
497                 checkIdentity(ident);
498 
499                 return newDirectProxy(ident, "");
500             }
501         }
502 
createIndirectProxy(Identity ident)503         public ObjectPrx createIndirectProxy(Identity ident)
504         {
505             lock(this)
506             {
507                 checkForDeactivation();
508                 checkIdentity(ident);
509 
510                 return newIndirectProxy(ident, "", _id);
511             }
512         }
513 
setLocator(LocatorPrx locator)514         public void setLocator(LocatorPrx locator)
515         {
516             lock(this)
517             {
518                 checkForDeactivation();
519 
520                 _locatorInfo = _instance.locatorManager().get(locator);
521             }
522         }
523 
getLocator()524         public LocatorPrx getLocator()
525         {
526             lock(this)
527             {
528                 checkForDeactivation();
529 
530                 if(_locatorInfo == null)
531                 {
532                     return null;
533                 }
534                 else
535                 {
536                     return _locatorInfo.getLocator();
537                 }
538             }
539         }
540 
getEndpoints()541         public Endpoint[] getEndpoints()
542         {
543             lock(this)
544             {
545                 List<Endpoint> endpoints = new List<Endpoint>();
546                 foreach(IncomingConnectionFactory factory in _incomingConnectionFactories)
547                 {
548                     endpoints.Add(factory.endpoint());
549                 }
550                 return endpoints.ToArray();
551             }
552         }
553 
refreshPublishedEndpoints()554         public void refreshPublishedEndpoints()
555         {
556             LocatorInfo locatorInfo = null;
557             EndpointI[] oldPublishedEndpoints;
558 
559             lock(this)
560             {
561                 checkForDeactivation();
562 
563                 oldPublishedEndpoints = _publishedEndpoints;
564                 _publishedEndpoints = computePublishedEndpoints();
565 
566                 locatorInfo = _locatorInfo;
567             }
568 
569             try
570             {
571                 Identity dummy = new Identity();
572                 dummy.name = "dummy";
573                 updateLocatorRegistry(locatorInfo, createDirectProxy(dummy));
574             }
575             catch(LocalException)
576             {
577                 lock(this)
578                 {
579                     //
580                     // Restore the old published endpoints.
581                     //
582                     _publishedEndpoints = oldPublishedEndpoints;
583                     throw;
584                 }
585             }
586         }
587 
getPublishedEndpoints()588         public Endpoint[] getPublishedEndpoints()
589         {
590             lock(this)
591             {
592                 return (Endpoint[])_publishedEndpoints.Clone();
593             }
594         }
595 
setPublishedEndpoints(Endpoint[] newEndpoints)596         public void setPublishedEndpoints(Endpoint[] newEndpoints)
597         {
598             LocatorInfo locatorInfo = null;
599             EndpointI[] oldPublishedEndpoints;
600 
601             lock(this)
602             {
603                 checkForDeactivation();
604                 if(_routerInfo != null)
605                 {
606                     throw new ArgumentException(
607                                     "can't set published endpoints on object adapter associated with a router");
608                 }
609 
610                 oldPublishedEndpoints = _publishedEndpoints;
611                 _publishedEndpoints = Array.ConvertAll(newEndpoints, endpt => (EndpointI)endpt);
612                 locatorInfo = _locatorInfo;
613             }
614 
615             try
616             {
617                 Identity dummy = new Identity();
618                 dummy.name = "dummy";
619                 updateLocatorRegistry(locatorInfo, createDirectProxy(dummy));
620             }
621             catch(LocalException)
622             {
623                 lock(this)
624                 {
625                     //
626                     // Restore the old published endpoints.
627                     //
628                     _publishedEndpoints = oldPublishedEndpoints;
629                     throw;
630                 }
631             }
632         }
633 
isLocal(ObjectPrx proxy)634         public bool isLocal(ObjectPrx proxy)
635         {
636             //
637             // NOTE: it's important that isLocal() doesn't perform any blocking operations as
638             // it can be called for AMI invocations if the proxy has no delegate set yet.
639             //
640 
641             Reference r = ((ObjectPrxHelperBase)proxy).iceReference();
642             if(r.isWellKnown())
643             {
644                 //
645                 // Check the active servant map to see if the well-known
646                 // proxy is for a local object.
647                 //
648                 return _servantManager.hasServant(r.getIdentity());
649             }
650             else if(r.isIndirect())
651             {
652                 //
653                 // Proxy is local if the reference adapter id matches this
654                 // adapter id or replica group id.
655                 //
656                 return r.getAdapterId().Equals(_id) || r.getAdapterId().Equals(_replicaGroupId);
657             }
658             else
659             {
660                 EndpointI[] endpoints = r.getEndpoints();
661 
662                 lock(this)
663                 {
664                     checkForDeactivation();
665 
666                     //
667                     // Proxies which have at least one endpoint in common with the
668                     // endpoints used by this object adapter's incoming connection
669                     // factories are considered local.
670                     //
671                     for(int i = 0; i < endpoints.Length; ++i)
672                     {
673                         foreach(EndpointI endpoint in _publishedEndpoints)
674                         {
675                             if(endpoints[i].equivalent(endpoint))
676                             {
677                                 return true;
678                             }
679                         }
680                         foreach(IncomingConnectionFactory factory in _incomingConnectionFactories)
681                         {
682                             if(factory.isLocal(endpoints[i]))
683                             {
684                                 return true;
685                             }
686                         }
687                     }
688                     return false;
689                 }
690             }
691         }
692 
flushAsyncBatchRequests(Ice.CompressBatch compressBatch, CommunicatorFlushBatchAsync outAsync)693         public void flushAsyncBatchRequests(Ice.CompressBatch compressBatch, CommunicatorFlushBatchAsync outAsync)
694         {
695             List<IncomingConnectionFactory> f;
696             lock(this)
697             {
698                 f = new List<IncomingConnectionFactory>(_incomingConnectionFactories);
699             }
700 
701             foreach(IncomingConnectionFactory factory in f)
702             {
703                 factory.flushAsyncBatchRequests(compressBatch, outAsync);
704             }
705         }
706 
updateConnectionObservers()707         public void updateConnectionObservers()
708         {
709             List<IncomingConnectionFactory> f;
710             lock(this)
711             {
712                 f = new List<IncomingConnectionFactory>(_incomingConnectionFactories);
713             }
714 
715             foreach(IncomingConnectionFactory p in f)
716             {
717                 p.updateConnectionObservers();
718             }
719         }
720 
updateThreadObservers()721         public void  updateThreadObservers()
722         {
723             ThreadPool threadPool = null;
724             lock(this)
725             {
726                 threadPool = _threadPool;
727             }
728 
729             if(threadPool != null)
730             {
731                 threadPool.updateObservers();
732             }
733         }
734 
incDirectCount()735         public void incDirectCount()
736         {
737             lock(this)
738             {
739                 checkForDeactivation();
740 
741                 Debug.Assert(_directCount >= 0);
742                 ++_directCount;
743             }
744         }
745 
decDirectCount()746         public void decDirectCount()
747         {
748             lock(this)
749             {
750                 // Not check for deactivation here!
751 
752                 Debug.Assert(_instance != null); // Must not be called after destroy().
753 
754                 Debug.Assert(_directCount > 0);
755                 if(--_directCount == 0)
756                 {
757                     System.Threading.Monitor.PulseAll(this);
758                 }
759             }
760         }
761 
getThreadPool()762         public ThreadPool getThreadPool()
763         {
764             // No mutex lock necessary, _threadPool and _instance are
765             // immutable after creation until they are removed in
766             // destroy().
767 
768             // Not check for deactivation here!
769 
770             Debug.Assert(_instance != null); // Must not be called after destroy().
771 
772             if(_threadPool != null)
773             {
774                 return _threadPool;
775             }
776             else
777             {
778                 return _instance.serverThreadPool();
779             }
780 
781         }
782 
getServantManager()783         public ServantManager getServantManager()
784         {
785             //
786             // No mutex lock necessary, _servantManager is immutable.
787             //
788             return _servantManager;
789         }
790 
getACM()791         public ACMConfig getACM()
792         {
793             // Not check for deactivation here!
794 
795             Debug.Assert(_instance != null); // Must not be called after destroy().
796             return _acm;
797         }
798 
setAdapterOnConnection(Ice.ConnectionI connection)799         public void setAdapterOnConnection(Ice.ConnectionI connection)
800         {
801             lock(this)
802             {
803                 checkForDeactivation();
804                 connection.setAdapterAndServantManager(this, _servantManager);
805             }
806         }
807 
messageSizeMax()808         public int messageSizeMax()
809         {
810             // No mutex lock, immutable.
811             return _messageSizeMax;
812         }
813 
814         //
815         // Only for use by ObjectAdapterFactory
816         //
ObjectAdapterI(Instance instance, Communicator communicator, ObjectAdapterFactory objectAdapterFactory, string name, RouterPrx router, bool noConfig)817         public ObjectAdapterI(Instance instance, Communicator communicator,
818                               ObjectAdapterFactory objectAdapterFactory, string name,
819                               RouterPrx router, bool noConfig)
820         {
821             _instance = instance;
822             _communicator = communicator;
823             _objectAdapterFactory = objectAdapterFactory;
824             _servantManager = new ServantManager(instance, name);
825             _name = name;
826             _incomingConnectionFactories = new List<IncomingConnectionFactory>();
827             _publishedEndpoints = new EndpointI[0];
828             _routerInfo = null;
829             _directCount = 0;
830             _noConfig = noConfig;
831 
832             if(_noConfig)
833             {
834                 _id = "";
835                 _replicaGroupId = "";
836                 _reference = _instance.referenceFactory().create("dummy -t", "");
837                 _acm = _instance.serverACM();
838                 return;
839             }
840 
841             Properties properties = _instance.initializationData().properties;
842             List<string> unknownProps = new List<string>();
843             bool noProps = filterProperties(unknownProps);
844 
845             //
846             // Warn about unknown object adapter properties.
847             //
848             if(unknownProps.Count != 0 && properties.getPropertyAsIntWithDefault("Ice.Warn.UnknownProperties", 1) > 0)
849             {
850                 StringBuilder message = new StringBuilder("found unknown properties for object adapter `");
851                 message.Append(_name);
852                 message.Append("':");
853                 foreach(string s in unknownProps)
854                 {
855                     message.Append("\n    ");
856                     message.Append(s);
857                 }
858                 _instance.initializationData().logger.warning(message.ToString());
859             }
860 
861             //
862             // Make sure named adapter has configuration.
863             //
864             if(router == null && noProps)
865             {
866                 //
867                 // These need to be set to prevent warnings/asserts in the destructor.
868                 //
869                 _state = StateDestroyed;
870                 _instance = null;
871                 _incomingConnectionFactories = null;
872 
873                 InitializationException ex = new InitializationException();
874                 ex.reason = "object adapter `" + _name + "' requires configuration";
875                 throw ex;
876             }
877 
878             _id = properties.getProperty(_name + ".AdapterId");
879             _replicaGroupId = properties.getProperty(_name + ".ReplicaGroupId");
880 
881             //
882             // Setup a reference to be used to get the default proxy options
883             // when creating new proxies. By default, create twoway proxies.
884             //
885             string proxyOptions = properties.getPropertyWithDefault(_name + ".ProxyOptions", "-t");
886             try
887             {
888                 _reference = _instance.referenceFactory().create("dummy " + proxyOptions, "");
889             }
890             catch(ProxyParseException)
891             {
892                 InitializationException ex = new InitializationException();
893                 ex.reason = "invalid proxy options `" + proxyOptions + "' for object adapter `" + _name + "'";
894                 throw ex;
895             }
896 
897             _acm = new ACMConfig(properties, communicator.getLogger(), _name + ".ACM", _instance.serverACM());
898 
899             {
900                 int defaultMessageSizeMax = instance.messageSizeMax() / 1024;
901                 int num = properties.getPropertyAsIntWithDefault(_name + ".MessageSizeMax", defaultMessageSizeMax);
902                 if(num < 1 || num > 0x7fffffff / 1024)
903                 {
904                     _messageSizeMax = 0x7fffffff;
905                 }
906                 else
907                 {
908                     _messageSizeMax = num * 1024; // Property is in kilobytes, _messageSizeMax in bytes
909                 }
910             }
911 
912             try
913             {
914                 int threadPoolSize = properties.getPropertyAsInt(_name + ".ThreadPool.Size");
915                 int threadPoolSizeMax = properties.getPropertyAsInt(_name + ".ThreadPool.SizeMax");
916                 if(threadPoolSize > 0 || threadPoolSizeMax > 0)
917                 {
918                     _threadPool = new ThreadPool(_instance, _name + ".ThreadPool", 0);
919                 }
920 
921                 if(router == null)
922                 {
923                     router = RouterPrxHelper.uncheckedCast(_instance.proxyFactory().propertyToProxy(_name + ".Router"));
924                 }
925                 if(router != null)
926                 {
927                     _routerInfo = _instance.routerManager().get(router);
928                     Debug.Assert(_routerInfo != null);
929 
930                     //
931                     // Make sure this router is not already registered with another adapter.
932                     //
933                     if(_routerInfo.getAdapter() != null)
934                     {
935                         AlreadyRegisteredException ex = new AlreadyRegisteredException();
936                         ex.kindOfObject = "object adapter with router";
937                         ex.id = Util.identityToString(router.ice_getIdentity(), _instance.toStringMode());
938                         throw ex;
939                     }
940 
941                     //
942                     // Associate this object adapter with the router. This way,
943                     // new outgoing connections to the router's client proxy will
944                     // use this object adapter for callbacks.
945                     //
946                     _routerInfo.setAdapter(this);
947 
948                     //
949                     // Also modify all existing outgoing connections to the
950                     // router's client proxy to use this object adapter for
951                     // callbacks.
952                     //
953                     _instance.outgoingConnectionFactory().setRouterInfo(_routerInfo);
954                 }
955                 else
956                 {
957                     //
958                     // Parse the endpoints, but don't store them in the adapter. The connection
959                     // factory might change it, for example, to fill in the real port number.
960                     //
961                     List<EndpointI> endpoints =  parseEndpoints(properties.getProperty(_name + ".Endpoints"), true);
962                     foreach(EndpointI endp in endpoints)
963                     {
964                         EndpointI publishedEndpoint;
965                         foreach(IceInternal.EndpointI expanded in endp.expandHost(out publishedEndpoint))
966                         {
967                             IncomingConnectionFactory factory = new IncomingConnectionFactory(instance,
968                                                                                               expanded,
969                                                                                               publishedEndpoint,
970                                                                                               this);
971                             _incomingConnectionFactories.Add(factory);
972                         }
973                     }
974                     if(endpoints.Count == 0)
975                     {
976                         TraceLevels tl = _instance.traceLevels();
977                         if(tl.network >= 2)
978                         {
979                             _instance.initializationData().logger.trace(tl.networkCat, "created adapter `" + _name +
980                                                                         "' without endpoints");
981                         }
982                     }
983                 }
984 
985                 //
986                 // Parse published endpoints.
987                 //
988                 _publishedEndpoints = computePublishedEndpoints();
989 
990                 if(properties.getProperty(_name + ".Locator").Length > 0)
991                 {
992                     setLocator(LocatorPrxHelper.uncheckedCast(
993                         _instance.proxyFactory().propertyToProxy(_name + ".Locator")));
994                 }
995                 else
996                 {
997                     setLocator(_instance.referenceFactory().getDefaultLocator());
998                 }
999             }
1000             catch(LocalException)
1001             {
1002                 destroy();
1003                 throw;
1004             }
1005         }
1006 
newProxy(Identity ident, string facet)1007         private ObjectPrx newProxy(Identity ident, string facet)
1008         {
1009             if(_id.Length == 0)
1010             {
1011                 return newDirectProxy(ident, facet);
1012             }
1013             else if(_replicaGroupId.Length == 0)
1014             {
1015                 return newIndirectProxy(ident, facet, _id);
1016             }
1017             else
1018             {
1019                 return newIndirectProxy(ident, facet, _replicaGroupId);
1020             }
1021         }
1022 
newDirectProxy(Identity ident, string facet)1023         private ObjectPrx newDirectProxy(Identity ident, string facet)
1024         {
1025             //
1026             // Create a reference and return a proxy for this reference.
1027             //
1028             Reference reference = _instance.referenceFactory().create(ident, facet, _reference, _publishedEndpoints);
1029             return _instance.proxyFactory().referenceToProxy(reference);
1030         }
1031 
newIndirectProxy(Identity ident, string facet, string id)1032         private ObjectPrx newIndirectProxy(Identity ident, string facet, string id)
1033         {
1034             //
1035             // Create a reference with the adapter id and return a
1036             // proxy for the reference.
1037             //
1038             Reference reference = _instance.referenceFactory().create(ident, facet, _reference, id);
1039             return _instance.proxyFactory().referenceToProxy(reference);
1040         }
1041 
checkForDeactivation()1042         private void checkForDeactivation()
1043         {
1044             if(_state >= StateDeactivating)
1045             {
1046                 ObjectAdapterDeactivatedException ex = new ObjectAdapterDeactivatedException();
1047                 ex.name = getName();
1048                 throw ex;
1049             }
1050         }
1051 
checkIdentity(Identity ident)1052         private static void checkIdentity(Identity ident)
1053         {
1054             if(ident.name == null || ident.name.Length == 0)
1055             {
1056                 throw new IllegalIdentityException(ident);
1057             }
1058             if(ident.category == null)
1059             {
1060                 ident.category = "";
1061             }
1062         }
1063 
checkServant(Object servant)1064         private static void checkServant(Object servant)
1065         {
1066             if(servant == null)
1067             {
1068                 throw new IllegalServantException("cannot add null servant to Object Adapter");
1069             }
1070         }
1071 
parseEndpoints(string endpts, bool oaEndpoints)1072         private List<EndpointI> parseEndpoints(string endpts, bool oaEndpoints)
1073         {
1074             int beg;
1075             int end = 0;
1076 
1077             string delim = " \t\n\r";
1078 
1079             List<EndpointI> endpoints = new List<EndpointI>();
1080             while(end < endpts.Length)
1081             {
1082                 beg = IceUtilInternal.StringUtil.findFirstNotOf(endpts, delim, end);
1083                 if(beg == -1)
1084                 {
1085                     if(endpoints.Count != 0)
1086                     {
1087                         throw new EndpointParseException("invalid empty object adapter endpoint");
1088                     }
1089                     break;
1090                 }
1091 
1092                 end = beg;
1093                 while(true)
1094                 {
1095                     end = endpts.IndexOf(':', end);
1096                     if(end == -1)
1097                     {
1098                         end = endpts.Length;
1099                         break;
1100                     }
1101                     else
1102                     {
1103                         bool quoted = false;
1104                         int quote = beg;
1105                         while(true)
1106                         {
1107                             quote = endpts.IndexOf('\"', quote);
1108                             if(quote == -1 || end < quote)
1109                             {
1110                                 break;
1111                             }
1112                             else
1113                             {
1114                                 quote = endpts.IndexOf('\"', ++quote);
1115                                 if(quote == -1)
1116                                 {
1117                                     break;
1118                                 }
1119                                 else if(end < quote)
1120                                 {
1121                                     quoted = true;
1122                                     break;
1123                                 }
1124                                 ++quote;
1125                             }
1126                         }
1127                         if(!quoted)
1128                         {
1129                             break;
1130                         }
1131                         ++end;
1132                     }
1133                 }
1134 
1135                 if(end == beg)
1136                 {
1137                     throw new EndpointParseException("invalid empty object adapter endpoint");
1138                 }
1139 
1140                 string s = endpts.Substring(beg, (end) - (beg));
1141                 EndpointI endp = _instance.endpointFactoryManager().create(s, oaEndpoints);
1142                 if(endp == null)
1143                 {
1144                     throw new EndpointParseException("invalid object adapter endpoint `" + s + "'");
1145                 }
1146                 endpoints.Add(endp);
1147 
1148                 ++end;
1149             }
1150 
1151             return endpoints;
1152         }
1153 
computePublishedEndpoints()1154         private EndpointI[] computePublishedEndpoints()
1155         {
1156             List<EndpointI> endpoints;
1157             if(_routerInfo != null)
1158             {
1159                 //
1160                 // Get the router's server proxy endpoints and use them as the published endpoints.
1161                 //
1162                 endpoints = new List<EndpointI>();
1163                 foreach(EndpointI endpt in  _routerInfo.getServerEndpoints())
1164                 {
1165                     if(!endpoints.Contains(endpt))
1166                     {
1167                         endpoints.Add(endpt);
1168                     }
1169                 }
1170             }
1171             else
1172             {
1173                 //
1174                 // Parse published endpoints. If set, these are used in proxies
1175                 // instead of the connection factory endpoints.
1176                 //
1177                 string endpts = _instance.initializationData().properties.getProperty(_name + ".PublishedEndpoints");
1178                 endpoints = parseEndpoints(endpts, false);
1179                 if(endpoints.Count == 0)
1180                 {
1181                     //
1182                     // If the PublishedEndpoints property isn't set, we compute the published enpdoints
1183                     // from the OA endpoints, expanding any endpoints that may be listening on INADDR_ANY
1184                     // to include actual addresses in the published endpoints.
1185                     //
1186                     foreach(IncomingConnectionFactory factory in _incomingConnectionFactories)
1187                     {
1188                         foreach(EndpointI endpt in factory.endpoint().expandIfWildcard())
1189                         {
1190                             //
1191                             // Check for duplicate endpoints, this might occur if an endpoint with a DNS name
1192                             // expands to multiple addresses. In this case, multiple incoming connection
1193                             // factories can point to the same published endpoint.
1194                             //
1195                             if(!endpoints.Contains(endpt))
1196                             {
1197                                 endpoints.Add(endpt);
1198                             }
1199                         }
1200                     }
1201                 }
1202             }
1203 
1204             if(_instance.traceLevels().network >= 1 && endpoints.Count > 0)
1205             {
1206                  StringBuilder s = new StringBuilder("published endpoints for object adapter `");
1207                  s.Append(_name);
1208                  s.Append("':\n");
1209                  bool first = true;
1210                  foreach(EndpointI endpoint in endpoints)
1211                  {
1212                      if(!first)
1213                      {
1214                          s.Append(":");
1215                      }
1216                      s.Append(endpoint.ToString());
1217                      first = false;
1218                  }
1219                  _instance.initializationData().logger.trace(_instance.traceLevels().networkCat, s.ToString());
1220              }
1221 
1222              return endpoints.ToArray();
1223         }
1224 
updateLocatorRegistry(LocatorInfo locatorInfo, ObjectPrx proxy)1225         private void updateLocatorRegistry(LocatorInfo locatorInfo, ObjectPrx proxy)
1226         {
1227             if(_id.Length == 0 || locatorInfo == null)
1228             {
1229                 return; // Nothing to update.
1230             }
1231 
1232             //
1233             // Call on the locator registry outside the synchronization to
1234             // blocking other threads that need to lock this OA.
1235             //
1236             LocatorRegistryPrx locatorRegistry = locatorInfo.getLocatorRegistry();
1237             if(locatorRegistry == null)
1238             {
1239                 return;
1240             }
1241 
1242             try
1243             {
1244                 if(_replicaGroupId.Length == 0)
1245                 {
1246                     locatorRegistry.setAdapterDirectProxy(_id, proxy);
1247                 }
1248                 else
1249                 {
1250                     locatorRegistry.setReplicatedAdapterDirectProxy(_id, _replicaGroupId, proxy);
1251                 }
1252             }
1253             catch(AdapterNotFoundException)
1254             {
1255                 if(_instance.traceLevels().location >= 1)
1256                 {
1257                     StringBuilder s = new StringBuilder();
1258                     s.Append("couldn't update object adapter `" + _id + "' endpoints with the locator registry:\n");
1259                     s.Append("the object adapter is not known to the locator registry");
1260                     _instance.initializationData().logger.trace(_instance.traceLevels().locationCat, s.ToString());
1261                 }
1262 
1263                 NotRegisteredException ex1 = new NotRegisteredException();
1264                 ex1.kindOfObject = "object adapter";
1265                 ex1.id = _id;
1266                 throw ex1;
1267             }
1268             catch(InvalidReplicaGroupIdException)
1269             {
1270                 if(_instance.traceLevels().location >= 1)
1271                 {
1272                     StringBuilder s = new StringBuilder();
1273                     s.Append("couldn't update object adapter `" + _id + "' endpoints with the locator registry:\n");
1274                     s.Append("the replica group `" + _replicaGroupId + "' is not known to the locator registry");
1275                     _instance.initializationData().logger.trace(_instance.traceLevels().locationCat, s.ToString());
1276                 }
1277 
1278                 NotRegisteredException ex1 = new NotRegisteredException();
1279                 ex1.kindOfObject = "replica group";
1280                 ex1.id = _replicaGroupId;
1281                 throw ex1;
1282             }
1283             catch(AdapterAlreadyActiveException)
1284             {
1285                 if(_instance.traceLevels().location >= 1)
1286                 {
1287                     StringBuilder s = new StringBuilder();
1288                     s.Append("couldn't update object adapter `" + _id + "' endpoints with the locator registry:\n");
1289                     s.Append("the object adapter endpoints are already set");
1290                     _instance.initializationData().logger.trace(_instance.traceLevels().locationCat, s.ToString());
1291                 }
1292 
1293                 ObjectAdapterIdInUseException ex1 = new ObjectAdapterIdInUseException();
1294                 ex1.id = _id;
1295                 throw;
1296             }
1297             catch(ObjectAdapterDeactivatedException)
1298             {
1299                 // Expected if collocated call and OA is deactivated, ignore.
1300             }
1301             catch(CommunicatorDestroyedException)
1302             {
1303                 // Ignore
1304             }
1305             catch(LocalException e)
1306             {
1307                 if(_instance.traceLevels().location >= 1)
1308                 {
1309                     StringBuilder s = new StringBuilder();
1310                     s.Append("couldn't update object adapter `" + _id + "' endpoints with the locator registry:\n");
1311                     s.Append(e.ToString());
1312                     _instance.initializationData().logger.trace(_instance.traceLevels().locationCat, s.ToString());
1313                 }
1314                 throw; // TODO: Shall we raise a special exception instead of a non obvious local exception?
1315             }
1316 
1317             if(_instance.traceLevels().location >= 1)
1318             {
1319                 StringBuilder s = new StringBuilder();
1320                 s.Append("updated object adapter `" + _id + "' endpoints with the locator registry\n");
1321                 s.Append("endpoints = ");
1322                 if(proxy != null)
1323                 {
1324                     Endpoint[] endpoints = proxy.ice_getEndpoints();
1325                     for(int i = 0; i < endpoints.Length; i++)
1326                     {
1327                         s.Append(endpoints[i].ToString());
1328                         if(i + 1 < endpoints.Length)
1329                         {
1330                             s.Append(":");
1331                         }
1332                     }
1333                 }
1334                 _instance.initializationData().logger.trace(_instance.traceLevels().locationCat, s.ToString());
1335             }
1336         }
1337 
1338         static private readonly string[] _suffixes =
1339         {
1340             "ACM",
1341             "ACM.Timeout",
1342             "ACM.Heartbeat",
1343             "ACM.Close",
1344             "AdapterId",
1345             "Endpoints",
1346             "Locator",
1347             "Locator.EncodingVersion",
1348             "Locator.EndpointSelection",
1349             "Locator.ConnectionCached",
1350             "Locator.PreferSecure",
1351             "Locator.CollocationOptimized",
1352             "Locator.Router",
1353             "MessageSizeMax",
1354             "PublishedEndpoints",
1355             "ReplicaGroupId",
1356             "Router",
1357             "Router.EncodingVersion",
1358             "Router.EndpointSelection",
1359             "Router.ConnectionCached",
1360             "Router.PreferSecure",
1361             "Router.CollocationOptimized",
1362             "Router.Locator",
1363             "Router.Locator.EndpointSelection",
1364             "Router.Locator.ConnectionCached",
1365             "Router.Locator.PreferSecure",
1366             "Router.Locator.CollocationOptimized",
1367             "Router.Locator.LocatorCacheTimeout",
1368             "Router.Locator.InvocationTimeout",
1369             "Router.LocatorCacheTimeout",
1370             "Router.InvocationTimeout",
1371             "ProxyOptions",
1372             "ThreadPool.Size",
1373             "ThreadPool.SizeMax",
1374             "ThreadPool.SizeWarn",
1375             "ThreadPool.StackSize",
1376             "ThreadPool.Serialize"
1377         };
1378 
filterProperties(List<string> unknownProps)1379         private bool filterProperties(List<string> unknownProps)
1380         {
1381             //
1382             // Do not create unknown properties list if Ice prefix, ie Ice, Glacier2, etc
1383             //
1384             bool addUnknown = true;
1385             string prefix = _name + ".";
1386             for(int i = 0; PropertyNames.clPropNames[i] != null; ++i)
1387             {
1388                 if(prefix.StartsWith(PropertyNames.clPropNames[i] + ".", StringComparison.Ordinal))
1389                 {
1390                     addUnknown = false;
1391                     break;
1392                 }
1393             }
1394 
1395             bool noProps = true;
1396             Dictionary<string, string> props =
1397                 _instance.initializationData().properties.getPropertiesForPrefix(prefix);
1398             foreach(string prop in props.Keys)
1399             {
1400                 bool valid = false;
1401                 for(int i = 0; i < _suffixes.Length; ++i)
1402                 {
1403                     if(prop.Equals(prefix + _suffixes[i]))
1404                     {
1405                         noProps = false;
1406                         valid = true;
1407                         break;
1408                     }
1409                 }
1410 
1411                 if(!valid && addUnknown)
1412                 {
1413                     unknownProps.Add(prop);
1414                 }
1415             }
1416 
1417             return noProps;
1418         }
1419 
1420         private const int StateUninitialized = 0; // Just constructed.
1421         private const int StateHeld = 1;
1422         private const int StateActivating = 2;
1423         private const int StateActive = 3;
1424         private const int StateDeactivating = 4;
1425         private const int StateDeactivated = 5;
1426         private const int StateDestroying  = 6;
1427         private const int StateDestroyed  = 7;
1428 
1429         private int _state = StateUninitialized;
1430         private Instance _instance;
1431         private Communicator _communicator;
1432         private ObjectAdapterFactory _objectAdapterFactory;
1433         private ThreadPool _threadPool;
1434         private ACMConfig _acm;
1435         private ServantManager _servantManager;
1436         private readonly string _name;
1437         private readonly string _id;
1438         private readonly string _replicaGroupId;
1439         private Reference _reference;
1440         private List<IncomingConnectionFactory> _incomingConnectionFactories;
1441         private RouterInfo _routerInfo;
1442         private EndpointI[] _publishedEndpoints;
1443         private LocatorInfo _locatorInfo;
1444         private int _directCount;  // The number of direct proxies dispatching on this object adapter.
1445         private bool _noConfig;
1446         private int _messageSizeMax;
1447     }
1448 }
1449