summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormitza <mitza@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2008-08-07 21:35:59 +0000
committermitza <mitza@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2008-08-07 21:35:59 +0000
commit4f990bd2b5b23db37708e801e5db2933c486cf99 (patch)
tree5e98982a9fce8989cd99dc27f26df4ac2c9a0241
parentb31aaa377282d63b9f4a6bd22f54257180fbad59 (diff)
downloadATCD-4f990bd2b5b23db37708e801e5db2933c486cf99.tar.gz
ChangeLogTag: Thu Aug 7 21:30:32 UTC 2008 Adam Mitz <mitza@ociweb.com>
-rw-r--r--TAO/ChangeLog6
-rw-r--r--TAO/tests/Bug_3068_Regression/Bug_3068_Regression.mpc15
-rw-r--r--TAO/tests/Bug_3068_Regression/README59
-rw-r--r--TAO/tests/Bug_3068_Regression/client.conf1
-rw-r--r--TAO/tests/Bug_3068_Regression/client.cpp153
-rwxr-xr-xTAO/tests/Bug_3068_Regression/run_test.pl79
-rw-r--r--TAO/tests/Bug_3068_Regression/server.conf3
-rw-r--r--TAO/tests/Bug_3068_Regression/server.cpp136
-rw-r--r--TAO/tests/Bug_3068_Regression/test.idl32
-rw-r--r--TAO/tests/Bug_3068_Regression/test_i.cpp120
-rw-r--r--TAO/tests/Bug_3068_Regression/test_i.h108
-rw-r--r--TAO/tests/Bug_3068_Regression/test_i.inl17
12 files changed, 729 insertions, 0 deletions
diff --git a/TAO/ChangeLog b/TAO/ChangeLog
index 0008069f2d5..a15b428840f 100644
--- a/TAO/ChangeLog
+++ b/TAO/ChangeLog
@@ -1,3 +1,9 @@
+Thu Aug 7 21:30:32 UTC 2008 Adam Mitz <mitza@ociweb.com>
+
+ * tests/Bug_3068_Regression:
+
+ Added a test for bug 3068.
+
Thu Aug 7 19:15:34 UTC 2008 Adam Mitz <mitza@ociweb.com>
* NEWS:
diff --git a/TAO/tests/Bug_3068_Regression/Bug_3068_Regression.mpc b/TAO/tests/Bug_3068_Regression/Bug_3068_Regression.mpc
new file mode 100644
index 00000000000..3de795d43ea
--- /dev/null
+++ b/TAO/tests/Bug_3068_Regression/Bug_3068_Regression.mpc
@@ -0,0 +1,15 @@
+project(*Server): taoserver, messaging, bidir_giop {
+ exename = server
+ Source_Files {
+ test_i.cpp
+ server.cpp
+ }
+}
+
+project(*Client): taoserver, bidir_giop {
+ exename = client
+ Source_Files {
+ test_i.cpp
+ client.cpp
+ }
+}
diff --git a/TAO/tests/Bug_3068_Regression/README b/TAO/tests/Bug_3068_Regression/README
new file mode 100644
index 00000000000..de64499b033
--- /dev/null
+++ b/TAO/tests/Bug_3068_Regression/README
@@ -0,0 +1,59 @@
+# $Id$
+
+This test is for validating the fix for a race condition exposed in the
+Transport_Cache_Manager. The problem is that an internal pointer used
+to test intermediate return values to the cache may be deleted by one
+thread before another thread tries to use it.
+
+This situation is replicated by having a bidirectional connection set up
+between a client and a server, the client provides a callback reference
+that the server uses via the bidir connection. The server uses multiple
+threads to force a thread into the wait state, and the client terminates
+abruptly, setting the condition for the race.
+
+$ server -ORBSvcConf server.conf -o <file.ior>
+$ client -ORBSvcConf client.conf -k file://<file.ior> -x
+
+Or, simply
+
+$ ./run_test.pl
+
+Even with this optimized test case, the condition is hard to trigger.
+To reliably trigger the error before fixing TAO, apply this patch to
+$TAO_ROOT/tao/Transport_Cache_Manager.cpp
+
+Index: Transport_Cache_Manager.cpp
+===================================================================
+RCS file: /cvs/ocitao/ACE_wrappers/TAO/tao/Transport_Cache_Manager.cpp,v
+retrieving revision 1.1.1.3.2.5.14.1
+diff -u -b -r1.1.1.3.2.5.14.1 Transport_Cache_Manager.cpp
+--- Transport_Cache_Manager.cpp 8 Mar 2007 22:33:14 -0000 1.1.1.3.2.5.14.1
++++ Transport_Cache_Manager.cpp 1 Aug 2007 19:18:21 -0000
+@@ -244,6 +244,9 @@
+
+ entry->int_id_.recycle_state (ACE_RECYCLABLE_BUSY);
+
++ ACE_Time_Value tv (0,500);
++ ACE_OS::sleep (tv);
++
+ // NOTE: This assignment operator indirectly incurs two
+ // lock operations since it duplicates and releases
+ // TAO_Transport objects.
+
+
+Once TAO is fixed, the following patch adds the same delay to the
+refactored Transport Cache Manager:
+
+
+--- .#Transport_Cache_Manager.cpp.1.1.1.3.2.5.14.1 2007-08-01 09:26:52.000000000 -0500
++++ Transport_Cache_Manager.cpp 2007-08-01 14:40:47.000000000 -0500
+@@ -227,6 +227,9 @@
+ found = CACHE_FOUND_AVAILABLE;
+ entry->int_id_.recycle_state (TAO::ENTRY_BUSY);
+
++ ACE_Time_Value tv (0,500);
++ ACE_OS::sleep (tv);
++
+ // NOTE: This assignment operator indirectly incurs two
+ // lock operations since it duplicates and releases
+ // TAO_Transport objects.
diff --git a/TAO/tests/Bug_3068_Regression/client.conf b/TAO/tests/Bug_3068_Regression/client.conf
new file mode 100644
index 00000000000..57a8c2df132
--- /dev/null
+++ b/TAO/tests/Bug_3068_Regression/client.conf
@@ -0,0 +1 @@
+static Client_Strategy_Factory "-ORBConnectStrategy blocked"
diff --git a/TAO/tests/Bug_3068_Regression/client.cpp b/TAO/tests/Bug_3068_Regression/client.cpp
new file mode 100644
index 00000000000..36ce6d9645e
--- /dev/null
+++ b/TAO/tests/Bug_3068_Regression/client.cpp
@@ -0,0 +1,153 @@
+// $Id$
+
+#include "ace/Get_Opt.h"
+#include "test_i.h"
+#include "tao/BiDir_GIOP/BiDirGIOP.h"
+
+#include "tao/ORB_Core.h"
+#include "tao/Transport_Cache_Manager.h"
+#include "tao/Thread_Lane_Resources.h"
+
+ACE_RCSID (Bug_3068_Regression, client, "$Id$")
+
+const char *ior = "file://test.ior";
+
+int
+parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt get_opts (argc, argv, ACE_TEXT ("k:"));
+ int c;
+
+ while ((c = get_opts ()) != -1)
+ switch (c)
+ {
+ case 'k':
+ ior = ACE_TEXT_ALWAYS_CHAR (get_opts.opt_arg ());
+ break;
+
+ case '?':
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("usage: %s -k <ior> \n"),
+ argv [0]), -1);
+ }
+ // Indicates sucessful parsing of the command line
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ try
+ {
+ CORBA::ORB_var orb = CORBA::ORB_init (argc, argv);
+
+ CORBA::Object_var poa_object =
+ orb->resolve_initial_references ("RootPOA");
+
+ if (CORBA::is_nil (poa_object.in ()))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ " (%P|%t) Unable to initialize the POA.\n"),
+ 1);
+
+ PortableServer::POA_var root_poa =
+ PortableServer::POA::_narrow (poa_object.in ());
+
+ PortableServer::POAManager_var poa_manager = root_poa->the_POAManager ();
+
+ // Policies for the childPOA to be created.
+ CORBA::PolicyList policies (1);
+ policies.length (1);
+
+ CORBA::Any pol;
+ pol <<= BiDirPolicy::BOTH;
+ policies[0] =
+ orb->create_policy (BiDirPolicy::BIDIRECTIONAL_POLICY_TYPE, pol);
+
+ // Create POA as child of RootPOA with the above policies. This POA
+ // will receive request in the same connection in which it sent
+ // the request
+ PortableServer::POA_var child_poa =
+ root_poa->create_POA ("childPOA", poa_manager.in (), policies);
+
+ // Creation of childPOA is over. Destroy the Policy objects.
+ for (CORBA::ULong i = 0; i < policies.length (); ++i)
+ {
+ policies[i]->destroy ();
+ }
+
+ poa_manager->activate ();
+
+ if (parse_args (argc, argv) != 0)
+ return 1;
+
+ CORBA::Object_var object = orb->string_to_object (ior);
+
+ Simple_Server_var server = Simple_Server::_narrow (object.in ());
+
+ if (CORBA::is_nil (server.in ()))
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Object reference <%C> is nil\n",
+ ior),
+ 1);
+ }
+
+ Callback_i callback_impl (orb.in ());
+
+ PortableServer::ObjectId_var id =
+ PortableServer::string_to_ObjectId ("client_callback");
+
+ child_poa->activate_object_with_id (id.in (), &callback_impl);
+
+ CORBA::Object_var callback_object =
+ child_poa->id_to_reference (id.in ());
+
+ Callback_var callback = Callback::_narrow (callback_object.in ());
+
+ CORBA::String_var ior = orb->object_to_string (callback.in ());
+
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) Client callback activated as <%C>\n",
+ ior.in ()));
+
+ // Send the calback object to the server
+ server->callback_object (callback.in ());
+
+ int pre_call_connections =
+ orb->orb_core ()->lane_resources ().transport_cache ().current_size ();
+
+ // A method to kickstart callbacks from the server
+ CORBA::Long r = server->test_method (1);
+
+ if (r != 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) unexpected result = %d ",
+ r));
+ }
+
+ orb->run ();
+
+ int cur_connections =
+ orb->orb_core ()->lane_resources ().transport_cache ().current_size ();
+
+ if (cur_connections > pre_call_connections)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "(%P|%t) Expected %d "
+ "connections in the transport cache, but found "
+ "%d instead. Aborting.\n",
+ pre_call_connections,
+ cur_connections));
+ ACE_OS::abort ();
+ }
+
+ root_poa->destroy (1, 1);
+ }
+ catch (CORBA::Exception &excep)
+ {
+ excep._tao_print_exception ("Caught exception:");
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/TAO/tests/Bug_3068_Regression/run_test.pl b/TAO/tests/Bug_3068_Regression/run_test.pl
new file mode 100755
index 00000000000..9b89b76dac6
--- /dev/null
+++ b/TAO/tests/Bug_3068_Regression/run_test.pl
@@ -0,0 +1,79 @@
+eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
+ & eval 'exec perl -S $0 $argv:q'
+ if 0;
+
+# $Id$
+# -*- perl -*-
+
+use lib "$ENV{'ACE_ROOT'}/bin";
+use PerlACE::Run_Test;
+use Getopt::Long;
+
+$status = 0;
+$opt = "-ORBListenendpoints iiop://:/reuse_addr=0 ";
+$conf_client = "";
+$conf_server = "";
+$iorfile = PerlACE::LocalFile ("test.ior");
+
+sub options () {
+ my $debug; # handled locally
+
+ # Process options.
+ if ( @ARGV > 0 ) {
+ GetOptions ('debug=i' => \$debug);
+ }
+
+ $conf_client = " -ORBSvcConf client.conf";
+ $conf_server = " -ORBSvcConf server.conf";
+
+ if ($debug) {
+ $opt = "$opt -ORBDebugLevel $debug";
+ }
+
+ return 1;
+}
+
+options () or die "Nothing executed";
+
+unlink $iorfile;
+
+print STDERR "Executing, server options=$conf_server $opt -o $iorfile\n";
+$SV = new PerlACE::Process ("server",
+ "$conf_server $opt -o $iorfile");
+
+print STDERR "Executing, client options=$conf_client -k file://$iorfile\n";
+$CL = new PerlACE::Process ("client",
+ "$conf_client -k file://$iorfile");
+
+$SV->Spawn ();
+
+if (PerlACE::waitforfile_timed ($iorfile, 15) == -1) {
+ print STDERR "ERROR: cannot find file <$iorfile>\n";
+ $SV->Kill ();
+ exit 1;
+}
+
+$client = $CL->SpawnWaitKill (120);
+
+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;
+
+if ($status != 0) {
+ print STDERR "Test failed\n";
+}
+else {
+ print STDERR "Test succeded\n";
+}
+
+exit $status;
diff --git a/TAO/tests/Bug_3068_Regression/server.conf b/TAO/tests/Bug_3068_Regression/server.conf
new file mode 100644
index 00000000000..f39d729f6d4
--- /dev/null
+++ b/TAO/tests/Bug_3068_Regression/server.conf
@@ -0,0 +1,3 @@
+static Resource_Factory "-ORBMuxedConnectionMax 1"
+
+static Client_Strategy_Factory "-ORBTransportMuxStrategy muxed -ORBConnectStrategy blocked"
diff --git a/TAO/tests/Bug_3068_Regression/server.cpp b/TAO/tests/Bug_3068_Regression/server.cpp
new file mode 100644
index 00000000000..ac74fb40309
--- /dev/null
+++ b/TAO/tests/Bug_3068_Regression/server.cpp
@@ -0,0 +1,136 @@
+// $Id$
+
+#include "ace/Get_Opt.h"
+#include "ace/OS_NS_stdio.h"
+#include "test_i.h"
+#include "ace/Task.h"
+
+#include "tao/Messaging/Messaging.h"
+#include "tao/BiDir_GIOP/BiDirGIOP.h"
+
+ACE_RCSID (Bug_3068_Regression, server, "$Id$")
+
+const char *ior_output_file = 0;
+int iterations = 10;
+
+int
+parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt get_opts (argc, argv, ACE_TEXT ("o:i:"));
+ int c;
+
+ while ((c = get_opts ()) != -1)
+ switch (c)
+ {
+ case 'o':
+ ior_output_file = ACE_TEXT_ALWAYS_CHAR (get_opts.opt_arg ());
+ break;
+ case 'i':
+ iterations = ACE_OS::atoi (get_opts.opt_arg ());
+ break;
+ case '?':
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("usage: %s -o <iorfile>")
+ ACE_TEXT ("-i <iterations>\n"), argv [0]),
+ -1);
+ }
+ // Indicates sucessful parsing of the command line
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ try
+ {
+ CORBA::ORB_var orb = CORBA::ORB_init (argc, argv);
+
+ CORBA::Object_var object =
+ orb->resolve_initial_references ("ORBPolicyManager");
+
+ CORBA::PolicyManager_var policy_mgr =
+ CORBA::PolicyManager::_narrow (object.in ());
+ if (CORBA::is_nil (policy_mgr.in ()))
+ ACE_ERROR_RETURN ((LM_ERROR, "failed to get policy manager\n"), 1);
+ CORBA::String_var ref_id = policy_mgr->_interface_repository_id ();
+ ACE_DEBUG ((LM_DEBUG, "Policy MGR intid = %C\n", ref_id.in ()));
+
+ CORBA::Object_var poa_object =
+ orb->resolve_initial_references ("RootPOA");
+ ACE_TRY_CHECK;
+
+ if (CORBA::is_nil (poa_object.in ()))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ " (%P|%t) Unable to initialize the POA.\n"),
+ 1);
+
+ PortableServer::POA_var root_poa =
+ PortableServer::POA::_narrow (poa_object.in ());
+ PortableServer::POAManager_var poa_manager = root_poa->the_POAManager ();
+
+ // Policies for the childPOA to be created.
+ CORBA::PolicyList policies (1);
+ policies.length (1);
+
+ CORBA::Any pol;
+ pol <<= BiDirPolicy::BOTH;
+ policies[0] =
+ orb->create_policy (BiDirPolicy::BIDIRECTIONAL_POLICY_TYPE, pol);
+
+ // Create POA as child of RootPOA with the above policies. This POA
+ // will receive request in the same connection in which it sent
+ // the request
+ PortableServer::POA_var child_poa =
+ root_poa->create_POA ("child", poa_manager.in (), policies);
+
+ // Creation of childPOA is over. Destroy the Policy objects.
+ for (CORBA::ULong i = 0; i < policies.length (); ++i)
+ {
+ policies[i]->destroy ();
+ }
+
+ poa_manager->activate ();
+
+ if (parse_args (argc, argv) != 0)
+ return 1;
+
+ Simple_Server_i server_impl (orb.in (), iterations);
+
+ PortableServer::ObjectId_var id =
+ PortableServer::string_to_ObjectId ("simple_server");
+
+ child_poa->activate_object_with_id (id.in (), &server_impl);
+
+ CORBA::Object_var obj = child_poa->id_to_reference (id.in ());
+
+ CORBA::String_var ior = orb->object_to_string (obj.in ());
+
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) Server activated as <%C>\n", ior.in ()));
+
+ // If the ior_output_file exists, output the ior to it
+ if (ior_output_file != 0)
+ {
+ 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: %C",
+ ior_output_file),
+ 1);
+ ACE_OS::fprintf (output_file, "%s", ior.in ());
+ ACE_OS::fclose (output_file);
+ }
+
+ orb->run();
+
+ ACE_Thread_Manager::instance ()->wait ();
+
+ root_poa->destroy (1, 1);
+ }
+ catch (CORBA::Exception &excep)
+ {
+ excep._tao_print_exception ("Caught exception:");
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/TAO/tests/Bug_3068_Regression/test.idl b/TAO/tests/Bug_3068_Regression/test.idl
new file mode 100644
index 00000000000..e43836d1d36
--- /dev/null
+++ b/TAO/tests/Bug_3068_Regression/test.idl
@@ -0,0 +1,32 @@
+//
+// $Id$
+//
+
+#include <tao/OctetSeq.pidl>
+
+interface Callback
+{
+ oneway void shutdown ();
+ // A safe way to shutdown the client, using either clean shutdowns
+ // or "catastrophic failures".
+
+ void callback_method (in CORBA::OctetSeq payload);
+ // A simple remote call takes a payload to increase the duration of
+ // call to trigger the wait strategy and thus the error.
+
+};
+
+interface Simple_Server
+{
+ oneway void ow_test ();
+
+ long test_method (in boolean do_callback);
+ // Just call a method on the server,
+
+ void callback_object (in Callback cb);
+ // send the callback object to the server
+
+ oneway void shutdown ();
+ // A safe way to shutdown the server, it is a oneway function so we
+ // will never get a COMM_FAILURE error
+};
diff --git a/TAO/tests/Bug_3068_Regression/test_i.cpp b/TAO/tests/Bug_3068_Regression/test_i.cpp
new file mode 100644
index 00000000000..d786affaec1
--- /dev/null
+++ b/TAO/tests/Bug_3068_Regression/test_i.cpp
@@ -0,0 +1,120 @@
+// $Id$
+
+#include "test_i.h"
+
+#include "tao/ORB_Core.h"
+#include "tao/debug.h"
+#include "tao/Transport_Cache_Manager.h"
+#include "tao/Thread_Lane_Resources.h"
+#include "ace/OS_NS_unistd.h"
+
+#if !defined(__ACE_INLINE__)
+#include "test_i.inl"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID (Bug_3068_Regression, test_i, "$Id$")
+
+void
+Callback_i::shutdown ()
+{
+ ACE_DEBUG ((LM_DEBUG, "Performing clean shutdown\n"));
+ this->orb_->shutdown (0);
+}
+
+void
+Callback_i::callback_method (const CORBA::OctetSeq &)
+{
+ static int count = 0;
+ if (count++ > 0)
+ ACE_OS::exit(0);
+}
+
+
+// ****************************************************************
+
+CORBA::Long
+Simple_Server_i::test_method (CORBA::Boolean do_callback)
+{
+ if (do_callback && this->caller_ != 0)
+ {
+ this->caller_->go ();
+ }
+
+ return 0;
+}
+
+
+void
+Simple_Server_i::ow_test ()
+{
+ int iter = this->ow_count_++;
+ ACE_DEBUG ((LM_DEBUG, "%t: Invoking ow test, iter = %d\n", iter));
+}
+
+void
+Simple_Server_i::callback_object (Callback_ptr callback)
+{
+ this->caller_ = new Caller (callback, orb_);
+}
+
+Caller::Caller (Callback_ptr callback, CORBA::ORB_ptr orb)
+ : cbobj_ (Callback::_duplicate (callback))
+ , orb_ (CORBA::ORB::_duplicate (orb))
+ , cond_ (this->lock_)
+ , going_ (false)
+{
+ this->payload_.length (0); //10000);
+ this->activate (THR_JOINABLE | THR_NEW_LWP, 4);
+ ACE_OS::sleep (1);
+ ACE_DEBUG ((LM_DEBUG, "%t returning\n"));
+}
+
+void
+Caller::go ()
+{
+ this->lock_.acquire ();
+ this->going_ = true;
+ this->cond_.broadcast ();
+ this->lock_.release ();
+}
+
+int
+Caller::svc ()
+{
+ this->lock_.acquire ();
+ ACE_DEBUG ((LM_DEBUG, "%t Getting ready to call\n"));
+ while (!this->going_) this->cond_.wait ();
+ this->lock_.release ();
+ try
+ {
+ while (1)
+ {
+ ACE_DEBUG ((LM_DEBUG, "%t calling, payload len = %d\n",
+ payload_.length ()));
+ this->cbobj_->callback_method (this->payload_);
+ ACE_DEBUG ((LM_DEBUG, "%t callback returned\n"));
+ ACE_Time_Value tv (0, 100);
+ ACE_OS::sleep (tv);
+ }
+ }
+ catch (CORBA::Exception &ex)
+ {
+ ACE_DEBUG ((LM_DEBUG, "%t caught: %C\n", ex._name ()));
+ }
+ try
+ {
+ ACE_OS::sleep (1);
+ this->orb_->shutdown (0);
+ }
+ catch (CORBA::Exception &ex)
+ {
+ ACE_DEBUG ((LM_DEBUG, "%t orb shutdown raised %C\n", ex._name ()));
+ }
+ return 0;
+}
+
+void
+Simple_Server_i::shutdown ()
+{
+ this->orb_->shutdown (0);
+}
diff --git a/TAO/tests/Bug_3068_Regression/test_i.h b/TAO/tests/Bug_3068_Regression/test_i.h
new file mode 100644
index 00000000000..90638355cbf
--- /dev/null
+++ b/TAO/tests/Bug_3068_Regression/test_i.h
@@ -0,0 +1,108 @@
+// -*- C++ -*-
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// TAO/tests/BiDirectional
+//
+// = FILENAME
+// test_i.h
+//
+// = AUTHOR
+// Balachandran Natarajan <bala@cs.wustl.edu>
+//
+// ============================================================================
+
+#ifndef TAO_BIDIRECTIONAL_TEST_I_H
+#define TAO_BIDIRECTIONAL_TEST_I_H
+
+#include "testS.h"
+#include "ace/Task.h"
+#include "ace/Synch.h"
+
+class Caller : public ACE_Task_Base
+{
+public:
+ Caller (Callback_ptr cb, CORBA::ORB_ptr orb);
+ void go (void);
+
+ int svc (void);
+
+private:
+ Callback_var cbobj_;
+ CORBA::ORB_var orb_;
+ ACE_Thread_Mutex lock_;
+ ACE_Condition<ACE_Thread_Mutex> cond_;
+ bool going_;
+ CORBA::OctetSeq payload_;
+};
+
+
+class Callback_i : public POA_Callback
+{
+ // = TITLE
+ // A callback object to the "client"
+ //
+ // = DESCRIPTION
+ // To test that the server can call the client on the same
+ // connection that was established by the client
+ //
+public:
+ Callback_i (CORBA::ORB_ptr orb);
+ // ctor
+
+ void shutdown (ACE_ENV_SINGLE_ARG_DECL);
+ // Safe way to shutdown
+
+ void callback_method (const CORBA::OctetSeq& payload);
+ // The callback method
+
+private:
+ CORBA::ORB_var orb_;
+ // The orb
+
+};
+
+class Simple_Server_i : public POA_Simple_Server
+{
+ // = TITLE
+ // Simpler Server implementation
+ //
+ // = DESCRIPTION
+ // Implements the Simple_Server interface in test.idl
+ // for (int loop = 0; loop < 10; loop++)
+
+public:
+ Simple_Server_i (CORBA::ORB_ptr orb, int no_iterations);
+ // ctor
+
+ // = The Simple_Server methods.
+ void ow_test ();
+
+ CORBA::Long test_method (CORBA::Boolean do_callback);
+
+ void callback_object (Callback_ptr callback);
+
+ void shutdown ();
+
+private:
+ CORBA::ORB_var orb_;
+ // The ORB
+
+ int flag_;
+ // Flag to indicate, whether we are ready for a remote call.
+
+ Caller *caller_;
+ // Callback Object
+
+ int iterations_;
+ // Number of times the callback needs to be called
+ int ow_count_;
+};
+
+#if defined(__ACE_INLINE__)
+#include "test_i.inl"
+#endif /* __ACE_INLINE__ */
+
+#endif /* TAO_BIDIRECTIONAL_TEST_I_H */
diff --git a/TAO/tests/Bug_3068_Regression/test_i.inl b/TAO/tests/Bug_3068_Regression/test_i.inl
new file mode 100644
index 00000000000..71a198710d1
--- /dev/null
+++ b/TAO/tests/Bug_3068_Regression/test_i.inl
@@ -0,0 +1,17 @@
+// $Id$
+
+ACE_INLINE
+Callback_i::Callback_i (CORBA::ORB_ptr orb)
+ : orb_ (CORBA::ORB::_duplicate (orb))
+{
+}
+
+ACE_INLINE
+Simple_Server_i::Simple_Server_i (CORBA::ORB_ptr orb,
+ int no_iterations)
+ : orb_ (CORBA::ORB::_duplicate (orb)),
+ flag_ (0),
+ caller_ (0),
+ iterations_ (no_iterations)
+{
+}