1 // -*- Mode: C++; -*-
2 //                            Package   : omniORB2
3 // objectAdapter.h            Created on: 5/3/99
4 //                            Author    : David Riddoch (djr)
5 //
6 //    Copyright (C) 2002-2013 Apasphere Ltd
7 //    Copyright (C) 1996,1999 AT&T Research Cambridge
8 //
9 //    This file is part of the omniORB library.
10 //
11 //    The omniORB library is free software; you can redistribute it and/or
12 //    modify it under the terms of the GNU Lesser General Public
13 //    License as published by the Free Software Foundation; either
14 //    version 2.1 of the License, or (at your option) any later version.
15 //
16 //    This library is distributed in the hope that it will be useful,
17 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
18 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19 //    Lesser General Public License for more details.
20 //
21 //    You should have received a copy of the GNU Lesser General Public
22 //    License along with this library. If not, see http://www.gnu.org/licenses/
23 //
24 //
25 // Description:
26 //
27 
28 #ifndef __OMNI_OBJECTADAPTER_H__
29 #define __OMNI_OBJECTADAPTER_H__
30 
31 #include <omniORB4/omniutilities.h>
32 #include <omniORB4/omniServer.h>
33 
34 #ifndef OMNIORB_USEHOSTNAME_VAR
35 #define OMNIORB_USEHOSTNAME_VAR "OMNIORB_USEHOSTNAME"
36 #endif
37 
38 #ifdef _core_attr
39 # error "A local CPP macro _core_attr has already been defined."
40 #endif
41 
42 #if defined(_OMNIORB_LIBRARY)
43 #     define _core_attr
44 #else
45 #     define _core_attr _OMNIORB_NTDLL_IMPORT
46 #endif
47 
48 class omniCallDescriptor;
49 class omniCallHandle;
50 class omniLocalIdentity;
51 
OMNI_NAMESPACE_BEGIN(omni)52 OMNI_NAMESPACE_BEGIN(omni)
53 
54 class Rope;
55 
56 class omniObjAdapter {
57 public:
58   virtual ~omniObjAdapter();
59 
60   static omniObjAdapter* getAdapter(const _CORBA_Octet* key, int keysize);
61   // Partially decode the key and locate the required object adapter,
62   // instantiating it if necassary and possible.  If the required adapter
63   // does not exist, returns 0.
64   //  Must be called without any ORB locks held.
65 
66   static _CORBA_Boolean isInitialised();
67   static _CORBA_Boolean isDeactivating();
68 
69   static void initialise();
70   // Initialises incoming rope factories.  May be called multiple
71   // times - subsequent calls are ignored (unless shutdown() is
72   // called).
73   //  This function is thread safe.
74   //  May throw exceptions if incoming rope factories fail to
75   // initialise.
76 
77   static void shutdown();
78   // Destroys incoming rope factories.  Stops the incoming scavenger.
79   // All object adapters should have already been deactivated before
80   // this is called.  However, does nothing if we have not already
81   // been initialised.
82   //  This function is thread safe.
83 
84   static _CORBA_Boolean endpointInList(const char* ep,
85 				       const orbServer::EndpointList& eps);
86   // Returns true if the endpoint is in the list.
87 
88   void adapterActive();
89   void adapterInactive();
90   // These two are used to ensure that connections are only accepted
91   // once an adapter is interested, and will not be accepted as soon
92   // as the last adapter has finished being interested.
93   //  These methods may throw exceptions if any of the rope factories
94   // has problems.
95 
96   void waitForActiveRequestsToComplete(int locked);
97   //  <locked> =>> hold <omni::internalLock>.
98 
99   void waitForAllRequestsToComplete(int locked);
100   //  <locked> =>> hold <omni::internalLock>.
101 
102   virtual void incrRefCount() = 0;
103   virtual void decrRefCount() = 0;
104   // Locking rules are object adapter specific.
105 
106   virtual void dispatch(omniCallHandle&, omniLocalIdentity*) = 0;
107   // Dispatch request to given object.
108 
109   virtual void dispatch(omniCallHandle&,
110 			const _CORBA_Octet* key, int keysize) = 0;
111   // Dispatch request to object with given key (which is not
112   // in the active object map).
113 
114   virtual void dispatch(omniCallDescriptor&, omniLocalIdentity*) = 0;
115   // Dispatch a local request.
116 
117   virtual int objectExists(const _CORBA_Octet* key, int keysize) = 0;
118   // This is only called for objects which are not in the active
119   // object map.  Should return true if the adapter is able to
120   // activate such an object on demand, otherwise it returns false.
121   //  Alternatively it may throw an omniORB::LOCATION_FORWARD
122   // exception, giving an alternative location for the object.
123 
124   inline void enterAdapter() {
125     ASSERT_OMNI_TRACEDMUTEX_HELD(*omni::internalLock, 1);
126     OMNIORB_ASSERT(pd_nReqInThis >= 0);
127     pd_nReqInThis++;
128   }
129   // Adapter calls this when a request enters the adapter.
130 
131   inline void startRequest() {
132     ASSERT_OMNI_TRACEDMUTEX_HELD(*omni::internalLock, 1);
133     OMNIORB_ASSERT(pd_nReqActive >= 0);
134     pd_nReqActive++;
135   }
136   // Adapter calls this when it is committed to making an
137   // upcall into the implementation, or is about to exit
138   // from the adapter (either normally or by throwing
139   // an exception).
140 
141   inline void leaveAdapter() {
142     ASSERT_OMNI_TRACEDMUTEX_HELD(*omni::internalLock, 1);
143     OMNIORB_ASSERT(pd_nReqInThis > 0);  OMNIORB_ASSERT(pd_nReqActive > 0);
144     --pd_nReqInThis;
145     --pd_nReqActive;
146     if( !pd_nReqActive && pd_signalOnZeroInvocations )
147       pd_signal->broadcast();
148   }
149   // This is called by the localIdentity when the request
150   // leaves the adapter.
151 
152   inline void exitAdapter(int loentry=0, int loexit=0) {
153     if( !loentry )  omni::internalLock->lock();
154     OMNIORB_ASSERT(pd_nReqInThis > 0);
155     --pd_nReqInThis;
156     int do_signal = !pd_nReqInThis && pd_signalOnZeroInvocations;
157     if( !loexit )  omni::internalLock->unlock();
158     if( do_signal )  pd_signal->broadcast();
159   }
160 
161   inline void detached_object() {
162     sd_detachedObjectLock.lock();
163     pd_nDetachedObjects++;
164     sd_detachedObjectLock.unlock();
165   }
166 
167   void met_detached_object();
168   // Decrements <pd_nDetachedObjects>.  Another thread can
169   // rendezvous with this going to zero using
170   // wait_for_detached_objects() below.
171   //  Must not hold <omni::internalLock>.
172 
173   void wait_for_detached_objects();
174   // Waits until all detached objects have been 'met'.
175   //  Must not hold <omni::internalLock>.
176 
177   virtual void lastInvocationHasCompleted(omniLocalIdentity* id) = 0;
178   // Called when an object which has been deactivated is idle.
179   // This may happen when the object is deactivated (in which
180   // case the object adapter calls this), or when any outstanding
181   // method invocations complete (in which case the
182   // omniLocalIdentity calls this).
183   //  The caller must hold <omni::internalLock> on entry. It is
184   //  released on exit.
185 
186   virtual void* _ptrToClass(int* cptr);
187   static inline omniObjAdapter* _downcast(omniObjAdapter* a) {
188     return a ? (omniObjAdapter*)a->_ptrToClass(&_classid) : 0;
189   }
190   static _core_attr int _classid;
191 
192 
193   ////////////////////
194   // Incoming       //
195   ////////////////////
196 
197   static _CORBA_Boolean matchMyEndpoints(const char*);
198   // Returns true(1) if the argument is the address of one of my endpoints
199   // returns false(0) otherwise.
200 
201   static const orbServer::EndpointList& listMyEndpoints();
202 
203   struct Options {
OptionsOMNI_NAMESPACE_BEGIN::Options204     inline Options() : publish_all(0) {}
205     ~Options();
206 
207     struct EndpointURI {
208       _CORBA_String_var uri;
209       _CORBA_Boolean    no_publish;
210     };
211     typedef omnivector<EndpointURI*> EndpointURIList;
212     EndpointURIList   endpoints;
213     _CORBA_String_var publish;
214 
215     // Backwards-compatibility:
216     EndpointURIList   no_listen;
217     CORBA::Boolean    publish_all;
218   };
219 
220   static _core_attr Options options;
221 
222 
223 protected:
224   omniObjAdapter(int is_nil=0);
225 
226   void adapterDestroyed();
227   // Called by derived adapter classes when the adapter has been destroyed.
228 
229   int                  pd_nReqInThis;
230   // The number of requests active in this adapter.
231   //  Protected by <omni::internalLock>.
232 
233   int                  pd_nReqActive;
234   // The number of requests actually in progress in this
235   // adapter.
236   //  Protected by <omni::internalLock>.
237 
238   int                  pd_signalOnZeroInvocations;
239   // If true then we broadcast on <pd_signal> when there are
240   // no more invocations in progress.  Each party waiting for
241   // this event increments this value, and decrements it
242   // when done.
243   //  Protected by <omni::internalLock>.
244 
245   omni_tracedcondition* pd_signal;
246   // Uses <omni::internalLock> as mutex.
247   //  Used to signal changes to:
248   //     pd_nReqInThis,
249   //     pd_nReqActive,
250   //  Used in POA for changes to:
251   //     pd_rq_state
252 
253 private:
254   static omni_tracedmutex     sd_detachedObjectLock;
255   static omni_tracedcondition sd_detachedObjectSignal;
256 
257   int pd_nDetachedObjects;
258   // The number of objects which have been placed deactivated,
259   // but have not yet been etherealised.
260   //  Protected by <sd_detachedObjectLock>.
261 
262   int pd_signalOnZeroDetachedObjects;
263   // This should be incremented to indicate that someone is
264   // interested in the completion of etherealisation of all
265   // objects which have been deactivated.  If this is non zero
266   // when that event occurs, <pd_signal> will be broadcast to.
267   //  Protected by <sd_detachedObjectLock>.
268 
269   int pd_isActive;
270   // True if this adapter is interested in accepting incoming
271   // connections.
272   //  Protected by <oa_lock>.
273 };
274 
275 
276 class omniObjAdapter_var {
277 public:
278   typedef omniObjAdapter_var T_var;
279   typedef omniObjAdapter*    T_ptr;
280 
omniObjAdapter_var()281   inline omniObjAdapter_var() : pd_val(0) {}
omniObjAdapter_var(T_ptr p)282   inline omniObjAdapter_var(T_ptr p) : pd_val(p) {}
~omniObjAdapter_var()283   inline ~omniObjAdapter_var() { if( pd_val )  pd_val->decrRefCount(); }
284 
285   inline T_var& operator = (T_ptr p) {
286     OMNIORB_ASSERT(!pd_val);
287     pd_val = p;
288     return *this;
289   }
290 
291   inline T_ptr operator -> () { return pd_val; }
T_ptr()292   inline operator T_ptr () { return pd_val; }
293 
294 private:
295   omniObjAdapter_var(const T_var&);
296   T_var& operator = (const T_var&);
297 
298   T_ptr pd_val;
299 };
300 
301 OMNI_NAMESPACE_END(omni)
302 
303 #undef _core_attr
304 
305 #endif // __OMNI_OBJECTADAPTER_H__
306