summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TAO/ChangeLog58
-rw-r--r--TAO/orbsvcs/orbsvcs/FaultTolerance/FT_ClientRequest_Interceptor.cpp124
-rw-r--r--TAO/orbsvcs/orbsvcs/FaultTolerance/FT_ClientRequest_Interceptor.h7
-rw-r--r--TAO/orbsvcs/orbsvcs/FaultTolerance/FT_Service_Callbacks.cpp36
-rw-r--r--TAO/orbsvcs/orbsvcs/FaultTolerance/FT_Service_Callbacks.h23
-rw-r--r--TAO/orbsvcs/tests/Bug_2285_Regression/Bug_2285_Regression.mpc38
-rw-r--r--TAO/orbsvcs/tests/Bug_2285_Regression/Hello.cpp74
-rw-r--r--TAO/orbsvcs/tests/Bug_2285_Regression/Hello.h64
-rw-r--r--TAO/orbsvcs/tests/Bug_2285_Regression/README96
-rw-r--r--TAO/orbsvcs/tests/Bug_2285_Regression/ServerORBInitializer.cpp52
-rw-r--r--TAO/orbsvcs/tests/Bug_2285_Regression/ServerORBInitializer.h63
-rw-r--r--TAO/orbsvcs/tests/Bug_2285_Regression/ServerORBInitializer2.cpp52
-rw-r--r--TAO/orbsvcs/tests/Bug_2285_Regression/ServerORBInitializer2.h63
-rw-r--r--TAO/orbsvcs/tests/Bug_2285_Regression/ServerRequest_Interceptor.cpp144
-rw-r--r--TAO/orbsvcs/tests/Bug_2285_Regression/ServerRequest_Interceptor.h101
-rw-r--r--TAO/orbsvcs/tests/Bug_2285_Regression/ServerRequest_Interceptor2.cpp239
-rw-r--r--TAO/orbsvcs/tests/Bug_2285_Regression/ServerRequest_Interceptor2.h106
-rw-r--r--TAO/orbsvcs/tests/Bug_2285_Regression/Test.idl43
-rw-r--r--TAO/orbsvcs/tests/Bug_2285_Regression/client.cpp137
-rw-r--r--TAO/orbsvcs/tests/Bug_2285_Regression/client2.cpp211
-rwxr-xr-xTAO/orbsvcs/tests/Bug_2285_Regression/run_test.pl49
-rwxr-xr-xTAO/orbsvcs/tests/Bug_2285_Regression/run_test2.pl70
-rw-r--r--TAO/orbsvcs/tests/Bug_2285_Regression/server.cpp241
-rw-r--r--TAO/orbsvcs/tests/Bug_2285_Regression/server2.cpp175
-rw-r--r--TAO/orbsvcs/tests/Bug_2287_Regression/Bug_2287_Regression.mpc20
-rw-r--r--TAO/orbsvcs/tests/Bug_2287_Regression/Hello.cpp32
-rw-r--r--TAO/orbsvcs/tests/Bug_2287_Regression/Hello.h46
-rw-r--r--TAO/orbsvcs/tests/Bug_2287_Regression/README32
-rw-r--r--TAO/orbsvcs/tests/Bug_2287_Regression/ServerORBInitializer2.cpp52
-rw-r--r--TAO/orbsvcs/tests/Bug_2287_Regression/ServerORBInitializer2.h63
-rw-r--r--TAO/orbsvcs/tests/Bug_2287_Regression/ServerRequest_Interceptor2.cpp174
-rw-r--r--TAO/orbsvcs/tests/Bug_2287_Regression/ServerRequest_Interceptor2.h108
-rw-r--r--TAO/orbsvcs/tests/Bug_2287_Regression/Test.idl24
-rw-r--r--TAO/orbsvcs/tests/Bug_2287_Regression/client.cpp110
-rwxr-xr-xTAO/orbsvcs/tests/Bug_2287_Regression/run_test.pl49
-rw-r--r--TAO/orbsvcs/tests/Bug_2287_Regression/server.cpp243
-rw-r--r--TAO/tao/PI/ClientRequestInfo.cpp24
-rw-r--r--TAO/tao/PI/ClientRequestInfo.h24
-rw-r--r--TAO/tao/operation_details.h16
-rw-r--r--TAO/tao/operation_details.i30
40 files changed, 3234 insertions, 79 deletions
diff --git a/TAO/ChangeLog b/TAO/ChangeLog
index 9cee1f37c82..e5a297a30a4 100644
--- a/TAO/ChangeLog
+++ b/TAO/ChangeLog
@@ -1,3 +1,61 @@
+Thu Oct 27 11:30:59 2005 Simon McQueen <sm@prismtech.com>
+
+ * tao/operation_details.h:
+ * tao/operation_details.i:
+
+ Add members (with accessors) for the FT request retention ID and
+ expiration time.
+
+ * tao/PI/ClientRequestInfo.cpp:
+ * tao/PI/ClientRequestInfo.h:
+
+ Add accessors for the FT request retention ID and expiration time
+ of the underlying request operation details (see above).
+
+ * orbsvcs/orbsvcs/FaultTolerance/FT_Service_Callbacks.h:
+ * orbsvcs/orbsvcs/FaultTolerance/FT_Service_Callbacks.cpp:
+ * orbsvcs/orbsvcs/FaultTolerance/FT_ClientRequest_Interceptor.h:
+ * orbsvcs/orbsvcs/FaultTolerance/FT_ClientRequest_Interceptor.cpp:
+
+ Transmit the correct retention ID and request expiration time in
+ the request service context. Bound retries by the expiration time.
+
+ This fixes bus #2285 and #2287.
+
+ * orbsvcs/tests/Bug_2285_Regression/Bug_2285_Regression.mpc:
+ * orbsvcs/tests/Bug_2285_Regression/Hello.cpp:
+ * orbsvcs/tests/Bug_2285_Regression/Hello.h:
+ * orbsvcs/tests/Bug_2285_Regression/README:
+ * orbsvcs/tests/Bug_2285_Regression/ServerORBInitializer.cpp:
+ * orbsvcs/tests/Bug_2285_Regression/ServerORBInitializer.h:
+ * orbsvcs/tests/Bug_2285_Regression/ServerORBInitializer2.cpp:
+ * orbsvcs/tests/Bug_2285_Regression/ServerORBInitializer2.h:
+ * orbsvcs/tests/Bug_2285_Regression/ServerRequest_Interceptor.cpp:
+ * orbsvcs/tests/Bug_2285_Regression/ServerRequest_Interceptor.h:
+ * orbsvcs/tests/Bug_2285_Regression/ServerRequest_Interceptor2.cpp:
+ * orbsvcs/tests/Bug_2285_Regression/ServerRequest_Interceptor2.h:
+ * orbsvcs/tests/Bug_2285_Regression/Test.idl:
+ * orbsvcs/tests/Bug_2285_Regression/client.cpp:
+ * orbsvcs/tests/Bug_2285_Regression/client2.cpp:
+ * orbsvcs/tests/Bug_2285_Regression/run_test.pl:
+ * orbsvcs/tests/Bug_2285_Regression/run_test2.pl:
+ * orbsvcs/tests/Bug_2285_Regression/server.cpp:
+ * orbsvcs/tests/Bug_2285_Regression/server2.cpp:
+ * orbsvcs/tests/Bug_2287_Regression/Bug_2287_Regression.mpc:
+ * orbsvcs/tests/Bug_2287_Regression/Hello.cpp:
+ * orbsvcs/tests/Bug_2287_Regression/Hello.h:
+ * orbsvcs/tests/Bug_2287_Regression/README:
+ * orbsvcs/tests/Bug_2287_Regression/ServerORBInitializer2.cpp:
+ * orbsvcs/tests/Bug_2287_Regression/ServerORBInitializer2.h:
+ * orbsvcs/tests/Bug_2287_Regression/ServerRequest_Interceptor2.cpp:
+ * orbsvcs/tests/Bug_2287_Regression/ServerRequest_Interceptor2.h:
+ * orbsvcs/tests/Bug_2287_Regression/Test.idl:
+ * orbsvcs/tests/Bug_2287_Regression/client.cpp:
+ * orbsvcs/tests/Bug_2287_Regression/run_test.pl:
+ * orbsvcs/tests/Bug_2287_Regression/server.cpp:
+
+ Regression tests for these bugs.
+
Thu Oct 27 09:34:12 UTC 2005 Johnny Willemsen <jwillemsen@remedy.nl>
* tao/Sequence_T.{h,cpp}:
diff --git a/TAO/orbsvcs/orbsvcs/FaultTolerance/FT_ClientRequest_Interceptor.cpp b/TAO/orbsvcs/orbsvcs/FaultTolerance/FT_ClientRequest_Interceptor.cpp
index a1a47f277b6..f914c45ae99 100644
--- a/TAO/orbsvcs/orbsvcs/FaultTolerance/FT_ClientRequest_Interceptor.cpp
+++ b/TAO/orbsvcs/orbsvcs/FaultTolerance/FT_ClientRequest_Interceptor.cpp
@@ -1,23 +1,25 @@
// $Id$
#include "FT_ClientRequest_Interceptor.h"
+#include "FT_Service_Callbacks.h"
#include "orbsvcs/FT_CORBA_ORBC.h"
#include "tao/CORBA_String.h"
#include "tao/debug.h"
#include "tao/ORB_Constants.h"
#include "tao/CDR.h"
+#include "tao/PI/ClientRequestInfo.h"
#include "ace/UUID.h"
#include "ace/Lock_Adapter_T.h"
#include "ace/Lock.h"
#include "ace/Synch_Traits.h"
-#include "ace/OS_NS_sys_time.h"
ACE_RCSID (FaultTolerance,
FT_ORBInitializer,
"$Id$")
+
namespace TAO
{
FT_ClientRequest_Interceptor::FT_ClientRequest_Interceptor (void)
@@ -43,11 +45,6 @@ namespace TAO
delete this->lock_;
}
- FT_TSS *
- FT_ClientRequest_Interceptor::tss_resources (void)
- {
- return ACE_TSS_GET (&this->tss_,FT_TSS);
- }
char *
FT_ClientRequest_Interceptor::name (ACE_ENV_SINGLE_ARG_DECL_NOT_USED)
ACE_THROW_SPEC ((CORBA::SystemException))
@@ -104,17 +101,66 @@ namespace TAO
ACE_ENV_ARG_DECL_NOT_USED)
ACE_THROW_SPEC ((CORBA::SystemException))
{
- this->tss_resources ()->clean_flag_ = true;
}
void
FT_ClientRequest_Interceptor::receive_other (
- PortableInterceptor::ClientRequestInfo_ptr
- ACE_ENV_ARG_DECL_NOT_USED)
+ PortableInterceptor::ClientRequestInfo_ptr ri
+ ACE_ENV_ARG_DECL)
ACE_THROW_SPEC ((CORBA::SystemException,
PortableInterceptor::ForwardRequest))
{
+ TAO_ClientRequestInfo* tao_ri = dynamic_cast<TAO_ClientRequestInfo*> (ri);
+
+ if (!tao_ri)
+ {
+ ACE_THROW (CORBA::INTERNAL ());
+ }
+
+ TimeBase::TimeT expires = tao_ri->tao_ft_expiration_time ();
+ if (!expires)
+ {
+ // Not an FT request
+ return;
+ }
+
+ PortableInterceptor::ReplyStatus status = -1;
+
+ ACE_TRY
+ {
+ status = ri->reply_status(ACE_ENV_SINGLE_ARG_PARAMETER);
+ }
+ ACE_CATCHANY
+ {
+ // No reply status => Not a location forward.
+ return;
+ }
+ ACE_ENDTRY;
+
+ if (status == PortableInterceptor::LOCATION_FORWARD)
+ {
+ // We are in an FT request and a location forward has been received.
+
+ if (expires < TAO_FT_Service_Callbacks::now ())
+ {
+ // The request has already expired...
+
+ if (TAO_debug_level > 3)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "TAO_FT (%P|%t): FT_ClientRequest_Interceptor::receive_other - LOCATION_FORWARD received after request expiration.\n"));
+ }
+
+ // The spec says throw a SYSTEM_EXCEPTION, but doesn't specify which one.
+ // I think a TRANSIENT is the most suitable.
+ ACE_THROW (CORBA::TRANSIENT (
+ CORBA::SystemException::_tao_minor_code (
+ TAO_INVOCATION_LOCATION_FORWARD_MINOR_CODE,
+ errno),
+ CORBA::COMPLETED_NO));
+ }
+ }
}
void
@@ -274,7 +320,6 @@ namespace TAO
IOP::ServiceContext sc;
sc.context_id = IOP::FT_REQUEST;
-
CORBA::Policy_var policy =
ri->get_request_policy (FT::REQUEST_DURATION_POLICY
ACE_ENV_ARG_PARAMETER);
@@ -283,33 +328,34 @@ namespace TAO
FT::FTRequestServiceContext ftrsc;
ftrsc.client_id =
CORBA::string_dup (this->uuid_->to_string ()->c_str ());
- ftrsc.expiration_time =
- this->request_expiration_time (policy.in ()
- ACE_ENV_ARG_PARAMETER);
- ACE_TRY_CHECK;
- FT_TSS *tss =
- this->tss_resources ();
+ TAO_ClientRequestInfo* tao_ri = dynamic_cast<TAO_ClientRequestInfo*> (ri);
- if (tss->clean_flag_)
- {
- ACE_GUARD (ACE_Lock,
- guard,
- *this->lock_);
+ if (!tao_ri)
+ {
+ ACE_THROW (CORBA::INTERNAL ());
+ }
- ftrsc.retention_id = ++this->retention_id_;
-
- // ACE_DEBUG ((LM_DEBUG,
- // ACE_TEXT ("TAO_FT (%P|%t) - Retention id [%d]\n"),
- // ftrsc.retention_id));
- tss->retention_id_ = ftrsc.retention_id;
- tss->clean_flag_ = false;
- }
+ if (tao_ri->tao_ft_expiration_time ())
+ {
+ ftrsc.retention_id = tao_ri->tao_ft_retention_id ();
+ ftrsc.expiration_time = tao_ri->tao_ft_expiration_time ();
+ }
else
- {
- ftrsc.retention_id =
- tss->retention_id_;
- }
+ {
+ ACE_GUARD (ACE_Lock,
+ guard,
+ *this->lock_);
+
+ ftrsc.retention_id = ++this->retention_id_;
+ ftrsc.expiration_time =
+ this->request_expiration_time (policy.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ tao_ri->tao_ft_retention_id (ftrsc.retention_id);
+ tao_ri->tao_ft_expiration_time (ftrsc.expiration_time);
+ }
TAO_OutputCDR ocdr;
if (!(ocdr << ACE_OutputCDR::from_boolean (TAO_ENCAP_BYTE_ORDER)))
@@ -361,7 +407,7 @@ namespace TAO
{
p = FT::RequestDurationPolicy::_narrow (policy
ACE_ENV_ARG_PARAMETER);
- ACE_CHECK_RETURN (0);
+ ACE_CHECK_RETURN (0);
}
TimeBase::TimeT t = 0;
@@ -384,15 +430,7 @@ namespace TAO
}
// Calculaton of the expiration time
-
- // Grab the localtime on the machine where this is running
- ACE_Time_Value time_val = ACE_OS::gettimeofday ();
-
- TimeBase::TimeT sec_part = time_val.sec () * 10000000;
- TimeBase::TimeT usec_part = time_val.usec ()* 10;
-
- // Now we have the total time
- t += (sec_part + usec_part);
+ t += TAO_FT_Service_Callbacks::now ();
return t;
}
diff --git a/TAO/orbsvcs/orbsvcs/FaultTolerance/FT_ClientRequest_Interceptor.h b/TAO/orbsvcs/orbsvcs/FaultTolerance/FT_ClientRequest_Interceptor.h
index 8f82b1f8089..67dff801d64 100644
--- a/TAO/orbsvcs/orbsvcs/FaultTolerance/FT_ClientRequest_Interceptor.h
+++ b/TAO/orbsvcs/orbsvcs/FaultTolerance/FT_ClientRequest_Interceptor.h
@@ -118,8 +118,6 @@ namespace TAO
ACE_ENV_ARG_DECL)
ACE_THROW_SPEC ((CORBA::SystemException));
- FT_TSS *tss_resources (void);
-
private:
/// Name of the interceptor
@@ -128,10 +126,7 @@ namespace TAO
/// UUID for this client
ACE_Utils::UUID *uuid_;
- /// TSS data
- ACE_TSS_TYPE (FT_TSS) tss_;
-
- /// @@ Need a resource factory for this too
+ /// @@ Need a resource factory for this too
ACE_Lock *lock_;
/// Retention id generated by the client
diff --git a/TAO/orbsvcs/orbsvcs/FaultTolerance/FT_Service_Callbacks.cpp b/TAO/orbsvcs/orbsvcs/FaultTolerance/FT_Service_Callbacks.cpp
index 87b81d728bc..3cee20d2237 100644
--- a/TAO/orbsvcs/orbsvcs/FaultTolerance/FT_Service_Callbacks.cpp
+++ b/TAO/orbsvcs/orbsvcs/FaultTolerance/FT_Service_Callbacks.cpp
@@ -3,6 +3,8 @@
#include "FT_Service_Callbacks.h"
#include "FT_ClientPolicy_i.h"
+#include "ace/OS_NS_sys_time.h"
+
#include "tao/MProfile.h"
#include "tao/Profile.h"
#include "tao/Tagged_Components.h"
@@ -20,11 +22,7 @@ TAO_FT_Service_Callbacks::TAO_FT_Service_Callbacks (
TAO_ORB_Core *orb_core)
: orb_core_ (orb_core),
- profile_lock_ (0),
- primary_failed_ (0),
- secondary_set_ (0),
- group_component_ (),
- group_component_flag_ (0)
+ profile_lock_ (0)
{
this->profile_lock_ =
this->orb_core_->client_factory ()->create_profile_lock ();
@@ -223,8 +221,20 @@ TAO_FT_Service_Callbacks::restart_policy_check (
{
if (service_list[i].context_id == IOP::FT_REQUEST)
{
- // Success
- return 1;
+ // This would be a heck of a lot easier if we had the invocation
+ // here rather than just the contexts, but lemons -> lemonade I guess.
+ TAO_InputCDR cdr (ACE_reinterpret_cast (const char*,
+ service_list[i].context_data.get_buffer()),
+ service_list[i].context_data.length());
+ CORBA::Boolean byte_order;
+ if ((cdr >> ACE_InputCDR::to_boolean (byte_order)) == 0)
+ return 0;
+ cdr.reset_byte_order (ACE_static_cast (int, byte_order));
+ FT::FTRequestServiceContext ftsrc;
+ if ((cdr >> ftsrc) == 0)
+ return 0;
+
+ return (ftsrc.expiration_time > now ());
}
}
}
@@ -232,3 +242,15 @@ TAO_FT_Service_Callbacks::restart_policy_check (
// Failure
return 0;
}
+
+TimeBase::TimeT
+TAO_FT_Service_Callbacks::now (void)
+{
+ // Grab the localtime on the machine where this is running
+ ACE_Time_Value time_val = ACE_OS::gettimeofday ();
+ TimeBase::TimeT sec_part = ((TimeBase::TimeT)time_val.sec ()) * 10000000;
+ TimeBase::TimeT usec_part = ((TimeBase::TimeT)time_val.usec ()) * 10;
+
+ // Add the offset to convert from posix time.
+ return (sec_part + usec_part + ACE_UINT64_LITERAL (0x1B21DD213814000));
+}
diff --git a/TAO/orbsvcs/orbsvcs/FaultTolerance/FT_Service_Callbacks.h b/TAO/orbsvcs/orbsvcs/FaultTolerance/FT_Service_Callbacks.h
index c3a83efba4c..c05c36eac39 100644
--- a/TAO/orbsvcs/orbsvcs/FaultTolerance/FT_Service_Callbacks.h
+++ b/TAO/orbsvcs/orbsvcs/FaultTolerance/FT_Service_Callbacks.h
@@ -70,6 +70,8 @@ public:
IOP::ServiceContextList &clist,
TAO_Profile *profile
ACE_ENV_ARG_DECL);
+
+ static TimeBase::TimeT now (void);
private:
@@ -85,27 +87,6 @@ private:
/// Mutex to protect access to the profile that gets passed along
/// @@ Lock needs to be removed...
ACE_Lock* profile_lock_;
-
- /**
- * A flag that indicates that the primary has already failed. So any
- * more calls to select_profile () should not reset the profile
- * pointer to the primary.
- */
- CORBA::Boolean primary_failed_;
-
- /**
- * A flag to indicate that a secondary has been selected for
- * invocation. We do this only once in the cycle. When we get there
- * again we dont select a primary again and again.
- */
- CORBA::Boolean secondary_set_;
-
- /// FT group component in the IOGR
- FT::TagFTGroupTaggedComponent group_component_;
-
- /// A flag to indicate whether we have extracted the
- /// <group_component> before.
- CORBA::Boolean group_component_flag_;
};
#include /**/ "ace/post.h"
diff --git a/TAO/orbsvcs/tests/Bug_2285_Regression/Bug_2285_Regression.mpc b/TAO/orbsvcs/tests/Bug_2285_Regression/Bug_2285_Regression.mpc
new file mode 100644
index 00000000000..6de5d11009a
--- /dev/null
+++ b/TAO/orbsvcs/tests/Bug_2285_Regression/Bug_2285_Regression.mpc
@@ -0,0 +1,38 @@
+// -*- MPC -*-
+// $Id$
+
+project(*Client): taoserver, ftclientorb {
+ exename = client
+ Source_Files {
+ client.cpp
+ Hello.cpp
+ }
+}
+
+project (*Server) : taoserver, ftclientorb, pi_server {
+ Source_Files {
+ server.cpp
+ Hello.cpp
+ ServerORBInitializer.cpp
+ ServerRequest_Interceptor.cpp
+ }
+}
+
+project(*Client2): taoclient, ftclientorb, iormanip {
+ exename = client2
+ Source_Files {
+ client2.cpp
+ TestC.cpp
+ }
+}
+
+project (*Server2) : taoserver, pi_server, ftclientorb {
+ exename = server2
+ Source_Files {
+ server2.cpp
+ Hello.cpp
+ ServerORBInitializer2.cpp
+ ServerRequest_Interceptor2.cpp
+ }
+}
+
diff --git a/TAO/orbsvcs/tests/Bug_2285_Regression/Hello.cpp b/TAO/orbsvcs/tests/Bug_2285_Regression/Hello.cpp
new file mode 100644
index 00000000000..6463bd8e9ec
--- /dev/null
+++ b/TAO/orbsvcs/tests/Bug_2285_Regression/Hello.cpp
@@ -0,0 +1,74 @@
+//
+// $Id$
+//
+#include "Hello.h"
+
+ACE_RCSID(Hello, Hello, "$Id$")
+
+CORBA::Boolean
+Hello::ids_differ_ = 1;
+
+Hello::Hello (CORBA::ORB_ptr orb, Test::Hello_ptr server, CORBA::ULong server_id)
+ : orb_ (CORBA::ORB::_duplicate (orb)),
+ server_ (Test::Hello::_duplicate (server)),
+ server_id_ (server_id)
+{
+}
+
+char *
+Hello::get_string (ACE_ENV_SINGLE_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ return CORBA::string_dup ("Hello there!");
+}
+
+void
+Hello::shutdown (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ this->orb_->shutdown (0 ACE_ENV_ARG_PARAMETER);
+}
+
+void
+Hello::throw_exception (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException, Test::MyException))
+{
+ ACE_THROW (Test::MyException ());
+}
+
+// Nested sequence step 1 - This op called by the client on the server
+CORBA::Boolean
+Hello::call_me_back (Test::Hello_ptr me ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ CORBA::Boolean result = me->call_back (ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+ return result;
+}
+
+// Nested sequence step 2 - This op called by the server on the client
+CORBA::Boolean
+Hello::call_back (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ CORBA::Boolean result = server_->check_request_id (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK;
+ return result;
+}
+
+// Nested sequence step 3 - This op called by the client on the server
+CORBA::Boolean
+Hello::check_request_id (ACE_ENV_SINGLE_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ // The server request interceptor will have set this public static member
+ // false if the same retention id has been used twice
+ return ids_differ_;
+}
+
+CORBA::ULong
+Hello::drop_down_dead (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ return server_id_;
+}
diff --git a/TAO/orbsvcs/tests/Bug_2285_Regression/Hello.h b/TAO/orbsvcs/tests/Bug_2285_Regression/Hello.h
new file mode 100644
index 00000000000..1d6904c2b35
--- /dev/null
+++ b/TAO/orbsvcs/tests/Bug_2285_Regression/Hello.h
@@ -0,0 +1,64 @@
+//
+// $Id$
+//
+
+#ifndef HELLO_H
+#define HELLO_H
+#include /**/ "ace/pre.h"
+
+#include "TestS.h"
+
+#if defined (_MSC_VER)
+# pragma warning(push)
+# pragma warning (disable:4250)
+#endif /* _MSC_VER */
+
+/// Implement the Test::Hello interface
+class Hello
+ : public virtual POA_Test::Hello
+ , public virtual PortableServer::RefCountServantBase
+{
+public:
+ /// Constructor
+ Hello (CORBA::ORB_ptr orb, Test::Hello_ptr server, CORBA::ULong server_id = 0);
+
+ // = The skeleton methods
+ virtual char * get_string (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ virtual void shutdown (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ virtual void throw_exception (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException, Test::MyException));
+
+ virtual CORBA::Boolean call_me_back (Test::Hello_ptr me ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ virtual CORBA::Boolean call_back (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ virtual CORBA::Boolean check_request_id (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ virtual CORBA::ULong drop_down_dead (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ static CORBA::Boolean ids_differ_;
+
+private:
+ /// Use an ORB reference to conver strings to objects and shutdown
+ /// the application.
+ CORBA::ORB_var orb_;
+
+ Test::Hello_var server_;
+
+ CORBA::ULong server_id_;
+};
+
+#if defined(_MSC_VER)
+# pragma warning(pop)
+#endif /* _MSC_VER */
+
+#include /**/ "ace/post.h"
+#endif /* HELLO_H */
diff --git a/TAO/orbsvcs/tests/Bug_2285_Regression/README b/TAO/orbsvcs/tests/Bug_2285_Regression/README
new file mode 100644
index 00000000000..eb174b925d9
--- /dev/null
+++ b/TAO/orbsvcs/tests/Bug_2285_Regression/README
@@ -0,0 +1,96 @@
+// $Id$
+
+See http://deuce.doc.wustl.edu/bugzilla/show_bug.cgi?id=2285 for more.
+
+These two test scenarios test that the following FT spec conditions are met:
+
+1 / "The retention_id uniquely identifies the request within the scope of the client and the expiration_time."
+2 / "Each repetition of a request must carry the same client_id, retention_id, and expiration_time as the original request."
+3 / "If a client ORB loses the connection with a server or incurs some other kind of transport fault, the ORB may attempt to retransmit the request message, or retransmit the request message to an alternative destination or using an alternative transport, up to the expiration_time."
+4 / "TimeBase::TimeT expiration_time" and "TimeT represents a single time value, which is 64 bits in size, and holds the number of 100 nanoseconds that have passed since the base time. For absolute time the base is 15 October 1582 00:00 of the Gregorian Calendar. All absolute time shall be computed using dates from the Gregorian Calendar."
+
+Test #1 checks that unique retention IDs are used in two scenarios:
+1/ When a request follows a previous request that concluded with an exception being returned to the application code.
+2/ When a subsequent request is made in a thread when that thread still as a response to a previous request outstanding.
+
+__Test #1 - Regression 1 & 2__
+
+TAO249_ServerRequest_Interceptor::receive_request (24807|3074381504) called for method: throw_exception ... client retention id is: 1
+Client catches a MyException, as expected. No problem !
+TAO249_ServerRequest_Interceptor::receive_request (24807|3074381504) called for method: call_me_back ... client retention id is: 1
+Test Failed - REGRESSION !!! Same client retention id has been used for TWO consecutive independent invocations!!
+TAO249_ServerRequest_Interceptor::receive_request (24807|3074381504) called for method: check_request_id ... client retention id is: 1
+Test Failed - REGRESSION !!! Same client retention id has been used for TWO consecutive independent invocations!!
+TAO249_ServerRequest_Interceptor::receive_request (24807|3074381504) called for method: shutdown ... client retention id is: 2
+(24807|3074381504) server - event loop finished
+Error: REGRESSION identified!!!
+ERROR: client returned 1
+
+__Test #1 - Successful result__
+
+E:\doc_cvs\ACE_wrappers\TAO\orbsvcs\tests\tao249_regression>run_test.pl
+TAO249_ServerRequest_Interceptor::receive_request (2844|1244) called for method: throw_exception ... client retention id is: 1
+Client catches a MyException, as expected. No problem !
+TAO249_ServerRequest_Interceptor::receive_request (2844|1244) called for method: call_me_back ... client retention id is: 2
+TAO249_ServerRequest_Interceptor::receive_request (2844|1244) called for method: check_request_id ... client retention id is: 3
+TAO249_ServerRequest_Interceptor::receive_request (2844|1244) called for method: shutdown ... client retention id is: 4
+(2844|1244) server - event loop finished
+Test passed !!!
+
+Test #2 checks that 4 conditions are met:
+1/ That the conversion from ACE_Time_Value to TimeT used in the calculation of the expiration time is done correctly.
+2/ That the correct offset has been applied to convert from posix to gregorian time.
+3/ That the client reuses the same original expiration time on all retries of the same request.
+4/ That the client stops retrying a request once the expiration time has passed.
+
+__Test #2 - Regression 1__
+
+Test Failed - REGRESSION !!! Expiration time is garbage - it is after 2358 A.D.!!
+Expiration time: 18446744072261958952
+2358 A.D. : 244385856000000000
+Error: REGRESSION identified by server 0. Test Failed !!
+Error: REGRESSION identified!!!
+ERROR: client returned 1
+
+__Test #2 - Regression 2__
+
+Test Failed - REGRESSION !!! Expiration time is in wrong format - it is before 1970 A.D. !!
+Expiration time: 11301710711718750
+1970 A.D. : 122192928000000000
+Error: REGRESSION identified by server 0. Test Failed !!
+Error: REGRESSION identified!!!
+ERROR: client returned 1
+
+__Test #2 - Regression 3__
+
+abnormal program termination
+Test Failed - REGRESSION !!! Different expiration times used on consecutive retries of the same op!!
+Previous expiration: 133494646145937500
+Current expiration : 133494646183906250
+Error: REGRESSION identified by server 1. Test Failed !!
+Error: REGRESSION identified!!!
+ERROR: client returned 1
+
+__Test #2 - Regression 4__
+
+abnormal program termination
+...
+abnormal program termination
+Test Failed - REGRESSION !!! Client ORB is still retrying after the expiration time!!
+Expiration time : 133494661968437500
+Previous attempt : 133494661990000000
+Time now : 133494662015156250
+Error: REGRESSION identified by server 2. Test Failed !!
+Error: REGRESSION identified!!!
+ERROR: client returned 1
+
+__Test #2 - Successful result:__
+
+abnormal program termination
+
+abnormal program termination
+(4084|3584) EXCEPTION, Client caught transport exception, as expected. No problem !
+
+system exception, ID 'IDL:omg.org/CORBA/COMM_FAILURE:1.0' TAO exception, minor code = 6 (failed to recv request response; ENOENT), completed = MAYBE
+
+Test passed !!!
diff --git a/TAO/orbsvcs/tests/Bug_2285_Regression/ServerORBInitializer.cpp b/TAO/orbsvcs/tests/Bug_2285_Regression/ServerORBInitializer.cpp
new file mode 100644
index 00000000000..e371cd8c9be
--- /dev/null
+++ b/TAO/orbsvcs/tests/Bug_2285_Regression/ServerORBInitializer.cpp
@@ -0,0 +1,52 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ServerORBInitializer.h"
+#include "ServerRequest_Interceptor.h"
+#include "tao/ORB_Constants.h"
+#include "tao/Exception.h"
+
+
+void
+Server_ORBInitializer::pre_init (
+ PortableInterceptor::ORBInitInfo_ptr
+ ACE_ENV_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+
+}
+
+void
+Server_ORBInitializer::post_init (
+ PortableInterceptor::ORBInitInfo_ptr info
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ this->register_server_request_interceptors (info
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+}
+
+void
+Server_ORBInitializer::register_server_request_interceptors (
+ PortableInterceptor::ORBInitInfo_ptr info
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ PortableInterceptor::ServerRequestInterceptor_ptr sri =
+ PortableInterceptor::ServerRequestInterceptor::_nil ();
+
+ ACE_NEW_THROW_EX (sri,
+ TAO249_ServerRequest_Interceptor,
+ CORBA::NO_MEMORY ());
+
+ PortableInterceptor::ServerRequestInterceptor_var
+ server_interceptor = sri;
+
+ info->add_server_request_interceptor (server_interceptor.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+}
+
+
diff --git a/TAO/orbsvcs/tests/Bug_2285_Regression/ServerORBInitializer.h b/TAO/orbsvcs/tests/Bug_2285_Regression/ServerORBInitializer.h
new file mode 100644
index 00000000000..2289b58c552
--- /dev/null
+++ b/TAO/orbsvcs/tests/Bug_2285_Regression/ServerORBInitializer.h
@@ -0,0 +1,63 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * $Id$
+ */
+//=============================================================================
+#ifndef TAO249_SERVER_ORBINITIALIZER_H
+#define TAO249_SERVER_ORBINITIALIZER_H
+
+#include /**/ "ace/pre.h"
+
+#include "tao/PortableInterceptorC.h"
+#include "tao/PI_Server/PI_Server_includeC.h"
+#include "tao/PI/PI.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "tao/LocalObject.h"
+
+// This is to remove "inherits via dominance" warnings from MSVC.
+// MSVC is being a little too paranoid.
+#if defined(_MSC_VER)
+#if (_MSC_VER >= 1200)
+#pragma warning(push)
+#endif /* _MSC_VER >= 1200 */
+#pragma warning(disable:4250)
+#endif /* _MSC_VER */
+
+/// RTCORBA ORB initializer.
+class Server_ORBInitializer :
+ public virtual PortableInterceptor::ORBInitializer,
+ public virtual TAO_Local_RefCounted_Object
+{
+public:
+
+ virtual void pre_init (PortableInterceptor::ORBInitInfo_ptr info
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ virtual void post_init (PortableInterceptor::ORBInitInfo_ptr info
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+private:
+
+ /// Register the necessary interceptors.
+ void register_server_request_interceptors (
+ PortableInterceptor::ORBInitInfo_ptr info
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+};
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+#pragma warning(pop)
+#endif /* _MSC_VER */
+
+#include /**/ "ace/post.h"
+
+#endif /* TAO249_SERVER_ORBINITIALIZER_H */
diff --git a/TAO/orbsvcs/tests/Bug_2285_Regression/ServerORBInitializer2.cpp b/TAO/orbsvcs/tests/Bug_2285_Regression/ServerORBInitializer2.cpp
new file mode 100644
index 00000000000..f7a7b408be7
--- /dev/null
+++ b/TAO/orbsvcs/tests/Bug_2285_Regression/ServerORBInitializer2.cpp
@@ -0,0 +1,52 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ServerORBInitializer2.h"
+#include "ServerRequest_Interceptor2.h"
+#include "tao/ORB_Constants.h"
+#include "tao/Exception.h"
+
+
+void
+Server_ORBInitializer2::pre_init (
+ PortableInterceptor::ORBInitInfo_ptr
+ ACE_ENV_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+
+}
+
+void
+Server_ORBInitializer2::post_init (
+ PortableInterceptor::ORBInitInfo_ptr info
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ this->register_server_request_interceptors (info
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+}
+
+void
+Server_ORBInitializer2::register_server_request_interceptors (
+ PortableInterceptor::ORBInitInfo_ptr info
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ PortableInterceptor::ServerRequestInterceptor_ptr sri =
+ PortableInterceptor::ServerRequestInterceptor::_nil ();
+
+ ACE_NEW_THROW_EX (sri,
+ TAO249_ServerRequest_Interceptor2,
+ CORBA::NO_MEMORY ());
+
+ PortableInterceptor::ServerRequestInterceptor_var
+ server_interceptor = sri;
+
+ info->add_server_request_interceptor (server_interceptor.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+}
+
+
diff --git a/TAO/orbsvcs/tests/Bug_2285_Regression/ServerORBInitializer2.h b/TAO/orbsvcs/tests/Bug_2285_Regression/ServerORBInitializer2.h
new file mode 100644
index 00000000000..2134d7a18af
--- /dev/null
+++ b/TAO/orbsvcs/tests/Bug_2285_Regression/ServerORBInitializer2.h
@@ -0,0 +1,63 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * $Id$
+ */
+//=============================================================================
+#ifndef TAO249_SERVER_ORBINITIALIZER2_H
+#define TAO249_SERVER_ORBINITIALIZER2_H
+
+#include /**/ "ace/pre.h"
+
+#include "tao/PortableInterceptorC.h"
+#include "tao/PI_Server/PI_Server_includeC.h"
+#include "tao/PI/PI.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "tao/LocalObject.h"
+
+// This is to remove "inherits via dominance" warnings from MSVC.
+// MSVC is being a little too paranoid.
+#if defined(_MSC_VER)
+#if (_MSC_VER >= 1200)
+#pragma warning(push)
+#endif /* _MSC_VER >= 1200 */
+#pragma warning(disable:4250)
+#endif /* _MSC_VER */
+
+/// RTCORBA ORB initializer.
+class Server_ORBInitializer2 :
+ public virtual PortableInterceptor::ORBInitializer,
+ public virtual TAO_Local_RefCounted_Object
+{
+public:
+
+ virtual void pre_init (PortableInterceptor::ORBInitInfo_ptr info
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ virtual void post_init (PortableInterceptor::ORBInitInfo_ptr info
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+private:
+
+ /// Register the necessary interceptors.
+ void register_server_request_interceptors (
+ PortableInterceptor::ORBInitInfo_ptr info
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+};
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+#pragma warning(pop)
+#endif /* _MSC_VER */
+
+#include /**/ "ace/post.h"
+
+#endif /* TAO249_SERVER_ORBINITIALIZER2_H */
diff --git a/TAO/orbsvcs/tests/Bug_2285_Regression/ServerRequest_Interceptor.cpp b/TAO/orbsvcs/tests/Bug_2285_Regression/ServerRequest_Interceptor.cpp
new file mode 100644
index 00000000000..fcc78e90810
--- /dev/null
+++ b/TAO/orbsvcs/tests/Bug_2285_Regression/ServerRequest_Interceptor.cpp
@@ -0,0 +1,144 @@
+// -*- C++ -*-
+
+#include "ServerRequest_Interceptor.h"
+#include "orbsvcs/FT_CORBA_ORBC.h"
+#include "tao/IOP_IORC.h"
+#include "tao/ORB_Constants.h"
+#include "tao/AnyTypeCode/DynamicC.h"
+#include "tao/AnyTypeCode/TypeCode.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_string.h"
+#include "Hello.h"
+
+ACE_RCSID (FaultTolerance,
+ TAO249_ServerRequest_Interceptor,
+ "$Id$")
+
+TAO249_ServerRequest_Interceptor::TAO249_ServerRequest_Interceptor (void)
+: orb_ (0),
+ client_id_ (0)
+{
+}
+
+TAO249_ServerRequest_Interceptor::~TAO249_ServerRequest_Interceptor (void)
+{
+}
+
+
+char *
+TAO249_ServerRequest_Interceptor::name (ACE_ENV_SINGLE_ARG_DECL_NOT_USED)
+ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ return CORBA::string_dup ("TAO_TAO249_ServerRequest_Interceptor");
+}
+
+void
+TAO249_ServerRequest_Interceptor::destroy (ACE_ENV_SINGLE_ARG_DECL_NOT_USED)
+ACE_THROW_SPEC ((CORBA::SystemException))
+{
+}
+
+void
+TAO249_ServerRequest_Interceptor::receive_request_service_contexts (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ ACE_ENV_ARG_DECL)
+ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest))
+{
+}
+
+void
+TAO249_ServerRequest_Interceptor::receive_request (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ ACE_ENV_ARG_DECL_NOT_USED)
+ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest))
+{
+ CORBA::String_var op = ri->operation (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_CHECK;
+ ACE_TRY
+ {
+ IOP::ServiceContext_var sc =
+ ri->get_request_service_context (IOP::FT_REQUEST
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ TAO_InputCDR cdr (reinterpret_cast <const char*>
+ (sc->context_data.get_buffer ()),
+ sc->context_data.length ());
+
+ CORBA::Boolean byte_order;
+
+ if ((cdr >> ACE_InputCDR::to_boolean (byte_order)) == 0)
+ {
+ ACE_THROW (CORBA::BAD_PARAM (CORBA::OMGVMCID | 28,
+ CORBA::COMPLETED_NO));
+ }
+ ACE_TRY_CHECK;
+
+ cdr.reset_byte_order (static_cast <int> (byte_order));
+
+ FT::FTRequestServiceContext ftrsc;
+
+ if ((cdr >> ftrsc) == 0)
+ ACE_THROW (CORBA::BAD_PARAM (CORBA::OMGVMCID | 28,
+ CORBA::COMPLETED_NO));
+ ACE_TRY_CHECK;
+
+ ACE_DEBUG ((LM_DEBUG, "TAO249_ServerRequest_Interceptor::receive_request (%P|%t) called for method: %s ... client retention id is: %d\n", op.in (), ftrsc.retention_id ));
+
+ if (client_id_ == 0)
+ {
+ client_id_ = ftrsc.retention_id;
+ }
+ else
+ {
+ if (client_id_ != ftrsc.retention_id)
+ {
+ client_id_ = ftrsc.retention_id;
+ }
+ else
+ {
+ ACE_DEBUG ((LM_ERROR, "Test Failed - REGRESSION !!! Same client retention id has been used for TWO consecutive independent invocations!!\n"));
+ Hello::ids_differ_ = 0;
+ }
+ }
+ }
+ACE_CATCHANY
+ {
+ ACE_DEBUG ((LM_ERROR, "Unexpected (non regression) error - test failed\n"));
+ ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,
+ "Exception in TAO249_ServerRequest_Interceptor::receive_request \n");
+ ACE_RE_THROW;
+ }
+ACE_ENDTRY;
+ACE_CHECK;
+
+}
+
+void
+TAO249_ServerRequest_Interceptor::send_reply (
+ PortableInterceptor::ServerRequestInfo_ptr
+ ACE_ENV_ARG_DECL_NOT_USED)
+ACE_THROW_SPEC ((CORBA::SystemException))
+{
+}
+
+void
+TAO249_ServerRequest_Interceptor::send_exception (
+ PortableInterceptor::ServerRequestInfo_ptr
+ ACE_ENV_ARG_DECL_NOT_USED)
+ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest))
+{
+}
+
+void
+TAO249_ServerRequest_Interceptor::send_other (
+ PortableInterceptor::ServerRequestInfo_ptr
+ ACE_ENV_ARG_DECL_NOT_USED)
+ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest))
+{
+}
+
diff --git a/TAO/orbsvcs/tests/Bug_2285_Regression/ServerRequest_Interceptor.h b/TAO/orbsvcs/tests/Bug_2285_Regression/ServerRequest_Interceptor.h
new file mode 100644
index 00000000000..139005e7a4a
--- /dev/null
+++ b/TAO/orbsvcs/tests/Bug_2285_Regression/ServerRequest_Interceptor.h
@@ -0,0 +1,101 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * $Id$
+ */
+//=============================================================================
+
+#ifndef TAO249_SERVER_REQUEST_INTERCEPTOR_H
+#define TAO249_SERVER_REQUEST_INTERCEPTOR_H
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+#include "tao/LocalObject.h"
+#include "tao/PortableInterceptorC.h"
+#include "tao/ORB.h"
+#include "tao/PI/PI.h"
+#include "tao/PI_Server/PI_Server.h"
+
+#if defined(_MSC_VER)
+#if (_MSC_VER >= 1200)
+#pragma warning(push)
+#endif /* _MSC_VER >= 1200 */
+#pragma warning(disable:4250)
+#endif /* _MSC_VER */
+
+/**
+* $Id$
+*/
+class TAO249_ServerRequest_Interceptor
+: public virtual PortableInterceptor::ServerRequestInterceptor,
+ public virtual TAO_Local_RefCounted_Object
+{
+public:
+
+/// Constructor.
+TAO249_ServerRequest_Interceptor (void);
+
+/// Destructor.
+~TAO249_ServerRequest_Interceptor (void);
+
+/**
+ * @name Methods Required by the Server Request Interceptor
+ * Interface
+ *
+ * These are methods that must be implemented since they are pure
+ * virtual in the abstract base class. They are the canonical
+ * methods required for all server request interceptors.
+ */
+//@{
+/// Return the name of this ServerRequestinterceptor.
+virtual char * name (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+virtual void destroy (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+virtual void receive_request_service_contexts (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ ACE_ENV_ARG_DECL)
+ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest));
+
+virtual void receive_request (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest));
+
+virtual void send_reply (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+virtual void send_exception (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest));
+
+virtual void send_other (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest));
+//@}
+private:
+
+CORBA::ORB_var orb_;
+
+CORBA:: Long client_id_;
+};
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+#pragma warning(pop)
+#endif /* _MSC_VER */
+
+#endif /* TAO249_SERVER_REQUEST_INTERCEPTOR_H */
diff --git a/TAO/orbsvcs/tests/Bug_2285_Regression/ServerRequest_Interceptor2.cpp b/TAO/orbsvcs/tests/Bug_2285_Regression/ServerRequest_Interceptor2.cpp
new file mode 100644
index 00000000000..b1b9cf78f48
--- /dev/null
+++ b/TAO/orbsvcs/tests/Bug_2285_Regression/ServerRequest_Interceptor2.cpp
@@ -0,0 +1,239 @@
+// -*- C++ -*-
+
+#include "ServerRequest_Interceptor2.h"
+#include "orbsvcs/FT_CORBA_ORBC.h"
+#include "tao/IOP_IORC.h"
+#include "tao/ORB_Constants.h"
+#include "tao/AnyTypeCode/DynamicC.h"
+#include "tao/AnyTypeCode/TypeCode.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_unistd.h"
+#include "Hello.h"
+#include "ace/OS_NS_sys_time.h"
+
+ACE_RCSID (FaultTolerance,
+ TAO249_ServerRequest_Interceptor2,
+ "$Id$")
+
+TAO249_ServerRequest_Interceptor2::TAO249_ServerRequest_Interceptor2 (void)
+: orb_ (0),
+ client_id_ (0)
+{
+}
+
+TAO249_ServerRequest_Interceptor2::~TAO249_ServerRequest_Interceptor2 (void)
+{
+}
+
+
+char *
+TAO249_ServerRequest_Interceptor2::name (ACE_ENV_SINGLE_ARG_DECL_NOT_USED)
+ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ return CORBA::string_dup ("TAO_TAO249_ServerRequest_Interceptor2");
+}
+
+void
+TAO249_ServerRequest_Interceptor2::destroy (ACE_ENV_SINGLE_ARG_DECL_NOT_USED)
+ACE_THROW_SPEC ((CORBA::SystemException))
+{
+}
+
+void
+TAO249_ServerRequest_Interceptor2::receive_request_service_contexts (
+ PortableInterceptor::ServerRequestInfo_ptr
+ ACE_ENV_ARG_DECL)
+ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest))
+{
+}
+
+void
+TAO249_ServerRequest_Interceptor2::receive_request (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ ACE_ENV_ARG_DECL_NOT_USED)
+ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest))
+{
+ CORBA::String_var op = ri->operation (ACE_ENV_SINGLE_ARG_PARAMETER);
+
+ if (ACE_OS::strcmp (op.in (), "drop_down_dead"))
+ {
+ // bail if not the op we are interested in -
+ // avoid excess spurious error clutter when client calls ::shutdown
+ return;
+ }
+
+ ACE_CHECK;
+ ACE_TRY
+ {
+ IOP::ServiceContext_var sc =
+ ri->get_request_service_context (IOP::FT_REQUEST
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ TAO_InputCDR cdr (reinterpret_cast <const char*>
+ (sc->context_data.get_buffer ()
+ ),
+ sc->context_data.length ());
+
+ CORBA::Boolean byte_order;
+
+ if ((cdr >> ACE_InputCDR::to_boolean (byte_order)) == 0)
+ {
+ ACE_THROW (CORBA::BAD_PARAM (CORBA::OMGVMCID | 28,
+ CORBA::COMPLETED_NO));
+ }
+ ACE_TRY_CHECK;
+
+ cdr.reset_byte_order (static_cast <int>(byte_order));
+
+ FT::FTRequestServiceContext ftrsc;
+
+ if ((cdr >> ftrsc) == 0)
+ ACE_THROW (CORBA::BAD_PARAM (CORBA::OMGVMCID | 28,
+ CORBA::COMPLETED_NO));
+ ACE_TRY_CHECK;
+
+ FILE* last_exp_time_file = ACE_OS::fopen ("last_expiration_time", "r+");
+ TimeBase::TimeT last_exp_time = 0;
+
+ if (!last_exp_time_file)
+ {
+ // file does not exist ... we're the first server
+ // create new file for the expiration time
+ last_exp_time_file = ACE_OS::fopen ("last_expiration_time", "w+");
+ last_exp_time = ftrsc.expiration_time;
+ }
+ else
+ {
+ // We're a subsequent server... read in the previous server's expiration time
+ ACE_OS::fread (&last_exp_time,
+ 1,
+ sizeof (TimeBase::TimeT),
+ last_exp_time_file);
+ ACE_OS::sleep (1);
+ }
+
+ if (last_exp_time != ftrsc.expiration_time)
+ {
+ ACE_DEBUG ((LM_DEBUG, "Test Failed - REGRESSION !!! Different expiration times used on consecutive retries of the same op!!\n"));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT("Previous expiration: %Q\n"), last_exp_time));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT("Current expiration : %Q\n"), ftrsc.expiration_time));
+ return;
+ }
+
+
+ // This is the offset from UTC to posix - a value less than than this will
+ // indicate posix is (mistakenly) being used
+ TimeBase::TimeT the_seventies = ACE_UINT64_LITERAL (0x1B21DD213814000);
+
+ // @warning - this test is fragile. It will break in 2358 A.D. :-)
+ if (last_exp_time <= the_seventies)
+ {
+ ACE_DEBUG ((LM_ERROR, "Test Failed - REGRESSION !!! Expiration time is in wrong format - it is before 1970 A.D. !!\n"));
+ ACE_DEBUG ((LM_DEBUG, "Expiration time: %Q\n", last_exp_time));
+ ACE_DEBUG ((LM_DEBUG, "1970 A.D. : %Q\n", the_seventies));
+ return;
+ }
+ else if ( last_exp_time > (the_seventies * 2))
+ {
+ ACE_DEBUG ((LM_ERROR, "Test Failed - REGRESSION !!! Expiration time is garbage - it is after 2358 A.D. !!\n"));
+ ACE_DEBUG ((LM_DEBUG, "Expiration time: %Q\n", last_exp_time));
+ ACE_DEBUG ((LM_DEBUG, "2358 A.D. : %Q\n", (the_seventies * 2)));
+ return;
+ }
+
+ TimeBase::TimeT now = get_now ();
+
+ if (now > last_exp_time)
+ {
+ // We have passed the exp time... there should be no more retries received after this point...
+ FILE* no_more_retries = ACE_OS::fopen ("no_more_retries", "r+");
+ if (no_more_retries)
+ {
+ TimeBase::TimeT last_expired_attempt = 0;
+ ACE_OS::fread (&last_expired_attempt, 1, sizeof (TimeBase::TimeT), no_more_retries);
+ ACE_OS::fclose (no_more_retries);
+
+ // There has already been an attempt after the last server passed the expiration time
+ ACE_DEBUG ((LM_ERROR, "Test Failed - REGRESSION !!! Client ORB is still retrying after the expiration time!!\n"));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT("Expiration time : %Q\n"), last_exp_time));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT("Previous attempt : %Q\n"), last_expired_attempt));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT("Time now : %Q\n"), now));
+ return;
+ }
+ else
+ {
+ // Tell the next server we've passed the point of no return
+ no_more_retries = ACE_OS::fopen ("no_more_retries", "w+");
+ ACE_OS::fwrite (&now, 1, sizeof (TimeBase::TimeT), no_more_retries);
+ ACE_OS::fflush (no_more_retries);
+ ACE_OS::fclose (no_more_retries);
+ }
+ }
+
+ // Everthing is fine so far. Write out the expiration time for the next server to check
+ ACE_OS::fwrite (&ftrsc.expiration_time, 1, sizeof (TimeBase::TimeT), last_exp_time_file);
+ ACE_OS::fflush (last_exp_time_file);
+ ACE_OS::fclose (last_exp_time_file);
+
+ // Goodbye cruel world !!
+ ACE_OS::abort ();
+ }
+ACE_CATCHANY
+ {
+ ACE_DEBUG ((LM_ERROR, "Unexpected (non regression problem) error - test failed\n"));
+ ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,
+ "Exception in TAO249_ServerRequest_Interceptor2::receive_request \n");
+ ACE_RE_THROW;
+ }
+ACE_ENDTRY;
+ACE_CHECK;
+
+}
+
+TimeBase::TimeT
+TAO249_ServerRequest_Interceptor2::get_now (void)
+{
+ // 1582...
+ const TimeBase::TimeT timeOffset = ACE_UINT64_LITERAL (0x1B21DD213814000);
+
+ // Now in posix
+ ACE_Time_Value time_value = ACE_OS::gettimeofday ();
+
+ TimeBase::TimeT sec_part = time_value.sec ();
+ sec_part = sec_part * 10000000;
+ TimeBase::TimeT usec_part = time_value.usec ();
+ usec_part = usec_part * 10;
+ return (sec_part + usec_part + timeOffset);
+}
+
+void
+TAO249_ServerRequest_Interceptor2::send_reply (
+ PortableInterceptor::ServerRequestInfo_ptr
+ ACE_ENV_ARG_DECL_NOT_USED)
+ACE_THROW_SPEC ((CORBA::SystemException))
+{
+}
+
+void
+TAO249_ServerRequest_Interceptor2::send_exception (
+ PortableInterceptor::ServerRequestInfo_ptr
+ ACE_ENV_ARG_DECL_NOT_USED)
+ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest))
+{
+}
+
+void
+TAO249_ServerRequest_Interceptor2::send_other (
+ PortableInterceptor::ServerRequestInfo_ptr
+ ACE_ENV_ARG_DECL_NOT_USED)
+ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest))
+{
+}
+
diff --git a/TAO/orbsvcs/tests/Bug_2285_Regression/ServerRequest_Interceptor2.h b/TAO/orbsvcs/tests/Bug_2285_Regression/ServerRequest_Interceptor2.h
new file mode 100644
index 00000000000..dba286df8cf
--- /dev/null
+++ b/TAO/orbsvcs/tests/Bug_2285_Regression/ServerRequest_Interceptor2.h
@@ -0,0 +1,106 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * $Id$
+ */
+//=============================================================================
+
+#ifndef TAO249_SERVER_REQUEST_INTERCEPTOR2_H
+#define TAO249_SERVER_REQUEST_INTERCEPTOR2_H
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+#include "tao/LocalObject.h"
+#include "tao/PortableInterceptorC.h"
+#include "tao/ORB.h"
+#include "tao/PI/PI.h"
+#include "tao/PI_Server/PI_Server.h"
+#include "tao/TimeBaseC.h"
+
+#if defined(_MSC_VER)
+#if (_MSC_VER >= 1200)
+#pragma warning(push)
+#endif /* _MSC_VER >= 1200 */
+#pragma warning(disable:4250)
+#endif /* _MSC_VER */
+
+/**
+* $Id$
+*/
+class TAO249_ServerRequest_Interceptor2
+: public virtual PortableInterceptor::ServerRequestInterceptor,
+ public virtual TAO_Local_RefCounted_Object
+{
+public:
+
+/// Constructor.
+TAO249_ServerRequest_Interceptor2 (void);
+
+/// Destructor.
+~TAO249_ServerRequest_Interceptor2 (void);
+
+/**
+ * @name Methods Required by the Server Request Interceptor
+ * Interface
+ *
+ * These are methods that must be implemented since they are pure
+ * virtual in the abstract base class. They are the canonical
+ * methods required for all server request interceptors.
+ */
+//@{
+/// Return the name of this ServerRequestinterceptor.
+virtual char * name (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+virtual void destroy (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+virtual void receive_request_service_contexts (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ ACE_ENV_ARG_DECL)
+ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest));
+
+virtual void receive_request (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest));
+
+virtual void send_reply (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+virtual void send_exception (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest));
+
+virtual void send_other (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest));
+//@}
+
+protected:
+ TimeBase::TimeT get_now (void);
+
+private:
+
+CORBA::ORB_var orb_;
+
+CORBA::Long client_id_;
+};
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+#pragma warning(pop)
+#endif /* _MSC_VER */
+
+#endif /* TAO249_SERVER_REQUEST_INTERCEPTOR2_H */
diff --git a/TAO/orbsvcs/tests/Bug_2285_Regression/Test.idl b/TAO/orbsvcs/tests/Bug_2285_Regression/Test.idl
new file mode 100644
index 00000000000..00cc73c174e
--- /dev/null
+++ b/TAO/orbsvcs/tests/Bug_2285_Regression/Test.idl
@@ -0,0 +1,43 @@
+//
+// $Id$
+//
+
+/// Put the interfaces in a module, to avoid global namespace pollution
+module Test
+{
+ exception MyException {};
+ /// A very simple interface
+ interface Hello
+ {
+ /// A method to shutdown the ORB
+ /**
+ * This method is used to simplify the test shutdown process
+ */
+ oneway void shutdown ();
+
+ // Methods for first test
+
+ // The client first calls this to generate a (user) exception
+ // which is handled in the application code
+ void throw_exception () raises (MyException);
+
+ // Starts the nested sequence - client calls...
+ boolean call_me_back (in Hello me);
+
+ // ... then the server calls this back onto the client,
+ // which prompts the client to call...
+ boolean call_back ();
+
+ // ... this ! The server interceptor will have been recording
+ // if any retention ID has been reused in the sequence of invocations
+ // @return true for all different, false otherwise.
+ boolean check_request_id ();
+
+ // Method for second test. Makes the servant perform
+ // a number of checks and then either commit suicide (to prompt a
+ // retry on the next member of the IOGR) or to return
+ // successfully if it has detected a regresssion.
+ // @return the number identifying this servant with teh group
+ unsigned long drop_down_dead ();
+ };
+};
diff --git a/TAO/orbsvcs/tests/Bug_2285_Regression/client.cpp b/TAO/orbsvcs/tests/Bug_2285_Regression/client.cpp
new file mode 100644
index 00000000000..60c37b8dff5
--- /dev/null
+++ b/TAO/orbsvcs/tests/Bug_2285_Regression/client.cpp
@@ -0,0 +1,137 @@
+// $Id$
+
+#include "TestS.h"
+#include "ace/Get_Opt.h"
+#include "orbsvcs/FaultTolerance/FT_ClientService_Activate.h"
+#include "Hello.h"
+
+ACE_RCSID(Hello, client, "$Id$")
+
+const char *ior = "file://test.ior";
+
+int
+parse_args (int argc, char *argv[])
+{
+ ACE_Get_Opt get_opts (argc, argv, "k:");
+ int c;
+
+ while ((c = get_opts ()) != -1)
+ switch (c)
+ {
+ case 'k':
+ ior = get_opts.opt_arg ();
+ break;
+
+ case '?':
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "usage: %s "
+ "-k <ior> "
+ "\n",
+ argv [0]),
+ -1);
+ }
+ // Indicates sucessful parsing of the command line
+ return 0;
+}
+
+int
+main (int argc, char *argv[])
+{
+ CORBA::Boolean result = 0;
+ ACE_TRY_NEW_ENV
+ {
+ CORBA::ORB_var orb =
+ CORBA::ORB_init (argc, argv, "" ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ if (parse_args (argc, argv) != 0)
+ return 1;
+
+ CORBA::Object_var tmp =
+ orb->string_to_object(ior ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ Test::Hello_var hello =
+ Test::Hello::_narrow(tmp.in () ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ if (CORBA::is_nil (hello.in ()))
+ {
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ "Test failed - Not regression - Unexpected Nil Test::Hello reference <%s>\n",
+ ior),
+ 1);
+ }
+
+ CORBA::Object_var poa_object =
+ orb->resolve_initial_references("RootPOA" ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ PortableServer::POA_var root_poa =
+ PortableServer::POA::_narrow (poa_object.in () ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ if (CORBA::is_nil (root_poa.in ()))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ " (%P|%t) Test failed - Not regression - unexpected nil RootPOA\n"),
+ 1);
+
+ PortableServer::POAManager_var poa_manager =
+ root_poa->the_POAManager (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ if (parse_args (argc, argv) != 0)
+ return 1;
+
+ Hello *hello_impl;
+ ACE_NEW_RETURN (hello_impl,
+ Hello (orb.in (), hello.in ()),
+ 1);
+ PortableServer::ServantBase_var owner_transfer(hello_impl);
+
+ Test::Hello_var me =
+ hello_impl->_this (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ poa_manager->activate (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ ACE_TRY
+ {
+ hello->throw_exception (ACE_ENV_SINGLE_ARG_PARAMETER);
+ }
+ ACE_CATCH (Test::MyException, my_ex)
+ {
+ ACE_UNUSED_ARG (my_ex);
+ ACE_DEBUG ((LM_DEBUG, "Client catches a MyException, as expected. No problem !\n"));
+ }
+ ACE_ENDTRY;
+
+ result = ! hello->call_me_back (me.in () ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ hello->shutdown (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ orb->destroy (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+ }
+ ACE_CATCHANY
+ {
+ ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,
+ "Test failed (Not regression) because unexpected exception caught:");
+ return 1;
+ }
+ ACE_ENDTRY;
+
+ if (result)
+ {
+ ACE_DEBUG ((LM_ERROR, "Error: REGRESSION identified!!!\n"));
+ }
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG, "Test passed !!!\n"));
+ }
+ return result;
+}
diff --git a/TAO/orbsvcs/tests/Bug_2285_Regression/client2.cpp b/TAO/orbsvcs/tests/Bug_2285_Regression/client2.cpp
new file mode 100644
index 00000000000..b583afa297a
--- /dev/null
+++ b/TAO/orbsvcs/tests/Bug_2285_Regression/client2.cpp
@@ -0,0 +1,211 @@
+// $Id$
+
+#include "TestC.h"
+#include "ace/Get_Opt.h"
+#include "orbsvcs/FaultTolerance/FT_ClientService_Activate.h"
+#include "tao/IORManipulation/IORManip_Loader.h"
+#include "orbsvcs/FaultTolerance/FT_IOGR_Property.h"
+
+ACE_RCSID(Hello, client, "$Id$")
+
+//const char *ior = "file://test.ior";
+TAO_IOP::TAO_IOR_Manipulation_var iorm = 0;
+CORBA::ULong number_of_servers = 0;
+
+int
+parse_args (int argc, char *argv[])
+{
+ ACE_Get_Opt get_opts (argc, argv, "k:n:");
+ int c;
+
+ while ((c = get_opts ()) != -1)
+ switch (c)
+ {
+ case 'k':
+ break;
+ case 'n':
+ number_of_servers = ACE_OS::atoi (get_opts.opt_arg ());
+ break;
+ case '?':
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "usage: %s "
+ "-k <ior> "
+ "\n",
+ argv [0]),
+ -1);
+ }
+ // Indicates sucessful parsing of the command line
+ return 0;
+}
+
+CORBA::Object_ptr
+make_iogr (const char* domain_id, CORBA::ULongLong group_id, CORBA::ULong group_version, Test::Hello_ptr* refs ACE_ENV_ARG_DECL)
+{
+ FT::TagFTGroupTaggedComponent ft_tag_component;
+ // Create the list
+ TAO_IOP::TAO_IOR_Manipulation::IORList iors (number_of_servers);
+ iors.length(number_of_servers);
+ for (CORBA::ULong i = 0; i < number_of_servers; ++i)
+ {
+ iors [i] = CORBA::Object::_duplicate (refs[i]);
+ }
+
+ CORBA::Object_var new_ref =
+ iorm->merge_iors (iors ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ // Property values
+
+ // Major and Minor revision numbers
+ ft_tag_component.component_version.major = (CORBA::Octet) 1;
+ ft_tag_component.component_version.minor = (CORBA::Octet) 0;
+
+ // Domain id
+ //const char *id = "iogr_testing";
+ ft_tag_component.group_domain_id = domain_id;
+
+ // Object group id
+ ft_tag_component.object_group_id = group_id;
+
+ // Version
+ ft_tag_component.object_group_ref_version = group_version;
+
+ // Construct the IOGR Property class
+ TAO_FT_IOGR_Property iogr_prop (ft_tag_component);
+
+ // Set the property
+ CORBA::Boolean retval = iorm->set_property (&iogr_prop,
+ new_ref.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ // Set the primary
+ // See we are setting the second ior as the primary
+ if (retval != 0)
+ {
+ retval = iorm->set_primary (&iogr_prop,
+ refs[0],
+ new_ref.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+ }
+
+ return new_ref._retn ();
+}
+
+int
+main (int argc, char *argv[])
+{
+ CORBA::Boolean result = 0;
+ ACE_TRY_NEW_ENV
+ {
+ CORBA::ORB_var orb =
+ CORBA::ORB_init (argc, argv, "" ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ if (parse_args (argc, argv) != 0)
+ return 1;
+
+ // Get a ref to the IORManipulation object
+ CORBA::Object_var IORM =
+ orb->resolve_initial_references (TAO_OBJID_IORMANIPULATION,
+ 0
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ // Narrow
+ iorm =
+ TAO_IOP::TAO_IOR_Manipulation::_narrow (IORM.in() ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ Test::Hello_ptr *servers = new Test::Hello_ptr [number_of_servers];
+
+ for (CORBA::ULong i = 0; i < number_of_servers; ++ i)
+ {
+ char buf[4]; // if you run more than 10000 servers then you need your head looking at
+ const char *number = ACE_OS::itoa ((int) i, buf, 10);
+ ACE_CString ior_file ("file://n");
+ const char *ior = ((ior_file += number) += ".ior").c_str ();
+
+ CORBA::Object_var tmp =
+ orb->string_to_object(ior ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ servers[i] =
+ Test::Hello::_narrow(tmp.in () ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ if (CORBA::is_nil (servers[i]))
+ {
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ "Test failed - Not regression - Unexpected Nil Test::Hello reference <%s>\n",
+ ior),
+ 1);
+ }
+ }
+
+ CORBA::Object_var iogr = make_iogr ("Domain_1", 1, 1, servers ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ Test::Hello_var hello_iogr = Test::Hello::_narrow(iogr.in () ACE_ENV_ARG_PARAMETER);
+
+ CORBA::ULong last_server = 0;
+
+ ACE_TRY
+ {
+ last_server = hello_iogr->drop_down_dead (ACE_ENV_SINGLE_ARG_PARAMETER);
+ // If the call 'succeeds' the server has identified a regression.
+ result = 1;
+ ACE_DEBUG ((LM_ERROR, "Error: REGRESSION identified by server %u. Test Failed !!\n", last_server));
+ }
+ ACE_CATCH (CORBA::COMM_FAILURE, my_ex)
+ {
+ ACE_PRINT_EXCEPTION (my_ex, "Client caught transport exception, as expected. No problem !\n");
+ }
+ ACE_ENDTRY;
+
+ for (CORBA::ULong j = last_server; j < number_of_servers; ++j)
+ {
+ ACE_TRY
+ {
+ servers[j]->shutdown (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+ }
+ ACE_CATCHALL
+ {
+ // Well we tried...
+ }
+ ACE_ENDTRY;
+
+ CORBA::release (servers [j]);
+ }
+
+ for (CORBA::ULong k = 0; k < last_server; ++k)
+ {
+ CORBA::release (servers [k]);
+ }
+
+ delete [] servers;
+
+ orb->destroy (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+ }
+ ACE_CATCHANY
+ {
+ ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,
+ "Test failed (Not regression) because unexpected exception caught:");
+ return 1;
+ }
+ ACE_ENDTRY;
+
+ if (result)
+ {
+ ACE_DEBUG ((LM_ERROR, "Error: REGRESSION identified!!!\n"));
+ }
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG, "Test passed !!!\n"));
+ }
+ return result;
+}
diff --git a/TAO/orbsvcs/tests/Bug_2285_Regression/run_test.pl b/TAO/orbsvcs/tests/Bug_2285_Regression/run_test.pl
new file mode 100755
index 00000000000..de69f709455
--- /dev/null
+++ b/TAO/orbsvcs/tests/Bug_2285_Regression/run_test.pl
@@ -0,0 +1,49 @@
+eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
+ & eval 'exec perl -S $0 $argv:q'
+ if 0;
+
+# $Id$
+# -*- perl -*-
+
+use lib '../../../../bin';
+use PerlACE::Run_Test;
+
+$status = 0;
+
+$iorfile = PerlACE::LocalFile ("server.ior");
+unlink $iorfile;
+
+if (PerlACE::is_vxworks_test()) {
+ $SV = new PerlACE::ProcessVX ("server", "-o server.ior");
+}
+else {
+ $SV = new PerlACE::Process ("server", "-o $iorfile");
+}
+$CL = new PerlACE::Process ("client", " -k file://$iorfile");
+
+$SV->Spawn ();
+
+if (PerlACE::waitforfile_timed ($iorfile,
+ $PerlACE::wait_interval_for_process_creation) == -1) {
+ print STDERR "ERROR: cannot find file <$iorfile>\n";
+ $SV->Kill (); $SV->TimedWait (1);
+ exit 1;
+}
+
+$client = $CL->SpawnWaitKill (300);
+
+if ($client != 0) {
+ print STDERR "ERROR: client returned $client\n";
+ $status = 1;
+}
+
+$server = $SV->WaitKill (10);
+
+if ($server != 0) {
+ print STDERR "ERROR: server returned $server\n";
+ $status = 1;
+}
+
+unlink $iorfile;
+
+exit $status;
diff --git a/TAO/orbsvcs/tests/Bug_2285_Regression/run_test2.pl b/TAO/orbsvcs/tests/Bug_2285_Regression/run_test2.pl
new file mode 100755
index 00000000000..e96b15a55b2
--- /dev/null
+++ b/TAO/orbsvcs/tests/Bug_2285_Regression/run_test2.pl
@@ -0,0 +1,70 @@
+eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
+ & eval 'exec perl -S $0 $argv:q'
+ if 0;
+
+# $Id$
+# -*- perl -*-
+
+use lib '../../../../bin';
+use PerlACE::Run_Test;
+
+$status = 0;
+$number_of_servers = 5;
+
+@SV;
+
+unlink PerlACE::LocalFile ("last_expiration_time");
+unlink PerlACE::LocalFile ("no_more_retries");
+
+for ($counter = 0; $counter < $number_of_servers; $counter++)
+{
+ unlink PerlACE::LocalFile ("n".$counter.".ior");
+}
+
+for($counter=0; $counter < $number_of_servers; $counter++)
+{
+ if (PerlACE::is_vxworks_test()) {
+ push (@SV, new PerlACE::ProcessVX ("server2", "-n $counter"));
+ }
+ else {
+ push (@SV, new PerlACE::Process ("server2", "-n $counter"));
+ }
+
+ $SV[$counter]->Spawn ();
+}
+
+# Loops are cheap.
+for ($counter2=0; $counter2 < $number_of_servers; $counter2++)
+{
+ if (PerlACE::waitforfile_timed (PerlACE::LocalFile ("n".$counter2.".ior"),
+ $PerlACE::wait_interval_for_process_creation) == -1)
+ {
+ print STDERR "ERROR: cannot find file <n$counter2.ior>\n";
+ for ($kill_count = 0; $kill_count < $number_of_servers; $kill_count++)
+ {
+ $SV[$kill_count]->Kill (); $SV[$kill_count]->TimedWait (1);
+ }
+ exit 1;
+ }
+}
+
+$CL = new PerlACE::Process ("client2", " -n $number_of_servers");
+
+$client = $CL->SpawnWaitKill (300);
+
+if ($client != 0) {
+ print STDERR "ERROR: client returned $client\n";
+ $status = 1;
+}
+
+for ($counter = 0; $counter < $number_of_servers; $counter++)
+{
+ $SV[$counter]->WaitKill (10);
+
+ unlink PerlACE::LocalFile ("n".$counter.".ior");
+}
+
+unlink PerlACE::LocalFile ("last_expiration_time");
+unlink PerlACE::LocalFile ("no_more_retries");
+
+exit $status;
diff --git a/TAO/orbsvcs/tests/Bug_2285_Regression/server.cpp b/TAO/orbsvcs/tests/Bug_2285_Regression/server.cpp
new file mode 100644
index 00000000000..8c27291400e
--- /dev/null
+++ b/TAO/orbsvcs/tests/Bug_2285_Regression/server.cpp
@@ -0,0 +1,241 @@
+// $Id$
+
+#include "Hello.h"
+#include "ace/Get_Opt.h"
+#include "ace/OS_NS_stdio.h"
+#include "tao/IORManipulation/IORManip_Loader.h"
+#include "tao/PortableServer/PortableServer.h"
+#include "orbsvcs/FaultTolerance/FT_IOGR_Property.h"
+#include "ServerORBInitializer.h"
+#include "ServerRequest_Interceptor.h"
+#include "tao/PI/PI.h"
+#include "tao/ORBInitializer_Registry.h"
+
+ACE_RCSID (Hello,
+ server,
+ "$Id$")
+
+const char *ior_output_file = "test.ior";
+TAO_IOP::TAO_IOR_Manipulation_var iorm = 0;
+
+int
+parse_args (int argc, char *argv[])
+{
+ ACE_Get_Opt get_opts (argc, argv, "o:");
+ int c;
+
+ while ((c = get_opts ()) != -1)
+ switch (c)
+ {
+ case 'o':
+ ior_output_file = get_opts.opt_arg ();
+ break;
+
+ case '?':
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "usage: %s "
+ "-o <iorfile>"
+ "\n",
+ argv [0]),
+ -1);
+ }
+ // Indicates sucessful parsing of the command line
+ return 0;
+}
+
+CORBA::Object_ptr
+make_iogr (const char* domain_id, CORBA::ULongLong group_id, CORBA::ULong group_version, CORBA::Object_ptr ref ACE_ENV_ARG_DECL)
+{
+ FT::TagFTGroupTaggedComponent ft_tag_component;
+ // Create the list
+ TAO_IOP::TAO_IOR_Manipulation::IORList iors (1);
+ iors.length(1);
+ iors [0] = CORBA::Object::_duplicate (ref);
+
+ CORBA::Object_var new_ref =
+ iorm->merge_iors (iors ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ // Property values
+
+ // Major and Minor revision numbers
+ ft_tag_component.component_version.major = (CORBA::Octet) 1;
+ ft_tag_component.component_version.minor = (CORBA::Octet) 0;
+
+ // Domain id
+ //const char *id = "iogr_testing";
+ ft_tag_component.group_domain_id = domain_id;
+
+ // Object group id
+ ft_tag_component.object_group_id = group_id;
+
+ // Version
+ ft_tag_component.object_group_ref_version = group_version;
+
+ // Construct the IOGR Property class
+ TAO_FT_IOGR_Property iogr_prop (ft_tag_component);
+
+ // Set the property
+ CORBA::Boolean retval = iorm->set_property (&iogr_prop,
+ new_ref.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ // Set the primary
+ // See we are setting the second ior as the primary
+ if (retval != 0)
+ {
+ retval = iorm->set_primary (&iogr_prop,
+ new_ref.in (),
+ new_ref.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+ }
+
+ return new_ref._retn ();
+}
+
+int
+main (int argc, char *argv[])
+{
+ ACE_TRY_NEW_ENV
+ {
+ Server_ORBInitializer *temp_initializer = 0;
+ ACE_NEW_RETURN (temp_initializer,
+ Server_ORBInitializer,
+ -1); // No exceptions yet!
+ PortableInterceptor::ORBInitializer_var orb_initializer =
+ temp_initializer;
+
+ PortableInterceptor::register_orb_initializer (orb_initializer.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ CORBA::ORB_var orb =
+ CORBA::ORB_init (argc, argv, "" ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ CORBA::Object_var poa_object =
+ orb->resolve_initial_references("RootPOA" ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ PortableServer::POA_var root_poa =
+ PortableServer::POA::_narrow (poa_object.in () ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ if (CORBA::is_nil (root_poa.in ()))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ " (%P|%t) Panic: nil RootPOA\n"),
+ 1);
+
+ PortableServer::POAManager_var poa_manager =
+ root_poa->the_POAManager (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ CORBA::PolicyList policies (2);
+ policies.length (2);
+
+ policies[0] =
+ root_poa->create_id_assignment_policy (PortableServer::USER_ID
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK
+
+ policies[1] =
+ root_poa->create_lifespan_policy (PortableServer::PERSISTENT
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ PortableServer::POA_var my_poa =
+ root_poa->create_POA ("my_poa",
+ poa_manager.in (),
+ policies
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ // Creation of the new POA is over, so destroy the Policy_ptr's.
+ for (CORBA::ULong i = 0; i < policies.length (); ++i)
+ {
+ CORBA::Policy_ptr policy = policies[i];
+ policy->destroy (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+ }
+
+
+ if (parse_args (argc, argv) != 0)
+ return 1;
+
+ Hello *hello_impl;
+ ACE_NEW_RETURN (hello_impl,
+ Hello (orb.in (), Test::Hello::_nil ()),
+ 1);
+
+ PortableServer::ObjectId_var server_id =
+ PortableServer::string_to_ObjectId ("server_id");
+
+ my_poa->activate_object_with_id (server_id.in (),
+ hello_impl
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ CORBA::Object_var hello =
+ my_poa->id_to_reference (server_id.in () ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ CORBA::String_var ior =
+ orb->object_to_string (hello.in () ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ // Get a ref to the IORManipulation object
+ CORBA::Object_var IORM =
+ orb->resolve_initial_references (TAO_OBJID_IORMANIPULATION,
+ 0
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ // Narrow
+ iorm =
+ TAO_IOP::TAO_IOR_Manipulation::_narrow (IORM.in() ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ CORBA::Object_var iogr = make_iogr ("Domain_1", 1, 1, orb->string_to_object (ior.in ()) ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ CORBA::String_var iorgr_string =
+ orb->object_to_string (iogr.in () ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ // Output the IOR to the <ior_output_file>
+ FILE *output_file= ACE_OS::fopen (ior_output_file, "w");
+ if (output_file == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Cannot open output file for writing IOR: %s",
+ ior_output_file),
+ 1);
+ ACE_OS::fprintf (output_file, "%s", iorgr_string.in ());
+ ACE_OS::fclose (output_file);
+
+ poa_manager->activate (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ orb->run (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) server - event loop finished\n"));
+
+ root_poa->destroy (1, 1 ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ orb->destroy (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+ }
+ ACE_CATCHANY
+ {
+ ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,
+ "Exception caught:");
+ return 1;
+ }
+ ACE_ENDTRY;
+
+ return 0;
+}
diff --git a/TAO/orbsvcs/tests/Bug_2285_Regression/server2.cpp b/TAO/orbsvcs/tests/Bug_2285_Regression/server2.cpp
new file mode 100644
index 00000000000..43a23d567ec
--- /dev/null
+++ b/TAO/orbsvcs/tests/Bug_2285_Regression/server2.cpp
@@ -0,0 +1,175 @@
+// $Id$
+
+#include "Hello.h"
+#include "ace/Get_Opt.h"
+#include "ace/OS_NS_stdio.h"
+#include "tao/PortableServer/PortableServer.h"
+#include "ServerORBInitializer2.h"
+#include "ServerRequest_Interceptor2.h"
+#include "tao/PI/PI.h"
+#include "tao/ORBInitializer_Registry.h"
+
+ACE_RCSID (Hello,
+ server,
+ "$Id$")
+
+const char *ior_output_file = "";
+
+CORBA::ULong my_id_number = 0;
+
+int
+parse_args (int argc, char *argv[])
+{
+ ACE_Get_Opt get_opts (argc, argv, "o:n:");
+ int c;
+ ACE_CString ior_file ("n");
+ while ((c = get_opts ()) != -1)
+ switch (c)
+ {
+ case 'o':
+ ior_output_file = get_opts.opt_arg ();
+ break;
+ case 'n':
+ my_id_number = (CORBA::ULong) ACE_OS::atoi (get_opts.opt_arg ());
+ ior_file += get_opts.opt_arg ();
+ ior_file += ".ior";
+ ior_output_file = CORBA::string_dup (ior_file.c_str ());
+ break;
+ case '?':
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "usage: %s "
+ "[-o <iorfile>]"
+ "[-i <server_id>]"
+ "\n",
+ argv [0]),
+ -1);
+ }
+ // Indicates sucessful parsing of the command line
+ return 0;
+}
+
+
+
+int
+main (int argc, char *argv[])
+{
+ ACE_TRY_NEW_ENV
+ {
+ Server_ORBInitializer2 *temp_initializer = 0;
+ ACE_NEW_RETURN (temp_initializer,
+ Server_ORBInitializer2,
+ -1); // No exceptions yet!
+ PortableInterceptor::ORBInitializer_var orb_initializer =
+ temp_initializer;
+
+ PortableInterceptor::register_orb_initializer (orb_initializer.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ CORBA::ORB_var orb =
+ CORBA::ORB_init (argc, argv, "" ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ CORBA::Object_var poa_object =
+ orb->resolve_initial_references("RootPOA" ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ PortableServer::POA_var root_poa =
+ PortableServer::POA::_narrow (poa_object.in () ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ if (CORBA::is_nil (root_poa.in ()))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ " (%P|%t) Panic: nil RootPOA\n"),
+ 1);
+
+ PortableServer::POAManager_var poa_manager =
+ root_poa->the_POAManager (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ CORBA::PolicyList policies (2);
+ policies.length (2);
+
+ policies[0] =
+ root_poa->create_id_assignment_policy (PortableServer::USER_ID
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK
+
+ policies[1] =
+ root_poa->create_lifespan_policy (PortableServer::PERSISTENT
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ PortableServer::POA_var my_poa =
+ root_poa->create_POA ("my_poa",
+ poa_manager.in (),
+ policies
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ // Creation of the new POA is over, so destroy the Policy_ptr's.
+ for (CORBA::ULong i = 0; i < policies.length (); ++i)
+ {
+ CORBA::Policy_ptr policy = policies[i];
+ policy->destroy (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+ }
+
+
+ if (parse_args (argc, argv) != 0)
+ return 1;
+
+ Hello *hello_impl;
+ ACE_NEW_RETURN (hello_impl,
+ Hello (orb.in (), Test::Hello::_nil (), my_id_number),
+ 1);
+
+ PortableServer::ObjectId_var server_id =
+ PortableServer::string_to_ObjectId ("server_id");
+
+ my_poa->activate_object_with_id (server_id.in (),
+ hello_impl
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ CORBA::Object_var hello =
+ my_poa->id_to_reference (server_id.in () ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ CORBA::String_var ior =
+ orb->object_to_string (hello.in () ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ // Output the IOR to the <ior_output_file>
+ FILE *output_file= ACE_OS::fopen (ior_output_file, "w");
+ if (output_file == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Cannot open output file for writing IOR: %s\n",
+ ior_output_file),
+ 1);
+ ACE_OS::fprintf (output_file, "%s", ior.in ());
+ ACE_OS::fclose (output_file);
+
+ poa_manager->activate (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ orb->run (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ root_poa->destroy (1, 1 ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ orb->destroy (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+ }
+ ACE_CATCHANY
+ {
+ ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,
+ "Exception caught:");
+ return 1;
+ }
+ ACE_ENDTRY;
+
+ return 0;
+}
diff --git a/TAO/orbsvcs/tests/Bug_2287_Regression/Bug_2287_Regression.mpc b/TAO/orbsvcs/tests/Bug_2287_Regression/Bug_2287_Regression.mpc
new file mode 100644
index 00000000000..5a457cc15fb
--- /dev/null
+++ b/TAO/orbsvcs/tests/Bug_2287_Regression/Bug_2287_Regression.mpc
@@ -0,0 +1,20 @@
+// -*- MPC -*-
+// $Id$
+
+project(*Client): taoserver, ftclientorb {
+ exename = client
+ Source_Files {
+ client.cpp
+ Hello.cpp
+ }
+}
+
+project (*Server) : taoserver, ftclientorb, pi_server {
+ Source_Files {
+ server.cpp
+ Hello.cpp
+ ServerORBInitializer2.cpp
+ ServerRequest_Interceptor2.cpp
+ }
+}
+
diff --git a/TAO/orbsvcs/tests/Bug_2287_Regression/Hello.cpp b/TAO/orbsvcs/tests/Bug_2287_Regression/Hello.cpp
new file mode 100644
index 00000000000..be3f00426a0
--- /dev/null
+++ b/TAO/orbsvcs/tests/Bug_2287_Regression/Hello.cpp
@@ -0,0 +1,32 @@
+//
+// $Id$
+//
+#include "Hello.h"
+
+ACE_RCSID(Hello, Hello, "$Id$")
+
+Hello::Hello (CORBA::ORB_ptr orb, Test::Hello_ptr server, CORBA::ULong server_id)
+ : orb_ (CORBA::ORB::_duplicate (orb))
+{
+}
+
+void
+Hello::shutdown (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ this->orb_->shutdown (0 ACE_ENV_ARG_PARAMETER);
+}
+
+void
+Hello::ping (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ return;
+}
+
+void
+Hello::throw_location_forward (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ return;
+}
diff --git a/TAO/orbsvcs/tests/Bug_2287_Regression/Hello.h b/TAO/orbsvcs/tests/Bug_2287_Regression/Hello.h
new file mode 100644
index 00000000000..157f7339351
--- /dev/null
+++ b/TAO/orbsvcs/tests/Bug_2287_Regression/Hello.h
@@ -0,0 +1,46 @@
+//
+// $Id$
+//
+
+#ifndef HELLO_H
+#define HELLO_H
+#include /**/ "ace/pre.h"
+
+#include "TestS.h"
+
+#if defined (_MSC_VER)
+# pragma warning(push)
+# pragma warning (disable:4250)
+#endif /* _MSC_VER */
+
+/// Implement the Test::Hello interface
+class Hello
+ : public virtual POA_Test::Hello
+ , public virtual PortableServer::RefCountServantBase
+{
+public:
+ /// Constructor
+ Hello (CORBA::ORB_ptr orb, Test::Hello_ptr server, CORBA::ULong server_id = 0);
+
+ // = The skeleton methods
+ virtual void shutdown (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ virtual void ping (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ virtual void throw_location_forward (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+private:
+ /// Use an ORB reference to conver strings to objects and shutdown
+ /// the application.
+ CORBA::ORB_var orb_;
+};
+
+#if defined(_MSC_VER)
+# pragma warning(pop)
+#endif /* _MSC_VER */
+
+#include /**/ "ace/post.h"
+#endif /* HELLO_H */
diff --git a/TAO/orbsvcs/tests/Bug_2287_Regression/README b/TAO/orbsvcs/tests/Bug_2287_Regression/README
new file mode 100644
index 00000000000..3c77b3edb08
--- /dev/null
+++ b/TAO/orbsvcs/tests/Bug_2287_Regression/README
@@ -0,0 +1,32 @@
+// $Id$
+
+This test provides regression coverage for bugzilla #2287.
+
+See http://deuce.doc.wustl.edu/bugzilla/show_bug.cgi?id=2287 for more.
+
+The server installs a server request interceptor and persistent servant and writes out an IOGR for itself.
+The client installs client side FT support and invokes the method "throw_location_forward" on the IOGR.
+The server request interceptor detects invocations of this method and in response either:
+a/ Throws a location forward back to the original IOGR if cannot determine (from the expiration_time member of the FT request service context) thatthe client must have despatched the request after the expiration time.
+b/ Allows the request to be completed if it can determine absolutely that the request was despatched after the expiration time. This indicates a regression to the client.
+
+A successful outcome is if the client stops following the location forwards once it detects that the expiration time has passed, and a TRANSIENT system exception is recived in the application code.
+
+__Regression Output__
+
+The expiration time has now passed !!
+Expiration time : 133496335605156250
+Time now : 133496335605312500
+Test Failed - REGRESSION !!! Client ORB is still retrying LOCATION_FORWARDs after the expiration time!!
+Expiration time : 133496335605156250
+Time now : 133496335605312500
+REGRESSION - Test has failed !!!
+(3128|3992) server - event loop finished
+Error: REGRESSION identified!!!
+ERROR: client returned 1
+
+__Successful Output__
+
+Client catches a TRANSIENT, as expected. No problem !
+(3528|3532) server - event loop finished
+Test passed !!!
diff --git a/TAO/orbsvcs/tests/Bug_2287_Regression/ServerORBInitializer2.cpp b/TAO/orbsvcs/tests/Bug_2287_Regression/ServerORBInitializer2.cpp
new file mode 100644
index 00000000000..f7a7b408be7
--- /dev/null
+++ b/TAO/orbsvcs/tests/Bug_2287_Regression/ServerORBInitializer2.cpp
@@ -0,0 +1,52 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ServerORBInitializer2.h"
+#include "ServerRequest_Interceptor2.h"
+#include "tao/ORB_Constants.h"
+#include "tao/Exception.h"
+
+
+void
+Server_ORBInitializer2::pre_init (
+ PortableInterceptor::ORBInitInfo_ptr
+ ACE_ENV_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+
+}
+
+void
+Server_ORBInitializer2::post_init (
+ PortableInterceptor::ORBInitInfo_ptr info
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ this->register_server_request_interceptors (info
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+}
+
+void
+Server_ORBInitializer2::register_server_request_interceptors (
+ PortableInterceptor::ORBInitInfo_ptr info
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ PortableInterceptor::ServerRequestInterceptor_ptr sri =
+ PortableInterceptor::ServerRequestInterceptor::_nil ();
+
+ ACE_NEW_THROW_EX (sri,
+ TAO249_ServerRequest_Interceptor2,
+ CORBA::NO_MEMORY ());
+
+ PortableInterceptor::ServerRequestInterceptor_var
+ server_interceptor = sri;
+
+ info->add_server_request_interceptor (server_interceptor.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+}
+
+
diff --git a/TAO/orbsvcs/tests/Bug_2287_Regression/ServerORBInitializer2.h b/TAO/orbsvcs/tests/Bug_2287_Regression/ServerORBInitializer2.h
new file mode 100644
index 00000000000..2134d7a18af
--- /dev/null
+++ b/TAO/orbsvcs/tests/Bug_2287_Regression/ServerORBInitializer2.h
@@ -0,0 +1,63 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * $Id$
+ */
+//=============================================================================
+#ifndef TAO249_SERVER_ORBINITIALIZER2_H
+#define TAO249_SERVER_ORBINITIALIZER2_H
+
+#include /**/ "ace/pre.h"
+
+#include "tao/PortableInterceptorC.h"
+#include "tao/PI_Server/PI_Server_includeC.h"
+#include "tao/PI/PI.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "tao/LocalObject.h"
+
+// This is to remove "inherits via dominance" warnings from MSVC.
+// MSVC is being a little too paranoid.
+#if defined(_MSC_VER)
+#if (_MSC_VER >= 1200)
+#pragma warning(push)
+#endif /* _MSC_VER >= 1200 */
+#pragma warning(disable:4250)
+#endif /* _MSC_VER */
+
+/// RTCORBA ORB initializer.
+class Server_ORBInitializer2 :
+ public virtual PortableInterceptor::ORBInitializer,
+ public virtual TAO_Local_RefCounted_Object
+{
+public:
+
+ virtual void pre_init (PortableInterceptor::ORBInitInfo_ptr info
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ virtual void post_init (PortableInterceptor::ORBInitInfo_ptr info
+ ACE_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+private:
+
+ /// Register the necessary interceptors.
+ void register_server_request_interceptors (
+ PortableInterceptor::ORBInitInfo_ptr info
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+};
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+#pragma warning(pop)
+#endif /* _MSC_VER */
+
+#include /**/ "ace/post.h"
+
+#endif /* TAO249_SERVER_ORBINITIALIZER2_H */
diff --git a/TAO/orbsvcs/tests/Bug_2287_Regression/ServerRequest_Interceptor2.cpp b/TAO/orbsvcs/tests/Bug_2287_Regression/ServerRequest_Interceptor2.cpp
new file mode 100644
index 00000000000..6c2bb345ee7
--- /dev/null
+++ b/TAO/orbsvcs/tests/Bug_2287_Regression/ServerRequest_Interceptor2.cpp
@@ -0,0 +1,174 @@
+// -*- C++ -*-
+
+#include "ServerRequest_Interceptor2.h"
+#include "orbsvcs/FT_CORBA_ORBC.h"
+#include "tao/IOP_IORC.h"
+#include "tao/ORB_Constants.h"
+#include "tao/AnyTypeCode/DynamicC.h"
+#include "tao/AnyTypeCode/TypeCode.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_unistd.h"
+#include "Hello.h"
+#include "ace/OS_NS_sys_time.h"
+
+ACE_RCSID (FaultTolerance,
+ TAO249_ServerRequest_Interceptor2,
+ "$Id$")
+
+CORBA::Object_var
+TAO249_ServerRequest_Interceptor2::server_iogr_ = CORBA::Object::_nil ();
+
+TAO249_ServerRequest_Interceptor2::TAO249_ServerRequest_Interceptor2 (void)
+: orb_ (0),
+ expired_ (0)
+{
+}
+
+TAO249_ServerRequest_Interceptor2::~TAO249_ServerRequest_Interceptor2 (void)
+{
+}
+
+char *
+TAO249_ServerRequest_Interceptor2::name (ACE_ENV_SINGLE_ARG_DECL_NOT_USED)
+ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ return CORBA::string_dup ("TAO_TAO249_ServerRequest_Interceptor2");
+}
+
+void
+TAO249_ServerRequest_Interceptor2::destroy (ACE_ENV_SINGLE_ARG_DECL_NOT_USED)
+ACE_THROW_SPEC ((CORBA::SystemException))
+{
+}
+
+void
+TAO249_ServerRequest_Interceptor2::receive_request_service_contexts (
+ PortableInterceptor::ServerRequestInfo_ptr
+ ACE_ENV_ARG_DECL)
+ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest))
+{
+}
+
+void
+TAO249_ServerRequest_Interceptor2::receive_request (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ ACE_ENV_ARG_DECL_NOT_USED)
+ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest))
+{
+ CORBA::String_var op = ri->operation (ACE_ENV_SINGLE_ARG_PARAMETER);
+
+ if (ACE_OS::strcmp (op.in (), "throw_location_forward"))
+ {
+ // bail if not the op we are interested in -
+ // avoid excess spurious error clutter when client calls ::shutdown
+ return;
+ }
+
+
+ IOP::ServiceContext_var sc =
+ ri->get_request_service_context (IOP::FT_REQUEST
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK;
+
+ TAO_InputCDR cdr (reinterpret_cast <const char*>
+ (sc->context_data.get_buffer ()
+ ),
+ sc->context_data.length ());
+
+ CORBA::Boolean byte_order;
+
+ if ((cdr >> ACE_InputCDR::to_boolean (byte_order)) == 0)
+ {
+ ACE_THROW (CORBA::BAD_PARAM (CORBA::OMGVMCID | 28,
+ CORBA::COMPLETED_NO));
+ }
+ ACE_CHECK;
+
+ cdr.reset_byte_order (static_cast <int>(byte_order));
+
+ FT::FTRequestServiceContext ftrsc;
+
+ if ((cdr >> ftrsc) == 0)
+ ACE_THROW (CORBA::BAD_PARAM (CORBA::OMGVMCID | 28,
+ CORBA::COMPLETED_NO));
+ ACE_CHECK;
+
+ TimeBase::TimeT now = get_now ();
+
+ if (now > ftrsc.expiration_time)
+ {
+ // We have passed the exp time... there should be no more retries received after this point...
+ if (expired_)
+ {
+ // The client has retried after the expiration time. This is a regression
+ ACE_DEBUG ((LM_ERROR, "Test Failed - REGRESSION !!! Client ORB is still retrying LOCATION_FORWARDs after the expiration time!!\n"));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT("Expiration time : %Q\n"), ftrsc.expiration_time));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT("Time now : %Q\n"), now));
+
+ // Let the request 'succeed' rather than throwing a forward exception.
+ return;
+ }
+ else
+ {
+ // A request has been recioved after the expiration time.
+ // This could legitimately happen - it is only definitely a problem if
+ // the client keeps on retrying after now. We set a flag so we can check for this.
+ expired_ = 1;
+ ACE_DEBUG ((LM_DEBUG, "The expiration time has now passed !!\n"));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT("Expiration time : %Q\n"), ftrsc.expiration_time));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT("Time now : %Q\n"), now));
+ }
+ }
+
+ // Let's forward the client back to us again. I would like to be able to make this a PERM
+ // but there's no such animal in the PortableInterceptor module. Plus as we (currently) transform
+ // and marshal *all* forward requests as vanilla LOCATION_FORWARD it doesn't really matter.
+ ACE_THROW ((PortableInterceptor::ForwardRequest::ForwardRequest (server_iogr_.in ())));
+}
+
+TimeBase::TimeT
+TAO249_ServerRequest_Interceptor2::get_now (void)
+{
+ // 1582...
+ const TimeBase::TimeT timeOffset = ACE_UINT64_LITERAL (0x1B21DD213814000);
+
+ // Now in posix
+ ACE_Time_Value time_value = ACE_OS::gettimeofday ();
+
+ TimeBase::TimeT sec_part = time_value.sec ();
+ sec_part = sec_part * 10000000;
+ TimeBase::TimeT usec_part = time_value.usec ();
+ usec_part = usec_part * 10;
+ return (sec_part + usec_part + timeOffset);
+}
+
+void
+TAO249_ServerRequest_Interceptor2::send_reply (
+ PortableInterceptor::ServerRequestInfo_ptr
+ ACE_ENV_ARG_DECL_NOT_USED)
+ACE_THROW_SPEC ((CORBA::SystemException))
+{
+}
+
+void
+TAO249_ServerRequest_Interceptor2::send_exception (
+ PortableInterceptor::ServerRequestInfo_ptr
+ ACE_ENV_ARG_DECL_NOT_USED)
+ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest))
+{
+}
+
+void
+TAO249_ServerRequest_Interceptor2::send_other (
+ PortableInterceptor::ServerRequestInfo_ptr
+ ACE_ENV_ARG_DECL_NOT_USED)
+ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest))
+{
+}
+
diff --git a/TAO/orbsvcs/tests/Bug_2287_Regression/ServerRequest_Interceptor2.h b/TAO/orbsvcs/tests/Bug_2287_Regression/ServerRequest_Interceptor2.h
new file mode 100644
index 00000000000..2c9bfb1242c
--- /dev/null
+++ b/TAO/orbsvcs/tests/Bug_2287_Regression/ServerRequest_Interceptor2.h
@@ -0,0 +1,108 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * $Id$
+ */
+//=============================================================================
+
+#ifndef TAO249_SERVER_REQUEST_INTERCEPTOR2_H
+#define TAO249_SERVER_REQUEST_INTERCEPTOR2_H
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+#include "tao/LocalObject.h"
+#include "tao/PortableInterceptorC.h"
+#include "tao/ORB.h"
+#include "tao/PI/PI.h"
+#include "tao/PI_Server/PI_Server.h"
+#include "tao/TimeBaseC.h"
+
+#if defined(_MSC_VER)
+#if (_MSC_VER >= 1200)
+#pragma warning(push)
+#endif /* _MSC_VER >= 1200 */
+#pragma warning(disable:4250)
+#endif /* _MSC_VER */
+
+/**
+* $Id$
+*/
+class TAO249_ServerRequest_Interceptor2
+: public virtual PortableInterceptor::ServerRequestInterceptor,
+ public virtual TAO_Local_RefCounted_Object
+{
+public:
+
+/// Constructor.
+TAO249_ServerRequest_Interceptor2 (void);
+
+/// Destructor.
+~TAO249_ServerRequest_Interceptor2 (void);
+
+/**
+ * @name Methods Required by the Server Request Interceptor
+ * Interface
+ *
+ * These are methods that must be implemented since they are pure
+ * virtual in the abstract base class. They are the canonical
+ * methods required for all server request interceptors.
+ */
+//@{
+/// Return the name of this ServerRequestinterceptor.
+virtual char * name (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+virtual void destroy (ACE_ENV_SINGLE_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+virtual void receive_request_service_contexts (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ ACE_ENV_ARG_DECL)
+ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest));
+
+virtual void receive_request (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest));
+
+virtual void send_reply (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+virtual void send_exception (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest));
+
+virtual void send_other (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ ACE_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest));
+//@}
+
+static CORBA::Object_var server_iogr_;
+
+protected:
+ TimeBase::TimeT get_now (void);
+
+private:
+
+CORBA::ORB_var orb_;
+
+CORBA::Boolean expired_;
+};
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+#pragma warning(pop)
+#endif /* _MSC_VER */
+
+#endif /* TAO249_SERVER_REQUEST_INTERCEPTOR2_H */
diff --git a/TAO/orbsvcs/tests/Bug_2287_Regression/Test.idl b/TAO/orbsvcs/tests/Bug_2287_Regression/Test.idl
new file mode 100644
index 00000000000..9e1fa22e0be
--- /dev/null
+++ b/TAO/orbsvcs/tests/Bug_2287_Regression/Test.idl
@@ -0,0 +1,24 @@
+//
+// $Id$
+//
+
+/// Put the interfaces in a module, to avoid global namespace pollution
+module Test
+{
+ interface Hello
+ {
+ /// A method to shutdown the ORB
+ /**
+ * This method is used to simplify the test shutdown process
+ */
+ oneway void shutdown ();
+
+ // Lets make sure things are working
+ void ping ();
+
+ // The client calls this method which will generate
+ // a locate forward to the same IOGR on every invocation
+ // until well after the request expiration time when it will then succeed
+ void throw_location_forward ();
+ };
+};
diff --git a/TAO/orbsvcs/tests/Bug_2287_Regression/client.cpp b/TAO/orbsvcs/tests/Bug_2287_Regression/client.cpp
new file mode 100644
index 00000000000..efc5c8c1da7
--- /dev/null
+++ b/TAO/orbsvcs/tests/Bug_2287_Regression/client.cpp
@@ -0,0 +1,110 @@
+// $Id$
+
+#include "TestS.h"
+#include "ace/Get_Opt.h"
+#include "orbsvcs/FaultTolerance/FT_ClientService_Activate.h"
+#include "Hello.h"
+
+ACE_RCSID(Hello, client, "$Id$")
+
+const char *ior = "file://test.ior";
+
+int
+parse_args (int argc, char *argv[])
+{
+ ACE_Get_Opt get_opts (argc, argv, "k:");
+ int c;
+
+ while ((c = get_opts ()) != -1)
+ switch (c)
+ {
+ case 'k':
+ ior = get_opts.opt_arg ();
+ break;
+
+ case '?':
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "usage: %s "
+ "-k <ior> "
+ "\n",
+ argv [0]),
+ -1);
+ }
+ // Indicates sucessful parsing of the command line
+ return 0;
+}
+
+int
+main (int argc, char *argv[])
+{
+ CORBA::Boolean result = 0;
+ ACE_TRY_NEW_ENV
+ {
+ CORBA::ORB_var orb =
+ CORBA::ORB_init (argc, argv, "" ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ if (parse_args (argc, argv) != 0)
+ return 1;
+
+ CORBA::Object_var tmp =
+ orb->string_to_object(ior ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ Test::Hello_var hello =
+ Test::Hello::_narrow(tmp.in () ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ if (CORBA::is_nil (hello.in ()))
+ {
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ "Test failed - Not regression - Unexpected Nil Test::Hello reference <%s>\n",
+ ior),
+ 1);
+ }
+
+ // Check this isn't generating transients for any other reason
+ hello->ping (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+
+ ACE_TRY
+ {
+ hello->throw_location_forward (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ ACE_DEBUG ((LM_ERROR, "REGRESSION - Test has failed !!!\n"));
+ result = 1;
+ }
+ ACE_CATCH (CORBA::TRANSIENT, my_ex)
+ {
+ ACE_UNUSED_ARG (my_ex);
+ ACE_DEBUG ((LM_DEBUG, "Client catches a TRANSIENT, as expected. No problem !\n"));
+ }
+ ACE_ENDTRY;
+
+ hello->shutdown (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ orb->destroy (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+ }
+ ACE_CATCHANY
+ {
+ ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,
+ "Test failed (Not regression) because unexpected exception caught:");
+ return 1;
+ }
+ ACE_ENDTRY;
+
+ if (result)
+ {
+ ACE_DEBUG ((LM_ERROR, "Error: REGRESSION identified!!!\n"));
+ }
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG, "Test passed !!!\n"));
+ }
+ return result;
+}
diff --git a/TAO/orbsvcs/tests/Bug_2287_Regression/run_test.pl b/TAO/orbsvcs/tests/Bug_2287_Regression/run_test.pl
new file mode 100755
index 00000000000..de69f709455
--- /dev/null
+++ b/TAO/orbsvcs/tests/Bug_2287_Regression/run_test.pl
@@ -0,0 +1,49 @@
+eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
+ & eval 'exec perl -S $0 $argv:q'
+ if 0;
+
+# $Id$
+# -*- perl -*-
+
+use lib '../../../../bin';
+use PerlACE::Run_Test;
+
+$status = 0;
+
+$iorfile = PerlACE::LocalFile ("server.ior");
+unlink $iorfile;
+
+if (PerlACE::is_vxworks_test()) {
+ $SV = new PerlACE::ProcessVX ("server", "-o server.ior");
+}
+else {
+ $SV = new PerlACE::Process ("server", "-o $iorfile");
+}
+$CL = new PerlACE::Process ("client", " -k file://$iorfile");
+
+$SV->Spawn ();
+
+if (PerlACE::waitforfile_timed ($iorfile,
+ $PerlACE::wait_interval_for_process_creation) == -1) {
+ print STDERR "ERROR: cannot find file <$iorfile>\n";
+ $SV->Kill (); $SV->TimedWait (1);
+ exit 1;
+}
+
+$client = $CL->SpawnWaitKill (300);
+
+if ($client != 0) {
+ print STDERR "ERROR: client returned $client\n";
+ $status = 1;
+}
+
+$server = $SV->WaitKill (10);
+
+if ($server != 0) {
+ print STDERR "ERROR: server returned $server\n";
+ $status = 1;
+}
+
+unlink $iorfile;
+
+exit $status;
diff --git a/TAO/orbsvcs/tests/Bug_2287_Regression/server.cpp b/TAO/orbsvcs/tests/Bug_2287_Regression/server.cpp
new file mode 100644
index 00000000000..eca1cfc94de
--- /dev/null
+++ b/TAO/orbsvcs/tests/Bug_2287_Regression/server.cpp
@@ -0,0 +1,243 @@
+// $Id$
+
+#include "Hello.h"
+#include "ace/Get_Opt.h"
+#include "ace/OS_NS_stdio.h"
+#include "tao/IORManipulation/IORManip_Loader.h"
+#include "tao/PortableServer/PortableServer.h"
+#include "orbsvcs/FaultTolerance/FT_IOGR_Property.h"
+#include "ServerORBInitializer2.h"
+#include "ServerRequest_Interceptor2.h"
+#include "tao/PI/PI.h"
+#include "tao/ORBInitializer_Registry.h"
+
+ACE_RCSID (Hello,
+ server,
+ "$Id$")
+
+const char *ior_output_file = "test.ior";
+TAO_IOP::TAO_IOR_Manipulation_var iorm = 0;
+
+int
+parse_args (int argc, char *argv[])
+{
+ ACE_Get_Opt get_opts (argc, argv, "o:");
+ int c;
+
+ while ((c = get_opts ()) != -1)
+ switch (c)
+ {
+ case 'o':
+ ior_output_file = get_opts.opt_arg ();
+ break;
+
+ case '?':
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "usage: %s "
+ "-o <iorfile>"
+ "\n",
+ argv [0]),
+ -1);
+ }
+ // Indicates sucessful parsing of the command line
+ return 0;
+}
+
+CORBA::Object_ptr
+make_iogr (const char* domain_id, CORBA::ULongLong group_id, CORBA::ULong group_version, CORBA::Object_ptr ref ACE_ENV_ARG_DECL)
+{
+ FT::TagFTGroupTaggedComponent ft_tag_component;
+ // Create the list
+ TAO_IOP::TAO_IOR_Manipulation::IORList iors (1);
+ iors.length(1);
+ iors [0] = CORBA::Object::_duplicate (ref);
+
+ CORBA::Object_var new_ref =
+ iorm->merge_iors (iors ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ // Property values
+
+ // Major and Minor revision numbers
+ ft_tag_component.component_version.major = (CORBA::Octet) 1;
+ ft_tag_component.component_version.minor = (CORBA::Octet) 0;
+
+ // Domain id
+ //const char *id = "iogr_testing";
+ ft_tag_component.group_domain_id = domain_id;
+
+ // Object group id
+ ft_tag_component.object_group_id = group_id;
+
+ // Version
+ ft_tag_component.object_group_ref_version = group_version;
+
+ // Construct the IOGR Property class
+ TAO_FT_IOGR_Property iogr_prop (ft_tag_component);
+
+ // Set the property
+ CORBA::Boolean retval = iorm->set_property (&iogr_prop,
+ new_ref.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+
+ // Set the primary
+ // See we are setting the second ior as the primary
+ if (retval != 0)
+ {
+ retval = iorm->set_primary (&iogr_prop,
+ new_ref.in (),
+ new_ref.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (0);
+ }
+
+ return new_ref._retn ();
+}
+
+int
+main (int argc, char *argv[])
+{
+ ACE_TRY_NEW_ENV
+ {
+ Server_ORBInitializer2 *temp_initializer = 0;
+ ACE_NEW_RETURN (temp_initializer,
+ Server_ORBInitializer2,
+ -1); // No exceptions yet!
+ PortableInterceptor::ORBInitializer_var orb_initializer =
+ temp_initializer;
+
+ PortableInterceptor::register_orb_initializer (orb_initializer.in ()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ CORBA::ORB_var orb =
+ CORBA::ORB_init (argc, argv, "" ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ CORBA::Object_var poa_object =
+ orb->resolve_initial_references("RootPOA" ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ PortableServer::POA_var root_poa =
+ PortableServer::POA::_narrow (poa_object.in () ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ if (CORBA::is_nil (root_poa.in ()))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ " (%P|%t) Panic: nil RootPOA\n"),
+ 1);
+
+ PortableServer::POAManager_var poa_manager =
+ root_poa->the_POAManager (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ CORBA::PolicyList policies (2);
+ policies.length (2);
+
+ policies[0] =
+ root_poa->create_id_assignment_policy (PortableServer::USER_ID
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK
+
+ policies[1] =
+ root_poa->create_lifespan_policy (PortableServer::PERSISTENT
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ PortableServer::POA_var my_poa =
+ root_poa->create_POA ("my_poa",
+ poa_manager.in (),
+ policies
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ // Creation of the new POA is over, so destroy the Policy_ptr's.
+ for (CORBA::ULong i = 0; i < policies.length (); ++i)
+ {
+ CORBA::Policy_ptr policy = policies[i];
+ policy->destroy (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+ }
+
+
+ if (parse_args (argc, argv) != 0)
+ return 1;
+
+ Hello *hello_impl;
+ ACE_NEW_RETURN (hello_impl,
+ Hello (orb.in (), Test::Hello::_nil ()),
+ 1);
+
+ PortableServer::ObjectId_var server_id =
+ PortableServer::string_to_ObjectId ("server_id");
+
+ my_poa->activate_object_with_id (server_id.in (),
+ hello_impl
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ CORBA::Object_var hello =
+ my_poa->id_to_reference (server_id.in () ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ CORBA::String_var ior =
+ orb->object_to_string (hello.in () ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ // Get a ref to the IORManipulation object
+ CORBA::Object_var IORM =
+ orb->resolve_initial_references (TAO_OBJID_IORMANIPULATION,
+ 0
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ // Narrow
+ iorm =
+ TAO_IOP::TAO_IOR_Manipulation::_narrow (IORM.in() ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ CORBA::Object_var iogr = make_iogr ("Domain_1", 1, 1, orb->string_to_object (ior.in ()) ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ CORBA::String_var iorgr_string =
+ orb->object_to_string (iogr.in () ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ // Output the IOR to the <ior_output_file>
+ FILE *output_file= ACE_OS::fopen (ior_output_file, "w");
+ if (output_file == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Cannot open output file for writing IOR: %s",
+ ior_output_file),
+ 1);
+ ACE_OS::fprintf (output_file, "%s", iorgr_string.in ());
+ ACE_OS::fclose (output_file);
+
+ TAO249_ServerRequest_Interceptor2::server_iogr_ = CORBA::Object::_duplicate (iogr.in ());
+
+ poa_manager->activate (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ orb->run (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) server - event loop finished\n"));
+
+ root_poa->destroy (1, 1 ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ orb->destroy (ACE_ENV_SINGLE_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+ }
+ ACE_CATCHANY
+ {
+ ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,
+ "Exception caught:");
+ return 1;
+ }
+ ACE_ENDTRY;
+
+ return 0;
+}
diff --git a/TAO/tao/PI/ClientRequestInfo.cpp b/TAO/tao/PI/ClientRequestInfo.cpp
index 544a2694509..58117d9903c 100644
--- a/TAO/tao/PI/ClientRequestInfo.cpp
+++ b/TAO/tao/PI/ClientRequestInfo.cpp
@@ -722,4 +722,28 @@ TAO_ClientRequestInfo::check_validity (ACE_ENV_SINGLE_ARG_DECL)
CORBA::COMPLETED_NO));
}
+void
+TAO_ClientRequestInfo::tao_ft_expiration_time (TimeBase::TimeT time)
+{
+ this->invocation_->operation_details ().ft_expiration_time (time);
+}
+
+TimeBase::TimeT
+TAO_ClientRequestInfo::tao_ft_expiration_time (void) const
+{
+ return this->invocation_->operation_details ().ft_expiration_time ();
+}
+
+void
+TAO_ClientRequestInfo::tao_ft_retention_id (CORBA::Long request_id)
+{
+ this->invocation_->operation_details ().ft_retention_id (request_id) ;
+}
+
+CORBA::Long
+TAO_ClientRequestInfo::tao_ft_retention_id (void) const
+{
+ return this->invocation_->operation_details ().ft_retention_id ();
+}
+
#endif /* TAO_HAS_INTERCEPTORS == 1 */
diff --git a/TAO/tao/PI/ClientRequestInfo.h b/TAO/tao/PI/ClientRequestInfo.h
index 4a47e23de92..e25052b7d67 100644
--- a/TAO/tao/PI/ClientRequestInfo.h
+++ b/TAO/tao/PI/ClientRequestInfo.h
@@ -39,6 +39,7 @@
#include "tao/ORB_Constants.h"
#include "tao/LocalObject.h"
#include "tao/Invocation_Utils.h"
+#include "tao/TimeBaseC.h"
class TAO_Service_Context;
@@ -67,7 +68,7 @@ namespace Messaging
* @brief Implementation of the PortableInterceptor::ClientRequestInfo
* interface.
*/
-class TAO_ClientRequestInfo
+class TAO_PI_Export TAO_ClientRequestInfo
: public virtual PortableInterceptor::ClientRequestInfo,
public virtual TAO_Local_RefCounted_Object
{
@@ -220,6 +221,27 @@ public:
ACE_ENV_ARG_DECL_WITH_DEFAULTS)
ACE_THROW_SPEC ((CORBA::SystemException));
+ /*
+ * Proprietary accessor methods for the FT retention ID and
+ * request expiration time.
+ */
+
+ /// Set the absolute FT expiration time for this request.
+ void tao_ft_expiration_time (TimeBase::TimeT time);
+
+ /// Get the absolute FT expiration time for this request
+ TimeBase::TimeT tao_ft_expiration_time (void) const;
+
+ /// Set the FT request retention ID for this request.
+ void tao_ft_retention_id (CORBA::Long request_id);
+
+ /// Get the FT request retention ID for this request.
+ CORBA::Long tao_ft_retention_id (void) const;
+
+ /*
+ * End proprietary FT methods.
+ */
+
private:
bool parameter_list (Dynamic::ParameterList &param_list);
diff --git a/TAO/tao/operation_details.h b/TAO/tao/operation_details.h
index 55df7ee8328..241635d7a20 100644
--- a/TAO/tao/operation_details.h
+++ b/TAO/tao/operation_details.h
@@ -21,6 +21,7 @@
#endif /* ACE_LACKS_PRAGMA_ONCE */
#include "Service_Context.h"
+#include "TimeBaseC.h"
#include "target_specification.h"
@@ -62,7 +63,7 @@ class TAO_Export TAO_Operation_Details
public:
/// Declare FW_Server_Request_Wrapper a friend
- /// This friendship makes the FW_Server_Request_Wrapper be able to
+ /// This friendship makes the FW_Server_Request_Wrapper be able to
/// clone the TAO_Operation_Details data member in TAO_ServerRequest.
friend class TAO::CSD::FW_Server_Request_Wrapper;
@@ -153,6 +154,12 @@ public:
TAO::Exception_Data const * ex_data (void) const;
+ void ft_expiration_time (TimeBase::TimeT time);
+ TimeBase::TimeT ft_expiration_time (void) const;
+
+ void ft_retention_id (CORBA::Long request_id);
+ CORBA::Long ft_retention_id (void) const;
+
private:
/// Name of the operation being invoked.
@@ -194,6 +201,13 @@ private:
/// Count of the exceptions that operations can throw.
CORBA::ULong ex_count_;
+#if TAO_HAS_INTERCEPTORS == 1
+ /// FT request expiration time (absolute gregorian)
+ TimeBase::TimeT ft_expiration_time_;
+
+ /// FT request retention id
+ CORBA::Long ft_retention_id_;
+#endif /*TAO_HAS_INTERCEPTORS == 1*/
};
#if defined (__ACE_INLINE__)
diff --git a/TAO/tao/operation_details.i b/TAO/tao/operation_details.i
index 599d37c767b..3c59cafd320 100644
--- a/TAO/tao/operation_details.i
+++ b/TAO/tao/operation_details.i
@@ -20,6 +20,10 @@ TAO_Operation_Details::TAO_Operation_Details (const char *name,
, num_args_ (num)
, ex_data_ (data)
, ex_count_ (count)
+#if TAO_HAS_INTERCEPTORS == 1
+ , ft_expiration_time_ (0)
+ , ft_retention_id_ (0)
+#endif /*TAO_HAS_INTERCEPTORS == 1*/
{
}
@@ -164,3 +168,29 @@ TAO_Operation_Details::args_num (void) const
{
return this->num_args_;
}
+
+#if TAO_HAS_INTERCEPTORS == 1
+ACE_INLINE void
+TAO_Operation_Details::ft_expiration_time (TimeBase::TimeT time)
+{
+ this->ft_expiration_time_ = time;
+}
+
+ACE_INLINE TimeBase::TimeT
+TAO_Operation_Details::ft_expiration_time (void) const
+{
+ return this->ft_expiration_time_;
+}
+
+ACE_INLINE void
+TAO_Operation_Details::ft_retention_id (CORBA::Long request_id)
+{
+ this->ft_retention_id_ = request_id;
+}
+
+ACE_INLINE CORBA::Long
+TAO_Operation_Details::ft_retention_id (void) const
+{
+ return this->ft_retention_id_;
+}
+#endif /*TAO_HAS_INTERCEPTORS == 1*/