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