summaryrefslogtreecommitdiff
path: root/trunk/TAO/tao/PortableServer/Upcall_Wrapper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/TAO/tao/PortableServer/Upcall_Wrapper.cpp')
-rw-r--r--trunk/TAO/tao/PortableServer/Upcall_Wrapper.cpp321
1 files changed, 321 insertions, 0 deletions
diff --git a/trunk/TAO/tao/PortableServer/Upcall_Wrapper.cpp b/trunk/TAO/tao/PortableServer/Upcall_Wrapper.cpp
new file mode 100644
index 00000000000..e3fa5544e75
--- /dev/null
+++ b/trunk/TAO/tao/PortableServer/Upcall_Wrapper.cpp
@@ -0,0 +1,321 @@
+// $Id$
+
+#include "tao/PortableServer/Upcall_Wrapper.h"
+#include "tao/PortableServer/Upcall_Command.h"
+#include "tao/PortableServer/DII_Arguments_Converter.h"
+
+#if TAO_HAS_INTERCEPTORS == 1
+# include "tao/ServerRequestInterceptor_Adapter.h"
+# include "tao/PortableInterceptorC.h"
+# include "tao/ORB_Core.h"
+#endif /* TAO_HAS_INTERCEPTORS == 1 */
+
+#include "tao/PortableInterceptor.h"
+
+#include "tao/TAO_Server_Request.h"
+#include "tao/CDR.h"
+#include "tao/Argument.h"
+#include "tao/operation_details.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID (PortableServer,
+ Upcall_Wrapper,
+ "$Id$")
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+void
+TAO::Upcall_Wrapper::upcall (TAO_ServerRequest & server_request,
+ TAO::Argument * const args[],
+ size_t nargs,
+ TAO::Upcall_Command & command
+
+#if TAO_HAS_INTERCEPTORS == 1
+ , void * servant_upcall
+ , CORBA::TypeCode_ptr const * exceptions
+ , CORBA::ULong nexceptions
+#endif /* TAO_HAS_INTERCEPTORS == 1 */
+
+ ACE_ENV_ARG_DECL
+ )
+{
+ if (server_request.collocated ()
+ && server_request.operation_details ()->is_dii_request ())
+ {
+ TAO_DII_Arguments_Converter* dii_arguments_converter
+ = ACE_Dynamic_Service<TAO_DII_Arguments_Converter>::instance ("DII_Arguments_Converter");
+
+ if (dii_arguments_converter != 0)
+ {
+ dii_arguments_converter->convert (server_request,
+ args,
+ nargs
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+ else
+ ACE_THROW (CORBA::NO_IMPLEMENT ());
+ }
+
+ if (server_request.incoming ())
+ {
+ this->pre_upcall (*server_request.incoming (),
+ args,
+ nargs
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+
+#if TAO_HAS_INTERCEPTORS == 1
+
+ // Make sure that, for the collocated case, we use the client-side
+ // arguments. For the non-collocated case, we will use the server-side
+ // arguments since they got set up in our pre_upcall() method. Note that
+ // our pre_upcall() method doesn't get invoked in the collocated case,
+ // and is the reason why we need to provide the client-side args instead
+ // of the (never set or initialized) server-side args.
+ //
+ // Before the following logic was added, the
+ // $TAO_ROOT/tests/Portable_Interceptors/Collocated/run_test.pl
+ // showed that the server-side request interceptor was getting bogus
+ // values when it took a look at the request arguments. Some
+ // additional testing revealed that this only occurred in the
+ // collocated request case.
+
+ // By default, we assume that we will use the server-side args.
+ TAO::Argument * const * the_args = args;
+ size_t the_nargs = nargs;
+
+ if (server_request.collocated())
+ {
+ // It is a collocated request so we need to use the client-side
+ // args instead.
+ the_args = server_request.operation_details()->args();
+ the_nargs = server_request.operation_details()->args_num();
+ }
+
+ TAO::ServerRequestInterceptor_Adapter *interceptor_adapter =
+ server_request.orb_core ()->serverrequestinterceptor_adapter ();
+
+ ACE_TRY
+ {
+ {
+ if (interceptor_adapter != 0)
+ {
+ // Invoke intermediate server side interception points.
+ interceptor_adapter->receive_request (server_request,
+ the_args,
+ the_nargs,
+ servant_upcall,
+ exceptions,
+ nexceptions
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+ }
+
+ // Don't bother performing the upcall if an interceptor caused a
+ // location forward.
+ CORBA::Object_var forward_to = server_request.forward_location ();
+ if (CORBA::is_nil (forward_to.in ()))
+ {
+ if (interceptor_adapter != 0)
+ {
+ interceptor_adapter->execute_command (server_request,
+ command
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+ }
+ else
+#endif /* TAO_HAS_INTERCEPTORS */
+ {
+ // The actual upcall.
+ command.execute (ACE_ENV_SINGLE_ARG_PARAMETER);
+ TAO_INTERCEPTOR_CHECK;
+ }
+
+#if TAO_HAS_INTERCEPTORS == 1
+ }
+ }
+
+ if (interceptor_adapter == 0)
+ {
+ server_request.reply_status (PortableInterceptor::SUCCESSFUL);
+ }
+ else
+ {
+ // Do not execute the send_reply() interception point if an
+ // interceptor caused a location forward. The send_other()
+ // interception point should already have been executed by the
+ // ServerRequestInterceptor_Adapter object.
+ //
+ // It should actually be safe to call this interception point,
+ // regardless, since the interceptor flow stack should have been
+ // emptied by the send_other() interception point. Note that
+ // we'd still need to avoid resetting the reply status to
+ // SUCCESSFUL, however.
+ CORBA::Object_var forward_to_after = server_request.forward_location ();
+ if (CORBA::is_nil (forward_to_after.in ()))
+ {
+ // No location forward by interceptors and successful upcall.
+ server_request.reply_status (PortableInterceptor::SUCCESSFUL);
+ interceptor_adapter->send_reply (server_request,
+ the_args,
+ the_nargs,
+ servant_upcall,
+ exceptions,
+ nexceptions
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+ }
+ }
+ }
+ ACE_CATCHANY
+ {
+ // Just assume the current exception is a system exception, the
+ // status can only change when the interceptor changes this
+ // and this is only done when the sri_adapter is available. If we
+ // don't have an sri_adapter we just rethrow the exception
+ PortableInterceptor::ReplyStatus status =
+ PortableInterceptor::SYSTEM_EXCEPTION;
+
+ server_request.caught_exception (&ACE_ANY_EXCEPTION);
+
+ if (interceptor_adapter != 0)
+ {
+ interceptor_adapter->send_exception (server_request,
+ the_args,
+ the_nargs,
+ servant_upcall,
+ exceptions,
+ nexceptions
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ status =
+ server_request.reply_status ();
+ }
+
+ if (status == PortableInterceptor::SYSTEM_EXCEPTION
+ || status == PortableInterceptor::USER_EXCEPTION)
+ {
+ ACE_RE_THROW;
+ }
+ }
+# if defined (ACE_HAS_EXCEPTIONS) \
+ && defined (ACE_HAS_BROKEN_UNEXPECTED_EXCEPTIONS)
+ ACE_CATCHALL
+ {
+ // Just assume the current exception is a system exception, the
+ // status can only change when the interceptor changes this
+ // and this is only done when the sri_adapter is available. If we
+ // don't have an sri_adapter we just rethrow the exception
+ PortableInterceptor::ReplyStatus status =
+ PortableInterceptor::SYSTEM_EXCEPTION;
+
+ CORBA::UNKNOWN ex;
+
+ server_request.caught_exception (&ex);
+
+ if (interceptor_adapter != 0)
+ {
+ interceptor_adapter->send_exception (server_request,
+ the_args,
+ the_nargs,
+ servant_upcall,
+ exceptions,
+ nexceptions
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ status =
+ server_request.reply_status ();
+ }
+
+ if (status == PortableInterceptor::SYSTEM_EXCEPTION)
+ ACE_TRY_THROW (ex);
+ }
+# endif /* ACE_HAS_EXCEPTIONS && ACE_HAS_BROKEN_UNEXPECTED_EXCEPTIONS */
+ ACE_ENDTRY;
+ ACE_CHECK;
+#endif /* TAO_HAS_INTERCEPTORS == 1 */
+
+ if (server_request.response_expected ()
+ && !server_request.sync_with_server ())
+ {
+ server_request.init_reply ();
+ }
+
+#if TAO_HAS_INTERCEPTORS == 1
+ // Don't bother marshaling inout/out/return values if an interceptor
+ // caused a location forward.
+ CORBA::Object_var forward_to_end = server_request.forward_location ();
+ if (CORBA::is_nil (forward_to_end.in ()))
+#endif /* TAO_HAS_INTERCEPTORS == 1 */
+ {
+ if (server_request.outgoing ())
+ {
+ this->post_upcall (*server_request.outgoing (),
+ args,
+ nargs
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+ }
+}
+
+void
+TAO::Upcall_Wrapper::pre_upcall (TAO_InputCDR & cdr,
+ TAO::Argument * const * args,
+ size_t nargs
+ ACE_ENV_ARG_DECL)
+{
+ // Demarshal the operation "in" and "inout" arguments, if any.
+
+ // NOTE: The TAO::Argument corresponding to the return value is
+ // always the first element in the array, regardless of
+ // whether or not the return type is void.
+
+ ACE_ASSERT (nargs != 0);
+
+ TAO::Argument * const * const begin = args + 1; // Skip the return value.
+ TAO::Argument * const * const end = args + nargs;
+
+ for (TAO::Argument * const * i = begin; i != end; ++i)
+ {
+ if (!(*i)->demarshal (cdr))
+ {
+ TAO_InputCDR::throw_skel_exception (errno
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+ }
+}
+
+void
+TAO::Upcall_Wrapper::post_upcall (TAO_OutputCDR & cdr,
+ TAO::Argument * const * args,
+ size_t nargs
+ ACE_ENV_ARG_DECL)
+{
+ // Marshal the operation "inout" and "out" arguments and return
+ // value, if any.
+
+ TAO::Argument * const * const begin = args;
+ TAO::Argument * const * const end = args + nargs;
+
+ for (TAO::Argument * const * i = begin; i != end; ++i)
+ {
+ if (!(*i)->marshal (cdr))
+ {
+ TAO_OutputCDR::throw_skel_exception (errno
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+ }
+ }
+
+ // Reply body marshaling completed. No other fragments to send.
+ cdr.more_fragments (false);
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+