diff options
author | Ossama Othman <ossama-othman@users.noreply.github.com> | 2001-04-10 17:54:40 +0000 |
---|---|---|
committer | Ossama Othman <ossama-othman@users.noreply.github.com> | 2001-04-10 17:54:40 +0000 |
commit | a82053be75cbe912a4598d758e54f3b6a4151016 (patch) | |
tree | 24e362138dc1a19d5450a0d3fc825d4490c45a7b | |
parent | c63e6e2c037356b62da60821d57bffee4b7bde91 (diff) | |
download | ATCD-a82053be75cbe912a4598d758e54f3b6a4151016.tar.gz |
ChangeLogTag:Tue Apr 10 10:45:26 2001 Ossama Othman <ossama@uci.edu>
-rw-r--r-- | TAO/ChangeLogs/ChangeLog-02a | 118 | ||||
-rw-r--r-- | TAO/tao/Asynch_Invocation.cpp | 35 | ||||
-rw-r--r-- | TAO/tao/Asynch_Invocation.h | 56 | ||||
-rw-r--r-- | TAO/tao/ClientRequestInfo.cpp | 2 | ||||
-rw-r--r-- | TAO/tao/ClientRequestInfo.h | 2 | ||||
-rw-r--r-- | TAO/tao/IIOP_Transport.cpp | 93 | ||||
-rw-r--r-- | TAO/tao/Invocation.cpp | 67 | ||||
-rw-r--r-- | TAO/tao/Invocation.h | 35 | ||||
-rw-r--r-- | TAO/tao/Invocation.i | 2 | ||||
-rw-r--r-- | TAO/tao/PortableInterceptor.cpp | 315 | ||||
-rw-r--r-- | TAO/tao/PortableInterceptor.h | 13 | ||||
-rw-r--r-- | TAO/tao/PortableInterceptor.i | 266 | ||||
-rw-r--r-- | TAO/tao/PortableServer/ServerRequestInfo.cpp | 37 | ||||
-rw-r--r-- | TAO/tao/PortableServer/ServerRequestInfo.h | 10 | ||||
-rw-r--r-- | TAO/tao/Sequence.i | 34 | ||||
-rw-r--r-- | TAO/tao/operation_details.h | 34 | ||||
-rw-r--r-- | TAO/tao/operation_details.i | 39 |
17 files changed, 760 insertions, 398 deletions
diff --git a/TAO/ChangeLogs/ChangeLog-02a b/TAO/ChangeLogs/ChangeLog-02a index 64320f17dd5..e17e019a787 100644 --- a/TAO/ChangeLogs/ChangeLog-02a +++ b/TAO/ChangeLogs/ChangeLog-02a @@ -1,3 +1,121 @@ +Tue Apr 10 10:45:26 2001 Ossama Othman <ossama@uci.edu> + + * tao/PortableInterceptor.i (send_request, receive_reply, + receive_other, receive_exception, + receive_request_service_contexts, receive_request, send_reply, + send_other, send_exception): + + Moved these interception points to the + `PortableInterceptor.cpp'. They were too big to be inlined, so + there was no point in leaving them in this inline source file. + + (receive_exception, send_exception): + + Fixed problem where the remaining interceptors in the flow stack + were not invoked if an exception was thrown from either of these + interception points. + + * tao/IIOP_Transport.cpp (get_listen_point): + + Use CORBA::String_var to improve exception safety, and simplify + the code. + + Improved performance of this method by comparing the numerical + forms of the IP addresses for equality rather than the + stringified IP addresses or hostnames. This saves the cost of a + strcmp(). + + Another performance improvement: don't bother creating a + temporary IIOP::ListenPoint and then copying it to the + IIOP::ListenPointList. Just use the one that was already + created in the IIOP::ListenPointList. + + Fixed busted code that casted away the const-ness of the + pointer to the INET_Addr array in the IIOP_Acceptor so that it + could be used as a temporary (modifiable!) variable. Since a + temporary INET_Addr was needed, just create one rather than + butchering what is supposed to be an immutable set of + INET_Addrs. + + (send): + + Use the peer's send_n() method instead of ACE::send_n(). This + is makes it clearer to pluggable protocol implementors that + ACE::send_n() should not always be used to when implementing + this method. For example, SSLIOP doesn't use ACE::send_n() + since the data being sent must be encrypted. + + * tao/Invocation.h: + * tao/Invocation.cpp (generate_request_id): + + New method for generating request IDs. It generates a request + ID based on the address of the TAO_GIOP_Invocation object. The + address is guaranteed to be unique within the process. This + makes it possible to generate a request ID without acquiring a + lock, which in turn allows to remove a lock from the critical + path. Neat, huh? :-) Things are slightly more complicated on + platforms with 64-bit addresses. On those platforms, we do some + bit manipulation and extract a 32-bit value from that address. + If all else fails, we fall back on the traditional request ID + generator that increments a CORBA::ULong atomically (i.e. by + acquiring a lock). [Bug 826] + + (start): + + Obtain a request ID from the new generate_request_id() method. + + * tao/operation_details.h: + + Cosmetic update. + + * tao/operation_details.i (modify_request_id): + + Do not adjust even-ness or odd-ness of the request ID by first + multiplying by two. It is not safe to do that since the request + ID may have been based on the address of the TAO_GIOP_Invocation + object (due to the above changes). In fact, it wasn't really + safe to multiply by two before the request ID optimization since + doing so may actually cause another outstanding request ID to be + re-used. Simply incrementing by one when appropriate is safer. + + * tao/Asynch_Invocation.h: + * tao/Asynch_Invocation.cpp (generate_request_id): + + Generate a request ID based on the address of the + TAO_Asynch_Reply_Dispatcher object. This is basically the same + optimization used in TAO_GIOP_Invocation. However, in the case + of AMI we need to used the TAO_Asynch_Reply_Dispatcher object + since it exists for the duration of the request, whereas the + Invocation object doesn't. + + * tao/Sequence.i (length): + + Optimized unbounded sequence growth. The internal buffer (hence + the maximum) now generally grows to twice the amount of the + previous maximum unless the desired length is larger than that + (doubled) value. The number of allocations and copies for large + numbers of small sequence length increases has been reduced + significantly by this optimization. For example, 8 sequence + length increases of 1 previously caused 8 allocations to occur + and 28 copies. The new scheme reduces those numbers to 4 + allocations and 7 copies. This change should make insertion + constant on the average (similar to an STL vector). [Bug 757] + + * tao/PortableServer/ServerRequestInfo.cpp (request_id): + + Generate a request ID based on the address of the + TAO_ServerRequest object. The request ID generated by this + method need not be the same as the GIOP request ID sent with the + request. It just needs to be unique within a given process. + This is the same trick used in the TAO_GIOP_Invocation object + described above. [Bug 826] + + * tests/BiDirectional_NestedUpcall/BiDirectional_NestedUpcall.dsw: + * tests/BiDirectional_NestedUpcall/client.dsp: + * tests/BiDirectional_NestedUpcall/server.dsp: + + Added these missing MSVC C++ project files. + Tue Apr 10 12:13:48 2001 Jeff Parsons <parsons@cs.wustl.edu> * tao/TypeCodeFactory/TAO_TypeCodeFactory_i.cpp: diff --git a/TAO/tao/Asynch_Invocation.cpp b/TAO/tao/Asynch_Invocation.cpp index eec74ba8c59..6b8644e4609 100644 --- a/TAO/tao/Asynch_Invocation.cpp +++ b/TAO/tao/Asynch_Invocation.cpp @@ -78,6 +78,41 @@ TAO_GIOP_Asynch_Invocation::start (CORBA::Environment &ACE_TRY_ENV) #if (TAO_HAS_AMI_CALLBACK == 1) || (TAO_HAS_AMI_POLLER == 1) +CORBA::ULong +TAO_GIOP_Twoway_Asynch_Invocation::generate_request_id (void) const +{ + // The request ID must be unique across all outstanding requests. + // To avoid synchronization overhead, the address of the + // TAO_Asynch_Reply_Dispatcher object is used as the request ID. + // This guarantees that the request ID is unique. + // + // For 64-bit platforms, only the lower 32 bits are used. Hopefully + // that will be enough to ensure uniqueness. + + // This is basically the same trick used in + // TAO_GIOP_Invocation::generate_request_id(). However, no right + // shifting of 64 bit addresses is performed since the + // TAO_Asynch_Reply_Dispatcher object is not large enough to allow + // that trick. + + CORBA::ULong id = 0; + + // 32 bit address + if (sizeof (this) == 4) + id = + ACE_reinterpret_cast (CORBA::ULong, this->rd_); + + // 64 bit address -- use lower 32 bits + else if (sizeof (this) == 8) + id = + ACE_reinterpret_cast (CORBA::ULong, this->rd_) & 0xFFFFFFFFu; + + else + id = this->transport_->tms ()->request_id (); // Fallback + + return id; +} + int TAO_GIOP_Twoway_Asynch_Invocation::invoke_i (CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException)) diff --git a/TAO/tao/Asynch_Invocation.h b/TAO/tao/Asynch_Invocation.h index 1ac4ebbd925..2390243cade 100644 --- a/TAO/tao/Asynch_Invocation.h +++ b/TAO/tao/Asynch_Invocation.h @@ -8,8 +8,7 @@ * * Encapsulate the logic for remote Asynchronous Invocations. * - * - * @author Carlos O'Ryan <coryan@cs.wustl.edu> + * @author Carlos O'Ryan <coryan@uci.edu> * @author Alexander Babu Arulanthu <alex@cs.wustl.edu> * @author Jeff Parsons <parsons@cs.wustl.edu> */ @@ -32,17 +31,17 @@ #include "tao/MessagingC.h" #endif /* (TAO_HAS_AMI_CALLBACK == 1) || (TAO_HAS_AMI_POLLER == 1) == 0 */ +/** + * @class TAO_GIOP_Asynch_Invocation + * + * @brief Base class for TAO_GIOP_Twoway_Asynch_Invocation and + * TAO_GIOP_DII_Deferred_Invocation. + */ class TAO_Export TAO_GIOP_Asynch_Invocation : public TAO_GIOP_Invocation { - // = TITLE - // TAO_Asynch_Invocation. - // - // = DESCRIPTION - // Base class for TAO_GIOP_Twoway_Asynch_Invocation and - // TAO_GIOP_DII_Deferred_Invocation. - // public: + /// Default constructor. This should never get called, it is here /// only to appease older versions of g++. TAO_GIOP_Asynch_Invocation (void); @@ -67,6 +66,7 @@ public: ACE_THROW_SPEC ((CORBA::SystemException)); protected: + /// Must be overridden. virtual int invoke_i (CORBA::Environment &ACE_TRY_ENV) ACE_THROW_SPEC ((CORBA::SystemException)) = 0; @@ -77,19 +77,20 @@ protected: #if (TAO_HAS_AMI_CALLBACK == 1) || (TAO_HAS_AMI_POLLER == 1) +/** + * @class TAO_GIOP_Twoway_Asynch_Invocation + * + * @brief Sends a two-way request does not expect the reply. This + * class connects (or lookups a connection from the cache) to + * the remote server, builds the CDR stream for the Request, + * send the CDR stream and returns. + */ class TAO_Export TAO_GIOP_Twoway_Asynch_Invocation : public TAO_GIOP_Asynch_Invocation { - // = TITLE - // TAO_GIOP_Twoway_Asynch_Invocation. - // - // = DESCRIPTION - // Sends a two-way request does not expect the reply. - // This class connects (or lookups a connection from the cache) to - // the remote server, builds the CDR stream for the Request, send - // the CDR stream and returns. - // + public: + /// Constructor. TAO_GIOP_Twoway_Asynch_Invocation ( TAO_Stub *stub, @@ -102,6 +103,25 @@ public: ); protected: + + /// Generate a request ID for an asynchronous invocation + /** + * The request ID must be unique across all outstanding requests. + * To avoid synchronization overhead, the address of the + * TAO_Asynch_Reply_Dispatcher object is used as the request ID. + * This guarantees that the request ID is unique. + * @par + * For 64-bit platforms, only the lower 32 bits are used. Hopefully + * that will be enough to ensure uniqueness. + * @par + * This is basically the same trick used in + * TAO_GIOP_Invocation::generate_request_id(). However, no right + * shifting of 64 bit addresses is performed since the + * TAO_Asynch_Reply_Dispatcher object is not large enough to allow + * that trick. + */ + virtual CORBA::ULong generate_request_id (void) const; + /// Implementation of the invoke() methods, handles the basic /// send/reply code and the system exceptions. virtual int invoke_i (CORBA::Environment &ACE_TRY_ENV) diff --git a/TAO/tao/ClientRequestInfo.cpp b/TAO/tao/ClientRequestInfo.cpp index bc93568befa..0ff821447e2 100644 --- a/TAO/tao/ClientRequestInfo.cpp +++ b/TAO/tao/ClientRequestInfo.cpp @@ -269,7 +269,7 @@ TAO_ClientRequestInfo::add_request_service_context ( TAO_Service_Context &service_context_list = this->invocation_->request_service_context (); - if (service_context_list.set_context (service_context,replace) == 0) + if (service_context_list.set_context (service_context, replace) == 0) { ACE_THROW (CORBA::BAD_INV_ORDER (TAO_OMG_VMCID | 11, CORBA::COMPLETED_NO)); diff --git a/TAO/tao/ClientRequestInfo.h b/TAO/tao/ClientRequestInfo.h index 3b559484d92..ef92b0c92c7 100644 --- a/TAO/tao/ClientRequestInfo.h +++ b/TAO/tao/ClientRequestInfo.h @@ -167,6 +167,7 @@ public: * an extension used internally by TAO. */ //@{ + /// Change the exception status. void exception (CORBA::Exception *exception); @@ -184,6 +185,7 @@ public: //@} protected: + /// Helper method to get the request and response service contexts. IOP::ServiceContext *get_service_context_i ( TAO_Service_Context &service_context_list, diff --git a/TAO/tao/IIOP_Transport.cpp b/TAO/tao/IIOP_Transport.cpp index 4ff0432bbd4..522f3560f50 100644 --- a/TAO/tao/IIOP_Transport.cpp +++ b/TAO/tao/IIOP_Transport.cpp @@ -1,4 +1,5 @@ // This may look like C, but it's really -*- C++ -*- +// // $Id$ #include "tao/IIOP_Transport.h" @@ -22,7 +23,9 @@ # include "tao/IIOP_Transport.i" #endif /* ! __ACE_INLINE__ */ -ACE_RCSID (tao, IIOP_Transport, "$Id$") +ACE_RCSID (TAO, + IIOP_Transport, + "$Id$") TAO_IIOP_Transport::TAO_IIOP_Transport (TAO_IIOP_Connection_Handler *handler, TAO_ORB_Core *orb_core, @@ -38,7 +41,7 @@ TAO_IIOP_Transport::TAO_IIOP_Transport (TAO_IIOP_Connection_Handler *handler, ACE_NEW (this->messaging_object_, TAO_GIOP_Message_Lite (orb_core)); } - else + else { // Use the normal GIOP object ACE_NEW (this->messaging_object_, @@ -107,7 +110,8 @@ TAO_IIOP_Transport::read_process_message (ACE_Time_Value *max_wait_time, if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("TAO (%P|%t) - %p\n"), - ACE_TEXT ("IIOP_Transport::read_message, failure in read_message ()"))); + ACE_TEXT ("IIOP_Transport::read_message, failure ") + ACE_TEXT ("in read_message ()"))); this->tms_->connection_closed (); return -1; @@ -210,7 +214,6 @@ TAO_IIOP_Transport::send_message (TAO_OutputCDR &stream, return 1; } - int TAO_IIOP_Transport::generate_request_header (TAO_Operation_Details &opdetails, TAO_Target_Specification &spec, @@ -226,7 +229,7 @@ TAO_IIOP_Transport::generate_request_header (TAO_Operation_Details &opdetails, { this->set_bidir_context_info (opdetails); - // Set the flag to 0 + // Set the flag to 0 (i.e., originating side) this->bidirectional_flag (0); } @@ -256,14 +259,14 @@ TAO_IIOP_Transport::tear_listen_point_list (TAO_InputCDR &cdr) if ((cdr >> ACE_InputCDR::to_boolean (byte_order)) == 0) return -1; - cdr.reset_byte_order (ACE_static_cast(int,byte_order)); + cdr.reset_byte_order (ACE_static_cast (int, byte_order)); IIOP::ListenPointList listen_list; if ((cdr >> listen_list) == 0) return -1; // As we have received a bidirectional information, set the flag to - // 1 + // 1 (i.e., non-originating side) this->bidirectional_flag (1); return this->connection_handler_->process_listen_point_list (listen_list); } @@ -289,29 +292,30 @@ TAO_IIOP_Transport::process_message (void) } else if (t == TAO_PLUGGABLE_MESSAGE_REQUEST) { - if (this->messaging_object_->process_request_message (this, - this->orb_core ()) == -1) + if (this->messaging_object_->process_request_message ( + this, + this->orb_core ()) == -1) return -1; } else if (t == TAO_PLUGGABLE_MESSAGE_REPLY) { TAO_Pluggable_Reply_Params params (this->orb_core ()); + if (this->messaging_object_->process_reply_message (params) == -1) { if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("TAO (%P|%t) - %p\n"), - ACE_TEXT ("IIOP_Transport::process_message, process_reply_message ()"))); + ACE_TEXT ("IIOP_Transport::process_message, ") + ACE_TEXT ("process_reply_message ()"))); this->messaging_object_->reset (); this->tms_->connection_closed (); return -1; } - - result = - this->tms_->dispatch_reply (params); + result = this->tms_->dispatch_reply (params); // @@ Somehow it seems dangerous to reset the state *after* // dispatching the request, what if another threads receives @@ -342,8 +346,6 @@ TAO_IIOP_Transport::process_message (void) // is going to take a look please contact bala@cs.wustl.edu // for details on this-- Bala - - if (result == -1) { // Something really critical happened, we will forget about @@ -391,8 +393,7 @@ TAO_IIOP_Transport::process_message (void) void TAO_IIOP_Transport::set_bidir_context_info (TAO_Operation_Details &opdetails) { - - // Get a handle on to the acceptor registry + // Get a handle to the acceptor registry TAO_Acceptor_Registry * ar = this->orb_core ()->acceptor_registry (); @@ -409,6 +410,8 @@ TAO_IIOP_Transport::set_bidir_context_info (TAO_Operation_Details &opdetails) // Check whether it is a IIOP acceptor if ((*acceptor)->tag () == TAO_TAG_IIOP_PROFILE) { + // @@ Why isn't the return value checked! + // -Ossama this->get_listen_point (listen_point_list, *acceptor); } @@ -419,7 +422,7 @@ TAO_IIOP_Transport::set_bidir_context_info (TAO_Operation_Details &opdetails) TAO_OutputCDR cdr; // Marshall the information into the stream - if ((cdr << ACE_OutputCDR::from_boolean (TAO_ENCAP_BYTE_ORDER)== 0) + if ((cdr << ACE_OutputCDR::from_boolean (TAO_ENCAP_BYTE_ORDER) == 0) || (cdr << listen_point_list) == 0) return; @@ -430,7 +433,6 @@ TAO_IIOP_Transport::set_bidir_context_info (TAO_Operation_Details &opdetails) return; } - int TAO_IIOP_Transport::get_listen_point ( IIOP::ListenPointList &listen_point_list, @@ -440,11 +442,11 @@ TAO_IIOP_Transport::get_listen_point ( ACE_dynamic_cast (TAO_IIOP_Acceptor *, acceptor ); - // Get the array of endpoints serviced by <iiop_acceptor> + // Get the array of endpoints serviced by TAO_IIOP_Acceptor const ACE_INET_Addr *endpoint_addr = iiop_acceptor->endpoints (); - // Get the count + // Get the endpoint count size_t count = iiop_acceptor->endpoint_count (); @@ -455,21 +457,21 @@ TAO_IIOP_Transport::get_listen_point ( == -1) { ACE_ERROR_RETURN ((LM_ERROR, - ACE_TEXT ("(%P|%t) Could not resolve local host") - ACE_TEXT (" address in set_bidir_context_info () \n")), + ACE_TEXT ("(%P|%t) Could not resolve local ") + ACE_TEXT ("host address in ") + ACE_TEXT ("get_listen_point()\n")), -1); } - // Note: Looks like there is no point in sending the list of // endpoints on interfaces on which this connection has not // been established. If this is wrong, please correct me. - char *local_interface = 0; + CORBA::String_var local_interface; // Get the hostname for the local address if (iiop_acceptor->hostname (this->orb_core_, local_addr, - local_interface) == -1) + local_interface.out ()) == -1) { ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("(%P|%t) Could not resolve local host") @@ -477,61 +479,50 @@ TAO_IIOP_Transport::get_listen_point ( -1); } - ACE_INET_Addr *tmp_addr = ACE_const_cast (ACE_INET_Addr *, - endpoint_addr); - for (size_t index = 0; index <= count; index++) { + ACE_INET_Addr tmp_addr; + CORBA::String_var acceptor_interface; + // Get the listen point on that acceptor if it has the same // interface on which this connection is established - char *acceptor_interface = 0; - if (iiop_acceptor->hostname (this->orb_core_, - tmp_addr[index], - acceptor_interface) == -1) + tmp_addr, + acceptor_interface.out ()) == -1) continue; - // @@ This is very bad for performance, but it is a one time - // affair - if (ACE_OS::strcmp (local_interface, - acceptor_interface) == 0) + if (local_addr.get_ip_address() + == endpoint_addr[index].get_ip_address()) { - // We have the connection and the acceptor endpoint on the - // same interface - IIOP::ListenPoint point; - point.host = CORBA::string_dup (local_interface); - point.port = endpoint_addr[index].get_port_number (); - // Get the count of the number of elements CORBA::ULong len = listen_point_list.length (); // Increase the length by 1 listen_point_list.length (len + 1); - // Add the new length to the list - listen_point_list[len] = point; + // We have the connection and the acceptor endpoint on the + // same interface + IIOP::ListenPoint &point = listen_point_list[len]; + point.host = CORBA::string_dup (local_interface.in ()); + point.port = endpoint_addr[index].get_port_number (); } - - // @@ This is bad.... - CORBA::string_free (acceptor_interface); } - CORBA::string_free (local_interface); return 1; } void TAO_IIOP_Transport::transition_handler_state_i (void) { - connection_handler_ = 0; + this->connection_handler_ = 0; } #if 0 TAO_Connection_Handler* TAO_IIOP_Transport::connection_handler (void) const { - return connection_handler_; + return this->connection_handler_; } #endif diff --git a/TAO/tao/Invocation.cpp b/TAO/tao/Invocation.cpp index 507e73b406e..a19ca539576 100644 --- a/TAO/tao/Invocation.cpp +++ b/TAO/tao/Invocation.cpp @@ -31,7 +31,9 @@ # include "Invocation.i" #endif /* ! __ACE_INLINE__ */ -ACE_RCSID(tao, Invocation, "$Id$") +ACE_RCSID (TAO, + Invocation, + "$Id$") #if defined (ACE_ENABLE_TIMEPROBES) @@ -304,9 +306,8 @@ TAO_GIOP_Invocation::start (CORBA::Environment &ACE_TRY_ENV) countdown.update (); } - // Obtain unique request id from the RMS. - this->op_details_.request_id ( - this->transport_->tms ()->request_id ()); + // Set the unique request ID associated with this request. + this->op_details_.request_id (this->generate_request_id ()); // Make sure that you have the right object key this->target_spec_.target_specifier (this->profile_->object_key ()); @@ -387,6 +388,64 @@ TAO_GIOP_Invocation::prepare_header (CORBA::Octet response_flags, } } +CORBA::ULong +TAO_GIOP_Invocation::generate_request_id (void) const +{ + // The request ID must be unique across all outstanding requests. + // To avoid synchronization overhead, the address of this Invocation + // object is used as the request ID. This guarantees that the + // request ID is unique without being forced to acquire a lock. + // + // For 64-bit platforms, we right shift 8 bits and then use the + // lower 32 bits of that shifted value. Rather than losing the + // upper 32 bits of significant digits by taking the lower 32 bits, + // we only lose the upper 24 by doing the shift. Basically, the + // resulting request ID will comprised of bits 8 through 39. This is + // made possible by the fact that this Invocation object is large + // enough to increase the likelihood that those bits (0 through 39) + // are unique. In particular, this->buffer_ is 512 bytes + // (ACE_CDR::DEFAULT_BUFSIZE) long by default; implying that + // dropping the lower 8 bits of the this Invocation object's 64 bit + // address (i.e. 256 bytes) is not a problem. + + CORBA::ULong id = 0; + + // 32 bit address + if (sizeof (this) == 4) + id = ACE_reinterpret_cast (CORBA::ULong, this); + + // 64 bit address -- bits 8 through 39 (see notes above!) + // In this case, we make sure this object is large enough to safely + // do the right shift. This is necessary since the size of the + // buffer that makes this object is configurable. + else if (sizeof (this) == 8 + && sizeof (*this) > 256 /* 2 << 8 */) + id = + (ACE_reinterpret_cast (CORBA::ULong, this) >> 8) & 0xFFFFFFFFu; + + // 64 bit address -- lower 32 bits + // + else if (sizeof (this) == 8) + id = ACE_reinterpret_cast (CORBA::ULong, this) & 0xFFFFFFFFu; + + // @@ The following request ID generator prevents the + // PortableInterceptor::ClientRequestInterceptor::send_request() + // interception point from occuring before the call to connect, + // thus preventing us from adding an optimization that itself + // prevents a connection from being unnecessarily performed. + // Thus, the ClientRequestInfo object is forced to have its own + // request ID generator in order to make it possible to implement + // the above optimization. + // + // Ideally, this request ID generator should go away, especially + // since it adds a lock to the critical path. + else // Fallback + id = this->transport_->tms ()->request_id (); + + return id; +} + + // Send request. int TAO_GIOP_Invocation::invoke (CORBA::Boolean is_roundtrip, diff --git a/TAO/tao/Invocation.h b/TAO/tao/Invocation.h index c6f26b9727e..10240976278 100644 --- a/TAO/tao/Invocation.h +++ b/TAO/tao/Invocation.h @@ -10,14 +10,12 @@ * twoways. * * THREADING NOTE: Threads should never manipulate another - * thread's invocations. In this implementation, all data - * structures used to represent invocations (and parts of them) - * are owned by the thread which created them. Multiple threads - * may make of course concurrent invocations safely, since the - * GIOP code is reentrant. + * thread's invocations. In this implementation, all data structures + * used to represent invocations (and parts of them) are owned by the + * thread which created them. Multiple threads may make of course + * concurrent invocations safely, since the GIOP code is reentrant. * - * - * @author Carlos O'Ryan <coryan@cs.wustl.edu> + * @author Carlos O'Ryan <coryan@uci.edu> * @author Alexander Babu Arulanthu <alex@cs.wustl.edu> */ //============================================================================= @@ -122,8 +120,29 @@ public: /// after receiving a reply message. TAO_Service_Context& reply_service_context (void); + /// Generate a request ID + /** + * The request ID must be unique across all outstanding requests. + * To avoid synchronization overhead, the address of this Invocation + * object is used as the request ID. This guarantees that the + * request ID is unique without being forced to acquire a lock. + * @par + * For 64-bit platforms, we right shift 8 bits and then use the + * lower 32 bits of that shifted value. Rather than losing the + * upper 32 bits of significant digits by taking the lower 32 bits, + * we only lose the upper 24 by doing the shift. Basically, the + * resulting request ID will comprised of bits 8 through 39. This is + * made possible by the fact that this Invocation object is large + * enough to increase the likelihood that those bits (0 through 39) + * are unique. In particular, this->buffer_ is 512 bytes + * (ACE_CDR::DEFAULT_BUFSIZE) long by default; implying that + * dropping the lower 8 bits of the this Invocation object's 64 bit + * address (i.e. 256 bytes) is not a problem. + */ + virtual CORBA::ULong generate_request_id (void) const; + /// Return the request id of this invocation. - CORBA::ULong request_id (void); + CORBA::ULong request_id (void) const; /// Return the name of the operation being invoked. const char *operation (void); diff --git a/TAO/tao/Invocation.i b/TAO/tao/Invocation.i index 98e1766fcfc..109904cfb81 100644 --- a/TAO/tao/Invocation.i +++ b/TAO/tao/Invocation.i @@ -15,7 +15,7 @@ TAO_GIOP_Invocation::reply_service_context (void) } ACE_INLINE CORBA::ULong -TAO_GIOP_Invocation::request_id (void) +TAO_GIOP_Invocation::request_id (void) const { return this->op_details_.request_id (); } diff --git a/TAO/tao/PortableInterceptor.cpp b/TAO/tao/PortableInterceptor.cpp index 6bc4021d9a3..6d30c7f083a 100644 --- a/TAO/tao/PortableInterceptor.cpp +++ b/TAO/tao/PortableInterceptor.cpp @@ -1,18 +1,157 @@ // $Id$: -#include "tao/PortableInterceptor.h" +#include "PortableInterceptor.h" #if TAO_HAS_INTERCEPTORS == 1 #if !defined (__ACE_INLINE__) -#include "tao/PortableInterceptor.i" +#include "PortableInterceptor.i" #endif /* defined INLINE */ +#include "ClientRequestInfo.h" + TAO_ClientRequestInterceptor_Adapter:: ~TAO_ClientRequestInterceptor_Adapter (void) { } +void +TAO_ClientRequestInterceptor_Adapter:: +send_request (TAO_ClientRequestInfo *ri, + CORBA::Environment &ACE_TRY_ENV) +{ + // This method implements one of the "starting" client side + // interception point. + for (size_t i = 0 ; i < this->len_; ++i) + { + this->interceptors_[i]->send_request (ri + TAO_ENV_ARG_PARAMETER); + ACE_CHECK; + + // The starting interception point completed successfully. Push + // the interceptor on to the flow stack. + ++this->stack_size_; + } + + ACE_UNUSED_ARG (ACE_TRY_ENV); +} + +ACE_INLINE void +TAO_ClientRequestInterceptor_Adapter:: +receive_reply (TAO_ClientRequestInfo *ri, + CORBA::Environment &ACE_TRY_ENV) +{ + // This is an "ending" interception point so we only process the + // interceptors pushed on to the flow stack. + + // Notice that the interceptors are processed in the opposite order + // they were pushed onto the stack since this is an "ending" + // interception point. + + // Unwind the stack. + size_t len = this->stack_size_; + for (size_t i = 0; i < len; ++i) + { + // Pop the interceptor off of the flow stack before it is + // invoked. This is necessary to prevent an interceptor already + // invoked in this "ending" interception point from being + // invoked in another "ending" interception point. + --this->stack_size_; + + this->interceptors_[this->stack_size_]->receive_reply ( + ri + TAO_ENV_ARG_PARAMETER); + ACE_CHECK; + } + + ACE_UNUSED_ARG (ACE_TRY_ENV); + +} + +ACE_INLINE void +TAO_ClientRequestInterceptor_Adapter:: +receive_exception (TAO_ClientRequestInfo *ri, + CORBA::Environment &ACE_TRY_ENV) +{ + // This is an "ending" interception point so we only process the + // interceptors pushed on to the flow stack. + + // Notice that the interceptors are processed in the opposite order + // they were pushed onto the stack since this is an "ending" + // interception point. + + ACE_TRY + { + // Unwind the flow stack. + size_t len = this->stack_size_; + for (size_t i = 0; i < len; ++i) + { + // Pop the interceptor off of the flow stack before it is + // invoked. This is necessary to prevent an interceptor + // already invoked in this "ending" interception point from + // being invoked in another "ending" interception point. + --this->stack_size_; + + this->interceptors_[this->stack_size_]->receive_exception ( + ri + TAO_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + } + ACE_CATCHANY + { + // The receive_exception() interception point in the remaining + // interceptors must be called so call this method (not the + // interceptor's corresponding method) recursively. The call is + // made recursively since the caught exception must survive + // until the remaining interceptors have been called. + + // Note that the recursion will stop once the flow stack size + // drops to zero, i.e., once each interceptor has been invoked. + // This prevents infinite recursion from occuring. + + ri->exception (&ACE_ANY_EXCEPTION); + + this->receive_exception (ri, ACE_TRY_ENV); + ACE_TRY_CHECK; + ACE_RE_THROW; + } + ACE_ENDTRY; + ACE_CHECK; +} + +ACE_INLINE void +TAO_ClientRequestInterceptor_Adapter:: +receive_other (TAO_ClientRequestInfo *ri, + CORBA::Environment &ACE_TRY_ENV) +{ + // This is an "ending" interception point so we only process the + // interceptors pushed on to the flow stack. + + // Notice that the interceptors are processed in the opposite order + // they were pushed onto the stack since this is an "ending" + // interception point. + + // Unwind the stack. + size_t len = this->stack_size_; + for (size_t i = 0; i < len; ++i) + { + // Pop the interceptor off of the flow stack before it is + // invoked. This is necessary to prevent an interceptor already + // invoked in this "ending" interception point from being + // invoked in another "ending" interception point. + --this->stack_size_; + + this->interceptors_[this->stack_size_]->receive_other ( + ri + TAO_ENV_ARG_PARAMETER); + ACE_CHECK; + } + + ACE_UNUSED_ARG (ACE_TRY_ENV); + +} + // ------------------------------------------------------------------- TAO_ServerRequestInterceptor_Adapter:: @@ -20,4 +159,176 @@ TAO_ServerRequestInterceptor_Adapter:: { } +ACE_INLINE void +TAO_ServerRequestInterceptor_Adapter:: +receive_request_service_contexts ( + PortableInterceptor::ServerRequestInfo_ptr ri, + CORBA::Environment &ACE_TRY_ENV) +{ + // This method implements one of the "starting" server side + // interception point. + for (size_t i = 0 ; i < this->len_; ++i) + { + this->interceptors_[i]->receive_request_service_contexts ( + ri + TAO_ENV_ARG_PARAMETER); + ACE_CHECK; + + // The starting interception point completed successfully. Push + // the interceptor on to the flow stack. + ++this->stack_size_; + } + + ACE_UNUSED_ARG (ACE_TRY_ENV); +} + +ACE_INLINE void +TAO_ServerRequestInterceptor_Adapter:: +receive_request (PortableInterceptor::ServerRequestInfo_ptr ri, + CORBA::Environment &ACE_TRY_ENV) +{ + // This method implements an "intermediate" server side interception + // point. Interceptors are invoked in the same order they were + // pushed on to the flow stack. + + if (this->len_ != this->stack_size_) + { + // This method (i.e. the receive_request() interception point) + // should only be invoked if all of the interceptors registered + // with the ORB were pushed on to the flow stack by one of the + // starting endpoints (such as + // receive_request_service_contexts()). If the above condition + // evaluates to "true," then it is likely that a starting + // interception point was never invoked. This is of course, an + // internal error that must be corrected. + ACE_THROW (CORBA::INTERNAL ()); + } + + for (size_t i = 0; i < this->stack_size_; ++i) + { + this->interceptors_[i]->receive_request (ri + TAO_ENV_ARG_PARAMETER); + ACE_CHECK; + + // Note that no interceptors are pushed on to or popped off of + // the flow stack in this interception point since it is an + // intermediate interception point. + } +} + +ACE_INLINE void +TAO_ServerRequestInterceptor_Adapter:: +send_reply (PortableInterceptor::ServerRequestInfo_ptr ri, + CORBA::Environment &ACE_TRY_ENV) +{ + // This is an "ending" interception point so we only process the + // interceptors pushed on to the flow stack. + + // Notice that the interceptors are processed in the opposite order + // they were pushed onto the stack since this is an "ending" + // interception point. + + // Unwind the stack. + size_t len = this->stack_size_; + for (size_t i = 0; i < len; ++i) + { + // Pop the interceptor off of the flow stack before it is + // invoked. This is necessary to prevent an interceptor already + // invoked in this "ending" interception point from being + // invoked in another "ending" interception point. + --this->stack_size_; + + this->interceptors_[this->stack_size_]->send_reply ( + ri + TAO_ENV_ARG_PARAMETER); + ACE_CHECK; + } + + ACE_UNUSED_ARG (ACE_TRY_ENV); +} + +ACE_INLINE void +TAO_ServerRequestInterceptor_Adapter:: +send_exception (PortableInterceptor::ServerRequestInfo_ptr ri, + CORBA::Environment &ACE_TRY_ENV) +{ + // This is an "ending" server side interception point so we only + // process the interceptors pushed on to the flow stack. + + // Notice that the interceptors are processed in the opposite order + // they were pushed onto the stack since this is an "ending" server + // side interception point. + + ACE_TRY + { + // Unwind the flow stack. + size_t len = this->stack_size_; + for (size_t i = 0; i < len; ++i) + { + // Pop the interceptor off of the flow stack before it is + // invoked. This is necessary to prevent an interceptor + // already invoked in this "ending" interception point from + // being invoked in another "ending" interception point. + --this->stack_size_; + + this->interceptors_[this->stack_size_]->send_exception ( + ri + TAO_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + } + ACE_CATCHANY + { + // The send_exception() interception point in the remaining + // interceptors must be called so call this method (not the + // interceptor's corresponding method) recursively. The call is + // made recursively since the caught exception must survive + // until the remaining interceptors have been called. + // + // Note that the recursion will stop once the flow stack size + // drops to zero, i.e., once each interceptor has been invoked. + // This prevents infinite recursion from occuring. + + // @@ FIXME! UNCOMMENT! + // ri->exception (&ACE_ANY_EXCEPTION); + + this->send_exception (ri, ACE_TRY_ENV); + ACE_TRY_CHECK; + ACE_RE_THROW; + } + ACE_ENDTRY; + ACE_CHECK; +} + +ACE_INLINE void +TAO_ServerRequestInterceptor_Adapter:: +send_other (PortableInterceptor::ServerRequestInfo_ptr ri, + CORBA::Environment &ACE_TRY_ENV) +{ + // This is an "ending" server side interception point so we only + // process the interceptors pushed on to the flow stack. + + // Notice that the interceptors are processed in the opposite order + // they were pushed onto the stack since this is an "ending" server + // side interception point. + + // Unwind the flow stack. + size_t len = this->stack_size_; + for (size_t i = 0; i < len; ++i) + { + // Pop the interceptor off of the flow stack before it is + // invoked. This is necessary to prevent an interceptor already + // invoked in this "ending" interception point from being + // invoked in another "ending" interception point. + --this->stack_size_; + + this->interceptors_[this->stack_size_]->send_other ( + ri + TAO_ENV_ARG_PARAMETER); + ACE_CHECK; + } + + ACE_UNUSED_ARG (ACE_TRY_ENV); +} + #endif /* TAO_HAS_INTERCEPTORS == 1 */ diff --git a/TAO/tao/PortableInterceptor.h b/TAO/tao/PortableInterceptor.h index 7de8a35d92c..730a87119af 100644 --- a/TAO/tao/PortableInterceptor.h +++ b/TAO/tao/PortableInterceptor.h @@ -14,8 +14,6 @@ * These macros allows us to disable/enable support of interceptors * easily. * - * - * * @author Nanbor Wang <nanbor@cs.wustl.edu> * @author Kirthika Parameswaran <kirthika@cs.wustl.edu> * @author Ossama Othman <ossama@uci.edu> @@ -53,6 +51,9 @@ #include "PortableInterceptorC.h" #include "Interceptor_List.h" +// Forward declarations +class TAO_ClientRequestInfo; + /** * @class TAO_ClientRequestInterceptor_Adapter * @@ -85,22 +86,22 @@ public: //@{ /// This method implements one of the "starting" client side /// interception points. - void send_request (PortableInterceptor::ClientRequestInfo_ptr ri, + void send_request (TAO_ClientRequestInfo *ri, CORBA::Environment &); /// This method implements one of the "ending" client side /// interception point. - void receive_reply (PortableInterceptor::ClientRequestInfo_ptr ri, + void receive_reply (TAO_ClientRequestInfo *ri, CORBA::Environment &); /// This method implements one of the "ending" client side /// interception point. - void receive_exception (PortableInterceptor::ClientRequestInfo_ptr ri, + void receive_exception (TAO_ClientRequestInfo *ri, CORBA::Environment &); /// This method implements one of the "ending" client side /// interception point. - void receive_other (PortableInterceptor::ClientRequestInfo_ptr ri, + void receive_other (TAO_ClientRequestInfo *ri, CORBA::Environment &); //@} diff --git a/TAO/tao/PortableInterceptor.i b/TAO/tao/PortableInterceptor.i index 83b10444fef..8d607f70c47 100644 --- a/TAO/tao/PortableInterceptor.i +++ b/TAO/tao/PortableInterceptor.i @@ -12,122 +12,6 @@ TAO_ClientRequestInterceptor_Adapter::TAO_ClientRequestInterceptor_Adapter this->len_ = interceptors.size (); } -ACE_INLINE void -TAO_ClientRequestInterceptor_Adapter:: -send_request (PortableInterceptor::ClientRequestInfo_ptr ri, - CORBA::Environment &ACE_TRY_ENV) -{ - // This method implements one of the "starting" client side - // interception point. - for (size_t i = 0 ; i < this->len_; ++i) - { - this->interceptors_[i]->send_request (ri - TAO_ENV_ARG_PARAMETER); - ACE_CHECK; - - // The starting interception point completed successfully. Push - // the interceptor on to the flow stack. - ++this->stack_size_; - } - - ACE_UNUSED_ARG (ACE_TRY_ENV); -} - -ACE_INLINE void -TAO_ClientRequestInterceptor_Adapter:: -receive_reply (PortableInterceptor::ClientRequestInfo_ptr ri, - CORBA::Environment &ACE_TRY_ENV) -{ - // This is an "ending" interception point so we only process the - // interceptors pushed on to the flow stack. - - // Notice that the interceptors are processed in the opposite order - // they were pushed onto the stack since this is an "ending" - // interception point. - - // Unwind the stack. - size_t len = this->stack_size_; - for (size_t i = 0; i < len; ++i) - { - // Pop the interceptor off of the flow stack before it is - // invoked. This is necessary to prevent an interceptor already - // invoked in this "ending" interception point from being - // invoked in another "ending" interception point. - --this->stack_size_; - - this->interceptors_[this->stack_size_]->receive_reply ( - ri - TAO_ENV_ARG_PARAMETER); - ACE_CHECK; - } - - ACE_UNUSED_ARG (ACE_TRY_ENV); - -} - -ACE_INLINE void -TAO_ClientRequestInterceptor_Adapter:: -receive_exception (PortableInterceptor::ClientRequestInfo_ptr ri, - CORBA::Environment &ACE_TRY_ENV) -{ - // This is an "ending" interception point so we only process the - // interceptors pushed on to the flow stack. - - // Notice that the interceptors are processed in the opposite order - // they were pushed onto the stack since this is an "ending" - // interception point. - - // Unwind the flow stack. - size_t len = this->stack_size_; - for (size_t i = 0; i < len; ++i) - { - // Pop the interceptor off of the flow stack before it is - // invoked. This is necessary to prevent an interceptor already - // invoked in this "ending" interception point from being - // invoked in another "ending" interception point. - --this->stack_size_; - - this->interceptors_[this->stack_size_]->receive_exception ( - ri - TAO_ENV_ARG_PARAMETER); - ACE_CHECK; - } - - ACE_UNUSED_ARG (ACE_TRY_ENV); -} - -ACE_INLINE void -TAO_ClientRequestInterceptor_Adapter:: -receive_other (PortableInterceptor::ClientRequestInfo_ptr ri, - CORBA::Environment &ACE_TRY_ENV) -{ - // This is an "ending" interception point so we only process the - // interceptors pushed on to the flow stack. - - // Notice that the interceptors are processed in the opposite order - // they were pushed onto the stack since this is an "ending" - // interception point. - - // Unwind the stack. - size_t len = this->stack_size_; - for (size_t i = 0; i < len; ++i) - { - // Pop the interceptor off of the flow stack before it is - // invoked. This is necessary to prevent an interceptor already - // invoked in this "ending" interception point from being - // invoked in another "ending" interception point. - --this->stack_size_; - - this->interceptors_[this->stack_size_]->receive_other ( - ri - TAO_ENV_ARG_PARAMETER); - ACE_CHECK; - } - - ACE_UNUSED_ARG (ACE_TRY_ENV); - -} - // ------------------------------------------------------------------- ACE_INLINE @@ -140,153 +24,3 @@ TAO_ServerRequestInterceptor_Adapter::TAO_ServerRequestInterceptor_Adapter { this->len_ = interceptors.size (); } - -ACE_INLINE void -TAO_ServerRequestInterceptor_Adapter:: -receive_request_service_contexts ( - PortableInterceptor::ServerRequestInfo_ptr ri, - CORBA::Environment &ACE_TRY_ENV) -{ - // This method implements one of the "starting" server side - // interception point. - for (size_t i = 0 ; i < this->len_; ++i) - { - this->interceptors_[i]->receive_request_service_contexts ( - ri - TAO_ENV_ARG_PARAMETER); - ACE_CHECK; - - // The starting interception point completed successfully. Push - // the interceptor on to the flow stack. - ++this->stack_size_; - } - - ACE_UNUSED_ARG (ACE_TRY_ENV); -} - -ACE_INLINE void -TAO_ServerRequestInterceptor_Adapter:: -receive_request (PortableInterceptor::ServerRequestInfo_ptr ri, - CORBA::Environment &ACE_TRY_ENV) -{ - // This method implements an "intermediate" server side interception - // point. Interceptors are invoked in the same order they were - // pushed on to the flow stack. - - if (this->len_ != this->stack_size_) - { - // This method (i.e. the receive_request() interception point) - // should only be invoked if all of the interceptors registered - // with the ORB were pushed on to the flow stack by one of the - // starting endpoints (such as - // receive_request_service_contexts()). If the above condition - // evaluates to "true," then it is likely that a starting - // interception point was never invoked. This is of course, an - // internal error that must be corrected. - ACE_THROW (CORBA::INTERNAL ()); - } - - for (size_t i = 0; i < this->stack_size_; ++i) - { - this->interceptors_[i]->receive_request (ri - TAO_ENV_ARG_PARAMETER); - ACE_CHECK; - - // Note that no interceptors are pushed on to or popped off of - // the flow stack in this interception point since it is an - // intermediate interception point. - } -} - -ACE_INLINE void -TAO_ServerRequestInterceptor_Adapter:: -send_reply (PortableInterceptor::ServerRequestInfo_ptr ri, - CORBA::Environment &ACE_TRY_ENV) -{ - // This is an "ending" interception point so we only process the - // interceptors pushed on to the flow stack. - - // Notice that the interceptors are processed in the opposite order - // they were pushed onto the stack since this is an "ending" - // interception point. - - // Unwind the stack. - size_t len = this->stack_size_; - for (size_t i = 0; i < len; ++i) - { - // Pop the interceptor off of the flow stack before it is - // invoked. This is necessary to prevent an interceptor already - // invoked in this "ending" interception point from being - // invoked in another "ending" interception point. - --this->stack_size_; - - this->interceptors_[this->stack_size_]->send_reply ( - ri - TAO_ENV_ARG_PARAMETER); - ACE_CHECK; - } - - ACE_UNUSED_ARG (ACE_TRY_ENV); -} - -ACE_INLINE void -TAO_ServerRequestInterceptor_Adapter:: -send_exception (PortableInterceptor::ServerRequestInfo_ptr ri, - CORBA::Environment &ACE_TRY_ENV) -{ - // This is an "ending" server side interception point so we only - // process the interceptors pushed on to the flow stack. - - // Notice that the interceptors are processed in the opposite order - // they were pushed onto the stack since this is an "ending" server - // side interception point. - - // Unwind the flow stack. - size_t len = this->stack_size_; - for (size_t i = 0; i < len; ++i) - { - // Pop the interceptor off of the flow stack before it is - // invoked. This is necessary to prevent an interceptor already - // invoked in this "ending" interception point from being - // invoked in another "ending" interception point. - --this->stack_size_; - - this->interceptors_[this->stack_size_]->send_exception ( - ri - TAO_ENV_ARG_PARAMETER); - ACE_CHECK; - } - - ACE_UNUSED_ARG (ACE_TRY_ENV); -} - -ACE_INLINE void -TAO_ServerRequestInterceptor_Adapter:: -send_other (PortableInterceptor::ServerRequestInfo_ptr ri, - CORBA::Environment &ACE_TRY_ENV) -{ - // This is an "ending" server side interception point so we only - // process the interceptors pushed on to the flow stack. - - // Notice that the interceptors are processed in the opposite order - // they were pushed onto the stack since this is an "ending" server - // side interception point. - - // Unwind the flow stack. - size_t len = this->stack_size_; - for (size_t i = 0; i < len; ++i) - { - // Pop the interceptor off of the flow stack before it is - // invoked. This is necessary to prevent an interceptor already - // invoked in this "ending" interception point from being - // invoked in another "ending" interception point. - --this->stack_size_; - - this->interceptors_[this->stack_size_]->send_other ( - ri - TAO_ENV_ARG_PARAMETER); - ACE_CHECK; - } - - ACE_UNUSED_ARG (ACE_TRY_ENV); -} diff --git a/TAO/tao/PortableServer/ServerRequestInfo.cpp b/TAO/tao/PortableServer/ServerRequestInfo.cpp index 05f48b2e885..0650252ce8c 100644 --- a/TAO/tao/PortableServer/ServerRequestInfo.cpp +++ b/TAO/tao/PortableServer/ServerRequestInfo.cpp @@ -22,7 +22,7 @@ TAO_ServerRequestInfo::TAO_ServerRequestInfo ( : server_request_ (server_request), forward_reference_ (), // poa_current_ (), - adapter_id_ (), + // adapter_id_ (), caught_exception_ (0), reply_status_ (-1) { @@ -32,7 +32,38 @@ CORBA::ULong TAO_ServerRequestInfo::request_id (CORBA::Environment &) ACE_THROW_SPEC ((CORBA::SystemException)) { - return this->server_request_.request_id (); + // The request ID returned by this method need not correspond to the + // GIOP request ID sent with the client request. The request ID + // must be unique across all outstanding requests. To avoid locking + // overhead, the address of the TAO_ServerRequest object is used as + // the request ID. This guarantees that the request ID is unique. + // + // For 64-bit platforms, only the lower 32 bits are used. Hopefully + // that will be enough to ensure uniqueness. + + // This is basically the same trick used in + // TAO_GIOP_Invocation::generate_request_id(). However, no right + // shifting of 64 bit addresses is performed since the + // TAO_ServerRequest object is not large enough to allow that trick. + + CORBA::ULong id = 0; + + if (sizeof (this) == 4) // 32 bit address + id = + ACE_reinterpret_cast (CORBA::ULong, &(this->server_request_)); + + else if (sizeof (this) == 8) // 64 bit address -- use lower 32 bits + id = + ACE_reinterpret_cast (CORBA::ULong, + &(this->server_request_)) & 0xFFFFFFFFu; + + else + // @@ Rather than fallback on the GIOP request ID, we should use + // an atomically incremented variable specific to the ORB, or + // perhaps specific to the process. + id = this->server_request_.request_id (); // Fallback + + return id; } char * @@ -384,7 +415,7 @@ TAO_ServerRequestInfo::add_reply_service_context ( TAO_Service_Context &service_context_list = this->server_request_.reply_service_context (); - if (service_context_list.set_context (service_context,replace) == 0) + if (service_context_list.set_context (service_context, replace) == 0) { ACE_THROW (CORBA::BAD_INV_ORDER (TAO_OMG_VMCID | 11, CORBA::COMPLETED_NO)); diff --git a/TAO/tao/PortableServer/ServerRequestInfo.h b/TAO/tao/PortableServer/ServerRequestInfo.h index 75705012037..30646626fc6 100644 --- a/TAO/tao/PortableServer/ServerRequestInfo.h +++ b/TAO/tao/PortableServer/ServerRequestInfo.h @@ -32,6 +32,9 @@ #include "tao/StringSeqC.h" #include "tao/OctetSeqC.h" #include "tao/Service_Context.h" + +//#include "PortableServerC.h" + #include "portableserver_export.h" #if defined(_MSC_VER) @@ -48,7 +51,7 @@ class TAO_PortableServer_Export TAO_ServerRequestInfo : public virtual PortableInterceptor::ServerRequestInfo, public virtual CORBA::LocalObject { - public: +public: TAO_ServerRequestInfo (TAO_ServerRequest &server_request); virtual CORBA::ULong request_id ( @@ -195,8 +198,9 @@ protected: CORBA::Object_var forward_reference_; - CORBA::OctetSeq_var object_id_; - CORBA::OctetSeq_var adapter_id_; + // PortableServer::Current_var poa_current_; + // CORBA::OctetSeq_var adapter_id_; + CORBA::Exception *caught_exception_; PortableInterceptor::ReplyStatus reply_status_; diff --git a/TAO/tao/Sequence.i b/TAO/tao/Sequence.i index bd1078e1deb..e1fddfa3707 100644 --- a/TAO/tao/Sequence.i +++ b/TAO/tao/Sequence.i @@ -100,8 +100,38 @@ TAO_Unbounded_Base_Sequence::length (CORBA::ULong length) { if (length > this->maximum_) { - this->_allocate_buffer (length); - this->maximum_ = length; + // At least double the size of the buffer each time the length + // is extended. This reduces the number of allocations, and + // copies accompanying those allocations signifantly for large + // numbers of small sequence length increases. + // + // Here is an example of the resulting buffer sizes during eigth + // iterations: + // + // desired length maximum allocation and copy + // -------------- ------- ------------------- + // 1 1 yes + // 2 2 yes + // 3 4 yes + // 4 4 NO! + // 5 8 yes + // 6 8 NO! + // 7 8 NO! + // 8 8 NO! + // + // In this example, the number of allocations was reduced from 8 + // to 4. Similarly, the number of copies was reduced from 28 to + // 7. + + // Double the length. Notice that the left shift eventually + // causes "new_maximum" to potentially become less than + // "this->length_". This isn't a problem since the new maximum + // (and length) will just become "length". + CORBA::ULong new_maximum = this->length_ << 2; + new_maximum = (length > new_maximum ? length : new_maximum); + + this->_allocate_buffer (new_maximum); + this->maximum_ = new_maximum; this->release_ = 1; } else if (length < this->length_) diff --git a/TAO/tao/operation_details.h b/TAO/tao/operation_details.h index b66ddd9c272..e309804aab4 100644 --- a/TAO/tao/operation_details.h +++ b/TAO/tao/operation_details.h @@ -12,16 +12,18 @@ #ifndef TAO_OPERATION_DETAILS_H #define TAO_OPERATION_DETAILS_H + #include "ace/pre.h" -#include "tao/corbafwd.h" + +#include "corbafwd.h" #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ -#include "tao/Service_Context.h" -#include "tao/target_specification.h" +#include "Service_Context.h" +#include "target_specification.h" // @@ Bala: Why is this not part of the RequestHeader?! @@ -31,15 +33,16 @@ * @brief Class with operation details * * This class stores some of the "operation" details that would be - * required by the invocation classes. this class is in its - * infancy now but I expect this one to grow as we come with + * required by the invocation classes. This class is in its + * infancy now but I expect this one to grow as we come with * different varieties of use cases. */ class TAO_Export TAO_Operation_Details { public: - ///Ctor + + ///Constructor TAO_Operation_Details (const char *name, CORBA::ULong len, CORBA::Boolean argument_flag); @@ -50,7 +53,7 @@ public: /// Length of the operation name CORBA::ULong opname_len (void) const; - /// Return the flag that indicates whether the operation has any + /// Return the flag that indicates whether the operation has any /// arguments CORBA::Boolean argument_flag (void) const; @@ -76,22 +79,22 @@ public: void request_id (CORBA::ULong id); /// Modify request id's for a BiDirectional setup - void modify_request_id (int flag); + void modify_request_id (int originator); - /// Get for request id + /// Return the request ID associated with the operation CORBA::ULong request_id (void); CORBA::ULong request_id (void) const; - /// Get method for the addressing mode + /// Accessor method for the addressing mode TAO_Target_Specification::TAO_Target_Address addressing_mode (void); TAO_Target_Specification::TAO_Target_Address addressing_mode (void) const; /// Set method for the addressing mode - void - addressing_mode (CORBA::Short addr); + void addressing_mode (CORBA::Short addr); private: + /// Name of the operation being invoked. const char *opname_; @@ -102,7 +105,7 @@ private: CORBA::ULong request_id_; /** - * Flag that indicates whether the operation has any arguments. If + * Flag that indicates whether the operation has any arguments. If * there are any arguments the flag will have a value of 1, 0 * otherwise. */ @@ -130,8 +133,9 @@ private: }; #if defined (__ACE_INLINE__) -# include "tao/operation_details.i" +# include "operation_details.i" #endif /* __ACE_INLINE__ */ #include "ace/post.h" -#endif /*TAO_OPERATION_DETAILS_H*/ + +#endif /* TAO_OPERATION_DETAILS_H */ diff --git a/TAO/tao/operation_details.i b/TAO/tao/operation_details.i index c1e310eb713..5987b895223 100644 --- a/TAO/tao/operation_details.i +++ b/TAO/tao/operation_details.i @@ -1,17 +1,18 @@ // -*- C++ -*- +// //$Id$ + ACE_INLINE TAO_Operation_Details::TAO_Operation_Details (const char *name, CORBA::ULong len, CORBA::Boolean argument_flag) - :opname_ (name), - opname_len_ (len), - request_id_ (0), - argument_flag_ (argument_flag), - response_flags_ (0), - addressing_mode_ (TAO_Target_Specification::Key_Addr) + : opname_ (name), + opname_len_ (len), + request_id_ (0), + argument_flag_ (argument_flag), + response_flags_ (0), + addressing_mode_ (TAO_Target_Specification::Key_Addr) { - //no-op } ACE_INLINE const char* @@ -91,14 +92,17 @@ TAO_Operation_Details::request_id (CORBA::ULong id) } ACE_INLINE void -TAO_Operation_Details::modify_request_id (int flag) +TAO_Operation_Details::modify_request_id (int originator) { - // If the flag value is -1 then BiDirectional connection has not - // been negotiated - if (flag >= 0) - { - this->request_id_ = (this->request_id_ * 2) + flag; - } + // originator == 1 --> originating side + // originator == 0 --> other side + // originator == -1 --> no bi-directional connection was negotiated + + // The originating side must have an even request ID, and the other + // side must have an odd request ID. Make sure that is the case. + if ((originator == 1 && ACE_ODD (this->request_id_)) + || (originator == 0 && ACE_EVEN (this->request_id_))) + ++(this->request_id_); } ACE_INLINE CORBA::ULong @@ -144,13 +148,12 @@ TAO_Operation_Details::addressing_mode (void) const } ACE_INLINE void -TAO_Operation_Details:: - addressing_mode (CORBA::Short mode) +TAO_Operation_Details::addressing_mode (CORBA::Short mode) { if (mode == 0) - this->addressing_mode_ = TAO_Target_Specification::Key_Addr; + this->addressing_mode_ = TAO_Target_Specification::Key_Addr; else if (mode == 1) this->addressing_mode_ = TAO_Target_Specification::Profile_Addr; else if (mode == 2) - this->addressing_mode_ = TAO_Target_Specification::Reference_Addr; + this->addressing_mode_ = TAO_Target_Specification::Reference_Addr; } |