1 // -*- Mode: C++; -*- 2 // Package : omniORB2 3 // giopStrand.h Created on: 05/01/2001 4 // Author : Sai Lai Lo (sll) 5 // 6 // Copyright (C) 2002-2012 Apasphere Ltd 7 // Copyright (C) 2001 AT&T Laboratories 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 // *** PROPRIETARY INTERFACE *** 27 // 28 29 #ifndef __GIOPSTRAND_H__ 30 #define __GIOPSTRAND_H__ 31 32 #include <omniORB4/omniTransport.h> 33 #include "giopStrandFlags.h" 34 35 #ifdef _core_attr 36 # error "A local CPP macro _core_attr has already been defined." 37 #endif 38 39 #if defined(_OMNIORB_LIBRARY) 40 # define _core_attr 41 #else 42 # define _core_attr _OMNIORB_NTDLL_IMPORT 43 #endif 44 45 46 OMNI_NAMESPACE_BEGIN(omni) 47 48 class giopStream; 49 class giopStreamImpl; 50 class giopWorker; 51 class giopServer; 52 class giopCompressor; 53 class GIOP_S; 54 struct giopStream_Buffer; 55 56 57 //////////////////////////////////////////////////////////////////////// 58 //////////////////////////////////////////////////////////////////////// 59 class giopStreamList { 60 public: 61 giopStreamList* next; 62 giopStreamList* prev; 63 giopStreamList()64 inline giopStreamList() { 65 next = this; 66 prev = this; 67 } 68 insert(giopStreamList & head)69 inline void insert(giopStreamList& head) { 70 next = head.prev->next; 71 head.prev->next = this; 72 prev = head.prev; 73 head.prev = this; 74 } 75 remove()76 inline void remove() { 77 prev->next = next; 78 next->prev = prev; 79 next = prev = this; 80 } 81 is_empty(giopStreamList & head)82 static inline CORBA::Boolean is_empty(giopStreamList& head) { 83 return (head.next == &head); 84 } 85 86 private: 87 giopStreamList(const giopStreamList&); 88 giopStreamList& operator=(const giopStreamList&); 89 }; 90 91 //////////////////////////////////////////////////////////////////////// 92 //////////////////////////////////////////////////////////////////////// 93 class giopStrand : public Strand { 94 public: 95 96 giopStrand(const giopAddress*); 97 // Ctor for an active strand. I.e. those that are used to connect to 98 // a remote address space. 99 // When a connection is establshed, the reference count goes to 1. 100 // 101 // No thread safety precondition 102 103 104 giopStrand(giopConnection*,giopServer*); 105 // Ctor for a passive strand. I.e. those that are created because a 106 // client has connected to this address space. 107 // Increment the reference count on the connection. 108 // 109 // No thread safety precondition 110 111 112 CORBA::Boolean safeDelete(CORBA::Boolean forced = 0); 113 // This should be the *ONLY* method to call to delete a strand. 114 // Return TRUE if the strand can be considered deleted. 115 // 116 // The function checks if this connection is satisfied before it returns 117 // true: 118 // 119 // giopStreamList::is_empty(clients) && 120 // giopStreamList::is_empty(servers) && 121 // giopStream::noLockWaiting(this) 122 // 123 // If the function returns true, the above condition becomes an invariant 124 // and should not be violated until the dtor of the strand is called. 125 // 126 // The <forced> flag, if set explicitly to 1, causes the function to 127 // skip checking for the above condition. Instead it just go ahead as if 128 // the condition is met. This flag is used for internal implementation 129 // and should not be used by any client of this class. 130 // 131 // Internally, the strand may stays on a bit longer until the connection's 132 // reference count goes to 0 as well. 133 // 134 // Thread Safety preconditions: 135 // Caller must hold omniTransportLock unless forced == 1. 136 137 private: 138 CORBA::Boolean pd_safelyDeleted; 139 140 public: 141 142 CORBA::Boolean deletePending(); 143 // Return true, if safeDelete() has been called and it returns true. 144 // 145 // If this method returns true, the following invariant is always true 146 // until the strand is deleted: 147 // 148 // giopStreamList::is_empty(clients) && 149 // giopStreamList::is_empty(servers) && 150 // giopStream::noLockWaiting(this) 151 // 152 // The caller must not do anything that would cause the strand to violate 153 // this invariant. For example, attempt or wait to acquire a lock on the 154 // strand, or to queue any GIOP_S or GIOP_C object to the strand. 155 // 156 // 157 // Thread Safety preconditions: 158 // Caller must hold omniTransportLock. 159 160 161 GIOP_S* acquireServer(giopWorker*); 162 // Acquire a GIOP_S from the strand. Normally this is only done on 163 // passive strands. However, it can also be used for active strands when 164 // they become birectional, i.e. BiDir == 1. 165 // 166 // Return 0 if a GIOP_S cannot be acquired. 167 // 168 // Thread Safety preconditions: 169 // Caller must not hold omniTransportLock, it is used internally for 170 // synchronisation. 171 172 void releaseServer(IOP_S*); 173 // Release the GIOP_S to the strand. The GIOP_S must have been acquired 174 // previously through acquireServer from this strand. Passing in a GIOP_S 175 // from a different strand would result in undefined behaviour. 176 // 177 // Thread Safety preconditions: 178 // Caller must not hold omniTransportLock, it is used internally for 179 // synchronisation. 180 181 182 enum State { ACTIVE, // The strand is in active use 183 184 DYING, // Something terminally wrong has happened to the 185 // strand, it should be removed at the earliest 186 // convenient time. 187 188 TIMEDOUT // This strand can still be used when required but 189 // it can also be removed if resources are scarce. 190 }; 191 state()192 State state() const { return pd_state; } 193 // No thread safety precondition, use with extreme care 194 state(State s)195 void state(State s) { pd_state = s; } 196 // No thread safety precondition, use with extreme care 197 198 199 ///////////////////////////////////////////////////////////////////////// 200 CORBA::Boolean startIdleCounter(); 201 // returns 1 if the idle counter has been successfully started. 202 // returns 0 if the idle counter is already active or has already expired. 203 // 204 // Thread Safety preconditions: 205 // Caller must hold omniTransportLock. 206 207 CORBA::Boolean stopIdleCounter(); 208 // returns 1 if the idle counter has been successfully stopped. 209 // returns 0 if the idle counter has already expired and cannot be reset. 210 // In the latter case, the caller should assume that the strand is about 211 // to be shutdown and hence should cleanup its usage accordingly. 212 // 213 // Thread Safety preconditions: 214 // Caller must hold omniTransportLock. 215 216 217 //////////////////////////////////////////////////////////////////////// 218 // When idlebeats go to 0, the strand has been idle for a sufficently 219 // long time and should be deleted. 220 // This variable SHOULD NOT be manipulated outside the implementation of 221 // giopStrand. 222 CORBA::Long idlebeats; 223 224 225 giopStreamList servers; 226 giopStreamList clients; 227 // a strand may have more than one giopStream instance associated with 228 // it. Mostly this is because from GIOP 1.2 onwards, requests can be 229 // interleaved on associated connection. Each of these request is 230 // represented by a giopStream instance. They are linked together by 231 // servers and clients. 232 // servers - all the GIOP_S that is serving calls for this strand 233 // clients - all the GIOP_C that is doing invocation using this strand 234 // 235 // Except when a strand is used to support bidirectional GIOP, only one of 236 // the list will be populated (because plain GIOP is asymetric and one 237 // end is either a client or a server but not both). With bidirectional GIOP, 238 // both lists may be populated. 239 isClient()240 inline CORBA::Boolean isClient() { return (address != 0); } 241 // Return TRUE if this is an active strand on the client side. Unless 242 // biDir is TRUE, only those messages expected by a GIOP client can be 243 // received from this connection. 244 isBiDir()245 inline CORBA::Boolean isBiDir() { return (flags & GIOPSTRAND_BIDIR) ? 1 : 0; } 246 // Return TRUE if this is a bidirectional strand. 247 248 const giopAddress* address; 249 // address is provided as ctor arg if this is a active strand, otherwise 250 // it is 0. 251 252 giopConnection* connection; 253 // connection is provided as ctor arg if this is a passive strand 254 // otherwise it is obtained by address->connect(). 255 256 giopServer* server; 257 // server is provided as ctor arg if this is a passive strand 258 // otherwise it is 0. 259 260 CORBA::ULong flags; 261 // Flags for use by interceptors. See giopStrandFlags.h for 262 // allocated flags values. 263 // Initialised to 0 in the constructor. 264 265 CORBA::Boolean gatekeeper_checked; 266 // only applies to passive strand. TRUE(1) means that the serverTransportRule 267 // has been checked. This flag is set by giopWorker and is 268 // not manipulated by the strand class. 269 270 CORBA::Boolean first_use; 271 // only applies to active strand. TRUE(1) means this connection has 272 // not been used for any purpose before. 273 // This flag is set to 1 by ctor and reset to 0 by GIOP_C. 274 275 CORBA::Boolean first_call; 276 // only applies to active strand. TRUE(1) means this connection has 277 // not yet been used to start a normal invocation. It may have been 278 // used for other purposes, e.g. a locate request. 279 // This flag is set to 1 by ctor and reset to 0 by GIOP_C. 280 281 CORBA::Boolean orderly_closed; 282 // only applies to active strand. TRUE(1) means a GIOP CloseConnection 283 // was received and cause the strand state to change to DYING. 284 // This flag is set to 0 by ctor and set to 1 by the giopImpl?? classes. 285 286 287 CORBA::Boolean biDir_initiated; 288 // only applies to active strand. TRUE(1) means biDir service context 289 // has been sent for this connection. 290 // This flag is initialised to 0 by ctor and set to 1 by 291 // setBiDirServiceContext. 292 293 CORBA::Boolean biDir_has_callbacks; 294 // only applies to active bidirectional strand. TRUE(1) means call back 295 // objects have been sent through this connection. In other words, the 296 // connection may receive invocations on these objects from the other 297 // end. 298 // This flag is initialised to 0 by ctor and set to 1 by 299 // omniObjRef::_marshal. 300 301 302 //////////////////////////////////////////////////////////////////////// 303 //////////////////////////////////////////////////////////////////////// 304 // The following are data structures used by the giopStream instances 305 // associated with this strand AND SHOULD NOT BE manipulated by the Strand 306 // class!!! 307 308 CORBA::Boolean tcs_selected; 309 omniCodeSet::TCS_C* tcs_c; 310 omniCodeSet::TCS_W* tcs_w; 311 GIOP::Version version; 312 giopStreamImpl* giopImpl; 313 // The transmission codesets for char, wchar, string and wstring are 314 // selected by the client based on the codeset info in the IOR. The 315 // client informs the server of its selection using a codeset service 316 // context. This is done only once per lifetime of a connection (strand). 317 // If <tcs_selected> == 1, 318 // <tcs_c>, <tcs_w> and <version> records the chosen code set convertors 319 // and the GIOP version for which the convertors apply. 320 321 giopCompressor* compressor; 322 // Compressor used for ZIOP. 323 324 // Condition variables and counters to implement giopStream locking 325 // functions. 326 omni_tracedcondition rdcond; 327 int rd_nwaiting; 328 int rd_n_justwaiting; 329 omni_tracedcondition wrcond; 330 int wr_nwaiting; 331 332 333 CORBA::ULong newSeqNumber(); 334 // Return a number suitable for use as the GIOP request id. 335 // 336 // Thread Safety preconditions: 337 // Caller must hold omniTransportLock. 338 339 private: 340 CORBA::ULong seqNumber; 341 // monotonically increasing number to be used as the GIOP request id. 342 343 344 public: 345 giopStream_Buffer* head; 346 giopStream_Buffer* spare; 347 348 public: 349 static _core_attr StrandList active; 350 static _core_attr StrandList active_timedout; 351 static _core_attr StrandList passive; 352 // Throughout the lifetime of a strand, it is a member of one and only one 353 // of the lists: 354 // active - the ORB uses this connection in the role of a client 355 // it is 'active' in the sense that the connection was 356 // initiated by this ORB 357 // active_timedout - the connection was previously active and has been 358 // idled for some time. It will be deleted soon. 359 // passive - the ORB uses this connection in the role of a server 360 // it is 'passive' because the connection was initiated 361 // by the remote party. 362 // 363 364 365 static _core_attr CORBA::ULong idleOutgoingBeats; 366 // Number to instantiate idlebeats when the active strand becomes idle. 367 368 static _core_attr CORBA::ULong idleIncomingBeats; 369 // idleIncomingBeats * scanPeriod == no. of sec. a passive strand should 370 // be allowed to stay idle. 371 372 public: 373 void deleteStrandAndConnection(CORBA::Boolean forced=0); 374 // Decrement connection's reference count. If it goes to 0, delete 375 // this strand as well. This call ensures that both the strand and 376 // connection die at the same time. 377 // 378 // Thread Safety preconditions: 379 // Caller must hold omniTransportLock unless forced == 1. 380 381 #ifdef __GNUG__ 382 friend class keep_gcc_happy; 383 #endif 384 385 private: 386 virtual ~giopStrand(); 387 388 State pd_state; 389 390 giopStrand(const giopStrand&); 391 giopStrand& operator=(const giopStrand&); 392 393 }; 394 395 OMNI_NAMESPACE_END(omni) 396 397 #undef _core_attr 398 399 #endif // __GIOPSTRAND_H__ 400