summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwilson_d <wilson_d@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2003-09-30 21:22:23 +0000
committerwilson_d <wilson_d@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2003-09-30 21:22:23 +0000
commitf04db615d7337acf24edf9be8e24f3e578fa5406 (patch)
tree0ffd8cd51c356a8d2d50230b87d069bb67b68651
parenteb012b1afe71dab3c0228bc6d4092ddf1edcdb2e (diff)
downloadATCD-f04db615d7337acf24edf9be8e24f3e578fa5406.tar.gz
ChangeLogTag: Tue Sep 30 15:58:42 2003 Dale Wilson <wilson_d@ociweb.com>
-rw-r--r--TAO/ChangeLog124
-rw-r--r--TAO/orbsvcs/Fault_Detector/Fault_Detector_i.cpp7
-rw-r--r--TAO/orbsvcs/tests/FT_App/FTAPP_FactoryRegistry_Main.cpp33
-rw-r--r--TAO/orbsvcs/tests/FT_App/FT_App.mpc27
-rw-r--r--TAO/orbsvcs/tests/FT_App/FT_Client.cpp3
-rw-r--r--TAO/orbsvcs/tests/FT_App/FT_TestReplica_i.cpp7
-rw-r--r--TAO/orbsvcs/tests/FT_App/FT_TestReplica_i.h4
-rw-r--r--TAO/orbsvcs/tests/FT_App/FactoryRegistry_i.cpp501
-rw-r--r--TAO/orbsvcs/tests/FT_App/FactoryRegistry_i.h204
-rw-r--r--TAO/orbsvcs/tests/FT_App/README47
-rw-r--r--TAO/orbsvcs/tests/FT_App/StubBatchConsumer.cpp2
-rw-r--r--TAO/orbsvcs/tests/FT_App/StubFaultAnalyzer.cpp2
-rw-r--r--TAO/orbsvcs/tests/FT_App/StubFaultConsumer.cpp2
-rw-r--r--TAO/orbsvcs/tests/FT_App/StubFaultNotifier.h12
-rwxr-xr-xTAO/orbsvcs/tests/FT_App/run_test_registry.pl263
15 files changed, 1145 insertions, 93 deletions
diff --git a/TAO/ChangeLog b/TAO/ChangeLog
index f1e40cacc9d..3ba98c333c8 100644
--- a/TAO/ChangeLog
+++ b/TAO/ChangeLog
@@ -1,59 +1,89 @@
+Tue Sep 30 15:58:42 2003 Dale Wilson <wilson_d@ociweb.com>
+
+ * orbsvcs/Fault_Detector/Fault_Detector_i.cpp:
+ New into a var rather than into a pointer that gets assigned to the var later.
+
+ * orbsvcs/tests/FT_App/FTAPP_FactoryRegistry_Main.cpp:
+ * orbsvcs/tests/FT_App/FactoryRegistry_i.h:
+ * orbsvcs/tests/FT_App/FactoryRegistry_i.cpp:
+ * orbsvcs/tests/FT_App/run_test_registry.pl:
+ New files: First implementation of FactoryRegistry interface (not working, yet.)
+
+ * orbsvcs/tests/FT_App/FT_App.mpc:
+ Add project for FactoryRegistry
+
+ * orbsvcs/tests/FT_App/README:
+ Mention FactoryRegistry in documentation.
+
+ * orbsvcs/tests/FT_App/FT_TestReplica_i.h:
+ * orbsvcs/tests/FT_App/FT_TestReplica_i.cpp:
+ * orbsvcs/tests/FT_App/FT_Client.cpp:
+ * orbsvcs/tests/FT_App/StubBatchConsumer.cpp:
+ * orbsvcs/tests/FT_App/StubFaultAnalyzer.cpp:
+ * orbsvcs/tests/FT_App/StubFaultConsumer.cpp:
+ * orbsvcs/tests/FT_App/StubFaultNotifier.h:
+ Minor changes to make these more ACE-like.
+
+
+
+
+
Tue Sep 30 11:45:49 2003 Balachandran Natarajan <bala@dre.vanderbilt.edu>
- * orbsvcs/tests/FaultTolerance/Replay_Reply/Server_Request_Interceptor.cpp:
-
- The send_reply () method now uses generic ways to marshall the
- value inside an Any into the CDR stream. This now uses the
- undocumented marshal_value () in Any_Impl class.
-
+ * orbsvcs/tests/FaultTolerance/Replay_Reply/Server_Request_Interceptor.cpp:
+
+ The send_reply () method now uses generic ways to marshall the
+ value inside an Any into the CDR stream. This now uses the
+ undocumented marshal_value () in Any_Impl class.
+
Mon Sep 29 18:55:08 2003 Balachandran Natarajan <bala@dre.vanderbilt.edu>
- * orbsvcs/tests/FaultTolerance/Replay_Reply:
+ * orbsvcs/tests/FaultTolerance/Replay_Reply:
- A new test for the feature mentioned below.
+ A new test for the feature mentioned below.
Mon Sep 29 18:39:05 2003 Balachandran Natarajan <bala@dre.vanderbilt.edu>
- A temporary hack for Boris to keep progressing. The aim of this
- hack in the branch is to add a propreietary interception
- point. This is what this checkin is all about
-
- - Added a new interception point, tao_ft_interception_point ()
- on the server side.
-
- - This will be called on the server even before the
- receive_request_service_context () is called
-
- - The server can use this interception point to send back a
- reply without dispatching it to the object.
-
- * tao/PortableInterceptor.pidl:
- * tao/PortableInterceptorC.h: Added the new interception point. A
- default implementation is provided, so that application
- developers don't need to implement the proprietary interception
- point.
-
- * tao/TAO_Server_Request.cpp:
- * tao/TAO_Server_Request.h:
- * tao/TAO_Server_Request.i: Added a new method which will be used
- to send cached replies back to the client.
-
- * tao/PortableServer/Object_Adapter.cpp: Called the proprietary
- interception point.
-
- * tao/PortableServer/ServerInterceptorAdapter.cpp:
- * tao/PortableServer/ServerInterceptorAdapter.h: Added the first
- interception point to be the tao's proprietary interception
- point.
-
- This shouldn't be needed once we merge in 1369. But till then we
- may need this hack.
-
+ A temporary hack for Boris to keep progressing. The aim of this
+ hack in the branch is to add a propreietary interception
+ point. This is what this checkin is all about
+
+ - Added a new interception point, tao_ft_interception_point ()
+ on the server side.
+
+ - This will be called on the server even before the
+ receive_request_service_context () is called
+
+ - The server can use this interception point to send back a
+ reply without dispatching it to the object.
+
+ * tao/PortableInterceptor.pidl:
+ * tao/PortableInterceptorC.h: Added the new interception point. A
+ default implementation is provided, so that application
+ developers don't need to implement the proprietary interception
+ point.
+
+ * tao/TAO_Server_Request.cpp:
+ * tao/TAO_Server_Request.h:
+ * tao/TAO_Server_Request.i: Added a new method which will be used
+ to send cached replies back to the client.
+
+ * tao/PortableServer/Object_Adapter.cpp: Called the proprietary
+ interception point.
+
+ * tao/PortableServer/ServerInterceptorAdapter.cpp:
+ * tao/PortableServer/ServerInterceptorAdapter.h: Added the first
+ interception point to be the tao's proprietary interception
+ point.
+
+ This shouldn't be needed once we merge in 1369. But till then we
+ may need this hack.
+
Mon Sep 29 18:19:51 2003 Steve Totten <totten_s@ociweb.com>
* orbsvcs/orbsvcs/PortableGroup/PG_Utils.cpp:
- Fixed compilation error in VC++ 6.0 involving re-use
+ Fixed compilation error in VC++ 6.0 involving re-use
of 'i' as a for loop control variable.
Mon Sep 29 16:15:55 2003 Curt Hibbs <hibbs_c@ociweb.com>
@@ -98,7 +128,7 @@ Mon Sep 29 07:22:35 2003 Curt Hibbs <hibbs_c@ociweb.com>
Fri Sep 26 19:31:11 2003 Balachandran Natarajan <bala@dre.vanderbilt.edu>
- * orbsvcs/orbsvcs/PortableGroup/PG_Utils.cpp (TAO):
+ * orbsvcs/orbsvcs/PortableGroup/PG_Utils.cpp (TAO):
* orbsvcs/orbsvcs/PortableGroup/PG_Utils.h: Moved group reference
manipulation functions to a new file which will be used within
the PortableGroup.
@@ -109,8 +139,8 @@ Fri Sep 26 19:31:11 2003 Balachandran Natarajan <bala@dre.vanderbilt.edu>
* orbsvcs/orbsvcs/PortableGroup/PG_ObjectGroup_Map.cpp:
* orbsvcs/orbsvcs/PortableGroup/PG_Property_Utils.cpp: Removed
dependency on the FT library which was unnecessary in the first
- place.
-
+ place.
+
Fixed warnings and errors with g++ builds.
Thu Sep 25 16:08:35 2003 Dale Wilson <wilson_d@ociweb.com>
diff --git a/TAO/orbsvcs/Fault_Detector/Fault_Detector_i.cpp b/TAO/orbsvcs/Fault_Detector/Fault_Detector_i.cpp
index 7db5f878691..ef3be4b0b85 100644
--- a/TAO/orbsvcs/Fault_Detector/Fault_Detector_i.cpp
+++ b/TAO/orbsvcs/Fault_Detector/Fault_Detector_i.cpp
@@ -120,11 +120,10 @@ void Fault_Detector_i::run()
void Fault_Detector_i::notify()
{
- CosNotification::StructuredEvent * pEvent;
- ACE_NEW_NORETURN(pEvent, CosNotification::StructuredEvent );
- if (pEvent != 0)
+ CosNotification::StructuredEvent_var vEvent;
+ ACE_NEW_NORETURN(vEvent, CosNotification::StructuredEvent );
+ if (vEvent.ptr() != 0)
{
- CosNotification::StructuredEvent_var vEvent(pEvent);
short length = 2;
if( object_type_ != 0)
{
diff --git a/TAO/orbsvcs/tests/FT_App/FTAPP_FactoryRegistry_Main.cpp b/TAO/orbsvcs/tests/FT_App/FTAPP_FactoryRegistry_Main.cpp
new file mode 100644
index 00000000000..b09ab0cb3da
--- /dev/null
+++ b/TAO/orbsvcs/tests/FT_App/FTAPP_FactoryRegistry_Main.cpp
@@ -0,0 +1,33 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file FTAPP_FactoryRegistry_Main.cpp
+ *
+ * $Id$
+ *
+ * This file is part of Fault Tolerant CORBA.
+ * This file provides the main routine for a stub FactoryRegistry
+ *
+ * @author Dale Wilson <wilson_d@ociweb.com>
+ */
+//=============================================================================
+
+#include <tao/Utils/ServantMain.h>
+#include "FactoryRegistry_i.h"
+
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ TAO::Utils::ServantMain<FactoryRegistry_i> servantMain("FactoryRegistry");
+ return servantMain.Main(argc, argv);
+}
+
+///////////////////////////////////
+// Template instantiation for
+// inept compilers.
+
+#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+ template TAO::Utils::ServantMain<FactoryRegistry_i>;
+#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+# pragma instantiate TAO::Utils::ServantMain<FactoryRegistry_i>
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
+
diff --git a/TAO/orbsvcs/tests/FT_App/FT_App.mpc b/TAO/orbsvcs/tests/FT_App/FT_App.mpc
index e0f2129fe93..121a7ea3a1f 100644
--- a/TAO/orbsvcs/tests/FT_App/FT_App.mpc
+++ b/TAO/orbsvcs/tests/FT_App/FT_App.mpc
@@ -85,3 +85,30 @@ project(*Analyzer): taoclient, fault_tolerance, orbsvcsexe {
run_test_notifier.pl
}
}
+
+project(*FactoryRegistry): taoclient, fault_tolerance, orbsvcsexe {
+ exename = ft_registry
+
+ Source_Files {
+ FTAPP_FactoryRegistry_Main.cpp
+ FactoryRegistry_i.cpp
+ }
+
+// // Custom folder: script to run this test
+// Define_Custom(Script){
+// inputext = .pl, .py, .rb
+// generic_outputext = .txt
+// }
+//
+// Script_Files {
+// run_test_detector.pl
+// }
+
+ // explicitly omit IDL files
+ IDL_Files {
+ }
+ Documentation_Files {
+ // pretend the pl file is documentation for now
+ run_test_registry.pl
+ }
+}
diff --git a/TAO/orbsvcs/tests/FT_App/FT_Client.cpp b/TAO/orbsvcs/tests/FT_App/FT_Client.cpp
index 4704340c261..e1a18c42e45 100644
--- a/TAO/orbsvcs/tests/FT_App/FT_Client.cpp
+++ b/TAO/orbsvcs/tests/FT_App/FT_Client.cpp
@@ -2,7 +2,7 @@
#include "FT_TestReplicaC.h"
// the following include is relative to $TAO_ROOT
-#include "examples/Simple/Simple_util.h"
+#include <examples/Simple/Simple_util.h>
#include <iostream>
#include <fstream>
@@ -597,6 +597,7 @@ int FTClientMain::run ()
}
if (! handled)
{
+ std::cout << "FT Client: Exception not handled. Rethrow. " << std::endl;
ACE_RE_THROW;
}
}
diff --git a/TAO/orbsvcs/tests/FT_App/FT_TestReplica_i.cpp b/TAO/orbsvcs/tests/FT_App/FT_TestReplica_i.cpp
index a232fd7cea1..d4334e51ca1 100644
--- a/TAO/orbsvcs/tests/FT_App/FT_TestReplica_i.cpp
+++ b/TAO/orbsvcs/tests/FT_App/FT_TestReplica_i.cpp
@@ -298,7 +298,7 @@ void FT_TestReplica_i::shutdown (ACE_ENV_SINGLE_ARG_DECL)
ACE_THROW_SPEC ((CORBA::SystemException))
{
factory_->removeReplica(factoryId_, this);
-// death_pending_ = FT_TEST::TestReplica::CLEAN_EXIT;
+ death_pending_ = FT_TEST::TestReplica::CLEAN_EXIT;
}
//////////////////////////////////////////////
@@ -318,11 +318,6 @@ int FT_TestReplica_i::idle (int & result)
}
else if (death_pending_ == FT_TEST::TestReplica::CLEAN_EXIT)
{
- ACE_ERROR ((LM_ERROR,
- "%s#%d: Simulated fault CLEAN_EXIT",
- factory_->identity(),
- ACE_static_cast(int, factoryId_ )
- ));
result = 0;
quit = 1;
}
diff --git a/TAO/orbsvcs/tests/FT_App/FT_TestReplica_i.h b/TAO/orbsvcs/tests/FT_App/FT_TestReplica_i.h
index 1e543c4df57..63d646ca1b1 100644
--- a/TAO/orbsvcs/tests/FT_App/FT_TestReplica_i.h
+++ b/TAO/orbsvcs/tests/FT_App/FT_TestReplica_i.h
@@ -17,7 +17,7 @@
#pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */
-#include "ace/pre.h"
+#include /**/ <ace/pre.h>
#include "FT_TestReplicaS.h"
////////////////////
@@ -191,6 +191,6 @@ private:
};
-#include "ace/post.h"
+#include /**/ "ace/post.h"
#endif /* FT_TESTREPLICA_I_H_ */
diff --git a/TAO/orbsvcs/tests/FT_App/FactoryRegistry_i.cpp b/TAO/orbsvcs/tests/FT_App/FactoryRegistry_i.cpp
new file mode 100644
index 00000000000..6db1278c848
--- /dev/null
+++ b/TAO/orbsvcs/tests/FT_App/FactoryRegistry_i.cpp
@@ -0,0 +1,501 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "FactoryRegistry_i.h"
+
+#include <ace/Get_Opt.h>
+#include <ace/Vector_T.h>
+#include <tao/PortableServer/ORB_Manager.h>
+#include <orbsvcs/PortableGroup/PG_Operators.h> // Borrow operator == on CosNaming::Name
+
+// Use this macro at the beginning of CORBA methods
+// to aid in debugging.
+#define METHOD_ENTRY(name) \
+ ACE_DEBUG (( LM_DEBUG, \
+ "Enter %s\n", #name \
+ ))
+
+// Use this macro to return from CORBA methods
+// to aid in debugging. Note that you can specify
+// the return value after the macro, for example:
+// METHOD_RETURN(Plugh::plover) xyzzy; is equivalent
+// to return xyzzy;
+// METHOD_RETURN(Plugh::troll); is equivalent to
+// return;
+// WARNING: THIS GENERATES TWO STATEMENTS!!! THE FOLLOWING
+// will not do what you want it to:
+// if (cave_is_closing) METHOD_RETURN(Plugh::pirate) aarrggh;
+// Moral: Always use braces.
+#define METHOD_RETURN(name) \
+ ACE_DEBUG (( LM_DEBUG, \
+ "Leave %s\n", #name \
+ )); \
+ return /* value goes here */
+
+FactoryRegistry_i::FactoryRegistry_i ()
+ : iorOutputFile(0)
+ , nsName_(0)
+ , quitOnIdle_(0)
+ , quitRequested_(0)
+
+{
+}
+
+FactoryRegistry_i::~FactoryRegistry_i (void)
+{
+}
+
+//////////////////////////////////////////////////////
+// FactoryRegistry_i public, non-CORBA methods
+
+int FactoryRegistry_i::parse_args (int argc, char * argv[])
+{
+ ACE_Get_Opt get_opts (argc, argv, "o:t:r:q");
+ int c;
+
+ while ((c = get_opts ()) != -1)
+ {
+ switch (c)
+ {
+ case 'o':
+ {
+ iorOutputFile = get_opts.opt_arg ();
+ break;
+ }
+ case 'q':
+ {
+ quitOnIdle_ = 1;
+ break;
+ }
+
+ case '?':
+ // fall thru
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "usage: %s"
+ " -o <factory ior file>"
+ " -t <test replica ior file>"
+ " -q{uit on idle}"
+ "\n",
+ argv [0]),
+ -1);
+ break;
+ }
+ }
+ // Indicates sucessful parsing of the command line
+ return 0;
+}
+
+const char * FactoryRegistry_i::identity () const
+{
+ return identity_.c_str();
+}
+
+int FactoryRegistry_i::idle (int & result)
+{
+ result = 0;
+ int quit = quitRequested_;
+ return quit;
+}
+
+
+int FactoryRegistry_i::fini (ACE_ENV_SINGLE_ARG_DECL)
+{
+ if (iorOutputFile != 0)
+ {
+ ACE_OS::unlink (iorOutputFile);
+ iorOutputFile = 0;
+ }
+ if (nsName_ != 0)
+ {
+ naming_context_->unbind (this_name_
+ ACE_ENV_ARG_PARAMETER);
+ nsName_ = 0;
+ }
+ return 0;
+}
+
+int FactoryRegistry_i::init (TAO_ORB_Manager & orbManager
+ ACE_ENV_ARG_DECL)
+{
+ int result = 0;
+
+ orbManager_ = & orbManager;
+ orb_ = orbManager.orb();
+
+ // Register with the ORB.
+ ior_ = orbManager.activate (this
+ ACE_ENV_ARG_PARAMETER);
+ ACE_CHECK_RETURN (-1);
+
+ if (iorOutputFile != 0)
+ {
+ identity_ = "file:";
+ identity_ += iorOutputFile;
+ result = writeIOR (iorOutputFile, ior_);
+ }
+ else
+ {
+ // if no IOR file specified,
+ // then always try to register with name service
+ nsName_ = "FactoryRegistry";
+ }
+
+ if (nsName_ != 0)
+ {
+ identity_ = "name:";
+ identity_ += nsName_;
+
+ CORBA::Object_var naming_obj =
+ orb_->resolve_initial_references ("NameService" ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ if (CORBA::is_nil(naming_obj.in ())){
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%T %n (%P|%t) Unable to find the Naming Service\n"),
+ 1);
+ }
+
+ naming_context_ =
+ CosNaming::NamingContext::_narrow (naming_obj.in () ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+
+ this_name_.length (1);
+ this_name_[0].id = CORBA::string_dup (nsName_);
+
+ naming_context_->rebind (this_name_, _this()
+ ACE_ENV_ARG_PARAMETER);
+ ACE_TRY_CHECK;
+ }
+
+ return result;
+}
+
+//////////////////////////////////////////
+// FactoryRegistry_i CORBA methods
+
+/* Reference:info
+ typedef CosNaming::Name Name;
+ typedef Name Location;
+ struct FactoryInfo {
+ GenericFactory the_factory;
+ Location the_location;
+ Criteria the_criteria;
+ };
+ typedef sequence<FactoryInfo> FactoryInfos;
+*/
+
+
+void FactoryRegistry_i::register_factory (
+ const char * type_id,
+ const PortableGroup::FactoryInfo & factory_info
+ ACE_ENV_ARG_DECL
+ )
+ ACE_THROW_SPEC ((CORBA::SystemException, PortableGroup::MemberAlreadyPresent))
+{
+ METHOD_ENTRY(FactoryRegistry_i::register_factory);
+
+ PortableGroup::FactoryInfos * infos;
+ if (registry_.find(type_id, infos) )
+ {
+ ACE_DEBUG(( LM_DEBUG,
+ "register_factory found infos for %s", type_id
+ ));
+ }
+ else
+ {
+ ACE_DEBUG(( LM_DEBUG,
+ "register_factory: no infos for %s", type_id
+ ));
+ // Note the 5. It's a guess about the number of factories
+ // that might exist for any particular type of object.
+ // todo: make it a parameter.
+ ACE_NEW_NORETURN (infos, PortableGroup::FactoryInfos(5));
+ if (infos == 0)
+ {
+ ACE_ERROR(( LM_ERROR,
+ "Can't allocate infos for type: %s\n" , type_id));
+ ACE_THROW (CORBA::NO_MEMORY (TAO_DEFAULT_MINOR_CODE,
+ CORBA::COMPLETED_NO));
+ }
+ registry_.bind(type_id, infos);
+ }
+ // at this point infos points to the infos structure
+ // for this type..
+ size_t length = infos->length();
+ for (size_t nInfo = 0; nInfo < length; ++nInfo)
+ {
+ PortableGroup::FactoryInfo & info = (*infos)[nInfo];
+ if (info.the_location == factory_info.the_location)
+ {
+ ACE_ERROR(( LM_ERROR,
+ "Found duplicate location for type: %s\n" , type_id));
+ ACE_THROW (PortableGroup::MemberAlreadyPresent() );
+ }
+ }
+
+ infos->length(length + 1);
+ (*infos)[length] = factory_info;
+
+ METHOD_RETURN(FactoryRegistry_i::register_factory);
+}
+
+void FactoryRegistry_i::unregister_factory (
+ const char * type_id,
+ const PortableGroup::Location & location
+ ACE_ENV_ARG_DECL
+ )
+ ACE_THROW_SPEC ((CORBA::SystemException, PortableGroup::MemberNotFound))
+{
+ METHOD_ENTRY(FactoryRegistry_i::unregister_factory);
+
+ PortableGroup::FactoryInfos * infos;
+ if (registry_.find(type_id, infos) )
+ {
+ ACE_DEBUG(( LM_DEBUG,
+ "register_factory found infos for %s", type_id
+ ));
+ // at this point infos points to the infos structure
+ // for this type..
+
+ int found = 0;
+ size_t length = infos->length();
+ for (size_t nInfo = 0; !found && nInfo < length; ++nInfo)
+ {
+ PortableGroup::FactoryInfo & info = (*infos)[nInfo];
+ if (info.the_location == location)
+ {
+ found = 1;
+ if (length > 1)
+ {
+ while (nInfo + 1 < length)
+ {
+ (*infos)[nInfo] = (*infos)[nInfo + 1];
+ nInfo += 1;
+ }
+ infos->length(nInfo);
+ }
+ else
+ {
+ assert ( length == 1 );
+ registry_.unbind (type_id);
+ delete infos;
+ }
+ }
+ }
+ }
+ else
+ {
+ ACE_ERROR(( LM_ERROR,
+ "nregister_factory: no infos for %s", type_id
+ ));
+ ACE_THROW ( PortableGroup::MemberNotFound() );
+ infos->length(0);
+ registry_.bind(type_id, infos);
+ }
+
+ METHOD_RETURN(FactoryRegistry_i::unregister_factory);
+}
+
+void FactoryRegistry_i::unregister_factory_by_type (
+ const char * type_id
+ ACE_ENV_ARG_DECL
+ )
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ METHOD_ENTRY(FactoryRegistry_i::unregister_factory_by_type);
+ PortableGroup::FactoryInfos * infos;
+ if (registry_.unbind(type_id, infos) )
+ {
+ ACE_DEBUG(( LM_DEBUG,
+ "unregister_factory_by_type found infos for %s", type_id
+ ));
+ // delete the entire set of factories for this location.
+ delete infos;
+ }
+ else
+ {
+ ACE_ERROR(( LM_INFO,
+ "Info: unregister_factory_by_type: no infos for %s", type_id
+ ));
+ }
+ METHOD_RETURN(FactoryRegistry_i::unregister_factory_by_type);
+}
+
+void FactoryRegistry_i::unregister_factory_by_location (
+ const PortableGroup::Location & location
+ ACE_ENV_ARG_DECL
+ )
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ METHOD_ENTRY(FactoryRegistry_i::unregister_factory_by_location);
+
+ ACE_Vector<ACE_CString> hitList;
+
+ // iterate through the registery
+ for (RegistryType_Iterator it = registry_.begin();
+ it != registry_.end();
+ ++it)
+ {
+ RegistryType_Entry & entry = *it;
+ PortableGroup::FactoryInfos * infos = entry.int_id_;
+
+ int found = 0;
+ size_t length = infos->length();
+ for (size_t nInfo = 0; !found && nInfo < length; ++nInfo)
+ {
+ PortableGroup::FactoryInfo & info = (*infos)[nInfo];
+ if (info.the_location == location)
+ {
+ found = 1;
+ if (length > 1)
+ {
+ while (nInfo + 1 < length)
+ {
+ infos[nInfo] = infos[nInfo + 1];
+ nInfo += 1;
+ }
+ infos->length(nInfo);
+ }
+ else
+ {
+ assert ( length == 1 );
+ // remember entries to be deleted
+ hitList.push_back(entry.ext_id_);
+ }
+ }
+ }
+ }
+
+ // now remove any types that became empty
+
+ for (size_t nHit = 0; nHit < hitList.size(); ++nHit)
+ {
+ PortableGroup::FactoryInfos * infos;
+ if (registry_.unbind(hitList[nHit], infos) )
+ {
+ delete infos;
+ }
+ else
+ {
+ ACE_ERROR ((LM_ERROR,
+ "LOGIC ERROR AT " __FILE__ " (%d): Entry to be deleted disappeared", __LINE__));
+ }
+ }
+
+ METHOD_RETURN(FactoryRegistry_i::unregister_factory_by_location);
+}
+
+::PortableGroup::FactoryInfos * FactoryRegistry_i::list_factories_by_type (
+ const char * type_id
+ ACE_ENV_ARG_DECL
+ )
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ METHOD_ENTRY(FactoryRegistry_i::list_factories_by_type);
+
+ PortableGroup::FactoryInfos_var infos;
+ ACE_NEW_NORETURN(infos, ::PortableGroup::FactoryInfos() );
+ if (infos.ptr() == 0)
+ {
+ ACE_ERROR(( LM_ERROR,
+ "list_factories_by_type: Can't allocate infos for type: %s\n" , type_id));
+ ACE_THROW (CORBA::NO_MEMORY (TAO_DEFAULT_MINOR_CODE,
+ CORBA::COMPLETED_NO));
+ }
+
+ PortableGroup::FactoryInfos * typeInfos;
+ if (registry_.unbind(type_id, typeInfos) )
+ {
+ ACE_DEBUG(( LM_DEBUG,
+ "unregister_factory_by_type found infos for %s", type_id
+ ));
+ (*infos) = (*typeInfos);
+ }
+ METHOD_RETURN(FactoryRegistry_i::list_factories_by_type) infos._retn();
+}
+
+::PortableGroup::FactoryInfos * FactoryRegistry_i::list_factories_by_location (
+ const PortableGroup::Location & location
+ ACE_ENV_ARG_DECL
+ )
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ METHOD_ENTRY(FactoryRegistry_i::list_factories_by_location);
+ ::PortableGroup::FactoryInfos_var infos;
+ ACE_NEW_NORETURN(infos, ::PortableGroup::FactoryInfos(registry_.current_size()) );
+ if (infos.ptr() == 0)
+ {
+ ACE_ERROR(( LM_ERROR,
+ "list_factories_by_location: Can't allocate infos\n"));
+ ACE_THROW (CORBA::NO_MEMORY (TAO_DEFAULT_MINOR_CODE,
+ CORBA::COMPLETED_NO));
+ }
+
+ size_t count = 0;
+
+ // iterate through the registery
+ for (RegistryType_Iterator it = registry_.begin();
+ it != registry_.end();
+ ++it)
+ {
+ RegistryType_Entry & entry = *it;
+ PortableGroup::FactoryInfos * infos = entry.int_id_;
+
+ // iterate through the entry for this type
+ int found = 0;
+ size_t length = infos->length();
+ for (size_t nInfo = 0; !found && nInfo < length; ++nInfo)
+ {
+ PortableGroup::FactoryInfo & info = (*infos)[nInfo];
+ if (info.the_location == location)
+ {
+ found = 1;
+ count += 1;
+ infos->length(count);
+ (*infos)[count-1] = info;
+ }
+ }
+ }
+
+ METHOD_RETURN(FactoryRegistry_i::list_factories_by_location) infos._retn();
+}
+
+//////////////////////////////
+// Implementation methods
+
+int FactoryRegistry_i::writeIOR(const char * outputFile, const char * ior)
+{
+ int result = -1;
+ FILE* out = ACE_OS::fopen (outputFile, "w");
+ if (out)
+ {
+ ACE_OS::fprintf (out, "%s", ior);
+ ACE_OS::fclose (out);
+ result = 0;
+ }
+ else
+ {
+ ACE_ERROR ((LM_ERROR,
+ "Open failed for %s\n", outputFile
+ ));
+ }
+ return result;
+}
+
+#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+
+ template class ACE_Hash_Map_Manager <ACE_CString, PortableGroup::FactoryInfos *, MapMutex>;
+ template class ACE_Hash_Map_Entry <ACE_CString, PortableGroup::FactoryInfos *>;
+ template class ACE_Hash_Map_Iterator <ACE_CString, PortableGroup::FactoryInfos *, MapMutex>;
+ template class ACE_Vector<ACE_CString>;
+
+#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+
+# pragma instantiate ACE_Hash_Map_Manager <ACE_CString, PortableGroup::FactoryInfos *, MapMutex>
+# pragma instantiate ACE_Hash_Map_Entry <ACE_CString, PortableGroup::FactoryInfos *>
+# pragma instantiate ACE_Hash_Map_Iterator <ACE_CString, PortableGroup::FactoryInfos *, MapMutex>
+# pragma instantiate ACE_Vector<ACE_CString>
+
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
diff --git a/TAO/orbsvcs/tests/FT_App/FactoryRegistry_i.h b/TAO/orbsvcs/tests/FT_App/FactoryRegistry_i.h
new file mode 100644
index 00000000000..58d5f2c8ca6
--- /dev/null
+++ b/TAO/orbsvcs/tests/FT_App/FactoryRegistry_i.h
@@ -0,0 +1,204 @@
+// -*- C++ -*-
+//=============================================================================
+/**
+ * @file FactoryRegistry_i.h
+ *
+ * $Id$
+ *
+ * This file declares the implementation of PortableGroup::FactoryRegistry.
+ * Eventually this should be folded into the Fault Tolerance ReplicationManager
+ *
+ * @author Dale Wilson <wilson_d@ociweb.com>
+ */
+//=============================================================================
+
+#ifndef FACTORYREGISTRY_I_H_
+#define FACTORYREGISTRY_I_H_
+
+#include <orbsvcs/PortableGroupS.h>
+#include <ace/Hash_Map_Manager.h>
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+//////////////////////////////////
+// Classes declared in this header
+class FactoryRegistry_i;
+
+/////////////////////////////////
+// Includes needed by this header
+
+/////////////////////
+// Forward references
+class TAO_ORB_Manager;
+
+/**
+ * Implement the PortableGroup::FactoryRegistry interface
+ * Note FactoryRegistry is not part of the OMG standard. It was added
+ * as part of the TAO implementation of Fault Tolerant Corba
+ */
+class FactoryRegistry_i : public virtual POA_PortableGroup::FactoryRegistry
+{
+ /* <DESIGN> originally I used FactoryInfos_vars rather than FactoryInfos *,
+ but it actually made memory management harder. DLW </DESIGN> */
+ typedef ACE_Null_Mutex MapMutex;
+ typedef ACE_Hash_Map_Manager <ACE_CString, PortableGroup::FactoryInfos *, MapMutex> RegistryType;
+ typedef ACE_Hash_Map_Entry <ACE_CString, PortableGroup::FactoryInfos *> RegistryType_Entry;
+ typedef ACE_Hash_Map_Iterator <ACE_CString, PortableGroup::FactoryInfos *, MapMutex> RegistryType_Iterator;
+
+ //////////////////////
+ // non-CORBA interface
+public:
+ /// Constructor
+ FactoryRegistry_i (void);
+
+ /// virtual Destructor
+ virtual ~FactoryRegistry_i (void);
+
+ /**
+ * Parse command line arguments.
+ * @param argc traditional C argc
+ * @param argv traditional C argv
+ * @return zero for success; nonzero is process return code for failure.
+ */
+ int parse_args (int argc, char * argv[]);
+
+ /**
+ * Initialize this object.
+ * @param orbManager our ORB -- we keep var to it.
+ * @return zero for success; nonzero is process return code for failure.
+ */
+ int init (TAO_ORB_Manager & orbManager ACE_ENV_ARG_DECL_WITH_DEFAULTS);
+
+ /**
+ * Prepare to exit.
+ * @return zero for success; nonzero is process return code for failure.
+ */
+ int fini (ACE_ENV_SINGLE_ARG_DECL);
+
+ /**
+ * Processing to happen when the ORB's event loop is idle.
+ * @param result is a place to return status to be returned by the process
+ * @returns 0 to continue. 1 to quit.
+ */
+ int idle(int & result);
+
+ /**
+ * Identify this object.
+ * @return a string to identify this object for logging/console message purposes.
+ */
+ const char * identity () const;
+
+ //////////////////
+ // CORBA interface
+ // See IDL for documentation
+
+ virtual void register_factory (
+ const char * type_id,
+ const PortableGroup::FactoryInfo & factory_info
+ ACE_ENV_ARG_DECL
+ )
+ ACE_THROW_SPEC ((CORBA::SystemException, PortableGroup::MemberAlreadyPresent));
+
+ virtual void unregister_factory (
+ const char * type_id,
+ const PortableGroup::Location & location
+ ACE_ENV_ARG_DECL
+ )
+ ACE_THROW_SPEC ((CORBA::SystemException, PortableGroup::MemberNotFound));
+
+ virtual void unregister_factory_by_type (
+ const char * type_id
+ ACE_ENV_ARG_DECL
+ )
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ virtual void unregister_factory_by_location (
+ const PortableGroup::Location & location
+ ACE_ENV_ARG_DECL
+ )
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ virtual ::PortableGroup::FactoryInfos * list_factories_by_type (
+ const char * type_id
+ ACE_ENV_ARG_DECL
+ )
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ virtual ::PortableGroup::FactoryInfos * list_factories_by_location (
+ const PortableGroup::Location & location
+ ACE_ENV_ARG_DECL
+ )
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ /////////////////////////
+ // Implementation methods
+private:
+ /**
+ * Write this factory's IOR to a file
+ */
+ int writeIOR (const char * outputFile, const char * ior);
+
+ ///////////////
+ // Data Members
+private:
+
+ /**
+ * A human-readable string to distinguish this from other Notifiers.
+ */
+ ACE_CString identity_;
+
+ /**
+ * Protect internal state.
+ * Mutex should be locked by corba methods, or by
+ * external (public) methods before calling implementation
+ * methods.
+ * Implementation methods should assume the mutex is
+ * locked if necessary.
+ */
+ ACE_Mutex internals_;
+ typedef ACE_Guard<ACE_Mutex> InternalGuard;
+
+ TAO_ORB_Manager * orbManager_;
+ /**
+ * The orb
+ */
+ CORBA::ORB_var orb_;
+
+ /**
+ * IOR of this object as assigned by poa.
+ */
+ CORBA::String_var ior_;
+
+ /**
+ * A file to which the factory's IOR should be written.
+ */
+ const char * iorOutputFile;
+
+ /**
+ * A name to be used to register the factory with the name service.
+ */
+ const char * nsName_;
+
+ CosNaming::NamingContext_var naming_context_;
+
+ CosNaming::Name this_name_;
+
+ /**
+ * Quit on idle flag.
+ */
+ int quitOnIdle_;
+
+ /**
+ * boolean: starts false. Set to true when it's time to quit.
+ */
+ int quitRequested_;
+
+
+ RegistryType registry_;
+
+};
+
+
+#endif /* __FACTORYREGISTRY_I_H_ */
diff --git a/TAO/orbsvcs/tests/FT_App/README b/TAO/orbsvcs/tests/FT_App/README
index 824c203fb90..2430fac4723 100644
--- a/TAO/orbsvcs/tests/FT_App/README
+++ b/TAO/orbsvcs/tests/FT_App/README
@@ -2,16 +2,16 @@ $Id$
This is a simple application intended to test Fault Tolerant Corba.
-The server implements the IDL in FT_TestReplica.idl which defines
-the interface FT_TEST::TestReplica .
+The server implements GenericFactory as a factory that creates TestReplicas.
+TestReplicas are defined in the IDL in FT_TestReplica.idl.
FT_TEST::TestReplica inherits from PullMonitorable and Checkpointable
to provide access needed by FT Corba's FaultDetector and Orb.
-An FT_TEST::TestReplica contains a long counter. Methods are defined
-to set, increment, and get the value of the counter. The counter
-is also exposed as an attribute named counter. (i.e. set(x) is
-exactly equivalent to counter(x), and get() is exactly equivalent
+An FT_TEST::TestReplica contains a long counter. Methods are defined
+to set, increment, and get the value of the counter. The counter
+is also exposed as an attribute named counter. (i.e. set(x) is
+exactly equivalent to counter(x), and get() is exactly equivalent
to counter())
In addition there is a method named die that lets the client request
@@ -28,6 +28,11 @@ to 10. +5 increments the counter by 5 (thereby setting the value to 15).
The '?' commmand lists the possible commands and their options.
+Additional programs:
+ ft_notifier is a stub implementation of a fault notifier for testing fault detectors.
+ ft_analyzer is a stub implementation of a fault analyzer for testing the fault notifier
+ ft_registry is an implementation of FactoryRegistry for testing GenericFactories.
+
To run:
Start one or more FT_Replicas. Use a -o <filename> to tell the replica
where to write its ior..
@@ -35,21 +40,23 @@ where to write its ior..
Start the FT_Client with -f file1<,filen>... (i.e. a comma separated list
of replica IOR files. To read commands from a file, use -c <command file>
-The counter is persistent and will survive server failures. It's
-stored in a file named persistent.dat.
+The counter is persistent and will survive server failures. It's
+stored in a file named persistent.dat.
-Replicas of the server may be run in separate directories to simulate
-replicated stateful objects (each replica has its own distinct state), or
-multiple replicas can be run in the same directory to simulate a server
-with a shared state or one that executes real-world unsafe-to-repeat
-action (i.e. "fire the retro rockets" or "expose the patient to
+Replicas of the server may be run in separate directories to simulate
+replicated stateful objects (each replica has its own distinct state), or
+multiple replicas can be run in the same directory to simulate a server
+with a shared state or one that executes real-world unsafe-to-repeat
+action (i.e. "fire the retro rockets" or "expose the patient to
theraputic radiation.")
-Tests:
-
-Two Fault Detection unit tests have been created based on this application.
- run_test_detector.pl uses this application plus a "stub" fault notifier
- to test the fault detectors and the fault detector factory.
- run_test_notifier.pl uses this application, the fault detectors+factory,
- and a stub fault analyzer to test the fault notifier.
+Unit Tests based on this application:
+ run_test_basic.pl tests this application, thereby answering the question,
+ "who will test the tester?".
+ run_test_detector.pl uses this application plus a "stub" fault notifier
+ to test the fault detectors and the fault detector factory.
+ run_test_notifier.pl uses this application, the fault detectors+factory,
+ and a stub fault analyzer to test the fault notifier.
+ run_test_factory.pl uses this application, et. al. to test the GenericFactory
+ implementation in FT_Replica.
See the internal documentation of the .pl files for more details.
diff --git a/TAO/orbsvcs/tests/FT_App/StubBatchConsumer.cpp b/TAO/orbsvcs/tests/FT_App/StubBatchConsumer.cpp
index 1d2416615dd..743c80625aa 100644
--- a/TAO/orbsvcs/tests/FT_App/StubBatchConsumer.cpp
+++ b/TAO/orbsvcs/tests/FT_App/StubBatchConsumer.cpp
@@ -2,7 +2,6 @@
//
// $Id$
-#include <ace/pre.h>
#include "StubBatchConsumer.h"
#include <ace/Get_Opt.h>
#include <tao/PortableServer/ORB_Manager.h>
@@ -127,4 +126,3 @@ void StubBatchConsumer::disconnect_sequence_push_consumer (
//# pragma instantiate ACE_Vector < const char * >
#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
-#include "ace/post.h"
diff --git a/TAO/orbsvcs/tests/FT_App/StubFaultAnalyzer.cpp b/TAO/orbsvcs/tests/FT_App/StubFaultAnalyzer.cpp
index e82018997d1..5eac532ee7c 100644
--- a/TAO/orbsvcs/tests/FT_App/StubFaultAnalyzer.cpp
+++ b/TAO/orbsvcs/tests/FT_App/StubFaultAnalyzer.cpp
@@ -2,7 +2,6 @@
//
// $Id$
-#include <ace/pre.h>
#include "StubFaultAnalyzer.h"
#include <ace/Get_Opt.h>
#include <tao/PortableServer/ORB_Manager.h>
@@ -367,4 +366,3 @@ int StubFaultAnalyzer::readIORFile(const char * fileName, CORBA::String_var & io
# pragma instantiate ACE_Vector < FT::PullMonitorable_var >
#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
-#include "ace/post.h"
diff --git a/TAO/orbsvcs/tests/FT_App/StubFaultConsumer.cpp b/TAO/orbsvcs/tests/FT_App/StubFaultConsumer.cpp
index ace3b39ad99..083c1643daa 100644
--- a/TAO/orbsvcs/tests/FT_App/StubFaultConsumer.cpp
+++ b/TAO/orbsvcs/tests/FT_App/StubFaultConsumer.cpp
@@ -2,7 +2,6 @@
//
// $Id$
-#include <ace/pre.h>
#include "StubFaultConsumer.h"
#include <ace/Get_Opt.h>
#include <tao/PortableServer/ORB_Manager.h>
@@ -256,4 +255,3 @@ void StubFaultConsumer::disconnect_structured_push_consumer(ACE_ENV_SINGLE_ARG_D
//# pragma instantiate ACE_Vector < const char * >
#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
-#include "ace/post.h"
diff --git a/TAO/orbsvcs/tests/FT_App/StubFaultNotifier.h b/TAO/orbsvcs/tests/FT_App/StubFaultNotifier.h
index 21c51538099..6daeeb9c49a 100644
--- a/TAO/orbsvcs/tests/FT_App/StubFaultNotifier.h
+++ b/TAO/orbsvcs/tests/FT_App/StubFaultNotifier.h
@@ -6,11 +6,11 @@
#if !defined (ACE_LACKS_PRAGMA_ONCE)
#pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */
-#include "ace/pre.h"
+#include /**/ <ace/pre.h>
-#include "orbsvcs/FT_NotifierS.h"
-#include "orbsvcs/FT_FaultDetectorFactoryC.h"
-#include "ace/Vector_T.h"
+#include <orbsvcs/FT_NotifierS.h>
+#include <orbsvcs/FT_FaultDetectorFactoryC.h>
+#include <ace/Vector_T.h>
//////////////////////
// Forward references
@@ -164,10 +164,8 @@ private:
* A human-readable string to distinguish this from other Notifiers.
*/
ACE_CString identity_;
-
-
};
-#include "ace/post.h"
+#include /**/ <ace/post.h>
#endif /* STUBFAULTNOTIFIER_H_ */
diff --git a/TAO/orbsvcs/tests/FT_App/run_test_registry.pl b/TAO/orbsvcs/tests/FT_App/run_test_registry.pl
new file mode 100755
index 00000000000..12beb068146
--- /dev/null
+++ b/TAO/orbsvcs/tests/FT_App/run_test_registry.pl
@@ -0,0 +1,263 @@
+eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
+ & eval 'exec perl -S $0 $argv:q'
+ if 0;
+
+# $Id$
+# -*- perl -*-
+
+# Purpose:
+# To test the FaultNotifier
+#
+# Process being tested:
+# Fault_Notifier
+# implements FaultNotifier interface.
+# Processes used in test:
+# FT_Replica
+# implements TestReplica interface.
+# implements PullMonitorable.
+# Fault_Detector
+# implements FaultDetectorFactory interface
+# implements PullMonitorable interface
+# FT_Client
+# client for TestReplica interface.
+# client for PullMonitorable.
+# StubAnalyzer
+# Subscribes to Fault_Notfier
+#
+# Test Scenario (***Test: marks behavior being tested):
+# Phase 1:
+# Start two FT_Replicas
+# FT_Replicas write TestReplica IORs (FR#1 and FR#2) to files
+# Start the Fault_Detector
+# Fault_Detector writes its IOR (FDF) to a file
+# Start the Fault_Notifier
+# Fault_Notifier writes its IOR (FN) to a file.
+# Phase 2:
+# Wait for IORs: FR#1, FR#2, FDF, and FN
+# Start the StubAnalyzer giving it IORS: FR#1, FR#2 FDF, FN
+# StubAnalyzer calls FDF to create a FaultDetector
+# for each Replica.
+# StubAnalyzer subscribes to Fault_Notifier
+# StubAnalyzer writes dummy message(READY) to a file.
+# Phase 3:
+# Wait for READY
+# Start FT_Client giving it IORS: FR#1 and FR#2. [1]
+# FT_Client interacts with FR#1.
+# FT_Client asks FR#1 to fault. It does so.
+# FT_Client notices fault and switches to FR#2. [1]
+# FD#1 notices fault and notifies Fault_Notifier
+# FD#1 terminates
+# ***Test: Fault_Notifier forwards notification to StubAnalyzer
+# StubAnalyzer prints notification.
+# FT_Client interacts with FR#2.
+# FT_Client asks FR#2 to shut down.
+# FT_Client shuts down.
+# FD#2 notices FR2 is gone, interprets this
+# as a fault, and sends notification to Fault_Notifier
+# FD#2 terminates.
+# ***Test: Fault_Notifier forwards notification to StubAnalyzer
+# StubAnalyzer prints notification.
+# Phase 4: shutting down.
+# All FaultDetectors have terminated so the FaultDetectorFactory
+# honors the "quit-on-idle" option on it's command line and exits.
+# StubAnalyzer compares # fault notifications to # replicas. When
+# they match, it "knows" that the test is over, so it shuts down.
+# As it does so, it disconnects its fault consumers from the FaultNotifier.
+# FaultNotifier notices the last fault consumer disconnecting and exits because
+# the "quit-on-idle" option was specified on the command line.
+# Phase 5: housekeeping
+# Wait for all processes to terminate.
+# Check termination status.
+# Delete temp files.
+#
+# [1] Client mediated fault tolerance. These points will
+# change when IOGR support is available.
+use lib '../../../../bin';
+#use lib '$ENV{ACE_ROOT}/bin';
+use PerlACE::Run_Test;
+
+########################
+#command line options
+#set defaults:
+my($verbose) = 0; # 1: report perl actions before executing them
+my($debug_builds) = 0; # 0: use exes from Release directories
+my($simulated) = 1; # 1: use "client simulated" fault tolerance
+
+foreach $i (@ARGV) {
+ if ($i eq "--debug_build")
+ {
+ $debug_builds = 1;
+ }
+ elsif ($i eq "--no_simulate") # reverse this once we have FT ORB support
+ {
+ $simulated = 0;
+ }
+ elsif ($i eq "-v")
+ {
+ $verbose += 1;
+ }
+}
+
+
+my($build_directory) = "/Release";
+if ( $debug_builds ) {
+ $build_directory = "";
+}
+
+if ( $verbose > 1) {
+ print "verbose: $verbose\n";
+ print "debug_builds: $debug_builds -> $build_directory\n";
+ print "simulated: $simulated\n";
+}
+
+
+#define temp files
+my($factory1_ior) = PerlACE::LocalFile ("factory1.ior");
+my($factory2_ior) = PerlACE::LocalFile ("factory2.ior");
+my($replica1_ior) = PerlACE::LocalFile ("replica1.ior");
+my($replica2_ior) = PerlACE::LocalFile ("replica2.ior");
+my($detector_ior) = PerlACE::LocalFile ("detector.ior");
+my($notifier_ior) = PerlACE::LocalFile ("notifier.ior");
+my($ready_file) = PerlACE::LocalFile ("ready.file");
+my($client_data) = PerlACE::LocalFile ("persistent.dat");
+
+#discard junk from previous tests
+unlink $factory1_ior;
+unlink $factory2_ior;
+unlink $replica1_ior;
+unlink $replica2_ior;
+unlink $detector_ior;
+unlink $notifier_ior;
+unlink $ready_file;
+unlink $client_data;
+
+my($status) = 0;
+
+my($REP1) = new PerlACE::Process (".$build_directory/ft_replica", "-o $factory1_ior -t $replica1_ior -r 1 -q");
+my($REP2) = new PerlACE::Process (".$build_directory/ft_replica", "-o $factory2_ior -t $replica2_ior -r 2 -q");
+my($DET) = new PerlACE::Process ("$ENV{'TAO_ROOT'}/orbsvcs/Fault_Detector$build_directory/Fault_Detector", "-o $detector_ior -q");
+my($NOT) = new PerlACE::Process ("$ENV{'TAO_ROOT'}/orbsvcs/Fault_Notifier$build_directory/Fault_Notifier", "-o $notifier_ior -v -q");
+my($ANA) = new PerlACE::Process (".$build_directory/ft_analyzer", "-o $ready_file -n $notifier_ior -q -d $detector_ior -r $replica1_ior,$replica2_ior");
+
+my($CL);
+if (simulated) {
+ $CL = new PerlACE::Process (".$build_directory/ft_client", "-f $replica1_ior,$replica2_ior -c testscript");
+}else{
+ #todo figure out how to get iogr
+ $CL = new PerlACE::Process (".$build_directory/ft_client", "-f $replica1_iogr -c testscript");
+}
+
+print "TEST: starting replica1 " . $REP1->CommandLine . "\n" if ($verbose);
+$REP1->Spawn ();
+
+print "TEST: waiting for replica 1's IOR\n" if ($verbose);
+if (PerlACE::waitforfile_timed ($replica1_ior, 5) == -1) {
+ print STDERR "ERROR: cannot find file <$replica1_ior>\n";
+ $REP1->Kill (); $REP1->TimedWait (1);
+ exit 1;
+}
+
+print "\nTEST: starting replica2 " . $REP2->CommandLine . "\n" if ($verbose);
+$REP2->Spawn ();
+
+print "TEST: waiting for replica 2's IOR\n" if ($verbose);
+if (PerlACE::waitforfile_timed ($replica2_ior, 5) == -1) {
+ print STDERR "ERROR: cannot find file <$replica2_ior>\n";
+ $REP1->Kill (); $REP1->TimedWait (1);
+ $REP2->Kill (); $REP2->TimedWait (1);
+ exit 1;
+}
+
+print "\nTEST: starting detector factory " . $DET->CommandLine . "\n" if ($verbose);
+$DET->Spawn ();
+
+print "TEST: waiting for detector's IOR\n" if ($verbose);
+if (PerlACE::waitforfile_timed ($detector_ior, 5) == -1) {
+ print STDERR "ERROR: cannot find file <$detector_ior>\n";
+ $REP1->Kill (); $REP1->TimedWait (1);
+ $REP2->Kill (); $REP2->TimedWait (1);
+ $DET->Kill (); $DET2->TimedWait(1);
+ exit 1;
+}
+
+print "\nTEST: starting notifier " . $NOT->CommandLine . "\n" if ($verbose);
+$NOT->Spawn ();
+
+print "TEST: waiting for notifier's IOR\n" if ($verbose);
+if (PerlACE::waitforfile_timed ($notifier_ior, 5) == -1) {
+ print STDERR "ERROR: cannot find file <$notifier_ior>\n";
+ $REP1->Kill (); $REP1->TimedWait (1);
+ $REP2->Kill (); $REP2->TimedWait (1);
+ $DET->Kill (); $DET2->TimedWait(1);
+ $ANA->Kill (); $ANA->TimedWait(1);
+ exit 1;
+}
+
+print "\nTEST: starting analyzer " . $ANA->CommandLine . "\n" if ($verbose);
+$ANA->Spawn ();
+
+print "TEST: waiting for READY.FILE from analyzer\n" if ($verbose);
+if (PerlACE::waitforfile_timed ($ready_file, 5) == -1) {
+ print STDERR "ERROR: cannot find file <$ready_file>\n";
+ $REP1->Kill (); $REP1->TimedWait (1);
+ $REP2->Kill (); $REP2->TimedWait (1);
+ $DET->Kill (); $DET2->TimedWait(1);
+ $NOT->Kill (); $NOT->TimedWait(1);
+ $ANA->Kill (); $ANA->TimedWait(1);
+ exit 1;
+}
+
+print "\nTEST: starting client " . $CL->CommandLine . "\n" if ($verbose);
+$client = $CL->SpawnWaitKill (60);
+
+if ($client != 0) {
+ print STDERR "ERROR: client returned $client\n";
+ $status = 1;
+}
+
+print "\nTEST: wait for replica 1.\n" if ($verbose);
+$replica1 = $REP1->WaitKill (60);
+if ($replica1 != 0) {
+ print STDERR "ERROR: replica returned $replica1\n";
+ $status = 1;
+}
+
+print "\nTEST: wait for replica 2.\n" if ($verbose);
+$replica2 = $REP2->WaitKill (60);
+if ($replica2 != 0) {
+ print STDERR "ERROR: replica returned $replica2\n";
+ $status = 1;
+}
+
+print "\nTEST: wait for detector factory to leave.\n" if ($verbose);
+$detector = $DET->WaitKill (60);
+if ($detector != 0) {
+ print STDERR "ERROR: detector returned $detector\n";
+ $status = 1;
+}
+
+print "\nTEST: wait for notifier to leave.\n" if ($verbose);
+$notifier = $NOT->WaitKill (60);
+if ($notifier != 0) {
+ print STDERR "ERROR: notifier returned $notifier\n";
+ $status = 1;
+}
+
+print "\nTEST: wait for analyzer to leave.\n" if ($verbose);
+$analyzer = $ANA->WaitKill (60);
+if ($analyzer != 0) {
+ print STDERR "ERROR: analyzer returned $analyzer\n";
+ $status = 1;
+}
+
+print "\nTEST: releasing scratch files.\n" if ($verbose);
+unlink $replica1_ior;
+unlink $replica2_ior;
+unlink $detector_ior;
+unlink $notifier_ior;
+unlink $ready_file;
+
+#client's work file
+unlink $client_data;
+
+exit $status;