diff options
Diffstat (limited to 'TAO')
393 files changed, 29812 insertions, 5 deletions
diff --git a/TAO/ChangeLog b/TAO/ChangeLog index 8aa7ab4702f..12ac174a5c5 100644 --- a/TAO/ChangeLog +++ b/TAO/ChangeLog @@ -1,3 +1,463 @@ +Tue Oct 18 17:24:26 MST 2005 Yan Dai <dai_y@ociweb.com> + + Merged in the CSD (Custom Servant Dispatching) feature from OCI. + + The main changes to existing code are: + + - Four hooks are added to TAO_Root_POA to notify the CSD when poa + is activated/deactivated and servant is activated/deactivated. + Some areas of the code were instrumented to call these hooks to + notify the CSD Strategy object of POA activation and deactivation + "events". Likewise, code was added to notify the CSD Strategy object + of servant activation and deactivation "events". + - A virtual method do_dispatch() is added to the TAO_Object_Adapter so + the CSD object adpater can override the default implementation to + dispatch the requests to the CSD strategy. + - The remote requests and the collocated oneway requests are cloned when + they are dispatched to the CSD strategy. To support the TAO_ServerRequest + clone in the CSD library, the friendship is added to the TAO_ServerRequest + class and it's data member classes such as TAO_Service_Context class, + TAO_Operation_Details class and TAO_Tagged_Profile class. + + * tao/PortableServer/Root_POA.cpp: + * tao/PortableServer/Root_POA.h: + + Added four hooks. + + * tao/PortableServer/Object_Adapter.cpp: + * tao/PortableServer/Object_Adapter.h: + * tao/PortableServer/POAManager.cpp: + * tao/PortableServer/ServantRetentionStrategyRetain.cpp: + + Instrumented to call the hooks. + + * tao/operation_details.h: + * tao/Service_Context.h: + * tao/Tagged_Profile.h: + + Added friendship with CSD_FW_Server_Request_Wrapper to support + the TAO_ServerRequest clone in CSD library. + + * tao/TAO_Server_Request.h: + + - Changed the operation_details_ to be pointer to const + TAO_Operation_Details object instead of const pointer to const + TAO_Operation_Details object. This change is made to accommodate + the change of TAO_ServerRequest clone in the CSD library. + - Added friendship with CSD_FW_Server_Request_Wrapper to support + the TAO_ServerRequest clone in CSD library. + + * tao/PortableServer/get_arg.h: + + Made the get_in_arg template function check whether the + detail argument is nil. If the detail is not nil and the + argument list in detail is nil(collocated oneway case) then it + will demarshall the input CDR stream and get arguments. This + change is made to accommodate the changes in TAO_Operation_Details + clone that writes the argument list to the input CDR of the + TAO_ServerRequest object. + + * tao/Intrusive_Ref_Count_Base_T.cpp: + * tao/Intrusive_Ref_Count_Base_T.h: + * tao/Intrusive_Ref_Count_Base_T.inl: + * tao/Intrusive_Ref_Count_Handle_T.cpp: + * tao/Intrusive_Ref_Count_Handle_T.h: + * tao/Intrusive_Ref_Count_Handle_T.inl: + + These are two new classes that provide infrastructure-level support + for classes that need an "intrusive" reference counting mechanism. + + * tao/CSD_Framework.mpc: + * tao/CSD_Framework/CSD_Default_Servant_Dispatcher.cpp: + * tao/CSD_Framework/CSD_Default_Servant_Dispatcher.h: + * tao/CSD_Framework/CSD_Framework.pidl: + * tao/CSD_Framework/CSD_Framework_Loader.cpp: + * tao/CSD_Framework/CSD_Framework_Loader.h: + * tao/CSD_Framework/CSD_FrameworkA.cpp: + * tao/CSD_Framework/CSD_FrameworkA.h: + * tao/CSD_Framework/CSD_FrameworkC.cpp: + * tao/CSD_Framework/CSD_FrameworkC.h: + * tao/CSD_Framework/CSD_FrameworkC.inl: + * tao/CSD_Framework/CSD_FW_Export.h: + * tao/CSD_Framework/CSD_FW_Server_Request_Wrapper.cpp: + * tao/CSD_Framework/CSD_FW_Server_Request_Wrapper.h: + * tao/CSD_Framework/CSD_FW_Server_Request_Wrapper.inl: + * tao/CSD_Framework/CSD_Object_Adapter.cpp: + * tao/CSD_Framework/CSD_Object_Adapter.h: + * tao/CSD_Framework/CSD_Object_Adapter_Factory.cpp: + * tao/CSD_Framework/CSD_Object_Adapter_Factory.h: + * tao/CSD_Framework/CSD_ORBInitializer.cpp: + * tao/CSD_Framework/CSD_ORBInitializer.h: + * tao/CSD_Framework/CSD_POA.cpp: + * tao/CSD_Framework/CSD_POA.h: + * tao/CSD_Framework/CSD_POA.inl: + * tao/CSD_Framework/CSD_Strategy_Base.cpp: + * tao/CSD_Framework/CSD_Strategy_Base.h: + * tao/CSD_Framework/CSD_Strategy_Base.inl: + * tao/CSD_Framework/CSD_Strategy_Proxy.cpp: + * tao/CSD_Framework/CSD_Strategy_Proxy.h: + * tao/CSD_Framework/CSD_Strategy_Proxy.inl: + * tao/CSD_Framework/CSD_Strategy_Repository.cpp: + * tao/CSD_Framework/CSD_Strategy_Repository.h: + * tao/CSD_Framework/diffs/CSD_Framework.diff: + + All of the files listed above are brand new and are used to build + the new CSD Framework library. This framework implements the base + classes for the concrete strategy implementation and implements + the service objects for CSD strategy static and dynamic loading + via the service configuration file. + + * tao/CSD_ThreadPool.mpc: + * tao/CSD_ThreadPool/CSD_ThreadPool.cpp: + * tao/CSD_ThreadPool/CSD_ThreadPool.h: + * tao/CSD_ThreadPool/CSD_TP_Cancel_Visitor.cpp: + * tao/CSD_ThreadPool/CSD_TP_Cancel_Visitor.h: + * tao/CSD_ThreadPool/CSD_TP_Cancel_Visitor.inl: + * tao/CSD_ThreadPool/CSD_TP_Collocated_Asynch_Request.cpp: + * tao/CSD_ThreadPool/CSD_TP_Collocated_Asynch_Request.h: + * tao/CSD_ThreadPool/CSD_TP_Collocated_Asynch_Request.inl: + * tao/CSD_ThreadPool/CSD_TP_Collocated_Synch_Request.cpp: + * tao/CSD_ThreadPool/CSD_TP_Collocated_Synch_Request.h: + * tao/CSD_ThreadPool/CSD_TP_Collocated_Synch_Request.inl: + * tao/CSD_ThreadPool/CSD_TP_Collocated_Synch_With_Server_Request.cpp: + * tao/CSD_ThreadPool/CSD_TP_Collocated_Synch_With_Server_Request.h: + * tao/CSD_ThreadPool/CSD_TP_Collocated_Synch_With_Server_Request.inl: + * tao/CSD_ThreadPool/CSD_TP_Corba_Request.cpp: + * tao/CSD_ThreadPool/CSD_TP_Corba_Request.h: + * tao/CSD_ThreadPool/CSD_TP_Corba_Request.inl: + * tao/CSD_ThreadPool/CSD_TP_Custom_Asynch_Request.cpp: + * tao/CSD_ThreadPool/CSD_TP_Custom_Asynch_Request.h: + * tao/CSD_ThreadPool/CSD_TP_Custom_Asynch_Request.inl: + * tao/CSD_ThreadPool/CSD_TP_Custom_Request.cpp: + * tao/CSD_ThreadPool/CSD_TP_Custom_Request.h: + * tao/CSD_ThreadPool/CSD_TP_Custom_Request.inl: + * tao/CSD_ThreadPool/CSD_TP_Custom_Request_Operation.cpp: + * tao/CSD_ThreadPool/CSD_TP_Custom_Request_Operation.h: + * tao/CSD_ThreadPool/CSD_TP_Custom_Request_Operation.inl: + * tao/CSD_ThreadPool/CSD_TP_Custom_Synch_Request.cpp: + * tao/CSD_ThreadPool/CSD_TP_Custom_Synch_Request.h: + * tao/CSD_ThreadPool/CSD_TP_Custom_Synch_Request.inl: + * tao/CSD_ThreadPool/CSD_TP_Dispatchable_Visitor.cpp: + * tao/CSD_ThreadPool/CSD_TP_Dispatchable_Visitor.h: + * tao/CSD_ThreadPool/CSD_TP_Dispatchable_Visitor.inl: + * tao/CSD_ThreadPool/CSD_TP_Export.h: + * tao/CSD_ThreadPool/CSD_TP_Queue.cpp: + * tao/CSD_ThreadPool/CSD_TP_Queue.h: + * tao/CSD_ThreadPool/CSD_TP_Queue.inl: + * tao/CSD_ThreadPool/CSD_TP_Queue_Visitor.cpp: + * tao/CSD_ThreadPool/CSD_TP_Queue_Visitor.h: + * tao/CSD_ThreadPool/CSD_TP_Queue_Visitor.inl: + * tao/CSD_ThreadPool/CSD_TP_Remote_Request.cpp: + * tao/CSD_ThreadPool/CSD_TP_Remote_Request.h: + * tao/CSD_ThreadPool/CSD_TP_Remote_Request.inl: + * tao/CSD_ThreadPool/CSD_TP_Request.cpp: + * tao/CSD_ThreadPool/CSD_TP_Request.h: + * tao/CSD_ThreadPool/CSD_TP_Request.inl: + * tao/CSD_ThreadPool/CSD_TP_Servant_State.cpp: + * tao/CSD_ThreadPool/CSD_TP_Servant_State.h: + * tao/CSD_ThreadPool/CSD_TP_Servant_State.inl: + * tao/CSD_ThreadPool/CSD_TP_Servant_State_Map.cpp: + * tao/CSD_ThreadPool/CSD_TP_Servant_State_Map.h: + * tao/CSD_ThreadPool/CSD_TP_Servant_State_Map.inl: + * tao/CSD_ThreadPool/CSD_TP_Strategy.cpp: + * tao/CSD_ThreadPool/CSD_TP_Strategy.h: + * tao/CSD_ThreadPool/CSD_TP_Strategy.inl: + * tao/CSD_ThreadPool/CSD_TP_Strategy_Factory.cpp: + * tao/CSD_ThreadPool/CSD_TP_Strategy_Factory.h: + * tao/CSD_ThreadPool/CSD_TP_Synch_Helper.cpp: + * tao/CSD_ThreadPool/CSD_TP_Synch_Helper.h: + * tao/CSD_ThreadPool/CSD_TP_Synch_Helper.inl: + * tao/CSD_ThreadPool/CSD_TP_Task.cpp: + * tao/CSD_ThreadPool/CSD_TP_Task.h: + * tao/CSD_ThreadPool/CSD_TP_Task.inl: + + All of the files listed above are brand new and are used to build + the new CSD ThreadPool library. Collectively, these classes + represent the reference-implementation for the CSD Strategy feature. + + * examples/CSD_Strategy/README: + * examples/CSD_Strategy/ThreadPool/client_main.cpp: + * examples/CSD_Strategy/ThreadPool/ClientApp.cpp: + * examples/CSD_Strategy/ThreadPool/ClientApp.h: + * examples/CSD_Strategy/ThreadPool/CSD_Test_ThreadPool.mpc: + * examples/CSD_Strategy/ThreadPool/Foo.idl: + * examples/CSD_Strategy/ThreadPool/Foo_i.cpp: + * examples/CSD_Strategy/ThreadPool/Foo_i.h: + * examples/CSD_Strategy/ThreadPool/OrbShutdownTask.cpp: + * examples/CSD_Strategy/ThreadPool/OrbShutdownTask.h: + * examples/CSD_Strategy/ThreadPool/README: + * examples/CSD_Strategy/ThreadPool/run_test.pl: + * examples/CSD_Strategy/ThreadPool/server_main.cpp: + * examples/CSD_Strategy/ThreadPool/ServerApp.cpp: + * examples/CSD_Strategy/ThreadPool/ServerApp.h: + * examples/CSD_Strategy/ThreadPool2/client_main.cpp: + * examples/CSD_Strategy/ThreadPool2/ClientApp.cpp: + * examples/CSD_Strategy/ThreadPool2/ClientApp.h: + * examples/CSD_Strategy/ThreadPool2/CSD_Test_ThreadPool2.mpc: + * examples/CSD_Strategy/ThreadPool2/Foo.idl: + * examples/CSD_Strategy/ThreadPool2/Foo_i.cpp: + * examples/CSD_Strategy/ThreadPool2/Foo_i.h: + * examples/CSD_Strategy/ThreadPool2/FooServantList.cpp: + * examples/CSD_Strategy/ThreadPool2/FooServantList.h: + * examples/CSD_Strategy/ThreadPool2/OrbShutdownTask.cpp: + * examples/CSD_Strategy/ThreadPool2/OrbShutdownTask.h: + * examples/CSD_Strategy/ThreadPool2/README: + * examples/CSD_Strategy/ThreadPool2/run_test.pl: + * examples/CSD_Strategy/ThreadPool2/server_main.cpp: + * examples/CSD_Strategy/ThreadPool2/ServerApp.cpp: + * examples/CSD_Strategy/ThreadPool2/ServerApp.h: + * examples/CSD_Strategy/ThreadPool3/client_main.cpp: + * examples/CSD_Strategy/ThreadPool3/ClientApp.cpp: + * examples/CSD_Strategy/ThreadPool3/ClientApp.h: + * examples/CSD_Strategy/ThreadPool3/CSD_Test_ThreadPool3.mpc: + * examples/CSD_Strategy/ThreadPool3/Foo.idl: + * examples/CSD_Strategy/ThreadPool3/Foo_i.cpp: + * examples/CSD_Strategy/ThreadPool3/Foo_i.h: + * examples/CSD_Strategy/ThreadPool3/OrbShutdownTask.cpp: + * examples/CSD_Strategy/ThreadPool3/OrbShutdownTask.h: + * examples/CSD_Strategy/ThreadPool3/OrbTask.cpp: + * examples/CSD_Strategy/ThreadPool3/OrbTask.h: + * examples/CSD_Strategy/ThreadPool3/README: + * examples/CSD_Strategy/ThreadPool3/run_test.pl: + * examples/CSD_Strategy/ThreadPool3/server_main.cpp: + * examples/CSD_Strategy/ThreadPool3/ServerApp.cpp: + * examples/CSD_Strategy/ThreadPool3/ServerApp.h: + * examples/CSD_Strategy/ThreadPool4/Callback.idl: + * examples/CSD_Strategy/ThreadPool4/Callback_i.cpp: + * examples/CSD_Strategy/ThreadPool4/Callback_i.h: + * examples/CSD_Strategy/ThreadPool4/ClientTask.cpp: + * examples/CSD_Strategy/ThreadPool4/ClientTask.h: + * examples/CSD_Strategy/ThreadPool4/CSD_Test_ThreadPool4.mpc: + * examples/CSD_Strategy/ThreadPool4/Foo.idl: + * examples/CSD_Strategy/ThreadPool4/Foo_i.cpp: + * examples/CSD_Strategy/ThreadPool4/Foo_i.h: + * examples/CSD_Strategy/ThreadPool4/OrbShutdownTask.cpp: + * examples/CSD_Strategy/ThreadPool4/OrbShutdownTask.h: + * examples/CSD_Strategy/ThreadPool4/README: + * examples/CSD_Strategy/ThreadPool4/run_test.pl: + * examples/CSD_Strategy/ThreadPool4/server_main.cpp: + * examples/CSD_Strategy/ThreadPool4/ServerApp.cpp: + * examples/CSD_Strategy/ThreadPool4/ServerApp.h: + * examples/CSD_Strategy/ThreadPool5/Callback.idl: + * examples/CSD_Strategy/ThreadPool5/Callback_i.cpp: + * examples/CSD_Strategy/ThreadPool5/Callback_i.h: + * examples/CSD_Strategy/ThreadPool5/client_main.cpp: + * examples/CSD_Strategy/ThreadPool5/ClientApp.cpp: + * examples/CSD_Strategy/ThreadPool5/ClientApp.h: + * examples/CSD_Strategy/ThreadPool5/ClientTask.cpp: + * examples/CSD_Strategy/ThreadPool5/ClientTask.h: + * examples/CSD_Strategy/ThreadPool5/CSD_Test_ThreadPool5.mpc: + * examples/CSD_Strategy/ThreadPool5/Foo.idl: + * examples/CSD_Strategy/ThreadPool5/Foo_i.cpp: + * examples/CSD_Strategy/ThreadPool5/Foo_i.h: + * examples/CSD_Strategy/ThreadPool5/FooServantList.cpp: + * examples/CSD_Strategy/ThreadPool5/FooServantList.h: + * examples/CSD_Strategy/ThreadPool5/OrbShutdownTask.cpp: + * examples/CSD_Strategy/ThreadPool5/OrbShutdownTask.h: + * examples/CSD_Strategy/ThreadPool5/OrbTask.cpp: + * examples/CSD_Strategy/ThreadPool5/OrbTask.h: + * examples/CSD_Strategy/ThreadPool5/README: + * examples/CSD_Strategy/ThreadPool5/run_test.pl: + * examples/CSD_Strategy/ThreadPool5/server_main.cpp: + * examples/CSD_Strategy/ThreadPool5/ServerApp.cpp: + * examples/CSD_Strategy/ThreadPool5/ServerApp.h: + * examples/CSD_Strategy/ThreadPool6/client_main.cpp: + * examples/CSD_Strategy/ThreadPool6/ClientApp.cpp: + * examples/CSD_Strategy/ThreadPool6/ClientApp.h: + * examples/CSD_Strategy/ThreadPool6/CSD_Test_ThreadPool6.mpc: + * examples/CSD_Strategy/ThreadPool6/Foo.idl: + * examples/CSD_Strategy/ThreadPool6/Foo_i.cpp: + * examples/CSD_Strategy/ThreadPool6/Foo_i.h: + * examples/CSD_Strategy/ThreadPool6/OrbShutdownTask.cpp: + * examples/CSD_Strategy/ThreadPool6/OrbShutdownTask.h: + * examples/CSD_Strategy/ThreadPool6/README: + * examples/CSD_Strategy/ThreadPool6/run_test.pl: + * examples/CSD_Strategy/ThreadPool6/server_main.cpp: + * examples/CSD_Strategy/ThreadPool6/ServerApp.cpp: + * examples/CSD_Strategy/ThreadPool6/ServerApp.h: + * performance-tests/CSD_Strategy/TestApps/client_main.cpp: + * performance-tests/CSD_Strategy/TestApps/ClientApp.cpp: + * performance-tests/CSD_Strategy/TestApps/ClientApp.h: + * performance-tests/CSD_Strategy/TestApps/csd_pt_testapps.mpc: + * performance-tests/CSD_Strategy/TestApps/run_test.pl: + * performance-tests/CSD_Strategy/TestApps/server_main.cpp: + * performance-tests/CSD_Strategy/TestApps/ServerApp.cpp: + * performance-tests/CSD_Strategy/TestApps/ServerApp.h: + * performance-tests/CSD_Strategy/TestApps/README: + * performance-tests/CSD_Strategy/TestInf/AppHelper.cpp: + * performance-tests/CSD_Strategy/TestInf/AppHelper.h: + * performance-tests/CSD_Strategy/TestInf/AppShutdown.cpp: + * performance-tests/CSD_Strategy/TestInf/AppShutdown.h: + * performance-tests/CSD_Strategy/TestInf/CancelledException.idl: + * performance-tests/CSD_Strategy/TestInf/ClientEngine.cpp: + * performance-tests/CSD_Strategy/TestInf/ClientEngine.h: + * performance-tests/CSD_Strategy/TestInf/ClientTask.cpp: + * performance-tests/CSD_Strategy/TestInf/ClientTask.h: + * performance-tests/CSD_Strategy/TestInf/csd_pt_testinf.mpc: + * performance-tests/CSD_Strategy/TestInf/CSD_PT_TestInf_Export.h: + * performance-tests/CSD_Strategy/TestInf/CustomException.idl: + * performance-tests/CSD_Strategy/TestInf/FooException.idl: + * performance-tests/CSD_Strategy/TestInf/OrbRunner.cpp: + * performance-tests/CSD_Strategy/TestInf/OrbRunner.h: + * performance-tests/CSD_Strategy/TestInf/OrbShutdownTask.cpp: + * performance-tests/CSD_Strategy/TestInf/OrbShutdownTask.h: + * performance-tests/CSD_Strategy/TestInf/OrbTask.cpp: + * performance-tests/CSD_Strategy/TestInf/OrbTask.h: + * performance-tests/CSD_Strategy/TestInf/ServantList_T.cpp: + * performance-tests/CSD_Strategy/TestInf/ServantList_T.h: + * performance-tests/CSD_Strategy/TestInf/TestAppBase.cpp: + * performance-tests/CSD_Strategy/TestInf/TestAppBase.h: + * performance-tests/CSD_Strategy/TestInf/TestAppException.idl: + * performance-tests/CSD_Strategy/TestInf/TestAppMain.h: + * performance-tests/CSD_Strategy/TestInf/README: + * performance-tests/CSD_Strategy/TestServant/csd_pt_testservant.mpc: + * performance-tests/CSD_Strategy/TestServant/CSD_PT_TestServant_Export.h: + * performance-tests/CSD_Strategy/TestServant/Foo.idl: + * performance-tests/CSD_Strategy/TestServant/Foo_ClientEngine.cpp: + * performance-tests/CSD_Strategy/TestServant/Foo_ClientEngine.h: + * performance-tests/CSD_Strategy/TestServant/Foo_i.cpp: + * performance-tests/CSD_Strategy/TestServant/Foo_i.h: + * performance-tests/CSD_Strategy/TestServant/Foo_Statistics.cpp: + * performance-tests/CSD_Strategy/TestServant/Foo_Statistics.h: + * performance-tests/CSD_Strategy/TestServant/README: + * tests/CSD_Strategy_Tests/README: + * tests/CSD_Strategy_Tests/Broken/client_main.cpp: + * tests/CSD_Strategy_Tests/Broken/ClientApp.cpp: + * tests/CSD_Strategy_Tests/Broken/ClientApp.h: + * tests/CSD_Strategy_Tests/Broken/CSD_TP_Broken.mpc: + * tests/CSD_Strategy_Tests/Broken/run_test.pl: + * tests/CSD_Strategy_Tests/Broken/server_main.cpp: + * tests/CSD_Strategy_Tests/Broken/ServerApp.cpp: + * tests/CSD_Strategy_Tests/Broken/ServerApp.h: + * tests/CSD_Strategy_Tests/TP_Common/AppHelper.cpp: + * tests/CSD_Strategy_Tests/TP_Common/AppHelper.h: + * tests/CSD_Strategy_Tests/TP_Common/AppShutdown.cpp: + * tests/CSD_Strategy_Tests/TP_Common/AppShutdown.h: + * tests/CSD_Strategy_Tests/TP_Common/CancelledException.idl: + * tests/CSD_Strategy_Tests/TP_Common/ClientEngine.cpp: + * tests/CSD_Strategy_Tests/TP_Common/ClientEngine.h: + * tests/CSD_Strategy_Tests/TP_Common/ClientTask.cpp: + * tests/CSD_Strategy_Tests/TP_Common/ClientTask.h: + * tests/CSD_Strategy_Tests/TP_Common/CSD_TP_Test_Export.h: + * tests/CSD_Strategy_Tests/TP_Common/CSD_TP_Test_Lib.mpc: + * tests/CSD_Strategy_Tests/TP_Common/CustomException.idl: + * tests/CSD_Strategy_Tests/TP_Common/FooException.idl: + * tests/CSD_Strategy_Tests/TP_Common/OrbRunner.cpp: + * tests/CSD_Strategy_Tests/TP_Common/OrbRunner.h: + * tests/CSD_Strategy_Tests/TP_Common/OrbShutdownTask.cpp: + * tests/CSD_Strategy_Tests/TP_Common/OrbShutdownTask.h: + * tests/CSD_Strategy_Tests/TP_Common/OrbTask.cpp: + * tests/CSD_Strategy_Tests/TP_Common/OrbTask.h: + * tests/CSD_Strategy_Tests/TP_Common/ServantList_T.cpp: + * tests/CSD_Strategy_Tests/TP_Common/ServantList_T.h: + * tests/CSD_Strategy_Tests/TP_Common/StatisticsHelper.cpp: + * tests/CSD_Strategy_Tests/TP_Common/StatisticsHelper.h: + * tests/CSD_Strategy_Tests/TP_Common/TestAppBase.cpp: + * tests/CSD_Strategy_Tests/TP_Common/TestAppBase.h: + * tests/CSD_Strategy_Tests/TP_Common/TestAppException.idl: + * tests/CSD_Strategy_Tests/TP_Common/TestAppMain.h: + * tests/CSD_Strategy_Tests/TP_Foo_A/CSD_TP_Foo_A_Export.h: + * tests/CSD_Strategy_Tests/TP_Foo_A/csd_tp_foo_a_lib.mpc: + * tests/CSD_Strategy_Tests/TP_Foo_A/Foo_A.idl: + * tests/CSD_Strategy_Tests/TP_Foo_A/Foo_A_ClientEngine.cpp: + * tests/CSD_Strategy_Tests/TP_Foo_A/Foo_A_ClientEngine.h: + * tests/CSD_Strategy_Tests/TP_Foo_A/Foo_A_i.cpp: + * tests/CSD_Strategy_Tests/TP_Foo_A/Foo_A_i.h: + * tests/CSD_Strategy_Tests/TP_Foo_A/Foo_A_Statistics.cpp: + * tests/CSD_Strategy_Tests/TP_Foo_A/Foo_A_Statistics.h: + * tests/CSD_Strategy_Tests/TP_Foo_B/Callback.idl: + * tests/CSD_Strategy_Tests/TP_Foo_B/Callback_i.cpp: + * tests/CSD_Strategy_Tests/TP_Foo_B/Callback_i.h: + * tests/CSD_Strategy_Tests/TP_Foo_B/CSD_TP_Foo_B_Export.h: + * tests/CSD_Strategy_Tests/TP_Foo_B/csd_tp_foo_b_lib.mpc: + * tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B.idl: + * tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B_ClientEngine.cpp: + * tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B_ClientEngine.h: + * tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B_i.cpp: + * tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B_i.h: + * tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B_SimpleClientEngine.cpp: + * tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B_SimpleClientEngine.h: + * tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B_Statistics.cpp: + * tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B_Statistics.h: + * tests/CSD_Strategy_Tests/TP_Foo_C/CSD_TP_Foo_C_Export.h: + * tests/CSD_Strategy_Tests/TP_Foo_C/csd_tp_foo_c_lib.mpc: + * tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C.idl: + * tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_ClientEngine.cpp: + * tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_ClientEngine.h: + * tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op1.cpp: + * tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op1.h: + * tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op2.cpp: + * tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op2.h: + * tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op3.cpp: + * tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op3.h: + * tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op4.cpp: + * tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op4.h: + * tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op5.cpp: + * tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op5.h: + * tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_Custom_ClientEngine.cpp: + * tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_Custom_ClientEngine.h: + * tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_Custom_Proxy.cpp: + * tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_Custom_Proxy.h: + * tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_i.cpp: + * tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_i.h: + * tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_Statistics.cpp: + * tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_Statistics.h: + * tests/CSD_Strategy_Tests/TP_Test_1/client_main.cpp: + * tests/CSD_Strategy_Tests/TP_Test_1/ClientApp.cpp: + * tests/CSD_Strategy_Tests/TP_Test_1/ClientApp.h: + * tests/CSD_Strategy_Tests/TP_Test_1/CSD_TP_Test_1.mpc: + * tests/CSD_Strategy_Tests/TP_Test_1/run_test.pl: + * tests/CSD_Strategy_Tests/TP_Test_1/server_main.cpp: + * tests/CSD_Strategy_Tests/TP_Test_1/ServerApp.cpp: + * tests/CSD_Strategy_Tests/TP_Test_1/ServerApp.h: + * tests/CSD_Strategy_Tests/TP_Test_2/client_main.cpp: + * tests/CSD_Strategy_Tests/TP_Test_2/ClientApp.cpp: + * tests/CSD_Strategy_Tests/TP_Test_2/ClientApp.h: + * tests/CSD_Strategy_Tests/TP_Test_2/CSD_TP_Test_2.mpc: + * tests/CSD_Strategy_Tests/TP_Test_2/run_test.pl: + * tests/CSD_Strategy_Tests/TP_Test_2/server_main.cpp: + * tests/CSD_Strategy_Tests/TP_Test_2/ServerApp.cpp: + * tests/CSD_Strategy_Tests/TP_Test_2/ServerApp.h: + * tests/CSD_Strategy_Tests/TP_Test_3/client_main.cpp: + * tests/CSD_Strategy_Tests/TP_Test_3/ClientApp.cpp: + * tests/CSD_Strategy_Tests/TP_Test_3/ClientApp.h: + * tests/CSD_Strategy_Tests/TP_Test_3/CSD_TP_Test_3.mpc: + * tests/CSD_Strategy_Tests/TP_Test_3/run_test.pl: + * tests/CSD_Strategy_Tests/TP_Test_3/server_main.cpp: + * tests/CSD_Strategy_Tests/TP_Test_3/ServerApp.cpp: + * tests/CSD_Strategy_Tests/TP_Test_3/ServerApp.h: + * tests/CSD_Strategy_Tests/TP_Test_4/client_main.cpp: + * tests/CSD_Strategy_Tests/TP_Test_4/ClientApp.cpp: + * tests/CSD_Strategy_Tests/TP_Test_4/ClientApp.h: + * tests/CSD_Strategy_Tests/TP_Test_4/CSD_TP_Test_4.mpc: + * tests/CSD_Strategy_Tests/TP_Test_4/README: + * tests/CSD_Strategy_Tests/TP_Test_4/run_test.pl: + * tests/CSD_Strategy_Tests/TP_Test_4/server_main.cpp: + * tests/CSD_Strategy_Tests/TP_Test_4/ServerApp.cpp: + * tests/CSD_Strategy_Tests/TP_Test_4/ServerApp.h: + * tests/CSD_Strategy_Tests/TP_Test_Dynamic/client.cpp: + * tests/CSD_Strategy_Tests/TP_Test_Dynamic/CSD_TP_Test_Dynamic.mpc: + * tests/CSD_Strategy_Tests/TP_Test_Dynamic/Hello.cpp: + * tests/CSD_Strategy_Tests/TP_Test_Dynamic/Hello.h: + * tests/CSD_Strategy_Tests/TP_Test_Dynamic/README: + * tests/CSD_Strategy_Tests/TP_Test_Dynamic/run_test.pl: + * tests/CSD_Strategy_Tests/TP_Test_Dynamic/server.cpp: + * tests/CSD_Strategy_Tests/TP_Test_Dynamic/svc.conf: + * tests/CSD_Strategy_Tests/TP_Test_Dynamic/Test.idl: + * tests/CSD_Strategy_Tests/TP_Test_Static/client_main.cpp: + * tests/CSD_Strategy_Tests/TP_Test_Static/ClientApp.cpp: + * tests/CSD_Strategy_Tests/TP_Test_Static/ClientApp.h: + * tests/CSD_Strategy_Tests/TP_Test_Static/CSD_TP_Test_Static.mpc: + * tests/CSD_Strategy_Tests/TP_Test_Static/README: + * tests/CSD_Strategy_Tests/TP_Test_Static/run_test.pl: + * tests/CSD_Strategy_Tests/TP_Test_Static/server_main.cpp: + * tests/CSD_Strategy_Tests/TP_Test_Static/ServerApp.cpp: + * tests/CSD_Strategy_Tests/TP_Test_Static/ServerApp.h: + * tests/CSD_Strategy_Tests/TP_Test_Static/svc.conf: + + All of the files above are part of the examples, tests and performance + tests added for the CSD feature. + Tue Oct 18 13:23:21 2005 Chris Cleeland <cleeland_c@ociweb.com> * docs/ec_options.html: Finally updated documentation to diff --git a/TAO/examples/CSD_Strategy/README b/TAO/examples/CSD_Strategy/README new file mode 100644 index 00000000000..05a14e7af7e --- /dev/null +++ b/TAO/examples/CSD_Strategy/README @@ -0,0 +1,20 @@ +The example ThreadPool, ThreadPool2 and ThreadPool3 use the same idl file which +defines some twoway calls and a simple oneway call and they are different just +because of their configurations such as the number of servants, the number of +ORB threads and the number of csd threads. + +ThreadPool - 1 servant, 1 ORB theread (main thread), 1 csd thread. +ThreadPool2 - multiple servants, 1 ORB theread (main thread), multiple +csd threads. +ThreadPool3 - 1 servant, multiple ORB thereads (main thread), multiple +csd threads. + +The example 6 is simply a copy of the threadpool example, the only difference +is it uses the TIE approach. + +The example ThreadPool4 and ThreadPool5 use the same idl file which includes +the operations defined in example ThreadPool, ThreadPool2 and ThreadPool3 in +addition of callbacks and the oneway "IN" argument test. The ThreadPool4 is +a collocated test. The ThreadPool5 combines all other test cases together except +the ThreadPool6 example. + diff --git a/TAO/examples/CSD_Strategy/ThreadPool/CSD_Test_ThreadPool.mpc b/TAO/examples/CSD_Strategy/ThreadPool/CSD_Test_ThreadPool.mpc new file mode 100644 index 00000000000..33b7e1a515b --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool/CSD_Test_ThreadPool.mpc @@ -0,0 +1,24 @@ +// -*- MPC -*- +// $Id$ + +project(*Server) : csd_threadpool, taoexe, portableserver { + exename = server_main + + Source_Files { + Foo_i.cpp + ServerApp.cpp + server_main.cpp + OrbShutdownTask.cpp + } +} + +project(*Client): taoexe, anytypecode { + exename = client_main + + Source_Files { + FooC.cpp + ClientApp.cpp + client_main.cpp + } +} + diff --git a/TAO/examples/CSD_Strategy/ThreadPool/ClientApp.cpp b/TAO/examples/CSD_Strategy/ThreadPool/ClientApp.cpp new file mode 100644 index 00000000000..a81a617566c --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool/ClientApp.cpp @@ -0,0 +1,143 @@ +// $Id$ +#include "ClientApp.h" +#include "FooC.h" +#include "ace/Get_Opt.h" +#include "ace/Log_Msg.h" + + +ClientApp::ClientApp() +{ +} + + +ClientApp::~ClientApp() +{ +} + + +int +ClientApp::run(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + CORBA::ORB_var orb + = CORBA::ORB_init(argc, argv, "" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Parse the command-line args for this application. + // * Raises -1 if problems are encountered. + // * Returns 1 if the usage statement was explicitly requested. + // * Returns 0 otherwise. + int result = this->parse_args(argc, argv); + if (result != 0) + { + return result; + } + + CORBA::Object_var obj + = orb->string_to_object(this->ior_.c_str() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(obj.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to convert IOR string to obj ref.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + Foo_var foo = Foo::_narrow(obj.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(foo.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to narrow obj ref to Foo interface.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + for (CORBA::Long i = 1; i <= 100; i++) + { + foo->op1(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + foo->op2(i ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + CORBA::Long value = foo->op3(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ===> Value retrieved from op3() == %d\n", + value)); + + for (CORBA::Long j = 1; j <= 5; j++) + { + foo->op4(495 + (i * 5) + j ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + } + + ACE_TRY_NEW_ENV + { + foo->op5(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCH (FooException, ex) + { + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ===> Caught FooException - as expected.\n")); + + } + ACE_ENDTRY; + } + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ===> Tell server that we are done().\n")); + + foo->done(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ===> Back from done().\n")); + + return 0; +} + + +int +ClientApp::parse_args(int argc, char* argv[]) +{ + this->exe_name_ = argv[0]; + + ACE_Get_Opt get_opts(argc, argv, "i:"); + + int c; + + while ((c = get_opts()) != -1) + { + switch (c) + { + case 'i': + this->ior_ = get_opts.opt_arg(); + break; + + case '?': + this->usage_statement(); + return 1; + + default: + this->usage_statement(); + return -1; + } + } + + return 0; +} + + +void +ClientApp::usage_statement() +{ + ACE_ERROR((LM_ERROR, + "Usage: %s [options]\n\n" + "OPTIONS:\n\n" + "\t[-i <ior>]\n" + "\t[-?]\n\n", + this->exe_name_.c_str())); +} + diff --git a/TAO/examples/CSD_Strategy/ThreadPool/ClientApp.h b/TAO/examples/CSD_Strategy/ThreadPool/ClientApp.h new file mode 100644 index 00000000000..1c706005563 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool/ClientApp.h @@ -0,0 +1,29 @@ +// $Id$ +#ifndef CLIENTAPP_H +#define CLIENTAPP_H + +#include "ace/SString.h" +#include "ace/CORBA_macros.h" +#include "tao/Environment.h" + +class ClientApp +{ + public: + + ClientApp(); + ~ClientApp(); + + int run(int argc, char* argv[] ACE_ENV_ARG_DECL); + + + private: + + int parse_args(int argc, char* argv[]); + void usage_statement(); + + ACE_CString ior_; + + ACE_CString exe_name_; +}; + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool/Foo.idl b/TAO/examples/CSD_Strategy/ThreadPool/Foo.idl new file mode 100644 index 00000000000..f4a756a31b1 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool/Foo.idl @@ -0,0 +1,29 @@ +// $Id$ +#ifndef FOO_IDL +#define FOO_IDL + +exception FooException {}; +exception TestException {}; + +interface Foo +{ + /// void return-type, no arguments + void op1(); + + /// void return-type, 1 "in" argument + void op2(in long value); + + /// long return-type, no arguments + long op3(); + + /// one-way version of op2 + oneway void op4(in long value); + + /// Operation that always raises an exception. + void op5() raises (FooException); + + /// Client calls this last. It will shutdown the server. + void done(); +}; + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool/Foo_i.cpp b/TAO/examples/CSD_Strategy/ThreadPool/Foo_i.cpp new file mode 100644 index 00000000000..66e424d8781 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool/Foo_i.cpp @@ -0,0 +1,112 @@ +// $Id$ +#include "Foo_i.h" +#include "OrbShutdownTask.h" +#include "ace/OS.h" + +Foo_i::Foo_i(unsigned num_clients) + : value_(0), + num_clients_(num_clients), + count_op1_(0), + count_op2_(0), + count_op3_(0), + count_op4_(0), + count_op5_(0) +{ + ACE_DEBUG((LM_DEBUG, + "(%P|%t) Number of clients for Foo_i servant: %d\n", + num_clients)); +} + + +Foo_i::~Foo_i() +{ +} + + +void +Foo_i::op1(ACE_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + ++this->count_op1_; + // Sleep for 10 milliseconds (10,000 microseconds) + //ACE_OS::sleep(ACE_Time_Value(0,10000)); +} + + +void +Foo_i::op2(CORBA::Long value ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + ++this->count_op2_; + this->value_ = value; +} + + +CORBA::Long +Foo_i::op3(ACE_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + ++this->count_op3_; + return this->value_; +} + + +void +Foo_i::op4(CORBA::Long value ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + ++this->count_op4_; + this->value_ = value; + + if (this->count_op4_ % 500 == 0) + { + ACE_DEBUG((LM_DEBUG, + "(%P|%t) op4() has been called %d times now. value == %d\n", + this->count_op4_, this->value_)); + } + + // Sleep for 10 milliseconds (10,000 microseconds) + //ACE_OS::sleep(ACE_Time_Value(0,10000)); +} + + +void +Foo_i::op5(ACE_ENV_SINGLE_ARG_DECL) + ACE_THROW_SPEC((CORBA::SystemException, FooException)) +{ + ++this->count_op5_; + ACE_THROW_SPEC (FooException()); +} + + +void +Foo_i::done(ACE_ENV_SINGLE_ARG_DECL) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + unsigned num_left = --this->num_clients_; + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) A client has reported that it is done(). " + "There are %d clients left.\n", num_left)); + + if (num_left == 0) + { + ACE_DEBUG((LM_DEBUG, "(%P|%t) Stats:\n" + "op1() count: %d\n" + "op2() count: %d\n" + "op3() count: %d\n" + "op4() count: %d\n" + "op5() count: %d\n", + this->count_op1_, + this->count_op2_, + this->count_op3_, + this->count_op4_, + this->count_op5_)); + + if (TheOrbShutdownTask::instance()->open(0) != 0) + { + ACE_ERROR((LM_ERROR, "(%P|%t)Foo_i::done: failed to create orb "\ + "shutdown thread.\n")); + } + } +} diff --git a/TAO/examples/CSD_Strategy/ThreadPool/Foo_i.h b/TAO/examples/CSD_Strategy/ThreadPool/Foo_i.h new file mode 100644 index 00000000000..cf1ee0968e1 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool/Foo_i.h @@ -0,0 +1,49 @@ +// $Id$ +#ifndef FOO_I_H +#define FOO_I_H + +#include "FooS.h" +#include "ace/CORBA_macros.h" +#include "tao/Environment.h" + + +class Foo_i : public virtual POA_Foo, + public virtual PortableServer::RefCountServantBase +{ + public: + + Foo_i(unsigned num_clients); + virtual ~Foo_i(); + + virtual void op1(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void op2(CORBA::Long value ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual CORBA::Long op3(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void op4(CORBA::Long value ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void op5(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException, FooException)); + + virtual void done(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + + private: + + CORBA::Long value_; + unsigned num_clients_; + + unsigned count_op1_; + unsigned count_op2_; + unsigned count_op3_; + unsigned count_op4_; + unsigned count_op5_; +}; + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool/OrbShutdownTask.cpp b/TAO/examples/CSD_Strategy/ThreadPool/OrbShutdownTask.cpp new file mode 100644 index 00000000000..f9d551e8aee --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool/OrbShutdownTask.cpp @@ -0,0 +1,77 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file OrbShutdownTask.cpp + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#include "OrbShutdownTask.h" +#include "ace/CORBA_macros.h" +#include "ace/OS_NS_unistd.h" + + +OrbShutdownTask::OrbShutdownTask() +{ +} + + +OrbShutdownTask::~OrbShutdownTask() +{ +} + + +void +OrbShutdownTask::orb(CORBA::ORB_ptr orb) +{ + this->orb_ = CORBA::ORB::_duplicate (orb); +} + + +int +OrbShutdownTask::open(void*) +{ + if (this->activate(THR_NEW_LWP | THR_JOINABLE, 1) != 0) + { + // Assumes that when activate returns non-zero return code that + // no threads were activated. + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) OrbShutdownTask failed to open().\n"), + -1); + } + + return 0; +} + + +int +OrbShutdownTask::svc() +{ + ACE_OS::sleep (2); + ACE_DEBUG ((LM_DEBUG, "(%P|%t)OrbShutdownTask::svc shutdown orb \n")); + ACE_TRY_NEW_ENV + { + this->orb_->shutdown(0 ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHALL + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Exception raised by ORB::shutdown() call " + "in OrbShutdownTask::svc().\n")); + } + ACE_ENDTRY; + + return 0; +} + + +int +OrbShutdownTask::close(u_long) +{ + return 0; +} diff --git a/TAO/examples/CSD_Strategy/ThreadPool/OrbShutdownTask.h b/TAO/examples/CSD_Strategy/ThreadPool/OrbShutdownTask.h new file mode 100644 index 00000000000..3795d12c3c9 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool/OrbShutdownTask.h @@ -0,0 +1,41 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file OrbShutdownTask.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef ORB_SHUTDOWN_TASK_H +#define ORB_SHUTDOWN_TASK_H + +#include "ace/Task.h" +#include "tao/ORB.h" + + +class OrbShutdownTask : public ACE_Task_Base +{ + public: + + OrbShutdownTask(); + virtual ~OrbShutdownTask(); + + void orb(CORBA::ORB_ptr orb); + + virtual int open(void*); + virtual int svc(); + virtual int close(u_long); + + + private: + + CORBA::ORB_var orb_; +}; + +typedef ACE_Singleton<OrbShutdownTask, ACE_Thread_Mutex> TheOrbShutdownTask; + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool/README b/TAO/examples/CSD_Strategy/ThreadPool/README new file mode 100644 index 00000000000..76a46ba103f --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool/README @@ -0,0 +1,57 @@ +# $Id$ + +Description: + +This is the simplest example shows the use of a Custom Servant Dispatching (CSD) +Strategy. This test uses the reference implementation, known as the Thread Pool +CSD Strategy. This tests some simple remote two-way CORBA requests and a simple +remote one-way request. + +The server application creates one servant object, runs the ORB event +loop using the main thread, and uses one worker thread for the +Thread Pool CSD Strategy. + +The client application invokes simple two-way calls on the object +reference. There is also a simple one-way call that is also made on +the object reference. + +The run_test.pl script will launch 1 sever process, and 40 client processes. +Each client process will make invocations on the single object reference +provided by the (single) server process. + +Executables: + + * client_main + + This is the client test executable. + + Command-line arguments: + + -? : Prints the executable's available command-line options, and + then exits. + + -i <ior string> : Provide the IOR to the client (ie, file://some.ior). + + * server_main + + This is the server test executable. + + Command-line arguments: + + -? : Prints the executable's available command-line options, and + then exits. + + -o <ior filename> : Name of file to which the IOR will be written. + + -n <num_clients> : The number of clients that will use the server. + + * run_test.pl + + This perl script will run an automated test using 40 client processes + and 1 server process. The script returns 0 if the test was successful. + + No command-line options are supported. Simply execute the perl script + as follows: + + $ ./run_test.pl + diff --git a/TAO/examples/CSD_Strategy/ThreadPool/ServerApp.cpp b/TAO/examples/CSD_Strategy/ThreadPool/ServerApp.cpp new file mode 100644 index 00000000000..b036b9ff205 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool/ServerApp.cpp @@ -0,0 +1,237 @@ +// $Id$ +#include "ServerApp.h" +#include "Foo_i.h" +#include "OrbShutdownTask.h" +#include "ace/Get_Opt.h" +#include "tao/CSD_ThreadPool/CSD_TP_Strategy.h" +#include "tao/Intrusive_Ref_Count_Handle_T.h" + + +ServerApp::ServerApp() +: num_clients_ (1) +{ +} + + +ServerApp::~ServerApp() +{ +} + + +int +ServerApp::run(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + CORBA::ORB_var orb = CORBA::ORB_init(argc, argv, "" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Parse the command-line args for this application. + // * Raises -1 if problems are encountered. + // * Returns 1 if the usage statement was explicitly requested. + // * Returns 0 otherwise. + int result = this->parse_args(argc, argv); + if (result != 0) + { + return result; + } + + TheOrbShutdownTask::instance()->orb (orb.in ()); + + CORBA::Object_var obj + = orb->resolve_initial_references("RootPOA" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(obj.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to resolve initial ref for 'RootPOA'.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + PortableServer::POA_var root_poa + = PortableServer::POA::_narrow(obj.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(root_poa.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to narrow obj ref to POA interface.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + PortableServer::POAManager_var poa_manager + = root_poa->the_POAManager( ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Create the child POA. + CORBA::PolicyList policies(0); + policies.length(0); + + PortableServer::POA_var child_poa + = root_poa->create_POA("ChildPoa", + poa_manager.in(), + policies + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(child_poa.in())) + { + ACE_ERROR((LM_ERROR, "(%P|%t) ERROR [ServerApp::run()]: " + "Failed to create the child POA.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + // Create the thread pool servant dispatching strategy object, and + // hold it in a (local) smart pointer variable. + TAO_Intrusive_Ref_Count_Handle<TAO::CSD::TP_Strategy> csd_tp_strategy = + new TAO::CSD::TP_Strategy(); + + // Tell the strategy to apply itself to the child poa. + if (csd_tp_strategy->apply_to(child_poa.in() ACE_ENV_ARG_PARAMETER) == false) + { + ACE_ERROR((LM_ERROR, "(%P|%t) ERROR [ServerApp::run()]: " + "Failed to apply custom dispatching strategy to child poa.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + ACE_CHECK_RETURN (-1); + + // Create the servant object. + Foo_i* servant = new Foo_i(this->num_clients_); + + // local smart pointer variable to deal with releasing the reference + // to the servant object when the smart pointer object falls out of scope. + PortableServer::ServantBase_var owner_transfer(servant); + + // Activate the servant using the Child POA. + PortableServer::ObjectId_var oid + = child_poa->activate_object(servant + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Obtain the object reference. + obj = child_poa->servant_to_reference(servant ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(obj.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to activate servant (Foo_i).\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + // Stringify the object reference + CORBA::String_var ior + = orb->object_to_string(obj.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Write the stringified object reference to the ior file. + FILE* ior_file = ACE_OS::fopen(this->ior_filename_.c_str(), "w"); + + if (ior_file == 0) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Cannot open output file for writing IOR: %s", + this->ior_filename_.c_str())); + ACE_THROW_RETURN (TestException(), -1); + } + + ACE_OS::fprintf(ior_file, "%s", ior.in ()); + ACE_OS::fclose(ior_file); + + // Activate the POA Manager + poa_manager->activate(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp is ready. Running the ORB event loop.\n")); + + // Run the ORB event loop. + orb->run(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp ORB has stopped running. " + "Stop the CSD strategy.\n")); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp is waiting for OrbShutdownTask.\n")); + TheOrbShutdownTask::instance()->wait (); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp is destroying the Root POA.\n")); + + // Sleep for 2 second to let the done() two-way call complete + // before cleanup. + ACE_OS::sleep (2); + + // Tear-down the root poa and orb. + root_poa->destroy(1, 1 ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp is destroying the ORB.\n")); + + orb->destroy( ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp has completed running successfully.\n")); + + return 0; +} + + +int +ServerApp::parse_args(int argc, char* argv[]) +{ + this->exe_name_ = argv[0]; + + ACE_Get_Opt get_opts(argc, argv, "o:n:"); + + int c; + + while ((c = get_opts()) != -1) + { + switch (c) + { + case 'o': + this->ior_filename_ = get_opts.opt_arg(); + break; + + case 'n': + { + int tmp = ACE_OS::atoi(get_opts.opt_arg()); + if (tmp < 1) + { + this->usage_statement(); + return -1; + } + + this->num_clients_ = tmp; + } + break; + + case '?': + this->usage_statement(); + return 1; + + default: + this->usage_statement(); + return -1; + } + } + + return 0; +} + + +void +ServerApp::usage_statement() +{ + ACE_ERROR((LM_ERROR, + "Usage: %s [options]\n\n" + "OPTIONS:\n\n" + "\t[-o <ior_filename>]\n" + "\t[-n <num_clients>]\n" + "\t[-?]\n\n", + this->exe_name_.c_str())); +} diff --git a/TAO/examples/CSD_Strategy/ThreadPool/ServerApp.h b/TAO/examples/CSD_Strategy/ThreadPool/ServerApp.h new file mode 100644 index 00000000000..ad89b43c972 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool/ServerApp.h @@ -0,0 +1,30 @@ +// $Id$ +#ifndef SERVERAPP_H +#define SERVERAPP_H + +#include "ace/SString.h" +#include "ace/CORBA_macros.h" +#include "tao/Environment.h" + + +class ServerApp +{ + public: + + ServerApp(); + ~ServerApp(); + + int run(int argc, char* argv[] ACE_ENV_ARG_DECL); + + + private: + + int parse_args(int argc, char* argv[]); + void usage_statement(); + + ACE_CString exe_name_; + ACE_CString ior_filename_; + unsigned num_clients_; +}; + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool/client_main.cpp b/TAO/examples/CSD_Strategy/ThreadPool/client_main.cpp new file mode 100644 index 00000000000..1f9c337ae54 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool/client_main.cpp @@ -0,0 +1,45 @@ +// $Id$ +#include "ClientApp.h" +#include "ace/Log_Msg.h" +#include "ace/SString.h" +#include "tao/Exception.h" + + +int +main(int argc, char* argv[]) +{ + ACE_LOG_MSG->priority_mask(LM_TRACE | + LM_DEBUG | + LM_INFO | + LM_NOTICE | + LM_WARNING | + LM_ERROR | + LM_CRITICAL | + LM_ALERT | + LM_EMERGENCY, + ACE_Log_Msg::PROCESS); + + + ClientApp app; + + ACE_TRY_NEW_ENV + { + int ret = app.run(argc,argv ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + return ret == 1 ? 0 : ret; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "Caught exception:"); + } + ACE_CATCHALL + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Unknown (...) exception caught in main() " + "for ClientApp\n")); + } + ACE_ENDTRY; + + return 1; +} diff --git a/TAO/examples/CSD_Strategy/ThreadPool/run_test.pl b/TAO/examples/CSD_Strategy/ThreadPool/run_test.pl new file mode 100755 index 00000000000..e15decb6a63 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool/run_test.pl @@ -0,0 +1,55 @@ +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; + +$iorfile = PerlACE::LocalFile ("server.ior"); +unlink $iorfile; +$status = 0; + +$num_clients=40; + +$SV = new PerlACE::Process ("server_main", "-o $iorfile -n $num_clients"); + +$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; +} + +for ($i = 0; $i < $num_clients; $i++) { + + @CLS[$i] = new PerlACE::Process ("client_main", " -i file://$iorfile"); + + @CLS[$i]->Spawn (); +} + +for ($i = 0; $i < $num_clients; $i++) { + + $client = @CLS[$i]->WaitKill (60); + + if ($client != 0) { + print STDERR "ERROR: client $i returned $client\n"; + $status = 1; + } +} + + +$server = $SV->WaitKill (60); + +if ($server != 0) { + print STDERR "ERROR: server returned $server\n"; + $status = 1; +} + +unlink $iorfile; + +exit $status; diff --git a/TAO/examples/CSD_Strategy/ThreadPool/server_main.cpp b/TAO/examples/CSD_Strategy/ThreadPool/server_main.cpp new file mode 100644 index 00000000000..8c3c4b192a0 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool/server_main.cpp @@ -0,0 +1,43 @@ +// $Id$ +#include "ServerApp.h" +#include "ace/Log_Msg.h" +#include "tao/Exception.h" + + +int +main(int argc, char* argv[]) +{ + ACE_LOG_MSG->priority_mask(LM_TRACE | + LM_DEBUG | + LM_INFO | + LM_NOTICE | + LM_WARNING | + LM_ERROR | + LM_CRITICAL | + LM_ALERT | + LM_EMERGENCY, + ACE_Log_Msg::PROCESS); + + ServerApp app; + + ACE_TRY_NEW_ENV + { + int ret = app.run(argc,argv ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + return ret == 1 ? 0 : ret; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "Caught exception in main() for ServerApp"); + } + ACE_CATCHALL + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Unknown (...) exception caught in main() " + "for ServerApp\n")); + } + ACE_ENDTRY; + + return 1; +} diff --git a/TAO/examples/CSD_Strategy/ThreadPool2/CSD_Test_ThreadPool2.mpc b/TAO/examples/CSD_Strategy/ThreadPool2/CSD_Test_ThreadPool2.mpc new file mode 100644 index 00000000000..c14935e056d --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool2/CSD_Test_ThreadPool2.mpc @@ -0,0 +1,25 @@ +// -*- MPC -*- +// $Id$ + +project(*Server): csd_threadpool, taoexe, portableserver { + exename = server_main + + Source_Files { + Foo_i.cpp + FooServantList.cpp + ServerApp.cpp + server_main.cpp + OrbShutdownTask.cpp + } +} + +project(*Client): taoexe, anytypecode { + exename = client_main + + Source_Files { + FooC.cpp + ClientApp.cpp + client_main.cpp + } +} + diff --git a/TAO/examples/CSD_Strategy/ThreadPool2/ClientApp.cpp b/TAO/examples/CSD_Strategy/ThreadPool2/ClientApp.cpp new file mode 100644 index 00000000000..14e52e52804 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool2/ClientApp.cpp @@ -0,0 +1,143 @@ +// $Id$ +#include "ClientApp.h" +#include "FooC.h" +#include "ace/Get_Opt.h" +#include "ace/Log_Msg.h" + + +ClientApp::ClientApp() +{ +} + + +ClientApp::~ClientApp() +{ +} + + +int +ClientApp::run(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + CORBA::ORB_var orb + = CORBA::ORB_init(argc, argv, "" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Parse the command-line args for this application. + // * Raises -1 if problems are encountered. + // * Returns 1 if the usage statement was explicitly requested. + // * Returns 0 otherwise. + int result = this->parse_args(argc, argv); + if (result != 0) + { + return result; + } + + CORBA::Object_var obj + = orb->string_to_object(this->ior_.c_str() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(obj.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to convert IOR string to obj ref.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + Foo_var foo = Foo::_narrow(obj.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(foo.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to narrow obj ref to Foo interface.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + for (CORBA::Long i = 1; i <= 100; i++) + { + foo->op1(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + foo->op2(i ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + CORBA::Long value = foo->op3(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ===> Value retrieved from op3() == %d\n", + value)); + + for (CORBA::Long j = 1; j <= 5; j++) + { + foo->op4(495 + (i * 5) + j ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + } + + ACE_TRY_NEW_ENV + { + foo->op5(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCH (FooException, ex) + { + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ===> Caught FooException - as expected.\n")); + + } + ACE_ENDTRY; + } + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ===> Tell server that we are done().\n")); + + foo->done(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ===> Back from done().\n")); + + return 0; +} + + + +int +ClientApp::parse_args(int argc, char* argv[]) +{ + this->exe_name_ = argv[0]; + + ACE_Get_Opt get_opts(argc, argv, "i:"); + + int c; + + while ((c = get_opts()) != -1) + { + switch (c) + { + case 'i': + this->ior_ = get_opts.opt_arg(); + break; + + case '?': + this->usage_statement(); + return 1; + default: + this->usage_statement(); + return -1; + } + } + + return 0; +} + + +void +ClientApp::usage_statement() +{ + ACE_ERROR((LM_ERROR, + "Usage: %s [options]\n\n" + "OPTIONS:\n\n" + "\t[-i <ior>]\n" + "\t[-?]\n\n", + this->exe_name_.c_str())); +} + diff --git a/TAO/examples/CSD_Strategy/ThreadPool2/ClientApp.h b/TAO/examples/CSD_Strategy/ThreadPool2/ClientApp.h new file mode 100644 index 00000000000..7dc57bb78dc --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool2/ClientApp.h @@ -0,0 +1,30 @@ +// $Id$ +#ifndef CLIENTAPP_H +#define CLIENTAPP_H + +#include "ace/SString.h" +#include "ace/CORBA_macros.h" +#include "tao/Environment.h" + + +class ClientApp +{ + public: + + ClientApp(); + ~ClientApp(); + + int run(int argc, char* argv[] ACE_ENV_ARG_DECL); + + + private: + + int parse_args(int argc, char* argv[]); + void usage_statement(); + + ACE_CString ior_; + + ACE_CString exe_name_; +}; + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool2/Foo.idl b/TAO/examples/CSD_Strategy/ThreadPool2/Foo.idl new file mode 100644 index 00000000000..f4a756a31b1 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool2/Foo.idl @@ -0,0 +1,29 @@ +// $Id$ +#ifndef FOO_IDL +#define FOO_IDL + +exception FooException {}; +exception TestException {}; + +interface Foo +{ + /// void return-type, no arguments + void op1(); + + /// void return-type, 1 "in" argument + void op2(in long value); + + /// long return-type, no arguments + long op3(); + + /// one-way version of op2 + oneway void op4(in long value); + + /// Operation that always raises an exception. + void op5() raises (FooException); + + /// Client calls this last. It will shutdown the server. + void done(); +}; + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool2/FooServantList.cpp b/TAO/examples/CSD_Strategy/ThreadPool2/FooServantList.cpp new file mode 100644 index 00000000000..1c1fc13eaf6 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool2/FooServantList.cpp @@ -0,0 +1,99 @@ +// $Id$ +#include "FooServantList.h" +#include "Foo_i.h" +#include "OrbShutdownTask.h" +#include "ace/OS.h" + + +FooServantList::FooServantList(const char* prefix, + unsigned num_servants, + unsigned num_clients, + CORBA::ORB_ptr orb) + : prefix_(prefix), + num_servants_(num_servants), + num_clients_(num_clients), + orb_ (CORBA::ORB::_duplicate(orb)) +{ + this->servants_ = new PortableServer::ServantBase_var[num_servants]; +} + + +FooServantList::~FooServantList() +{ + delete [] this->servants_; +} + + +void +FooServantList::create_and_activate(PortableServer::POA_ptr poa + ACE_ENV_ARG_DECL) +{ + for (unsigned i = 0; i < this->num_servants_; i++) + { + char buf[32]; + ACE_OS::sprintf(buf, "%02d", i + 1); + ACE_CString servant_name = this->prefix_ + "_" + buf; + + this->servants_[i] = new Foo_i(servant_name.c_str(),this); + + PortableServer::ObjectId_var id = + PortableServer::string_to_ObjectId(servant_name.c_str()); + + poa->activate_object_with_id(id.in(), + this->servants_[i].in() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + CORBA::Object_var obj = poa->id_to_reference(id.in() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + if (CORBA::is_nil(obj.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to activate servant (%s).\n", + servant_name.c_str())); + ACE_THROW (TestException()); + } + + CORBA::String_var ior + = this->orb_->object_to_string(obj.in() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + ACE_CString filename = servant_name + ".ior"; + FILE* ior_file = ACE_OS::fopen(filename.c_str(), "w"); + + if (ior_file == 0) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Cannot open output file (%s) for writing IOR.", + filename.c_str())); + ACE_THROW (TestException()); + } + + ACE_OS::fprintf(ior_file, "%s", ior.in()); + ACE_OS::fclose(ior_file); + } +} + + +void +FooServantList::client_done(ACE_ENV_SINGLE_ARG_DECL) +{ + unsigned num_left; + + { + GuardType guard(this->num_clients_lock_); + num_left = --this->num_clients_; + } + + if (num_left == 0) + { + if (TheOrbShutdownTask::instance()->open(0) != 0) + { + ACE_ERROR((LM_ERROR, "(%P|%t)FooServantList::client_done: " + "failed to create orb shutdown thread.\n")); + } + } +} diff --git a/TAO/examples/CSD_Strategy/ThreadPool2/FooServantList.h b/TAO/examples/CSD_Strategy/ThreadPool2/FooServantList.h new file mode 100644 index 00000000000..d6e35ff894a --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool2/FooServantList.h @@ -0,0 +1,42 @@ +// $Id$ +#ifndef FOOSERVANTLIST_H +#define FOOSERVANTLIST_H + +#include "tao/ORB.h" +#include "tao/PortableServer/PortableServer.h" +#include "tao/PortableServer/Servant_Base.h" +#include "ace/SString.h" + + +class FooServantList +{ + public: + + FooServantList(const char* prefix, + unsigned num_servants, + unsigned num_clients, + CORBA::ORB_ptr orb); + ~FooServantList(); + + void create_and_activate(PortableServer::POA_ptr poa + ACE_ENV_ARG_DECL); + + void client_done(ACE_ENV_SINGLE_ARG_DECL); + + + private: + + typedef ACE_SYNCH_MUTEX LockType; + typedef ACE_Guard<LockType> GuardType; + + PortableServer::ServantBase_var* servants_; + ACE_CString prefix_; + unsigned num_servants_; + + LockType num_clients_lock_; + unsigned num_clients_; + + CORBA::ORB_var orb_; +}; + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool2/Foo_i.cpp b/TAO/examples/CSD_Strategy/ThreadPool2/Foo_i.cpp new file mode 100644 index 00000000000..5923bb5b022 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool2/Foo_i.cpp @@ -0,0 +1,86 @@ +// $Id$ +#include "Foo_i.h" +#include "FooServantList.h" +#include "ace/OS.h" + +Foo_i::Foo_i(const char* servant_name,FooServantList* mgr) + : value_(0), + count_op1_(0), + count_op2_(0), + count_op3_(0), + count_op4_(0), + count_op5_(0), + servant_name_(servant_name), + mgr_(mgr) +{ +} + + +Foo_i::~Foo_i() +{ +} + + +void +Foo_i::op1(ACE_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + ++this->count_op1_; + // Sleep for 10 milliseconds (10,000 microseconds) + //ACE_OS::sleep(ACE_Time_Value(0,10000)); +} + + +void +Foo_i::op2(CORBA::Long value ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + ++this->count_op2_; + this->value_ = value; +} + + +CORBA::Long +Foo_i::op3(ACE_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + ++this->count_op3_; + return this->value_; +} + + +void +Foo_i::op4(CORBA::Long value ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + ++this->count_op4_; + this->value_ = value; + + if (this->count_op4_ % 100 == 0) + { + ACE_DEBUG((LM_DEBUG, + "(%P|%t) op4() has been called %d times now. value == %d\n", + this->count_op4_, this->value_)); + } + + // Sleep for 10 milliseconds (10,000 microseconds) + //ACE_OS::sleep(ACE_Time_Value(0,10000)); +} + + +void +Foo_i::op5(ACE_ENV_SINGLE_ARG_DECL) + ACE_THROW_SPEC((CORBA::SystemException, FooException)) +{ + ++this->count_op5_; + ACE_THROW_SPEC (FooException()); +} + + +void +Foo_i::done(ACE_ENV_SINGLE_ARG_DECL) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + this->mgr_->client_done(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; +} diff --git a/TAO/examples/CSD_Strategy/ThreadPool2/Foo_i.h b/TAO/examples/CSD_Strategy/ThreadPool2/Foo_i.h new file mode 100644 index 00000000000..5cc2a45e467 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool2/Foo_i.h @@ -0,0 +1,53 @@ +// $Id$ +#ifndef FOO_I_H +#define FOO_I_H + +#include "FooS.h" +#include "ace/SString.h" +#include "ace/CORBA_macros.h" +#include "tao/Environment.h" + +class FooServantList; + +class Foo_i : public virtual POA_Foo, + public virtual PortableServer::RefCountServantBase +{ + public: + + Foo_i(const char* servant_name, FooServantList* mgr); + virtual ~Foo_i(); + + virtual void op1(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void op2(CORBA::Long value ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual CORBA::Long op3(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void op4(CORBA::Long value ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void op5(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException, FooException)); + + virtual void done(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + + private: + + CORBA::Long value_; + + unsigned count_op1_; + unsigned count_op2_; + unsigned count_op3_; + unsigned count_op4_; + unsigned count_op5_; + + ACE_CString servant_name_; + FooServantList* mgr_; +}; + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool2/OrbShutdownTask.cpp b/TAO/examples/CSD_Strategy/ThreadPool2/OrbShutdownTask.cpp new file mode 100644 index 00000000000..f9d551e8aee --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool2/OrbShutdownTask.cpp @@ -0,0 +1,77 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file OrbShutdownTask.cpp + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#include "OrbShutdownTask.h" +#include "ace/CORBA_macros.h" +#include "ace/OS_NS_unistd.h" + + +OrbShutdownTask::OrbShutdownTask() +{ +} + + +OrbShutdownTask::~OrbShutdownTask() +{ +} + + +void +OrbShutdownTask::orb(CORBA::ORB_ptr orb) +{ + this->orb_ = CORBA::ORB::_duplicate (orb); +} + + +int +OrbShutdownTask::open(void*) +{ + if (this->activate(THR_NEW_LWP | THR_JOINABLE, 1) != 0) + { + // Assumes that when activate returns non-zero return code that + // no threads were activated. + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) OrbShutdownTask failed to open().\n"), + -1); + } + + return 0; +} + + +int +OrbShutdownTask::svc() +{ + ACE_OS::sleep (2); + ACE_DEBUG ((LM_DEBUG, "(%P|%t)OrbShutdownTask::svc shutdown orb \n")); + ACE_TRY_NEW_ENV + { + this->orb_->shutdown(0 ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHALL + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Exception raised by ORB::shutdown() call " + "in OrbShutdownTask::svc().\n")); + } + ACE_ENDTRY; + + return 0; +} + + +int +OrbShutdownTask::close(u_long) +{ + return 0; +} diff --git a/TAO/examples/CSD_Strategy/ThreadPool2/OrbShutdownTask.h b/TAO/examples/CSD_Strategy/ThreadPool2/OrbShutdownTask.h new file mode 100644 index 00000000000..3795d12c3c9 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool2/OrbShutdownTask.h @@ -0,0 +1,41 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file OrbShutdownTask.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef ORB_SHUTDOWN_TASK_H +#define ORB_SHUTDOWN_TASK_H + +#include "ace/Task.h" +#include "tao/ORB.h" + + +class OrbShutdownTask : public ACE_Task_Base +{ + public: + + OrbShutdownTask(); + virtual ~OrbShutdownTask(); + + void orb(CORBA::ORB_ptr orb); + + virtual int open(void*); + virtual int svc(); + virtual int close(u_long); + + + private: + + CORBA::ORB_var orb_; +}; + +typedef ACE_Singleton<OrbShutdownTask, ACE_Thread_Mutex> TheOrbShutdownTask; + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool2/README b/TAO/examples/CSD_Strategy/ThreadPool2/README new file mode 100644 index 00000000000..4c770475642 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool2/README @@ -0,0 +1,61 @@ +# $Id$ + +Description: + +This is another test showing the use of a Custom Servant Dispatching +(CSD) Strategy. This test uses the reference implementation, known as the +Thread Pool CSD Strategy. This tests some simple remote two-way CORBA +requests and a simple remote one-way request. + +The server application creates 10 servant object, runs the ORB event +loop using the main thread, and uses 10 worker thread for the +Thread Pool CSD Strategy. + +The client application invokes simple two-way calls on the object +reference. There is also a simple one-way call that is also made on +the object reference. + +The run_test.pl script will launch 1 sever process, and 40 client processes. +Since the server process contains 10 distinct servants, the clients are +evenly divided such that each servant "serves" 4 distinct clients. + + +Executables: + + * client_main + + This is the client test executable. + + Command-line arguments: + + -? : Prints the executable's available command-line options, and + then exits. + + -i <ior string> : Provide the IOR to the client (ie, file://some.ior). + + * server_main + + This is the server test executable. + + Command-line arguments: + + -? : Prints the executable's available command-line options, and + then exits. + + -p <ior filename prefix> : Common prefix used in all ior filenames + that are output. + + -s <num servants> : The number of servant objects in the server. + + -c <num clients> : The number of clients that will use the server. + + * run_test.pl + + This perl script will run an automated test using 40 client processes + and 1 server process. The script returns 0 if the test was successful. + + No command-line options are supported. Simply execute the perl script + as follows: + + $ ./run_test.pl + diff --git a/TAO/examples/CSD_Strategy/ThreadPool2/ServerApp.cpp b/TAO/examples/CSD_Strategy/ThreadPool2/ServerApp.cpp new file mode 100644 index 00000000000..a9986df9ec5 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool2/ServerApp.cpp @@ -0,0 +1,229 @@ +// $Id$ +#include "ServerApp.h" +#include "FooServantList.h" +#include "FooC.h" +#include "OrbShutdownTask.h" +#include "ace/Get_Opt.h" +#include "tao/CSD_ThreadPool/CSD_TP_Strategy.h" +#include "tao/Intrusive_Ref_Count_Handle_T.h" + + +ServerApp::ServerApp() + : ior_filename_("foo"), + num_servants_(1), + num_clients_(1) +{ +} + + +ServerApp::~ServerApp() +{ +} + + +int +ServerApp::run(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + CORBA::ORB_var orb = CORBA::ORB_init(argc, argv, "" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Parse the command-line args for this application. + // * Raises -1 if problems are encountered. + // * Returns 1 if the usage statement was explicitly requested. + // * Returns 0 otherwise. + int result = this->parse_args(argc, argv); + if (result != 0) + { + return result; + } + + TheOrbShutdownTask::instance()->orb (orb.in ()); + + CORBA::Object_var obj + = orb->resolve_initial_references("RootPOA" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(obj.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to resolve initial ref for 'RootPOA'.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + PortableServer::POA_var root_poa + = PortableServer::POA::_narrow(obj.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(root_poa.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to narrow obj ref to POA interface.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + PortableServer::POAManager_var poa_manager + = root_poa->the_POAManager(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Create the child POA. + CORBA::PolicyList policies(1); + policies.length(1); + + policies[0] = root_poa->create_id_assignment_policy(PortableServer::USER_ID + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + PortableServer::POA_var child_poa + = root_poa->create_POA("ChildPoa", + poa_manager.in(), + policies + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(child_poa.in())) + { + ACE_ERROR((LM_ERROR, "(%P|%t) ERROR [ServerApp::run()]: " + "Failed to create the child POA.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + policies[0]->destroy (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Create the thread pool servant dispatching strategy object, and + // hold it in a (local) smart pointer variable. + TAO_Intrusive_Ref_Count_Handle<TAO::CSD::TP_Strategy> csd_tp_strategy = + new TAO::CSD::TP_Strategy(); + + csd_tp_strategy->set_num_threads(this->num_servants_); + + // Tell the strategy to apply itself to the child poa. + if (csd_tp_strategy->apply_to(child_poa.in() ACE_ENV_ARG_PARAMETER) == false) + { + ACE_ERROR((LM_ERROR, "(%P|%t) ERROR [ServerApp::run()]: " + "Failed to apply custom dispatching strategy to child poa.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + ACE_CHECK_RETURN (-1); + + FooServantList servants(this->ior_filename_.c_str(), + this->num_servants_, + this->num_clients_, + orb.in()); + + servants.create_and_activate(child_poa.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Activate the POA Manager + poa_manager->activate(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp is ready. Running the ORB event loop.\n")); + + // Run the ORB event loop. + orb->run(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp ORB has stopped running. " + "Stop the CSD strategy.\n")); + + // Sleep for 2 second to let the done() two-way call complete + // before cleanup. + ACE_OS::sleep (2); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp is waiting for OrbShutdownTask.\n")); + TheOrbShutdownTask::instance()->wait (); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp is destroying the Root POA.\n")); + + // Tear-down the root poa and orb. + root_poa->destroy(1, 1 ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp is destroying the ORB.\n")); + + orb->destroy(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp has completed running successfully.\n")); + + return 0; +} + + +int +ServerApp::parse_args(int argc, char* argv[]) +{ + this->exe_name_ = argv[0]; + + ACE_Get_Opt get_opts(argc, argv, "p:s:c:"); + + int c; + int tmp; + + while ((c = get_opts()) != -1) + { + switch (c) + { + case 'p': + this->ior_filename_ = get_opts.opt_arg(); + break; + + case 's': + tmp = ACE_OS::atoi(get_opts.opt_arg()); + if (tmp < 1) + { + this->usage_statement(); + return -1; + } + + this->num_servants_ = tmp; + break; + + case 'c': + tmp = ACE_OS::atoi(get_opts.opt_arg()); + if (tmp < 1) + { + this->usage_statement(); + return -1; + } + + this->num_clients_ = tmp; + break; + + case '?': + this->usage_statement(); + return 1; + + default: + this->usage_statement(); + return -1; + } + } + + return 0; +} + + +void +ServerApp::usage_statement() +{ + ACE_ERROR((LM_ERROR, + "Usage: %s [options]\n\n" + "OPTIONS:\n\n" + "\t[-p <ior_filename_prefix>]\n" + "\t[-s <num_servants>]\n" + "\t[-c <num_clients>]\n" + "\t[-?]\n", + "Default ior_filename_prefix is 'foo'.\n" + "Default num_servants is 1.\n" + "Default num_clients is 1.\n\n", + this->exe_name_.c_str())); +} + diff --git a/TAO/examples/CSD_Strategy/ThreadPool2/ServerApp.h b/TAO/examples/CSD_Strategy/ThreadPool2/ServerApp.h new file mode 100644 index 00000000000..7556826f1e2 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool2/ServerApp.h @@ -0,0 +1,30 @@ +// $Id$ +#ifndef SERVERAPP_H +#define SERVERAPP_H + +#include "ace/SString.h" +#include "ace/CORBA_macros.h" +#include "tao/Environment.h" + +class ServerApp +{ + public: + + ServerApp(); + ~ServerApp(); + + int run(int argc, char* argv[] ACE_ENV_ARG_DECL); + + + private: + + int parse_args(int argc, char* argv[]); + void usage_statement(); + + ACE_CString exe_name_; + ACE_CString ior_filename_; + unsigned num_servants_; + unsigned num_clients_; +}; + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool2/client_main.cpp b/TAO/examples/CSD_Strategy/ThreadPool2/client_main.cpp new file mode 100644 index 00000000000..545d6b52a9a --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool2/client_main.cpp @@ -0,0 +1,44 @@ +// $Id$ +#include "ClientApp.h" +#include "ace/Log_Msg.h" +#include "ace/SString.h" +#include "tao/Exception.h" + +int +main(int argc, char* argv[]) +{ + ACE_LOG_MSG->priority_mask(LM_TRACE | + LM_DEBUG | + LM_INFO | + LM_NOTICE | + LM_WARNING | + LM_ERROR | + LM_CRITICAL | + LM_ALERT | + LM_EMERGENCY, + ACE_Log_Msg::PROCESS); + + + ClientApp app; + + ACE_TRY_NEW_ENV + { + int ret = app.run(argc,argv ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + return ret == 1 ? 0 : ret; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "Caught exception:"); + } + ACE_CATCHALL + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Unknown (...) exception caught in main() " + "for ClientApp\n")); + } + ACE_ENDTRY; + + return 1; +} diff --git a/TAO/examples/CSD_Strategy/ThreadPool2/run_test.pl b/TAO/examples/CSD_Strategy/ThreadPool2/run_test.pl new file mode 100755 index 00000000000..60be2077f11 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool2/run_test.pl @@ -0,0 +1,77 @@ +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; + +$iorfname_prefix = "server"; +$num_servants=10; +$num_clients_per_servant=4; +$num_clients=$num_servants * $num_clients_per_servant; + +#Delete old ior files. +for (my $i = 0; $i < $num_servants; $i++) { + $servant_id = sprintf("%02d", ($i + 1)); + $iorfile[$i] = PerlACE::LocalFile($iorfname_prefix . "_$servant_id.ior"); + + unlink $iorfile[$i]; +} + +$SV = new PerlACE::Process ("server_main", "-p $iorfname_prefix -s $num_servants -c $num_clients"); + +$SV->Spawn (); + +# Wait for the servant ior files created by server. +for (my $i = 0; $i < $num_servants; $i++) { + $servant_id = sprintf("%02d", ($i + 1)); + $iorfile[$i] = PerlACE::LocalFile($iorfname_prefix . "_$servant_id.ior"); + + if (PerlACE::waitforfile_timed ($iorfile[$i], + $PerlACE::wait_interval_for_process_creation) == -1) { + print STDERR "ERROR: cannot find file <$iorfile[$i]>\n"; + $SV->Kill (); $SV->TimedWait (1); + exit 1; + } +} + +$count = 0; + +for (my $i = 0; $i < $num_servants; $i++) { + for ($j = 0; $j < $num_clients_per_servant; $j++) { + $CLS[$count] = new PerlACE::Process ("client_main", " -i file://$iorfile[$i]"); + $CLS[$count]->Spawn (); + $count ++; + } +} + +for (my $i = 0; $i < $num_clients; $i++) { + $client = $CLS[$i]->WaitKill (60); + + if ($client != 0) { + print STDERR "ERROR: client $i returned $client\n"; + $status = 1; + } +} + +$server = $SV->WaitKill (60); + +if ($server != 0) { + print STDERR "ERROR: server returned $server\n"; + $status = 1; +} + +#Delete ior files generated by this run. +for (my $i = 0; $i < $num_servants; $i++) { + $servant_id = sprintf("%02d", ($i + 1)); + $iorfile[$i] = PerlACE::LocalFile($iorfname_prefix . "_$servant_id.ior"); + + unlink $iorfile[$i]; +} + +exit $status; diff --git a/TAO/examples/CSD_Strategy/ThreadPool2/server_main.cpp b/TAO/examples/CSD_Strategy/ThreadPool2/server_main.cpp new file mode 100644 index 00000000000..bb14220d3c7 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool2/server_main.cpp @@ -0,0 +1,44 @@ +// $Id$ +#include "ServerApp.h" +#include "ace/Log_Msg.h" +#include "tao/Exception.h" +#include "tao/Environment.h" + + +int +main(int argc, char* argv[]) +{ + ACE_LOG_MSG->priority_mask(LM_TRACE | + LM_DEBUG | + LM_INFO | + LM_NOTICE | + LM_WARNING | + LM_ERROR | + LM_CRITICAL | + LM_ALERT | + LM_EMERGENCY, + ACE_Log_Msg::PROCESS); + + ServerApp app; + + ACE_TRY_NEW_ENV + { + int ret = app.run(argc,argv ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + return ret == 1 ? 0 : ret; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "Caught exception:"); + } + ACE_CATCHALL + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Unknown (...) exception caught in main() " + "for ServerApp\n")); + } + ACE_ENDTRY; + + return 1; +} diff --git a/TAO/examples/CSD_Strategy/ThreadPool3/CSD_Test_ThreadPool3.mpc b/TAO/examples/CSD_Strategy/ThreadPool3/CSD_Test_ThreadPool3.mpc new file mode 100644 index 00000000000..04902011dd3 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool3/CSD_Test_ThreadPool3.mpc @@ -0,0 +1,25 @@ +// -*- MPC -*- +// $Id$ + +project(*Server): csd_threadpool, taoexe, portableserver { + exename = server_main + + Source_Files { + Foo_i.cpp + OrbTask.cpp + ServerApp.cpp + server_main.cpp + OrbShutdownTask.cpp + } +} + +project(*Client): taoexe, anytypecode { + exename = client_main + + Source_Files { + FooC.cpp + ClientApp.cpp + client_main.cpp + } +} + diff --git a/TAO/examples/CSD_Strategy/ThreadPool3/ClientApp.cpp b/TAO/examples/CSD_Strategy/ThreadPool3/ClientApp.cpp new file mode 100644 index 00000000000..b55bdff6842 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool3/ClientApp.cpp @@ -0,0 +1,142 @@ +// $Id$ +#include "ClientApp.h" +#include "FooC.h" +#include "ace/Get_Opt.h" +#include "ace/Log_Msg.h" + + +ClientApp::ClientApp() +{ +} + + +ClientApp::~ClientApp() +{ +} + + +int +ClientApp::run(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + CORBA::ORB_var orb + = CORBA::ORB_init(argc, argv, "" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Parse the command-line args for this application. + // * Raises -1 if problems are encountered. + // * Returns 1 if the usage statement was explicitly requested. + // * Returns 0 otherwise. + int result = this->parse_args(argc, argv); + if (result != 0) + { + return result; + } + + CORBA::Object_var obj + = orb->string_to_object(this->ior_.c_str() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(obj.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to convert IOR string to obj ref.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + Foo_var foo = Foo::_narrow(obj.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(foo.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to narrow obj ref to Foo interface.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + for (CORBA::Long i = 1; i <= 100; i++) + { + foo->op1(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + foo->op2(i ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + CORBA::Long value = foo->op3(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ===> Value retrieved from op3() == %d\n", + value)); + + for (CORBA::Long j = 1; j <= 5; j++) + { + foo->op4(495 + (i * 5) + j ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + } + + ACE_TRY_NEW_ENV + { + foo->op5(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCH (FooException, ex) + { + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ===> Caught FooException - as expected.\n")); + + } + ACE_ENDTRY; + } + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ===> Tell server that we are done().\n")); + + foo->done(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ===> Back from done().\n")); + + return 0; +} + + +int +ClientApp::parse_args(int argc, char* argv[]) +{ + this->exe_name_ = argv[0]; + + ACE_Get_Opt get_opts(argc, argv, "i:"); + + int c; + + while ((c = get_opts()) != -1) + { + switch (c) + { + case 'i': + this->ior_ = get_opts.opt_arg(); + break; + + case '?': + this->usage_statement(); + return 1; + default: + this->usage_statement(); + return -1; + } + } + + return 0; +} + + +void +ClientApp::usage_statement() +{ + ACE_ERROR((LM_ERROR, + "Usage: %s [options]\n\n" + "OPTIONS:\n\n" + "\t[-i <ior>]\n" + "\t[-?]\n\n", + this->exe_name_.c_str())); +} + diff --git a/TAO/examples/CSD_Strategy/ThreadPool3/ClientApp.h b/TAO/examples/CSD_Strategy/ThreadPool3/ClientApp.h new file mode 100644 index 00000000000..7dc57bb78dc --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool3/ClientApp.h @@ -0,0 +1,30 @@ +// $Id$ +#ifndef CLIENTAPP_H +#define CLIENTAPP_H + +#include "ace/SString.h" +#include "ace/CORBA_macros.h" +#include "tao/Environment.h" + + +class ClientApp +{ + public: + + ClientApp(); + ~ClientApp(); + + int run(int argc, char* argv[] ACE_ENV_ARG_DECL); + + + private: + + int parse_args(int argc, char* argv[]); + void usage_statement(); + + ACE_CString ior_; + + ACE_CString exe_name_; +}; + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool3/Foo.idl b/TAO/examples/CSD_Strategy/ThreadPool3/Foo.idl new file mode 100644 index 00000000000..f4a756a31b1 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool3/Foo.idl @@ -0,0 +1,29 @@ +// $Id$ +#ifndef FOO_IDL +#define FOO_IDL + +exception FooException {}; +exception TestException {}; + +interface Foo +{ + /// void return-type, no arguments + void op1(); + + /// void return-type, 1 "in" argument + void op2(in long value); + + /// long return-type, no arguments + long op3(); + + /// one-way version of op2 + oneway void op4(in long value); + + /// Operation that always raises an exception. + void op5() raises (FooException); + + /// Client calls this last. It will shutdown the server. + void done(); +}; + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool3/Foo_i.cpp b/TAO/examples/CSD_Strategy/ThreadPool3/Foo_i.cpp new file mode 100644 index 00000000000..39a83de2507 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool3/Foo_i.cpp @@ -0,0 +1,72 @@ +// $Id$ +#include "Foo_i.h" +#include "OrbShutdownTask.h" + + +Foo_i::Foo_i(unsigned num_clients) + : value_(0), + num_clients_(num_clients) +{ +} + + +Foo_i::~Foo_i() +{ +} + + +void +Foo_i::op1(ACE_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ +} + + +void +Foo_i::op2(CORBA::Long value ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + this->value_ = value; +} + + +CORBA::Long +Foo_i::op3(ACE_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + return this->value_; +} + + + +void +Foo_i::op4(CORBA::Long value ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + this->value_ = value; +} + + +void +Foo_i::op5(ACE_ENV_SINGLE_ARG_DECL) + ACE_THROW_SPEC((CORBA::SystemException, FooException)) +{ + ACE_THROW (FooException()); +} + + +void +Foo_i::done(ACE_ENV_SINGLE_ARG_DECL) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + unsigned num_left = --this->num_clients_; + + if (num_left == 0) + { + if (TheOrbShutdownTask::instance()->open(0) != 0) + { + ACE_ERROR((LM_ERROR, "(%P|%t)Foo_i::done: " + "failed to create orb shutdown thread.\n")); + } + } +} diff --git a/TAO/examples/CSD_Strategy/ThreadPool3/Foo_i.h b/TAO/examples/CSD_Strategy/ThreadPool3/Foo_i.h new file mode 100644 index 00000000000..0d897194358 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool3/Foo_i.h @@ -0,0 +1,40 @@ +// $Id$ +#ifndef FOO_I_H +#define FOO_I_H + +#include "FooS.h" + + +class Foo_i : public virtual POA_Foo, + public virtual PortableServer::RefCountServantBase +{ + public: + + Foo_i(unsigned num_clients); + virtual ~Foo_i(); + + virtual void op1(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void op2(CORBA::Long value ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual CORBA::Long op3(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void op4(CORBA::Long value ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void op5(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException, FooException)); + + virtual void done(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + private: + + CORBA::Long value_; + unsigned num_clients_; +}; + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool3/OrbShutdownTask.cpp b/TAO/examples/CSD_Strategy/ThreadPool3/OrbShutdownTask.cpp new file mode 100644 index 00000000000..f9d551e8aee --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool3/OrbShutdownTask.cpp @@ -0,0 +1,77 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file OrbShutdownTask.cpp + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#include "OrbShutdownTask.h" +#include "ace/CORBA_macros.h" +#include "ace/OS_NS_unistd.h" + + +OrbShutdownTask::OrbShutdownTask() +{ +} + + +OrbShutdownTask::~OrbShutdownTask() +{ +} + + +void +OrbShutdownTask::orb(CORBA::ORB_ptr orb) +{ + this->orb_ = CORBA::ORB::_duplicate (orb); +} + + +int +OrbShutdownTask::open(void*) +{ + if (this->activate(THR_NEW_LWP | THR_JOINABLE, 1) != 0) + { + // Assumes that when activate returns non-zero return code that + // no threads were activated. + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) OrbShutdownTask failed to open().\n"), + -1); + } + + return 0; +} + + +int +OrbShutdownTask::svc() +{ + ACE_OS::sleep (2); + ACE_DEBUG ((LM_DEBUG, "(%P|%t)OrbShutdownTask::svc shutdown orb \n")); + ACE_TRY_NEW_ENV + { + this->orb_->shutdown(0 ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHALL + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Exception raised by ORB::shutdown() call " + "in OrbShutdownTask::svc().\n")); + } + ACE_ENDTRY; + + return 0; +} + + +int +OrbShutdownTask::close(u_long) +{ + return 0; +} diff --git a/TAO/examples/CSD_Strategy/ThreadPool3/OrbShutdownTask.h b/TAO/examples/CSD_Strategy/ThreadPool3/OrbShutdownTask.h new file mode 100644 index 00000000000..3795d12c3c9 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool3/OrbShutdownTask.h @@ -0,0 +1,41 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file OrbShutdownTask.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef ORB_SHUTDOWN_TASK_H +#define ORB_SHUTDOWN_TASK_H + +#include "ace/Task.h" +#include "tao/ORB.h" + + +class OrbShutdownTask : public ACE_Task_Base +{ + public: + + OrbShutdownTask(); + virtual ~OrbShutdownTask(); + + void orb(CORBA::ORB_ptr orb); + + virtual int open(void*); + virtual int svc(); + virtual int close(u_long); + + + private: + + CORBA::ORB_var orb_; +}; + +typedef ACE_Singleton<OrbShutdownTask, ACE_Thread_Mutex> TheOrbShutdownTask; + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool3/OrbTask.cpp b/TAO/examples/CSD_Strategy/ThreadPool3/OrbTask.cpp new file mode 100644 index 00000000000..390bbe8a317 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool3/OrbTask.cpp @@ -0,0 +1,98 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file OrbTask.cpp + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#include "OrbTask.h" + +namespace { enum { MAX_ORB_TASK_WORKER_THREADS = 20 }; } + + +OrbTask::OrbTask(CORBA::ORB_ptr orb, unsigned num_threads) + : orb_ (CORBA::ORB::_duplicate(orb)), + num_threads_(num_threads) +{ +} + + +OrbTask::~OrbTask() +{ +} + + +int +OrbTask::open(void*) +{ + if (this->num_threads_ < 1) + { + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) OrbTask failed to open. " + "num_threads_ (%d) is less-than 1.\n", + this->num_threads_), + -1); + } + + if (this->num_threads_ > MAX_ORB_TASK_WORKER_THREADS) + { + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) OrbTask failed to open. " + "num_threads_ (%d) is too large. Max is %d.\n", + this->num_threads_, MAX_ORB_TASK_WORKER_THREADS), + -1); + } + + if (CORBA::is_nil(this->orb_.in())) + { + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) OrbTask failed to open. " + "ORB object reference is nil.\n"), + -1); + } + + if (this->activate(THR_NEW_LWP | THR_JOINABLE, this->num_threads_) != 0) + { + // Assumes that when activate returns non-zero return code that + // no threads were activated. + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) OrbTask failed to activate " + "(%d) worker threads.\n", + this->num_threads_), + -1); + } + + return 0; +} + + +int +OrbTask::svc() +{ + ACE_TRY_NEW_ENV + { + this->orb_->run(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHALL + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Exception raised by ORB::run() method. " + "OrbTask is stopping.\n")); + } + ACE_ENDTRY; + + return 0; +} + + +int +OrbTask::close(u_long) +{ + return 0; +} diff --git a/TAO/examples/CSD_Strategy/ThreadPool3/OrbTask.h b/TAO/examples/CSD_Strategy/ThreadPool3/OrbTask.h new file mode 100644 index 00000000000..dde50d15f66 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool3/OrbTask.h @@ -0,0 +1,37 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file OrbTask.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef ORB_TASK_H +#define ORB_TASK_H + +#include "ace/Task.h" +#include "tao/ORB.h" + +class OrbTask : public ACE_Task_Base +{ + public: + + OrbTask(CORBA::ORB_ptr orb, unsigned num_threads = 1); + virtual ~OrbTask(); + + virtual int open(void* x = 0); + virtual int svc(); + virtual int close(u_long); + + + private: + + CORBA::ORB_var orb_; + unsigned num_threads_; +}; + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool3/README b/TAO/examples/CSD_Strategy/ThreadPool3/README new file mode 100644 index 00000000000..ebad7aba505 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool3/README @@ -0,0 +1,58 @@ +# $Id$ + +Description: + +This is another test showing the use of a Custom Servant Dispatching +(CSD) Strategy. This test uses the reference implementation, known as the +Thread Pool CSD Strategy. This tests some simple remote two-way CORBA +requests and a simple remote one-way request. + +The server application creates 1 servant object, runs the ORB event +loop using 4 threads (one being the main thread), and uses 10 worker +threads for the Thread Pool CSD Strategy. + +The client application invokes simple two-way calls on the object +reference. There is also a simple one-way call that is also made on +the object reference. + +The run_test.pl script will launch 1 sever process, and 40 client processes. + + +Executables: + + * client_main + + This is the client test executable. + + Command-line arguments: + + -? : Prints the executable's available command-line options, and + then exits. + + -i <ior string> : Provide the IOR to the client (ie, file://some.ior). + + * server_main + + This is the server test executable. + + Command-line arguments: + + -? : Prints the executable's available command-line options, and + then exits. + + -o <ior filename> : Name of file to which IOR will be written. + + -n <num clients> : The number of clients that will use the server. + + -t <num ORB threads> : Number of threads running the ORB event loop. + + * run_test.pl + + This perl script will run an automated test using 40 client processes + and 1 server process. The script returns 0 if the test was successful. + + No command-line options are supported. Simply execute the perl script + as follows: + + $ ./run_test.pl + diff --git a/TAO/examples/CSD_Strategy/ThreadPool3/ServerApp.cpp b/TAO/examples/CSD_Strategy/ThreadPool3/ServerApp.cpp new file mode 100644 index 00000000000..0625e2baf67 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool3/ServerApp.cpp @@ -0,0 +1,269 @@ +// $Id$ +#include "ServerApp.h" +#include "Foo_i.h" +#include "OrbTask.h" +#include "OrbShutdownTask.h" +#include "ace/Get_Opt.h" +#include "tao/CSD_ThreadPool/CSD_TP_Strategy.h" +#include "tao/Intrusive_Ref_Count_Handle_T.h" + + +ServerApp::ServerApp() + : ior_filename_("ServerApp.default.ior"), + num_clients_(1), + num_orb_threads_(1) +{ +} + + +ServerApp::~ServerApp() +{ +} + + +int +ServerApp::run(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + CORBA::ORB_var orb = CORBA::ORB_init(argc, argv, "" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Parse the command-line args for this application. + // * Raises -1 if problems are encountered. + // * Returns 1 if the usage statement was explicitly requested. + // * Returns 0 otherwise. + int result = this->parse_args(argc, argv); + if (result != 0) + { + return result; + } + + TheOrbShutdownTask::instance()->orb (orb.in ()); + + CORBA::Object_var obj + = orb->resolve_initial_references("RootPOA" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(obj.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to resolve initial ref for 'RootPOA'.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + PortableServer::POA_var root_poa + = PortableServer::POA::_narrow(obj.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(root_poa.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to narrow obj ref to POA interface.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + PortableServer::POAManager_var poa_manager + = root_poa->the_POAManager(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Create the child POA. + CORBA::PolicyList policies(0); + policies.length(0); + + PortableServer::POA_var child_poa + = root_poa->create_POA("ChildPoa", + poa_manager.in(), + policies + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(child_poa.in())) + { + ACE_ERROR((LM_ERROR, "(%P|%t) ERROR [ServerApp::run()]: " + "Failed to create the child POA.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + // Create the thread pool servant dispatching strategy object, and + // hold it in a (local) smart pointer variable. + TAO_Intrusive_Ref_Count_Handle<TAO::CSD::TP_Strategy> csd_tp_strategy = + new TAO::CSD::TP_Strategy(); + + // Tell the strategy to apply itself to the child poa. + if (csd_tp_strategy->apply_to(child_poa.in() ACE_ENV_ARG_PARAMETER) == false) + { + ACE_ERROR((LM_ERROR, "(%P|%t) ERROR [ServerApp::run()]: " + "Failed to apply custom dispatching strategy to child poa.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + ACE_CHECK_RETURN (-1); + + // Create the servant object. + Foo_i* servant = new Foo_i(this->num_clients_); + + // local smart pointer variable to deal with releasing the reference + // to the servant object when the smart pointer object falls out of scope. + PortableServer::ServantBase_var owner_transfer(servant); + + // Activate the servant using the Child POA. + PortableServer::ObjectId_var oid + = child_poa->activate_object(servant ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Obtain the object reference. + obj = child_poa->servant_to_reference(servant ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(obj.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to activate servant (Foo_i).\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + // Stringify the object reference + CORBA::String_var ior + = orb->object_to_string(obj.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Write the stringified object reference to the ior file. + FILE* ior_file = ACE_OS::fopen(this->ior_filename_.c_str(), "w"); + + if (ior_file == 0) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Cannot open output file for writing IOR: %s", + this->ior_filename_.c_str())); + ACE_THROW_RETURN (TestException(), -1); + } + + ACE_OS::fprintf(ior_file, "%s", ior.in ()); + ACE_OS::fclose(ior_file); + + // Activate the POA Manager + poa_manager->activate(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp is ready.\n")); + + // If the num_orb_threads_ is exactly one, then just use the current + // (mainline) thread to run the ORB event loop. + if (this->num_orb_threads_ == 1) + { + // Since the num_orb_threads_ is exactly one, we just use the current + // (mainline) thread to run the ORB event loop. + orb->run(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + } + else + { + // The num_orb_threads_ is greater than 1, so we will use an OrbTask + // (active object) to run the ORB event loop in (num_orb_threads_ - 1) + // threads. We use the current (mainline) thread as the other thread + // running the ORB event loop. + OrbTask orb_task(orb.in(), this->num_orb_threads_ - 1); + + // Activate the OrbTask worker threads + if (orb_task.open() != 0) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to open the OrbTask.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + // This will use the current (mainline) thread to run the ORB event loop. + orb->run(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Now that the current thread has unblocked from running the orb, + // make sure to wait for all of the worker threads to complete. + orb_task.wait(); + } + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp is waiting for OrbShutdownTask.\n")); + TheOrbShutdownTask::instance()->wait (); + + // Sleep for 2 second to let the done() two-way call complete + // before cleanup. + ACE_OS::sleep (2); + + // Tear-down the root poa and orb. + root_poa->destroy(1, 1 ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + orb->destroy(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + return 0; +} + + +int +ServerApp::parse_args(int argc, char* argv[]) +{ + this->exe_name_ = argv[0]; + + ACE_Get_Opt get_opts(argc, argv, "o:n:t:"); + + int c; + int tmp; + + while ((c = get_opts()) != -1) + { + switch (c) + { + case 'o': + this->ior_filename_ = get_opts.opt_arg(); + break; + + case 'n': + tmp = ACE_OS::atoi(get_opts.opt_arg()); + if (tmp < 1) + { + this->usage_statement(); + return -1; + } + + this->num_clients_ = tmp; + break; + + case 't': + tmp = ACE_OS::atoi(get_opts.opt_arg()); + if (tmp < 1) + { + this->usage_statement(); + return -1; + } + + this->num_orb_threads_ = tmp; + break; + case '?': + this->usage_statement(); + return 1; + + default: + this->usage_statement(); + return -1; + } + } + + return 0; +} + + +void +ServerApp::usage_statement() +{ + ACE_ERROR((LM_ERROR, + "Usage: %s [options]\n\n" + "OPTIONS:\n\n" + "\t[-o <ior_filename>]\n" + "\t[-n <num_clients>]\n" + "\t[-t <num_orb_threads>]\n" + "\t[-?]\n", + "Default ior_filename_prefix is 'foo'.\n" + "Default num_servants is 1.\n" + "Default num_clients is 1.\n\n", + this->exe_name_.c_str())); +} + diff --git a/TAO/examples/CSD_Strategy/ThreadPool3/ServerApp.h b/TAO/examples/CSD_Strategy/ThreadPool3/ServerApp.h new file mode 100644 index 00000000000..9ffd10f0507 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool3/ServerApp.h @@ -0,0 +1,31 @@ +// $Id$ +#ifndef SERVERAPP_H +#define SERVERAPP_H + +#include "ace/SString.h" +#include "ace/CORBA_macros.h" +#include "tao/Environment.h" + + +class ServerApp +{ + public: + + ServerApp(); + ~ServerApp(); + + int run(int argc, char* argv[] ACE_ENV_ARG_DECL); + + + private: + + int parse_args(int argc, char* argv[]); + void usage_statement(); + + ACE_CString exe_name_; + ACE_CString ior_filename_; + unsigned num_clients_; + unsigned num_orb_threads_; +}; + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool3/client_main.cpp b/TAO/examples/CSD_Strategy/ThreadPool3/client_main.cpp new file mode 100644 index 00000000000..f1b0c4cb08a --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool3/client_main.cpp @@ -0,0 +1,44 @@ +// $Id$ +#include "ClientApp.h" +#include "ace/Log_Msg.h" +#include "tao/Exception.h" + + +int +main(int argc, char* argv[]) +{ + ACE_LOG_MSG->priority_mask(LM_TRACE | + LM_DEBUG | + LM_INFO | + LM_NOTICE | + LM_WARNING | + LM_ERROR | + LM_CRITICAL | + LM_ALERT | + LM_EMERGENCY, + ACE_Log_Msg::PROCESS); + + + ClientApp app; + + ACE_TRY_NEW_ENV + { + int ret = app.run(argc,argv ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + return ret == 1 ? 0 : ret; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "Caught exception:"); + } + ACE_CATCHALL + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Unknown (...) exception caught in main() " + "for ClientApp\n")); + } + ACE_ENDTRY; + + return 1; +} diff --git a/TAO/examples/CSD_Strategy/ThreadPool3/run_test.pl b/TAO/examples/CSD_Strategy/ThreadPool3/run_test.pl new file mode 100755 index 00000000000..b0c25a6456b --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool3/run_test.pl @@ -0,0 +1,56 @@ +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; + +$iorfile = PerlACE::LocalFile ("server.ior"); +unlink $iorfile; +$status = 0; + +$num_clients=40; +$num_orb_threads=4; + +$SV = new PerlACE::Process ("server_main", "-o $iorfile -n $num_clients -t $num_orb_threads"); + +$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; +} + +for ($i = 0; $i < $num_clients; $i++) { + + @CLS[$i] = new PerlACE::Process ("client_main", " -i file://$iorfile"); + + @CLS[$i]->Spawn (); +} + +for ($i = 0; $i < $num_clients; $i++) { + + $client = @CLS[$i]->WaitKill (60); + + if ($client != 0) { + print STDERR "ERROR: client $i returned $client\n"; + $status = 1; + } +} + + +$server = $SV->WaitKill (60); + +if ($server != 0) { + print STDERR "ERROR: server returned $server\n"; + $status = 1; +} + +unlink $iorfile; + +exit $status; diff --git a/TAO/examples/CSD_Strategy/ThreadPool3/server_main.cpp b/TAO/examples/CSD_Strategy/ThreadPool3/server_main.cpp new file mode 100644 index 00000000000..cad2b8e119d --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool3/server_main.cpp @@ -0,0 +1,42 @@ +// $Id$ +#include "ServerApp.h" +#include "ace/Log_Msg.h" +#include "tao/Exception.h" + +int +main(int argc, char* argv[]) +{ + ACE_LOG_MSG->priority_mask(LM_TRACE | + LM_DEBUG | + LM_INFO | + LM_NOTICE | + LM_WARNING | + LM_ERROR | + LM_CRITICAL | + LM_ALERT | + LM_EMERGENCY, + ACE_Log_Msg::PROCESS); + + ServerApp app; + + ACE_TRY_NEW_ENV + { + int ret = app.run(argc,argv ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + return ret == 1 ? 0 : ret; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "Caught exception:"); + } + ACE_CATCHALL + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Unknown (...) exception caught in main() " + "for ServerApp\n")); + } + ACE_ENDTRY; + + return 1; +} diff --git a/TAO/examples/CSD_Strategy/ThreadPool4/CSD_Test_ThreadPool4.mpc b/TAO/examples/CSD_Strategy/ThreadPool4/CSD_Test_ThreadPool4.mpc new file mode 100644 index 00000000000..386d4964863 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool4/CSD_Test_ThreadPool4.mpc @@ -0,0 +1,15 @@ +// -*- MPC -*- +// $Id$ + +project(*Server): csd_threadpool, messaging, taoexe, portableserver { + exename = server_main + + Source_Files { + Foo_i.cpp + Callback_i.cpp + ServerApp.cpp + server_main.cpp + ClientTask.cpp + OrbShutdownTask.cpp + } +} diff --git a/TAO/examples/CSD_Strategy/ThreadPool4/Callback.idl b/TAO/examples/CSD_Strategy/ThreadPool4/Callback.idl new file mode 100644 index 00000000000..49be42260cb --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool4/Callback.idl @@ -0,0 +1,11 @@ +// $Id$ +#ifndef CALLBACK_IDL +#define CALLBACK_IDL + +interface Callback +{ + void test_method(); +}; + + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool4/Callback_i.cpp b/TAO/examples/CSD_Strategy/ThreadPool4/Callback_i.cpp new file mode 100644 index 00000000000..c243461dcaa --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool4/Callback_i.cpp @@ -0,0 +1,26 @@ +// $Id$ +#include "Callback_i.h" + + +Callback_i::Callback_i() +{ +} + + +Callback_i::~Callback_i () +{ +} + + +void +Callback_i::test_method ( + ACE_ENV_SINGLE_ARG_DECL_NOT_USED +) +ACE_THROW_SPEC (( + CORBA::SystemException +)) +{ + ACE_DEBUG((LM_DEBUG, "(%P|%t)Callback_i::test_method called \n")); + +} + diff --git a/TAO/examples/CSD_Strategy/ThreadPool4/Callback_i.h b/TAO/examples/CSD_Strategy/ThreadPool4/Callback_i.h new file mode 100644 index 00000000000..c66fe818f94 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool4/Callback_i.h @@ -0,0 +1,27 @@ +// $Id$ +#ifndef CALLBACK_I_H +#define CALLBACK_I_H + +#include "CallbackS.h" + + +class Callback_i : public virtual POA_Callback, + public virtual PortableServer::RefCountServantBase +{ + public: + + Callback_i(); + + virtual ~Callback_i(); + + virtual void test_method ( + ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + CORBA::SystemException + )); + +}; + + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool4/ClientTask.cpp b/TAO/examples/CSD_Strategy/ThreadPool4/ClientTask.cpp new file mode 100644 index 00000000000..93aadcf0e78 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool4/ClientTask.cpp @@ -0,0 +1,213 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file ClientTask.cpp + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#include "ClientTask.h" +#include "ace/SString.h" +#include "ace/OS.h" + + +ClientTask::ClientTask(Foo_ptr foo, + Callback_ptr callback) +: foo_(Foo::_duplicate(foo)), + callback_(Callback::_duplicate(callback)) +{ +} + + +ClientTask::~ClientTask() +{ +} + + +int +ClientTask::open(void*) +{ + if (this->activate(THR_NEW_LWP | THR_JOINABLE, 1) != 0) + { + // Assumes that when activate returns non-zero return code that + // no threads were activated. + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) ClientTask failed to activate " + "the client thread.\n"), + -1); + } + + return 0; +} + + +int +ClientTask::svc() +{ + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ClientTask::svc start\n")); + + ACE_TRY_NEW_ENV + { + for (CORBA::Long i = 1; i <= 100; i++) + { + // Simple Two-way calls. + this->foo_->op1(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + this->foo_->op2(i ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + CORBA::Long value = this->foo_->op3(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ===> Value retrieved from op3() == %d\n", + value)); + + for (CORBA::Long j = 1; j <= 5; j++) + { + this->foo_->op4(495 + (i * 5) + j ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + + ACE_TRY_EX (op5) + { + ACE_DEBUG((LM_DEBUG, "(%P|%t) ===> Invoke op5()\n")); + this->foo_->op5(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK_EX (op5); + ACE_DEBUG((LM_DEBUG, "(%P|%t) ===> No exception raised from op5(). :-(\n")); + } + ACE_CATCH (FooException, ex) + { + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ===> Caught FooException - as expected.\n")); + + } + ACE_ENDTRY; + + // Two-Way calls with inout parameters. + CORBA::String_var message = CORBA::string_dup( "Hello! " ); + CORBA::Boolean result + = this->foo_->op6( "TAO User", message.inout() ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (result) + { + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ===> Message from op6() == %s\n", + message.in ())); + } + else + { + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ===> op6() returned false.\n")); + } + + // Callback test. + this->foo_->callback_object (this->callback_.in () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + this->foo_->test_callback (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + // One-Way calls with various arguments. + CORBA::String_var ub_string = CORBA::string_dup( "UNBOUNDED STRING" ); + this->foo_->test_unbounded_string_arg (ub_string.in () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + CORBA::String_var bd_string = CORBA::string_dup( "BOUNDED STRING" ); + this->foo_->test_bounded_string_arg (bd_string.in () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + Fixed_Array fixed_array; + + for (CORBA::ULong m = 0; m < 20; m ++) + { + fixed_array[m] = i + m; + } + + this->foo_->test_fixed_array_arg (fixed_array ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + Var_Array var_array; + var_array[0] = CORBA::string_dup( "STRING 1" ); + var_array[1] = CORBA::string_dup( "STRING 2" ); + var_array[2] = CORBA::string_dup( "STRING 3" ); + this->foo_->test_var_array_arg (var_array ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + Bounded_Var_Size_var bd_var_size_string = new Bounded_Var_Size(); + const char* buffer1 = "BOUNDED VAR SIZE CHAR"; + bd_var_size_string->replace (bd_var_size_string->maximum (), + ACE_OS::strlen (buffer1) + 1, + (CORBA::Char*)buffer1); + this->foo_->test_bounded_var_size_arg (bd_var_size_string.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + const char* buffer2 = "UNBOUNDED VAR SIZE CHAR"; + Unbounded_Var_Size_var ub_var_size_string = new Unbounded_Var_Size(100); + ub_var_size_string->replace (ub_var_size_string->maximum (), + ACE_OS::strlen (buffer2) + 1, + (CORBA::Char*)buffer2); + this->foo_->test_unbounded_var_size_arg (ub_var_size_string.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + TimeOfDay t; + t.hour = 12; + t.minute = 30; + t.second = 10; + this->foo_->test_fixed_size_arg (t ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + this->foo_->test_fixed_size_arg_two_way (t ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + CORBA::Boolean special_value = 1; + this->foo_->test_special_basic_arg (special_value ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + this->foo_->test_objref_arg (this->callback_.in () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ClientTask::svc - Invoke foo->done()\n")); + + this->foo_->done (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ClientTask::svc - Back from foo->done()\n")); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "Caught exception in ClientTask::svc():"); + } + ACE_CATCHALL + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Unknown (...) exception caught in ClientTask::svc()\n")); + } + ACE_ENDTRY; + + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ClientTask::svc end\n")); + + return 0; +} + + +int +ClientTask::close(u_long) +{ + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ClientTask::close() - enter/exit\n")); + return 0; +} diff --git a/TAO/examples/CSD_Strategy/ThreadPool4/ClientTask.h b/TAO/examples/CSD_Strategy/ThreadPool4/ClientTask.h new file mode 100644 index 00000000000..2f0aa572f8a --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool4/ClientTask.h @@ -0,0 +1,38 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file ClientTask.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef CLIENT_TASK_H +#define CLIENT_TASK_H + +#include "FooC.h" +#include "CallbackC.h" +#include "ace/Task.h" + +class ClientTask : public ACE_Task_Base +{ + public: + + ClientTask(Foo_ptr foo, + Callback_ptr callback); + + virtual ~ClientTask(); + + virtual int open(void* x = 0); + virtual int svc(); + virtual int close(u_long); + + private: + Foo_var foo_; + Callback_var callback_; +}; + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool4/Foo.idl b/TAO/examples/CSD_Strategy/ThreadPool4/Foo.idl new file mode 100644 index 00000000000..715dd264d41 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool4/Foo.idl @@ -0,0 +1,73 @@ +// $Id$ +#ifndef FOO_IDL +#define FOO_IDL + +#include "Callback.idl" + +exception FooException {}; +exception TestException {}; + +typedef sequence<char, 32> Bounded_Var_Size; +typedef sequence<char> Unbounded_Var_Size; +typedef long Fixed_Array[20]; +typedef string Var_Array [3]; + +struct TimeOfDay { + short hour; // 0 - 23 + short minute; // 0 - 59 + short second; // 0 - 59 +}; +interface Foo +{ + /// void return-type, no arguments + void op1(); + + /// void return-type, 1 "in" argument + void op2(in long value); + + /// long return-type, no arguments + long op3(); + + /// one-way version of op2 + oneway void op4(in long value); + + /// Operation that always raises an exception. + void op5() raises (FooException); + + /// Operation with the inout parameter. + boolean op6(in string user_name, + inout string message); + + oneway void test_unbounded_string_arg(in string message); + + oneway void test_bounded_string_arg(in string<20> message); + + oneway void test_fixed_array_arg(in Fixed_Array message); + + oneway void test_var_array_arg(in Var_Array messages); + + oneway void test_bounded_var_size_arg(in Bounded_Var_Size message); + + oneway void test_unbounded_var_size_arg(in Unbounded_Var_Size message); + + oneway void test_fixed_size_arg (in TimeOfDay t); + + oneway void test_special_basic_arg(in boolean value); + + oneway void test_objref_arg (in Callback cb); + + void test_fixed_size_arg_two_way (in TimeOfDay t); + + /// Operation with the object reference parameter. + void callback_object (in Callback cb); + + /// Operation that invoke remote operation on + // callback object. + void test_callback (); + + /// Client calls this last. It will shutdown the server. + void done(); +}; + + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool4/Foo_i.cpp b/TAO/examples/CSD_Strategy/ThreadPool4/Foo_i.cpp new file mode 100644 index 00000000000..e94e00c0226 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool4/Foo_i.cpp @@ -0,0 +1,301 @@ +// $Id$ +#include "Foo_i.h" +#include "OrbShutdownTask.h" +#include "ace/OS.h" + +Foo_i::Foo_i(const char* servant_name) +: value_(0), + count_op1_(0), + count_op2_(0), + count_op3_(0), + count_op4_(0), + count_op5_(0), + servant_name_(servant_name) +{ +} + + +Foo_i::~Foo_i() +{ +} + + +void +Foo_i::op1(ACE_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + ++this->count_op1_; + // Sleep for 10 milliseconds (10,000 microseconds) + //ACE_OS::sleep(ACE_Time_Value(0,10000)); +} + + +void +Foo_i::op2(CORBA::Long value ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + ++this->count_op2_; + this->value_ = value; +} + + +CORBA::Long +Foo_i::op3(ACE_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + ++this->count_op3_; + return this->value_; +} + + +void +Foo_i::op4(CORBA::Long value ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + ++this->count_op4_; + this->value_ = value; + + if (this->count_op4_ % 1 == 0) + { + ACE_DEBUG((LM_DEBUG, + "(%P|%t) op4() has been called %d times now. value == %d\n", + this->count_op4_, this->value_)); + } + + // Sleep for 10 milliseconds (10,000 microseconds) + //ACE_OS::sleep(ACE_Time_Value(0,10000)); +} + + +void +Foo_i::op5(ACE_ENV_SINGLE_ARG_DECL) + ACE_THROW_SPEC((CORBA::SystemException, FooException)) +{ + ACE_DEBUG((LM_DEBUG, "(%P|%t) Foo_i::op5() - ENTER\n")); + ACE_DEBUG((LM_DEBUG, "(%P|%t) Foo_i::op5() - Increment counter.\n")); + unsigned newcount = ++this->count_op5_; + ACE_DEBUG((LM_DEBUG, "(%P|%t) Foo_i::op5() - Counter is now %d.\n", newcount)); + ACE_DEBUG((LM_DEBUG, "(%P|%t) Foo_i::op5() - EXIT - Raise a FooException.\n")); + ACE_THROW_SPEC (FooException()); +} + + +CORBA::Boolean +Foo_i::op6 ( + const char * user_name, + char *& message + ACE_ENV_ARG_DECL_NOT_USED +) +ACE_THROW_SPEC (( + CORBA::SystemException +)) +{ + ACE_CString str(message); + str += user_name; + message = CORBA::string_dup (str.c_str ()); + return 1; +} + + +void +Foo_i::test_unbounded_string_arg ( + const char * message + ACE_ENV_ARG_DECL_NOT_USED +) +ACE_THROW_SPEC (( +CORBA::SystemException +)) +{ + ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_i::test_unbounded_string_arg ") + ACE_TEXT("got unbounded string %s\n"), + message)); +} + + +void +Foo_i::test_bounded_string_arg ( + const char * message + ACE_ENV_ARG_DECL_NOT_USED +) +ACE_THROW_SPEC (( +CORBA::SystemException +)) +{ + ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_i::test_bounded_string_arg ") + ACE_TEXT("got bounded string %s\n"), + message)); +} + + +void +Foo_i::test_fixed_array_arg ( + const ::Fixed_Array message + ACE_ENV_ARG_DECL_NOT_USED +) +ACE_THROW_SPEC (( + CORBA::SystemException +)) +{ + for (CORBA::ULong i = 0; i < 20; i++) + { + ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_i::test_fixed_array_arg ") + ACE_TEXT("got fixed_array[i] = %d\n"), + i, message[i])); + } +} + + +void +Foo_i::test_bounded_var_size_arg ( + const ::Bounded_Var_Size & message + ACE_ENV_ARG_DECL_NOT_USED +) +ACE_THROW_SPEC (( + CORBA::SystemException +)) +{ + ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_i::test_bounded_var_size_arg ") + ACE_TEXT("got var array chars %s\n"), + message.get_buffer ())); +} + + +void +Foo_i::test_unbounded_var_size_arg ( + const ::Unbounded_Var_Size & message + ACE_ENV_ARG_DECL_NOT_USED +) +ACE_THROW_SPEC (( + CORBA::SystemException +)) +{ + ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_i::test_unbounded_var_size_arg ") + ACE_TEXT("got var array chars %s\n"), + message.get_buffer ())); +} + + +void +Foo_i::test_fixed_size_arg ( + const ::TimeOfDay & t + ACE_ENV_ARG_DECL_NOT_USED +) +ACE_THROW_SPEC (( + CORBA::SystemException +)) +{ + ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_i::test_fixed_size_arg ") + ACE_TEXT("got timeofday %d:%d:%d\n"), + t.hour, t.minute, t.second)); +} + +void +Foo_i::test_fixed_size_arg_two_way ( + const ::TimeOfDay & t + ACE_ENV_ARG_DECL_NOT_USED +) +ACE_THROW_SPEC (( + CORBA::SystemException +)) +{ + ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_i::test_fixed_size_arg_two_way ") + ACE_TEXT("got timeofday %d:%d:%d\n"), + t.hour, t.minute, t.second)); +} + +void +Foo_i::test_var_array_arg ( + const ::Var_Array messages + ACE_ENV_ARG_DECL_NOT_USED +) +ACE_THROW_SPEC (( + CORBA::SystemException +)) +{ + ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_i::test_var_array_arg ") + ACE_TEXT(" %s \n"), messages[0].in ())); + ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_i::test_var_array_arg ") + ACE_TEXT(" %s \n"), messages[1].in ())); + ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_i::test_var_array_arg ") + ACE_TEXT(" %s \n"), messages[2].in ())); +} + + +void +Foo_i::test_special_basic_arg ( + ::CORBA::Boolean value + ACE_ENV_ARG_DECL_NOT_USED +) +ACE_THROW_SPEC (( + CORBA::SystemException +)) +{ + ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_i::test_special_basic_arg ") + ACE_TEXT(" got special basic arg: %d \n"), value)); +} + + +void +Foo_i::test_objref_arg ( + ::Callback_ptr cb + ACE_ENV_ARG_DECL_NOT_USED +) +ACE_THROW_SPEC (( + CORBA::SystemException +)) +{ + this->callback_ = Callback::_duplicate (cb); + ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_i::test_objref_arg ") + ACE_TEXT(" got callback object. \n"))); +} + + +void +Foo_i::callback_object ( + ::Callback_ptr cb + ACE_ENV_ARG_DECL_NOT_USED +) +ACE_THROW_SPEC (( + CORBA::SystemException +)) +{ + this->callback_ = Callback::_duplicate (cb); +} + +void +Foo_i::test_callback ( + ACE_ENV_SINGLE_ARG_DECL +) +ACE_THROW_SPEC (( + CORBA::SystemException +)) +{ + if (CORBA::is_nil (this->callback_.in ())) + { + ACE_THROW_SPEC (TestException ()); + } + else + { + this->callback_->test_method (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + } +} + + +void +Foo_i::done(ACE_ENV_SINGLE_ARG_DECL) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + static ACE_Atomic_Op <ACE_SYNCH_MUTEX, unsigned> num_clients = 2; + + num_clients --; + + if (num_clients == 0) + { + if (TheOrbShutdownTask::instance()->open(0) != 0) + { + ACE_ERROR((LM_ERROR, "(%P|%t)Foo_i::done: " + "failed to create orb shutdown thread.\n")); + } + } +} diff --git a/TAO/examples/CSD_Strategy/ThreadPool4/Foo_i.h b/TAO/examples/CSD_Strategy/ThreadPool4/Foo_i.h new file mode 100644 index 00000000000..82c115ecbe6 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool4/Foo_i.h @@ -0,0 +1,158 @@ +// $Id$ +#ifndef FOO_I_H +#define FOO_I_H + +#include "FooS.h" +#include "CallbackC.h" +#include "ace/SString.h" +#include "ace/CORBA_macros.h" +#include "tao/Environment.h" + +class FooServantList; + +class Foo_i : public virtual POA_Foo, + public virtual PortableServer::RefCountServantBase +{ + public: + + Foo_i(const char* servant_name); + virtual ~Foo_i(); + + virtual void op1(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void op2(CORBA::Long value ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual CORBA::Long op3(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void op4(CORBA::Long value ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void op5(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException, FooException)); + + virtual CORBA::Boolean op6 ( + const char * user_name, + char *& message + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + CORBA::SystemException + )); + + virtual void test_unbounded_string_arg ( + const char * message + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + CORBA::SystemException + )); + + virtual void test_bounded_string_arg ( + const char * message + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + CORBA::SystemException + )); + + virtual void test_fixed_array_arg ( + const ::Fixed_Array message + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + CORBA::SystemException + )); + + virtual void test_var_array_arg ( + const ::Var_Array messages + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + CORBA::SystemException + )); + + virtual void test_bounded_var_size_arg ( + const ::Bounded_Var_Size & message + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + CORBA::SystemException + )); + + virtual void test_unbounded_var_size_arg ( + const ::Unbounded_Var_Size & message + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + CORBA::SystemException + )); + + virtual void test_fixed_size_arg ( + const ::TimeOfDay & t + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + CORBA::SystemException + )); + + virtual void test_fixed_size_arg_two_way ( + const ::TimeOfDay & t + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + CORBA::SystemException + )); + + virtual void test_special_basic_arg ( + ::CORBA::Boolean value + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + CORBA::SystemException + )); + + virtual void test_objref_arg ( + ::Callback_ptr cb + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + CORBA::SystemException + )); + + virtual void callback_object ( + ::Callback_ptr cb + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + CORBA::SystemException + )); + + virtual void test_callback ( + ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + CORBA::SystemException + )); + + virtual void done(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + + private: + + CORBA::Long value_; + + unsigned count_op1_; + unsigned count_op2_; + unsigned count_op3_; + unsigned count_op4_; + unsigned count_op5_; + + ACE_CString servant_name_; + Callback_var callback_; +}; + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool4/OrbShutdownTask.cpp b/TAO/examples/CSD_Strategy/ThreadPool4/OrbShutdownTask.cpp new file mode 100644 index 00000000000..f9d551e8aee --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool4/OrbShutdownTask.cpp @@ -0,0 +1,77 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file OrbShutdownTask.cpp + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#include "OrbShutdownTask.h" +#include "ace/CORBA_macros.h" +#include "ace/OS_NS_unistd.h" + + +OrbShutdownTask::OrbShutdownTask() +{ +} + + +OrbShutdownTask::~OrbShutdownTask() +{ +} + + +void +OrbShutdownTask::orb(CORBA::ORB_ptr orb) +{ + this->orb_ = CORBA::ORB::_duplicate (orb); +} + + +int +OrbShutdownTask::open(void*) +{ + if (this->activate(THR_NEW_LWP | THR_JOINABLE, 1) != 0) + { + // Assumes that when activate returns non-zero return code that + // no threads were activated. + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) OrbShutdownTask failed to open().\n"), + -1); + } + + return 0; +} + + +int +OrbShutdownTask::svc() +{ + ACE_OS::sleep (2); + ACE_DEBUG ((LM_DEBUG, "(%P|%t)OrbShutdownTask::svc shutdown orb \n")); + ACE_TRY_NEW_ENV + { + this->orb_->shutdown(0 ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHALL + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Exception raised by ORB::shutdown() call " + "in OrbShutdownTask::svc().\n")); + } + ACE_ENDTRY; + + return 0; +} + + +int +OrbShutdownTask::close(u_long) +{ + return 0; +} diff --git a/TAO/examples/CSD_Strategy/ThreadPool4/OrbShutdownTask.h b/TAO/examples/CSD_Strategy/ThreadPool4/OrbShutdownTask.h new file mode 100644 index 00000000000..3795d12c3c9 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool4/OrbShutdownTask.h @@ -0,0 +1,41 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file OrbShutdownTask.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef ORB_SHUTDOWN_TASK_H +#define ORB_SHUTDOWN_TASK_H + +#include "ace/Task.h" +#include "tao/ORB.h" + + +class OrbShutdownTask : public ACE_Task_Base +{ + public: + + OrbShutdownTask(); + virtual ~OrbShutdownTask(); + + void orb(CORBA::ORB_ptr orb); + + virtual int open(void*); + virtual int svc(); + virtual int close(u_long); + + + private: + + CORBA::ORB_var orb_; +}; + +typedef ACE_Singleton<OrbShutdownTask, ACE_Thread_Mutex> TheOrbShutdownTask; + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool4/README b/TAO/examples/CSD_Strategy/ThreadPool4/README new file mode 100644 index 00000000000..923174c8d78 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool4/README @@ -0,0 +1,23 @@ +# $Id$ + +Description: + +This is another test showing the use of a Custom Servant Dispatching +(CSD) Strategy. This test uses the reference implementation, known as the +Thread Pool CSD Strategy. This tests collocated requests. + +The server application creates two servants, each with a different child +POA. One of the POAs has a CSD Strategy applied to it, and the other does +not. Also created are two collocated callback servants to test the +passing of object references as arguments in collocated requests. + +The server activates a new thread for each of the two collocated "clients". + +To run the test use the run_test.pl script: + +$ ./run_test.pl + + The script returns 0 if the test was successful. + + + diff --git a/TAO/examples/CSD_Strategy/ThreadPool4/ServerApp.cpp b/TAO/examples/CSD_Strategy/ThreadPool4/ServerApp.cpp new file mode 100644 index 00000000000..9db3f5c7785 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool4/ServerApp.cpp @@ -0,0 +1,357 @@ +// $Id$ +#include "ServerApp.h" +#include "Foo_i.h" +#include "Callback_i.h" +#include "ClientTask.h" +#include "OrbShutdownTask.h" +#include "ace/Get_Opt.h" +#include "tao/CSD_ThreadPool/CSD_TP_Strategy.h" +#include "tao/Intrusive_Ref_Count_Handle_T.h" +#include "tao/Messaging/Messaging.h" +#include "tao/AnyTypeCode/Any.h" + + +ServerApp::ServerApp() +: synch_with_server_ (0) +{ +} + + +ServerApp::~ServerApp() +{ +} + + +int +ServerApp::run(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + this->orb_ = CORBA::ORB_init(argc, argv, "" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Parse the command-line args for this application. + // * Raises -1 if problems are encountered. + // * Returns 1 if the usage statement was explicitly requested. + // * Returns 0 otherwise. + int result = this->parse_args(argc, argv); + if (result != 0) + { + return result; + } + + TheOrbShutdownTask::instance()->orb (this->orb_.in ()); + + if (synch_with_server_) + { + CORBA::Object_var manager_object = + orb_->resolve_initial_references("ORBPolicyManager" + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + CORBA::PolicyManager_var policy_manager + = CORBA::PolicyManager::_narrow(manager_object.in() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil (policy_manager.in ())) + { + ACE_ERROR ((LM_ERROR, + " (%P|%t) Panic: nil PolicyManager\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + CORBA::Any policy_value; + policy_value <<= Messaging::SYNC_WITH_SERVER; + CORBA::PolicyList policies(1); + policies.length(1); + + policies[0] = + orb_->create_policy (Messaging::SYNC_SCOPE_POLICY_TYPE, + policy_value + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + policy_manager->set_policy_overrides (policies, + CORBA::ADD_OVERRIDE + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + policies[0]->destroy (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + } + + CORBA::Object_var obj + = orb_->resolve_initial_references("RootPOA" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(obj.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to resolve initial ref for 'RootPOA'.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + PortableServer::POA_var root_poa + = PortableServer::POA::_narrow(obj.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(root_poa.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to narrow obj ref to POA interface.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + PortableServer::POAManager_var poa_manager + = root_poa->the_POAManager(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Create the child POA. + CORBA::PolicyList policies(1); + policies.length(1); + + policies[0] = root_poa->create_id_assignment_policy(PortableServer::USER_ID + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + PortableServer::POA_var child_poa_1 = root_poa->create_POA("ChildPoa_1", + poa_manager.in(), + policies + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(child_poa_1.in())) + { + ACE_ERROR((LM_ERROR, "(%P|%t) ERROR [ServerApp::run()]: " + "Failed to create the ChildPoa_1.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + PortableServer::POA_var child_poa_2 = root_poa->create_POA("ChildPoa_2", + poa_manager.in(), + policies + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(child_poa_2.in())) + { + ACE_ERROR((LM_ERROR, "(%P|%t) ERROR [ServerApp::run()]: " + "Failed to create the ChildPoa_2.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + policies[0]->destroy (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Create the thread pool servant dispatching strategy object, and + // hold it in a (local) smart pointer variable. + TAO_Intrusive_Ref_Count_Handle<TAO::CSD::TP_Strategy> csd_tp_strategy = + new TAO::CSD::TP_Strategy(); + + // We need create multiple working threads otherwise it would deadlock + // with the callback test. + csd_tp_strategy->set_num_threads(2); + + // Tell the strategy to apply itself to the child poa. + if (csd_tp_strategy->apply_to(child_poa_1.in() ACE_ENV_ARG_PARAMETER) == false) + { + ACE_ERROR((LM_ERROR, "(%P|%t) ERROR [ServerApp::run()]: " + "Failed to apply custom dispatching strategy to child poa 1.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + ACE_CHECK_RETURN (-1); + + Foo_var foo1 = this->create_foo(child_poa_1.in(), + "foo_applied_strategy" + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + Foo_var foo2 = this->create_foo(child_poa_2.in(), + "foo_not_applied_strategy" + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + Callback_var callback1 + = this->create_callback(child_poa_1.in(), + "callback_applied_strategy" + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + Callback_var callback2 + = this->create_callback(child_poa_2.in(), + "callback_not_applied_strategy" + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Activate the POA Manager + poa_manager->activate(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp is ready. Running the ORB event loop.\n")); + + // Wait for the custom stretegy launch the dispatching threads. + ACE_OS::sleep (2); + + ClientTask client1 (foo1.in (), callback1.in ()); + if (client1.open() != 0) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to open the collocated client1.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + ClientTask client2 (foo2.in (), callback2.in ()); + if (client2.open() != 0) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to open the collocated client2.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + // Run the ORB event loop. + orb_->run(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp ORB has stopped running.\n")); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) Wait for the OrbShutdownTask.\n")); + + TheOrbShutdownTask::instance()->wait (); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) Wait for the collocated client task.\n")); + + client1.wait (); + client2.wait (); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) Stop the CSD strategy.\n")); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp is destroying the Root POA.\n")); + + // Tear-down the root poa and orb_. + root_poa->destroy(1, 1 ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp is destroying the ORB.\n")); + + orb_->destroy(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp has completed running successfully.\n")); + + return 0; +} + + +int +ServerApp::parse_args(int argc, char* argv[]) +{ + this->exe_name_ = argv[0]; + + ACE_Get_Opt get_opts(argc, argv, "s"); + + int c; + + while ((c = get_opts()) != -1) + { + switch (c) + { + case 's': + this->synch_with_server_ = 1; + break; + + case '?': + this->usage_statement(); + return 1; + + default: + this->usage_statement(); + return -1; + } + } + + return 0; +} + + +Foo_ptr +ServerApp::create_foo ( + PortableServer::POA_ptr poa, + const char* servant_name + ACE_ENV_ARG_DECL) +{ + PortableServer::ServantBase_var servant + = new Foo_i(servant_name); + + PortableServer::ObjectId_var id = + PortableServer::string_to_ObjectId(servant_name); + + poa->activate_object_with_id(id.in(), servant.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (Foo::_nil ()); + + CORBA::Object_var obj = poa->id_to_reference(id.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (Foo::_nil ()); + + if (CORBA::is_nil(obj.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to activate servant (%s).\n", + servant_name)); + ACE_THROW_RETURN (TestException(), Foo::_nil ()); + } + + Foo_var foo = Foo::_narrow (obj.in () ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (Foo::_nil ()); + + return foo._retn (); +} + +Callback_ptr +ServerApp::create_callback( + PortableServer::POA_ptr poa, + const char* servant_name + ACE_ENV_ARG_DECL) +{ + PortableServer::ServantBase_var servant + = new Callback_i(); + + PortableServer::ObjectId_var id = + PortableServer::string_to_ObjectId("callback"); + + poa->activate_object_with_id(id.in(), servant.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (Callback::_nil ()); + + CORBA::Object_var obj = poa->id_to_reference(id.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (Callback::_nil ()); + + if (CORBA::is_nil(obj.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to activate servant (%s).\n", + servant_name)); + ACE_THROW_RETURN (TestException(), Callback::_nil ()); + } + + Callback_var callback = Callback::_narrow (obj.in () ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (Callback::_nil ()); + + return callback._retn (); +} + +void +ServerApp::usage_statement() +{ + ACE_ERROR((LM_ERROR, + "Usage: %s [options]\n\n" + "OPTIONS:\n\n" + "\t[-s <synch_with_server>]\n" + "\t[-?]\n\n", + this->exe_name_.c_str())); +} + diff --git a/TAO/examples/CSD_Strategy/ThreadPool4/ServerApp.h b/TAO/examples/CSD_Strategy/ThreadPool4/ServerApp.h new file mode 100644 index 00000000000..0c10f8341d0 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool4/ServerApp.h @@ -0,0 +1,44 @@ +// $Id$ +#ifndef SERVERAPP_H +#define SERVERAPP_H + +#include "FooC.h" +#include "tao/PortableServer/PortableServer.h" +#include "ace/SString.h" + +class ServerApp +{ + public: + + ServerApp(); + ~ServerApp(); + + int run(int argc, char* argv[] ACE_ENV_ARG_DECL); + + + private: + + int parse_args(int argc, char* argv[]); + void usage_statement(); + + Foo_ptr + create_foo( + PortableServer::POA_ptr poa, + const char* servant_name + ACE_ENV_ARG_DECL); + + Callback_ptr + create_callback( + PortableServer::POA_ptr poa, + const char* servant_name + ACE_ENV_ARG_DECL); + + + ACE_CString exe_name_; + + CORBA::ORB_var orb_; + + int synch_with_server_; +}; + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool4/run_test.pl b/TAO/examples/CSD_Strategy/ThreadPool4/run_test.pl new file mode 100755 index 00000000000..1a39bd75ae2 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool4/run_test.pl @@ -0,0 +1,39 @@ +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; + +$synch_with_server_option = ""; + +if ($ARGV[0] eq 'synch_with_server') { + $synch_with_server_option = "-s"; +} +elsif ($ARGV[0] eq '') { + #synch with transport +} +else { + print STDERR "ERROR: invalid parameter $ARGV[0] \n"; + exit 1; +} + +$SV = new PerlACE::Process ("server_main", "$synch_with_server_option"); + +$SV->Spawn (); + + +$server = $SV->WaitKill (60); + +if ($server != 0) { + print STDERR "ERROR: server returned $server\n"; + $status = 1; +} + + +exit $status; diff --git a/TAO/examples/CSD_Strategy/ThreadPool4/server_main.cpp b/TAO/examples/CSD_Strategy/ThreadPool4/server_main.cpp new file mode 100644 index 00000000000..d0884b4aeb4 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool4/server_main.cpp @@ -0,0 +1,43 @@ +// $Id$ +#include "ServerApp.h" +#include "ace/Log_Msg.h" +#include "tao/Exception.h" + + +int +main(int argc, char* argv[]) +{ + ACE_LOG_MSG->priority_mask(LM_TRACE | + LM_DEBUG | + LM_INFO | + LM_NOTICE | + LM_WARNING | + LM_ERROR | + LM_CRITICAL | + LM_ALERT | + LM_EMERGENCY, + ACE_Log_Msg::PROCESS); + + ServerApp app; + + ACE_TRY_NEW_ENV + { + int ret = app.run(argc,argv ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + return ret == 1 ? 0 : ret; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "Caught exception:"); + } + ACE_CATCHALL + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Unknown (...) exception caught in main() " + "for ServerApp\n")); + } + ACE_ENDTRY; + + return 1; +} diff --git a/TAO/examples/CSD_Strategy/ThreadPool5/CSD_Test_ThreadPool5.mpc b/TAO/examples/CSD_Strategy/ThreadPool5/CSD_Test_ThreadPool5.mpc new file mode 100644 index 00000000000..a5c323adc01 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool5/CSD_Test_ThreadPool5.mpc @@ -0,0 +1,36 @@ +// -*- MPC -*- +// $Id$ + +project(*Server): csd_threadpool, taoexe, portableserver { + exename = server_main + + Source_Files { + server_main.cpp + Foo_i.cpp + FooC.cpp + FooS.cpp + Callback_i.cpp + CallbackC.cpp + CallbackS.cpp + ServerApp.cpp + ClientTask.cpp + FooServantList.cpp + OrbTask.cpp + OrbShutdownTask.cpp + } +} + +project(*Client): csd_threadpool, taoexe, portableserver { + exename = client_main + + Source_Files { + client_main.cpp + Callback_i.cpp + CallbackC.cpp + CallbackS.cpp + FooC.cpp + ClientTask.cpp + ClientApp.cpp + } +} + diff --git a/TAO/examples/CSD_Strategy/ThreadPool5/Callback.idl b/TAO/examples/CSD_Strategy/ThreadPool5/Callback.idl new file mode 100644 index 00000000000..49be42260cb --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool5/Callback.idl @@ -0,0 +1,11 @@ +// $Id$ +#ifndef CALLBACK_IDL +#define CALLBACK_IDL + +interface Callback +{ + void test_method(); +}; + + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool5/Callback_i.cpp b/TAO/examples/CSD_Strategy/ThreadPool5/Callback_i.cpp new file mode 100644 index 00000000000..c243461dcaa --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool5/Callback_i.cpp @@ -0,0 +1,26 @@ +// $Id$ +#include "Callback_i.h" + + +Callback_i::Callback_i() +{ +} + + +Callback_i::~Callback_i () +{ +} + + +void +Callback_i::test_method ( + ACE_ENV_SINGLE_ARG_DECL_NOT_USED +) +ACE_THROW_SPEC (( + CORBA::SystemException +)) +{ + ACE_DEBUG((LM_DEBUG, "(%P|%t)Callback_i::test_method called \n")); + +} + diff --git a/TAO/examples/CSD_Strategy/ThreadPool5/Callback_i.h b/TAO/examples/CSD_Strategy/ThreadPool5/Callback_i.h new file mode 100644 index 00000000000..0837c30df81 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool5/Callback_i.h @@ -0,0 +1,26 @@ +// $Id$ +#ifndef CALLBACK_I_H +#define CALLBACK_I_H + +#include "CallbackS.h" + + +class Callback_i : public virtual POA_Callback, + public virtual PortableServer::RefCountServantBase +{ + public: + + Callback_i(); + + virtual ~Callback_i(); + + virtual void test_method ( + ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + CORBA::SystemException + )); +}; + + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool5/ClientApp.cpp b/TAO/examples/CSD_Strategy/ThreadPool5/ClientApp.cpp new file mode 100644 index 00000000000..02db9e8a2f2 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool5/ClientApp.cpp @@ -0,0 +1,226 @@ +// $Id$ +#include "ClientApp.h" +#include "Callback_i.h" +#include "ClientTask.h" +#include "tao/CSD_ThreadPool/CSD_TP_Strategy.h" +#include "tao/Intrusive_Ref_Count_Handle_T.h" +#include "ace/Get_Opt.h" +#include "ace/Log_Msg.h" + + +ClientApp::ClientApp() +{ +} + + +ClientApp::~ClientApp() +{ +} + + +int +ClientApp::run(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + CORBA::ORB_var orb + = CORBA::ORB_init(argc, argv, "" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Parse the command-line args for this application. + // * Raises -1 if problems are encountered. + // * Returns 1 if the usage statement was explicitly requested. + // * Returns 0 otherwise. + int result = this->parse_args(argc, argv); + if (result != 0) + { + return result; + } + + CORBA::Object_var obj + = orb->string_to_object(this->ior_.c_str() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(obj.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to convert IOR string to obj ref.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + Foo_var foo = Foo::_narrow(obj.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(foo.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to narrow obj ref to Foo interface.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + // Create the callback object using the child poa with the custom + // strategy. + obj = orb->resolve_initial_references("RootPOA" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(obj.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to resolve initial ref for 'RootPOA'.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + PortableServer::POA_var root_poa + = PortableServer::POA::_narrow(obj.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(root_poa.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to narrow obj ref to POA interface.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + PortableServer::POAManager_var poa_manager + = root_poa->the_POAManager(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Create the child POA. + CORBA::PolicyList policies(0); + policies.length(0); + + PortableServer::POA_var child_poa + = root_poa->create_POA("ChildPoa", + poa_manager.in(), + policies + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(child_poa.in())) + { + ACE_ERROR((LM_ERROR, "(%P|%t) ERROR [ServerApp::run()]: " + "Failed to create the child POA.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + // Create the thread pool servant dispatching strategy object, and + // hold it in a (local) smart pointer variable. + TAO_Intrusive_Ref_Count_Handle<TAO::CSD::TP_Strategy> csd_tp_strategy = + new TAO::CSD::TP_Strategy(); + + csd_tp_strategy->set_num_threads(1); + + // Tell the strategy to apply itself to the child poa. + if (csd_tp_strategy->apply_to(child_poa.in() ACE_ENV_ARG_PARAMETER) == false) + { + ACE_ERROR((LM_ERROR, "(%P|%t) ERROR [ServerApp::run()]: " + "Failed to apply custom dispatching strategy to child poa.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + ACE_CHECK_RETURN (-1); + + // Create the servant object. + Callback_i* servant = new Callback_i (); + + // local smart pointer variable to deal with releasing the reference + // to the servant object when the smart pointer object falls out of scope. + PortableServer::ServantBase_var owner_transfer(servant); + + // Activate the servant using the Child POA. + PortableServer::ObjectId_var oid + = child_poa->activate_object(servant + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Obtain the object reference. + obj = child_poa->servant_to_reference(servant ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(obj.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to activate servant (Callback_i).\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + Callback_var callback = Callback::_narrow (obj.in () ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ClientTask client_task(orb.in (), foo.in (), callback.in ()); + + if (client_task.open () != 0) + { + ACE_THROW_RETURN (TestException(), -1); + } + + // Activate the POA Manager + poa_manager->activate(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ClientApp is ready.\n")); + + orb->run(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + client_task.wait (); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ClientApp is destroying the Root POA.\n")); + + // Tear-down the root poa and orb. + root_poa->destroy(1, 1 ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ClientApp is destroying the ORB.\n")); + + orb->destroy(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ClientApp has completed running successfully.\n")); + + return 0; +} + + +int +ClientApp::parse_args(int argc, char* argv[]) +{ + this->exe_name_ = argv[0]; + + ACE_Get_Opt get_opts(argc, argv, "i:"); + + int c; + + while ((c = get_opts()) != -1) + { + switch (c) + { + case 'i': + this->ior_ = get_opts.opt_arg(); + break; + + case '?': + this->usage_statement(); + return 1; + default: + this->usage_statement(); + return -1; + } + } + + return 0; +} + + +void +ClientApp::usage_statement() +{ + ACE_ERROR((LM_ERROR, + "Usage: %s [options]\n\n" + "OPTIONS:\n\n" + "\t[-i <ior>]\n" + "\t[-?]\n\n", + this->exe_name_.c_str())); +} + diff --git a/TAO/examples/CSD_Strategy/ThreadPool5/ClientApp.h b/TAO/examples/CSD_Strategy/ThreadPool5/ClientApp.h new file mode 100644 index 00000000000..4bb06ef0cac --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool5/ClientApp.h @@ -0,0 +1,31 @@ +// $Id$ +#ifndef CLIENTAPP_H +#define CLIENTAPP_H + +#include "ace/SString.h" +#include "ace/CORBA_macros.h" +#include "tao/Environment.h" + +class ClientTask; + +class ClientApp +{ + public: + + ClientApp(); + ~ClientApp(); + + int run(int argc, char* argv[] ACE_ENV_ARG_DECL); + + + private: + + int parse_args(int argc, char* argv[]); + void usage_statement(); + + ACE_CString ior_; + + ACE_CString exe_name_; +}; + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool5/ClientTask.cpp b/TAO/examples/CSD_Strategy/ThreadPool5/ClientTask.cpp new file mode 100644 index 00000000000..db9ed7c43f1 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool5/ClientTask.cpp @@ -0,0 +1,263 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file ClientTask.cpp + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#include "ClientTask.h" +#include "ace/SString.h" +#include "ace/OS.h" + + +ClientTask::ClientTask(CORBA::ORB_ptr orb, + Foo_ptr foo, + Callback_ptr callback, + bool collocated) +: orb_ (CORBA::ORB::_duplicate (orb)), + foo_(Foo::_duplicate(foo)), + callback_(Callback::_duplicate(callback)), + collocated_ (collocated) +{ +} + + +ClientTask::~ClientTask() +{ +} + + +int +ClientTask::open(void*) +{ + if (this->activate(THR_NEW_LWP | THR_JOINABLE, 1) != 0) + { + // Assumes that when activate returns non-zero return code that + // no threads were activated. + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) ClientTask failed to activate " + "the client thread.\n"), + -1); + } + + return 0; +} + + +int +ClientTask::svc() +{ + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ClientTask::svc start\n")); + + ACE_TRY_NEW_ENV + { + // Make sure the connection is established before making + // remote invocations. + if (this->validate_connection () == false) + { + ACE_ERROR((LM_ERROR, "(%P|%t)ClientTask::svc " \ + "client connect failed.\n")); + return -1; + } + + for (CORBA::Long i = 1; i <= 100; i++) + { + // Simple Two-way calls. + this->foo_->op1(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + this->foo_->op2(i ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + CORBA::Long value = this->foo_->op3(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ===> Value retrieved from op3() == %d\n", + value)); + + for (CORBA::ULong j = 1; j <= 5; j++) + { + this->foo_->op4(495 + (i * 5) + j ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + + ACE_TRY_EX (op5) + { + ACE_DEBUG((LM_DEBUG, "(%P|%t) ===> Invoke op5()\n")); + this->foo_->op5(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK_EX (op5); + ACE_DEBUG((LM_DEBUG, "(%P|%t) ===> No exception raised from op5(). :-(\n")); + } + ACE_CATCH (FooException, ex) + { + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ===> Caught FooException - as expected.\n")); + + } + ACE_ENDTRY; + + // Two-Way calls with inout parameters. + CORBA::String_var message = CORBA::string_dup( "Hello! " ); + CORBA::Boolean result + = this->foo_->op6( "TAO User", message.inout() ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (result) + { + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ===> Message from op6() == %s\n", + message.in ())); + } + else + { + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ===> op6() returned false.\n")); + } + + // Callback test. + this->foo_->callback_object (this->callback_.in () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + this->foo_->test_callback (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + // One-Way calls with various arguments. + CORBA::String_var ub_string = CORBA::string_dup( "UNBOUNDED STRING" ); + this->foo_->test_unbounded_string_arg (ub_string.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + CORBA::String_var bd_string = CORBA::string_dup( "BOUNDED STRING" ); + this->foo_->test_bounded_string_arg (bd_string.in () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + Fixed_Array fixed_array; + + for (CORBA::ULong m = 0; m < 20; m ++) + { + fixed_array[m] = i + m; + } + + this->foo_->test_fixed_array_arg (fixed_array ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + Var_Array var_array; + var_array[0] = CORBA::string_dup( "STRING 1" ); + var_array[1] = CORBA::string_dup( "STRING 2" ); + var_array[2] = CORBA::string_dup( "STRING 3" ); + this->foo_->test_var_array_arg (var_array ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + Bounded_Var_Size_var bd_var_size_string = new Bounded_Var_Size(); + const char* buffer1 = "BOUNDED VAR SIZE CHAR"; + bd_var_size_string->replace (bd_var_size_string->maximum (), + ACE_OS::strlen (buffer1) + 1, + (CORBA::Char*)buffer1); + this->foo_->test_bounded_var_size_arg (bd_var_size_string.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + const char* buffer2 = "UNBOUNDED VAR SIZE CHAR"; + Unbounded_Var_Size_var ub_var_size_string = new Unbounded_Var_Size(100); + ub_var_size_string->replace (ub_var_size_string->maximum (), + ACE_OS::strlen (buffer2) + 1, + (CORBA::Char*)buffer2); + this->foo_->test_unbounded_var_size_arg (ub_var_size_string.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + TimeOfDay t; + t.hour = 12; + t.minute = 30; + t.second = 10; + this->foo_->test_fixed_size_arg (t ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + this->foo_->test_fixed_size_arg_two_way (t ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + CORBA::Boolean special_value = 1; + this->foo_->test_special_basic_arg (special_value ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + this->foo_->test_objref_arg (this->callback_.in () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ClientTask::svc - Invoke foo->done()\n")); + + this->foo_->done (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ClientTask::svc - Back from foo->done()\n")); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "Caught exception in ClientTask::svc:"); + } + ACE_CATCHALL + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Unknown (...) exception caught in ClientTask::svc()\n")); + } + ACE_ENDTRY; + + if (! collocated_) + { + ACE_OS::sleep (2); + this->orb_->shutdown(0); + } + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ClientTask::svc end\n")); + + return 0; +} + + +int +ClientTask::close(u_long) +{ + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ClientTask::close() - enter/exit\n")); + return 0; +} + + +bool +ClientTask::validate_connection () +{ + for (CORBA::ULong j = 0; j != 1000; ++j) + { + ACE_TRY_NEW_ENV + { +#if (TAO_HAS_CORBA_MESSAGING == 1) + CORBA::PolicyList_var unused; + this->foo_->_validate_connection (unused + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; +#else + this->foo_->_is_a ("Not_An_IDL_Type" + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; +#endif /* TAO_HAS_MESSAGING == 1 */ + return true; + } + ACE_CATCHANY + { + } + ACE_ENDTRY; + } + + return false; +} diff --git a/TAO/examples/CSD_Strategy/ThreadPool5/ClientTask.h b/TAO/examples/CSD_Strategy/ThreadPool5/ClientTask.h new file mode 100644 index 00000000000..aec109d9ed6 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool5/ClientTask.h @@ -0,0 +1,44 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file ClientTask.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef CLIENT_TASK_H +#define CLIENT_TASK_H + +#include "FooC.h" +#include "CallbackC.h" +#include "ace/Task.h" + +class ClientTask : public ACE_Task_Base +{ + public: + + ClientTask(CORBA::ORB_ptr orb, + Foo_ptr foo, + Callback_ptr callback, + bool collocated = false); + + virtual ~ClientTask(); + + virtual int open(void* x = 0); + virtual int svc(); + virtual int close(u_long); + + private: + bool validate_connection (); + + CORBA::ORB_var orb_; + Foo_var foo_; + Callback_var callback_; + bool collocated_; +}; + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool5/Foo.idl b/TAO/examples/CSD_Strategy/ThreadPool5/Foo.idl new file mode 100644 index 00000000000..ad4f1cc77cb --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool5/Foo.idl @@ -0,0 +1,73 @@ +// $Id$ +#ifndef FOO_IDL +#define FOO_IDL + +#include "Callback.idl" + +exception FooException {}; +exception TestException {}; + +typedef sequence<char, 32> Bounded_Var_Size; +typedef sequence<char> Unbounded_Var_Size; +typedef long Fixed_Array[20]; +typedef string Var_Array [3]; + +struct TimeOfDay { + short hour; // 0 - 23 + short minute; // 0 - 59 + short second; // 0 - 59 +}; +interface Foo +{ + /// void return-type, no arguments + void op1(); + + /// void return-type, 1 "in" argument + void op2(in long value); + + /// long return-type, no arguments + long op3(); + + /// one-way version of op2 + oneway void op4(in long value); + + /// Operation that always raises an exception. + void op5() raises (FooException); + + /// Operation with the inout parameter. + boolean op6(in string user_name, + inout string message); + + oneway void test_unbounded_string_arg(in string message); + + oneway void test_bounded_string_arg(in string<20> message); + + oneway void test_fixed_array_arg(in Fixed_Array message); + + oneway void test_var_array_arg(in Var_Array messages); + + oneway void test_bounded_var_size_arg(in Bounded_Var_Size message); + + oneway void test_unbounded_var_size_arg(in Unbounded_Var_Size message); + + oneway void test_fixed_size_arg (in TimeOfDay t); + + oneway void test_special_basic_arg(in boolean value); + + oneway void test_objref_arg (in Callback cb); + + void test_fixed_size_arg_two_way (in TimeOfDay t); + + /// Operation with the object reference parameter. + void callback_object (in Callback cb); + + /// Operation that invoke remote operation on + // callback object. + void test_callback (); + + /// Client calls this last. It will shutdown the server. + void done(); +}; + + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool5/FooServantList.cpp b/TAO/examples/CSD_Strategy/ThreadPool5/FooServantList.cpp new file mode 100644 index 00000000000..4f2bddc3ab8 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool5/FooServantList.cpp @@ -0,0 +1,226 @@ +// $Id$ +#include "FooServantList.h" +#include "Foo_i.h" +#include "Callback_i.h" +#include "ClientTask.h" +#include "OrbShutdownTask.h" +#include "ace/OS.h" + + +FooServantList::FooServantList(const char* prefix, + unsigned num_servants, + unsigned num_clients, + int collocated_test, + int servant_to_deactivate, + CORBA::ORB_ptr orb) + : prefix_(prefix), + num_servants_(num_servants), + num_clients_(num_clients), + init_num_clients_ (num_clients_), + collocated_test_(collocated_test), + servant_to_deactivate_ (servant_to_deactivate), + collocated_client_ (0), + orb_ (CORBA::ORB::_duplicate(orb)) +{ + this->servants_ = new Foo_i* [num_servants]; + this->safe_servants_ = new PortableServer::ServantBase_var[num_servants]; +} + + +FooServantList::~FooServantList() +{ + delete [] this->safe_servants_; + delete [] this->servants_; + delete collocated_client_; +} + + +void +FooServantList::create_and_activate(CORBA::ORB_ptr orb, + PortableServer::POA_ptr poa + ACE_ENV_ARG_DECL) +{ + poa_ = PortableServer::POA::_duplicate (poa); + + for (unsigned i = 0; i < this->num_servants_; i++) + { + char buf[32]; + ACE_OS::sprintf(buf, "%02d", i + 1); + ACE_CString servant_name = this->prefix_ + "_" + buf; + + this->servants_[i] = new Foo_i(servant_name.c_str(),this); + this->safe_servants_[i] = this->servants_[i]; + + PortableServer::ObjectId_var id = + PortableServer::string_to_ObjectId(servant_name.c_str()); + + poa->activate_object_with_id(id.in(), + this->safe_servants_[i].in() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + CORBA::Object_var obj = poa->id_to_reference(id.in() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + if (CORBA::is_nil(obj.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to activate servant (%s).\n", + servant_name.c_str())); + ACE_THROW (TestException()); + } + + // create the collocated object reference. + if (this->collocated_test_ && i == 0) + { + Foo_var collocated = Foo::_narrow (obj.in () ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + // Create the servant object. + Callback_i* servant = new Callback_i (); + + // local smart pointer variable to deal with releasing the reference + // to the servant object when the smart pointer object falls out of scope. + PortableServer::ServantBase_var safe_servant(servant); + + PortableServer::ObjectId_var id = + PortableServer::string_to_ObjectId("callback"); + + poa->activate_object_with_id(id.in(), safe_servant.in()); + + CORBA::Object_var obj = poa->id_to_reference(id.in() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + if (CORBA::is_nil(obj.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to activate servant (%s).\n", + servant_name.c_str())); + ACE_THROW (TestException()); + } + + Callback_var callback + = Callback::_narrow (obj.in () ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + collocated_client_ + = new ClientTask(orb, collocated.in (), callback.in (), true); + if (collocated_client_->open() != 0) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to open the collocated client.\n")); + ACE_THROW (TestException()); + } + } + + CORBA::String_var ior + = this->orb_->object_to_string(obj.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + ACE_CString filename = servant_name + ".ior"; + FILE* ior_file = ACE_OS::fopen(filename.c_str(), "w"); + + if (ior_file == 0) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Cannot open output file (%s) for writing IOR.", + filename.c_str())); + ACE_THROW (TestException()); + } + else + { + ACE_DEBUG((LM_DEBUG, + "(%P|%t) writing IOR to file %s\n", + filename.c_str())); + } + ACE_OS::fprintf(ior_file, "%s", ior.in()); + ACE_OS::fclose(ior_file); + } +} + + +void +FooServantList::client_done(ACE_ENV_SINGLE_ARG_DECL) +{ + unsigned num_left; + + { + GuardType guard(this->num_clients_lock_); + num_left = --this->num_clients_; + } + + if (num_left == 0) + { + if (TheOrbShutdownTask::instance()->open(0) != 0) + { + ACE_ERROR((LM_ERROR, "(%P|%t)FooServantList::client_done: " + "failed to create orb shutdown thread.\n")); + } + } +} + + +ClientTask* +FooServantList::collocated_client () const +{ + return collocated_client_; +} + + +void +FooServantList::deactivate_servant (ACE_ENV_SINGLE_ARG_DECL) +{ + for (unsigned i = 0; i < this->num_servants_; i++) + { + // To eliminate compiler warning about comparison of signed vs unsigned. + int signed_i = i; + + if ((servant_to_deactivate_ == 0 ) || + ((servant_to_deactivate_ > 0) && + (signed_i == servant_to_deactivate_ - 1))) + { + if (servants_[i]->active()) + { + servants_[i]->active(false); + ACE_DEBUG((LM_DEBUG, "(%P|%t)FooServantList::deactivate_servant " + "deactivate %dth servant \n", i+1)); + + PortableServer::ObjectId_var id = + poa_->servant_to_id (safe_servants_[i].in () + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + poa_->deactivate_object (id.in () ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + if (this->num_servants_ == 1) + { + // If there is only one servant and we deactivate it then + // all clients will catch exception and we need a way to + // shutdown the orb. + // Wait for 5 seconds so we can see the requests queued + // will be cancelled by deactivate servant. + ACE_OS::sleep (5); + ACE_DEBUG((LM_DEBUG, "(%P|%t)shutdown ORB\n")); + if (TheOrbShutdownTask::instance()->open(0) != 0) + { + ACE_ERROR((LM_ERROR, "(%P|%t)FooServantList::deactivate_servant: " + "failed to create orb shutdown thread.\n")); + } + } + else + { + GuardType guard(this->num_clients_lock_); + // The clients that requests this deactivated servant + // will catch exception due to the deactivated servant. + // We need descrease the num_clients so the alived + // servant can be called to shutdown the orb. + this->num_clients_ -= this->init_num_clients_/num_servants_; + } + } + } + } +} + diff --git a/TAO/examples/CSD_Strategy/ThreadPool5/FooServantList.h b/TAO/examples/CSD_Strategy/ThreadPool5/FooServantList.h new file mode 100644 index 00000000000..fb40809e62e --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool5/FooServantList.h @@ -0,0 +1,63 @@ +// $Id$ +#ifndef FOOSERVANTLIST_H +#define FOOSERVANTLIST_H + +#include "tao/PortableServer/PortableServer.h" +#include "tao/PortableServer/Servant_Base.h" +#include "ace/SString.h" + + +class ClientTask; +class Foo_i; + +class FooServantList +{ + public: + + FooServantList(const char* prefix, + unsigned num_servants, + unsigned num_clients, + int collocated_test, + int servant_to_deactivate, + CORBA::ORB_ptr orb); + ~FooServantList(); + + void create_and_activate(CORBA::ORB_ptr orb, + PortableServer::POA_ptr poa + ACE_ENV_ARG_DECL); + + void client_done(ACE_ENV_SINGLE_ARG_DECL); + + ClientTask* collocated_client () const; + + void deactivate_servant (ACE_ENV_SINGLE_ARG_DECL); + + private: + + typedef ACE_SYNCH_MUTEX LockType; + typedef ACE_Guard<LockType> GuardType; + + Foo_i** servants_; + PortableServer::ServantBase_var* safe_servants_; + ACE_CString prefix_; + unsigned num_servants_; + + LockType num_clients_lock_; + unsigned num_clients_; + unsigned init_num_clients_; + int collocated_test_; + // The servant_to_be_deactivate_ should be an integer greater than -2. + // -1 => defatult value, DONT deactivate servant. + // 0 => deactivate all servants. + // > 0 => the index of the servant to be deactivated. + int servant_to_deactivate_; + + ClientTask* collocated_client_; + + /// The poa to activate and deactivate servant. + PortableServer::POA_var poa_; + + CORBA::ORB_var orb_; +}; + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool5/Foo_i.cpp b/TAO/examples/CSD_Strategy/ThreadPool5/Foo_i.cpp new file mode 100644 index 00000000000..073c0d85283 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool5/Foo_i.cpp @@ -0,0 +1,312 @@ +// $Id$ +#include "Foo_i.h" +#include "FooServantList.h" +#include "ace/OS.h" + +Foo_i::Foo_i(const char* servant_name,FooServantList* mgr) + : value_(0), + count_op1_(0), + count_op2_(0), + count_op3_(0), + count_op4_(0), + count_op5_(0), + servant_name_(servant_name), + mgr_(mgr), + active_ (true) +{ +} + + +Foo_i::~Foo_i() +{ +} + + +void +Foo_i::op1(ACE_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + ++this->count_op1_; + // Sleep for 10 milliseconds (10,000 microseconds) + //ACE_OS::sleep(ACE_Time_Value(0,10000)); +} + + +void +Foo_i::op2(CORBA::Long value ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + ++this->count_op2_; + this->value_ = value; +} + + +CORBA::Long +Foo_i::op3(ACE_ENV_SINGLE_ARG_DECL) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + ++this->count_op3_; + + if (this->count_op3_ == 30) + { + this->mgr_->deactivate_servant (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (0); + } + + return this->value_.value (); +} + + +void +Foo_i::op4(CORBA::Long value ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + ++this->count_op4_; + this->value_ = value; + + if (this->count_op4_.value () % 1 == 0) + { + ACE_DEBUG((LM_DEBUG, + "(%P|%t) op4() has been called %d times now. value == %d\n", + this->count_op4_.value (), this->value_.value ())); + } + + // Sleep for 10 milliseconds (10,000 microseconds) + //ACE_OS::sleep(ACE_Time_Value(0,10000)); +} + + +void +Foo_i::op5(ACE_ENV_SINGLE_ARG_DECL) + ACE_THROW_SPEC((CORBA::SystemException, FooException)) +{ + ++this->count_op5_; + ACE_THROW (FooException()); +} + + +CORBA::Boolean +Foo_i::op6 ( + const char * user_name, + char *& message + ACE_ENV_ARG_DECL_NOT_USED +) +ACE_THROW_SPEC (( + CORBA::SystemException +)) +{ + ACE_CString str(message); + str += user_name; + message = CORBA::string_dup (str.c_str ()); + return 1; +} + + +void +Foo_i::test_unbounded_string_arg ( + const char * message + ACE_ENV_ARG_DECL_NOT_USED +) +ACE_THROW_SPEC (( +CORBA::SystemException +)) +{ + ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_i::test_unbounded_string_arg ") + ACE_TEXT("got unbounded string %s\n"), + message)); +} + + +void +Foo_i::test_bounded_string_arg ( + const char * message + ACE_ENV_ARG_DECL_NOT_USED +) +ACE_THROW_SPEC (( +CORBA::SystemException +)) +{ + ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_i::test_bounded_string_arg ") + ACE_TEXT("got bounded string %s\n"), + message)); +} + + +void +Foo_i::test_fixed_array_arg ( + const ::Fixed_Array message + ACE_ENV_ARG_DECL_NOT_USED +) +ACE_THROW_SPEC (( + CORBA::SystemException +)) +{ + for (CORBA::ULong i = 0; i < 20; i++) + { + ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_i::test_fixed_array_arg ") + ACE_TEXT("got fixed_array[i] = %d\n"), + i, message[i])); + } +} + + +void +Foo_i::test_bounded_var_size_arg ( + const ::Bounded_Var_Size & message + ACE_ENV_ARG_DECL_NOT_USED +) +ACE_THROW_SPEC (( + CORBA::SystemException +)) +{ + ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_i::test_bounded_var_size_arg ") + ACE_TEXT("got var array chars %s\n"), + message.get_buffer ())); +} + + +void +Foo_i::test_unbounded_var_size_arg ( + const ::Unbounded_Var_Size & message + ACE_ENV_ARG_DECL_NOT_USED +) +ACE_THROW_SPEC (( + CORBA::SystemException +)) +{ + ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_i::test_unbounded_var_size_arg ") + ACE_TEXT("got var array chars %s\n"), + message.get_buffer ())); +} + + +void +Foo_i::test_fixed_size_arg ( + const ::TimeOfDay & t + ACE_ENV_ARG_DECL_NOT_USED +) +ACE_THROW_SPEC (( + CORBA::SystemException +)) +{ + ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_i::test_fixed_size_arg ") + ACE_TEXT("got timeofday %d:%d:%d\n"), + t.hour, t.minute, t.second)); +} + +void +Foo_i::test_fixed_size_arg_two_way ( + const ::TimeOfDay & t + ACE_ENV_ARG_DECL_NOT_USED +) +ACE_THROW_SPEC (( + CORBA::SystemException +)) +{ + ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_i::test_fixed_size_arg_two_way ") + ACE_TEXT("got timeofday %d:%d:%d\n"), + t.hour, t.minute, t.second)); +} + +void +Foo_i::test_var_array_arg ( + const ::Var_Array messages + ACE_ENV_ARG_DECL_NOT_USED +) +ACE_THROW_SPEC (( + CORBA::SystemException +)) +{ + ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_i::test_var_array_arg ") + ACE_TEXT(" %s \n"), messages[0].in ())); + ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_i::test_var_array_arg ") + ACE_TEXT(" %s \n"), messages[1].in ())); + ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_i::test_var_array_arg ") + ACE_TEXT(" %s \n"), messages[2].in ())); +} + + +void +Foo_i::test_special_basic_arg ( + ::CORBA::Boolean value + ACE_ENV_ARG_DECL_NOT_USED +) +ACE_THROW_SPEC (( + CORBA::SystemException +)) +{ + ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_i::test_special_basic_arg ") + ACE_TEXT(" got special basic arg: %d \n"), value)); +} + + +void +Foo_i::test_objref_arg ( + ::Callback_ptr cb + ACE_ENV_ARG_DECL_NOT_USED +) +ACE_THROW_SPEC (( + CORBA::SystemException +)) +{ + this->callback_ = Callback::_duplicate (cb); + ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_i::test_objref_arg ") + ACE_TEXT(" got callback object. \n"))); +} + + +void +Foo_i::callback_object ( + ::Callback_ptr cb + ACE_ENV_ARG_DECL_NOT_USED +) +ACE_THROW_SPEC (( + CORBA::SystemException +)) +{ + this->callback_ = Callback::_duplicate (cb); +} + +void +Foo_i::test_callback ( + ACE_ENV_SINGLE_ARG_DECL +) +ACE_THROW_SPEC (( + CORBA::SystemException +)) +{ + if (CORBA::is_nil (this->callback_.in ())) + { + ACE_THROW_SPEC (TestException ()); + } + else + { + this->callback_->test_method (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + } +} + + +void +Foo_i::done(ACE_ENV_SINGLE_ARG_DECL) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + this->mgr_->client_done(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; +} + + +void +Foo_i::active (bool flag) +{ + active_ = flag; +} + + +bool +Foo_i::active () +{ + return active_.value (); +} + + diff --git a/TAO/examples/CSD_Strategy/ThreadPool5/Foo_i.h b/TAO/examples/CSD_Strategy/ThreadPool5/Foo_i.h new file mode 100644 index 00000000000..f28d9aeeacc --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool5/Foo_i.h @@ -0,0 +1,166 @@ +// $Id$ +#ifndef FOO_I_H +#define FOO_I_H + +#include "FooS.h" +#include "CallbackC.h" +#include "ace/SString.h" + +class FooServantList; + + +class Foo_i : public virtual POA_Foo, + public virtual PortableServer::RefCountServantBase +{ + public: + + Foo_i(const char* servant_name, FooServantList* mgr); + virtual ~Foo_i(); + + virtual void op1(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void op2(CORBA::Long value ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual CORBA::Long op3(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void op4(CORBA::Long value ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void op5(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException, FooException)); + + virtual CORBA::Boolean op6 ( + const char * user_name, + char *& message + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + CORBA::SystemException + )); + + virtual void test_unbounded_string_arg ( + const char * message + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + CORBA::SystemException + )); + + virtual void test_bounded_string_arg ( + const char * message + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + CORBA::SystemException + )); + + virtual void test_fixed_array_arg ( + const ::Fixed_Array message + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + CORBA::SystemException + )); + + virtual void test_var_array_arg ( + const ::Var_Array messages + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + CORBA::SystemException + )); + + virtual void test_bounded_var_size_arg ( + const ::Bounded_Var_Size & message + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + CORBA::SystemException + )); + + virtual void test_unbounded_var_size_arg ( + const ::Unbounded_Var_Size & message + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + CORBA::SystemException + )); + + virtual void test_fixed_size_arg ( + const ::TimeOfDay & t + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + CORBA::SystemException + )); + + virtual void test_fixed_size_arg_two_way ( + const ::TimeOfDay & t + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + CORBA::SystemException + )); + + virtual void test_special_basic_arg ( + ::CORBA::Boolean value + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + CORBA::SystemException + )); + + virtual void test_objref_arg ( + ::Callback_ptr cb + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + CORBA::SystemException + )); + + virtual void callback_object ( + ::Callback_ptr cb + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + CORBA::SystemException + )); + + virtual void test_callback ( + ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + CORBA::SystemException + )); + + virtual void done(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + void active (bool flag); + + bool active (); + + private: + + typedef ACE_Atomic_Op <ACE_SYNCH_MUTEX, CORBA::Long> AtomicLong; + typedef ACE_Atomic_Op <ACE_SYNCH_MUTEX, unsigned> AtomicUnsigned; + typedef ACE_Atomic_Op <ACE_SYNCH_MUTEX, bool> AtomicBool; + + AtomicLong value_; + AtomicUnsigned count_op1_; + AtomicUnsigned count_op2_; + AtomicUnsigned count_op3_; + AtomicUnsigned count_op4_; + AtomicUnsigned count_op5_; + + ACE_CString servant_name_; + FooServantList* mgr_; + AtomicBool active_; + Callback_var callback_; +}; + + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool5/OrbShutdownTask.cpp b/TAO/examples/CSD_Strategy/ThreadPool5/OrbShutdownTask.cpp new file mode 100644 index 00000000000..f9d551e8aee --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool5/OrbShutdownTask.cpp @@ -0,0 +1,77 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file OrbShutdownTask.cpp + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#include "OrbShutdownTask.h" +#include "ace/CORBA_macros.h" +#include "ace/OS_NS_unistd.h" + + +OrbShutdownTask::OrbShutdownTask() +{ +} + + +OrbShutdownTask::~OrbShutdownTask() +{ +} + + +void +OrbShutdownTask::orb(CORBA::ORB_ptr orb) +{ + this->orb_ = CORBA::ORB::_duplicate (orb); +} + + +int +OrbShutdownTask::open(void*) +{ + if (this->activate(THR_NEW_LWP | THR_JOINABLE, 1) != 0) + { + // Assumes that when activate returns non-zero return code that + // no threads were activated. + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) OrbShutdownTask failed to open().\n"), + -1); + } + + return 0; +} + + +int +OrbShutdownTask::svc() +{ + ACE_OS::sleep (2); + ACE_DEBUG ((LM_DEBUG, "(%P|%t)OrbShutdownTask::svc shutdown orb \n")); + ACE_TRY_NEW_ENV + { + this->orb_->shutdown(0 ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHALL + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Exception raised by ORB::shutdown() call " + "in OrbShutdownTask::svc().\n")); + } + ACE_ENDTRY; + + return 0; +} + + +int +OrbShutdownTask::close(u_long) +{ + return 0; +} diff --git a/TAO/examples/CSD_Strategy/ThreadPool5/OrbShutdownTask.h b/TAO/examples/CSD_Strategy/ThreadPool5/OrbShutdownTask.h new file mode 100644 index 00000000000..3795d12c3c9 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool5/OrbShutdownTask.h @@ -0,0 +1,41 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file OrbShutdownTask.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef ORB_SHUTDOWN_TASK_H +#define ORB_SHUTDOWN_TASK_H + +#include "ace/Task.h" +#include "tao/ORB.h" + + +class OrbShutdownTask : public ACE_Task_Base +{ + public: + + OrbShutdownTask(); + virtual ~OrbShutdownTask(); + + void orb(CORBA::ORB_ptr orb); + + virtual int open(void*); + virtual int svc(); + virtual int close(u_long); + + + private: + + CORBA::ORB_var orb_; +}; + +typedef ACE_Singleton<OrbShutdownTask, ACE_Thread_Mutex> TheOrbShutdownTask; + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool5/OrbTask.cpp b/TAO/examples/CSD_Strategy/ThreadPool5/OrbTask.cpp new file mode 100644 index 00000000000..fcfb7c919ac --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool5/OrbTask.cpp @@ -0,0 +1,98 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file OrbTask.cpp + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#include "OrbTask.h" + +namespace { enum { MAX_ORB_TASK_WORKER_THREADS = 20 }; } + + +OrbTask::OrbTask(CORBA::ORB_ptr orb, unsigned num_threads) + : num_threads_(num_threads) +{ + this->orb_ = CORBA::ORB::_duplicate(orb); +} + + +OrbTask::~OrbTask() +{ +} + + +int +OrbTask::open(void*) +{ + if (this->num_threads_ < 1) + { + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) OrbTask failed to open. " + "num_threads_ (%d) is less-than 1.\n", + this->num_threads_), + -1); + } + + if (this->num_threads_ > MAX_ORB_TASK_WORKER_THREADS) + { + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) OrbTask failed to open. " + "num_threads_ (%d) is too large. Max is %d.\n", + this->num_threads_, MAX_ORB_TASK_WORKER_THREADS), + -1); + } + + if (CORBA::is_nil(this->orb_.in())) + { + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) OrbTask failed to open. " + "ORB object reference is nil.\n"), + -1); + } + + if (this->activate(THR_NEW_LWP | THR_JOINABLE, this->num_threads_) != 0) + { + // Assumes that when activate returns non-zero return code that + // no threads were activated. + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) OrbTask failed to activate " + "(%d) worker threads.\n", + this->num_threads_), + -1); + } + + return 0; +} + + +int +OrbTask::svc() +{ + ACE_TRY_NEW_ENV + { + this->orb_->run(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHALL + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Exception raised by ORB::run() method. " + "OrbTask is stopping.\n")); + } + ACE_ENDTRY; + + return 0; +} + + +int +OrbTask::close(u_long) +{ + return 0; +} diff --git a/TAO/examples/CSD_Strategy/ThreadPool5/OrbTask.h b/TAO/examples/CSD_Strategy/ThreadPool5/OrbTask.h new file mode 100644 index 00000000000..dde50d15f66 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool5/OrbTask.h @@ -0,0 +1,37 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file OrbTask.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef ORB_TASK_H +#define ORB_TASK_H + +#include "ace/Task.h" +#include "tao/ORB.h" + +class OrbTask : public ACE_Task_Base +{ + public: + + OrbTask(CORBA::ORB_ptr orb, unsigned num_threads = 1); + virtual ~OrbTask(); + + virtual int open(void* x = 0); + virtual int svc(); + virtual int close(u_long); + + + private: + + CORBA::ORB_var orb_; + unsigned num_threads_; +}; + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool5/README b/TAO/examples/CSD_Strategy/ThreadPool5/README new file mode 100644 index 00000000000..29b72f8a861 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool5/README @@ -0,0 +1,47 @@ +# $Id$ + +Description: + +This test is a combination of other tests and has also added some +other test cases such as cancel_servant. It uses the command +line options for the number of orb threads, number of servants, +collocated test options, etc. + +The client application acts as a server too because of the callback +test. The client application also uses a custom dispatching strategy. + +To run the test use the run_test.pl script: + +$ ./run_test.pl + + This test is similar to the "ThreadPool" test. + +$ ./run_test.pl collocated + + This runs the collocated test. + + The server application creates one servant, runs one orb + thread, runs two custom dispatching threads and one client + thread to invoke the operations. + + Running two custom dispatching threads instead of one is + required to avoid deadlock. + +$ ./run_test.pl multiple_servants + + This test is similar to the "ThreadPool2" test. + +$ ./run_test.pl multiple_orb_threads + + This test is similar to the "ThreadPool3" test. + +$ ./run_test.pl cancel_servant + + This test shows that requests stuck in the request queue are + cancelled when a servant is deactivated. + + The client invokes multiple two-way operations and catches the + OBJECT_NOT_EXIST or NO_IMPLEMENTATION exception after the servant + is deactivated - this is what it is supposed to do - the exceptions + are expected. + diff --git a/TAO/examples/CSD_Strategy/ThreadPool5/ServerApp.cpp b/TAO/examples/CSD_Strategy/ThreadPool5/ServerApp.cpp new file mode 100644 index 00000000000..2e996f83e15 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool5/ServerApp.cpp @@ -0,0 +1,354 @@ +// $Id$ +#include "ServerApp.h" +#include "OrbTask.h" +#include "FooServantList.h" +#include "ClientTask.h" +#include "OrbShutdownTask.h" +#include "ace/Get_Opt.h" +#include "tao/CSD_ThreadPool/CSD_TP_Strategy.h" +#include "tao/Intrusive_Ref_Count_Handle_T.h" + + +ServerApp::ServerApp() + : ior_filename_("foo"), + num_servants_(1), + num_csd_threads_ (1), + num_clients_(1), + num_orb_threads_ (1), + collocated_test_ (0), + servant_to_deactivate_ (-1) +{ +} + + +ServerApp::~ServerApp() +{ +} + + +int +ServerApp::run(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + CORBA::ORB_var orb = CORBA::ORB_init(argc, argv, "" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Parse the command-line args for this application. + // * Raises -1 if problems are encountered. + // * Returns 1 if the usage statement was explicitly requested. + // * Returns 0 otherwise. + int result = this->parse_args(argc, argv); + if (result != 0) + { + return result; + } + + TheOrbShutdownTask::instance()->orb (orb.in ()); + + CORBA::Object_var obj + = orb->resolve_initial_references("RootPOA" + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(obj.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to resolve initial ref for 'RootPOA'.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + PortableServer::POA_var root_poa + = PortableServer::POA::_narrow(obj.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(root_poa.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to narrow obj ref to POA interface.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + PortableServer::POAManager_var poa_manager + = root_poa->the_POAManager(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Create the child POA. + CORBA::PolicyList policies(1); + policies.length(1); + + policies[0] + = root_poa->create_id_assignment_policy(PortableServer::USER_ID + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + PortableServer::POA_var child_poa + = root_poa->create_POA("ChildPoa", + poa_manager.in(), + policies + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(child_poa.in())) + { + ACE_ERROR((LM_ERROR, "(%P|%t) ERROR [ServerApp::run()]: " + "Failed to create the child POA.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + policies[0]->destroy (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Create the thread pool servant dispatching strategy object, and + // hold it in a (local) smart pointer variable. + TAO_Intrusive_Ref_Count_Handle<TAO::CSD::TP_Strategy> csd_tp_strategy = + new TAO::CSD::TP_Strategy(); + + csd_tp_strategy->set_num_threads(this->num_csd_threads_); + + // Tell the strategy to apply itself to the child poa. + if (csd_tp_strategy->apply_to(child_poa.in() ACE_ENV_ARG_PARAMETER) == false) + { + ACE_ERROR((LM_ERROR, "(%P|%t) ERROR [ServerApp::run()]: " + "Failed to apply custom dispatching strategy to child poa.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + ACE_CHECK_RETURN (-1); + + FooServantList servants(this->ior_filename_.c_str(), + this->num_servants_, + this->num_clients_, + this->collocated_test_, + this->servant_to_deactivate_, + orb.in()); + + // Activate the POA Manager before start the ClientTask thread so that + // we do not need coordinate the ClientTask and main thread for the + // collocated test. + poa_manager->activate(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + servants.create_and_activate(orb.in (), + child_poa.in() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp is ready.\n")); + + // If the num_orb_threads_ is exactly one, then just use the current + // (mainline) thread to run the ORB event loop. + if (this->num_orb_threads_ == 1) + { + // Since the num_orb_threads_ is exactly one, we just use the current + // (mainline) thread to run the ORB event loop. + orb->run(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + } + else + { + // The num_orb_threads_ is greater than 1, so we will use an OrbTask + // (active object) to run the ORB event loop in (num_orb_threads_ - 1) + // threads. We use the current (mainline) thread as the other thread + // running the ORB event loop. + OrbTask orb_task(orb.in(), this->num_orb_threads_ - 1); + + // Activate the OrbTask worker threads + if (orb_task.open() != 0) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to open the OrbTask.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + // This will use the current (mainline) thread to run the ORB event loop. + orb->run(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Now that the current thread has unblocked from running the orb, + // make sure to wait for all of the worker threads to complete. + orb_task.wait(); + } + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp is waiting for OrbShutdownTask.\n")); + TheOrbShutdownTask::instance()->wait (); + + // Sleep for 2 second to let the done() two-way call complete + // before cleanup. + ACE_OS::sleep (2); + + if (collocated_test_) + { + servants.collocated_client ()->wait (); + } + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp is destroying the Root POA.\n")); + + // Tear-down the root poa and orb. + root_poa->destroy(1, 1 ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp is destroying the ORB.\n")); + + orb->destroy(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp has completed running successfully.\n")); + + return 0; +} + + +int +ServerApp::parse_args(int argc, char* argv[]) +{ + this->exe_name_ = argv[0]; + + ACE_Get_Opt get_opts(argc, argv, "p:s:c:t:l:d:n:"); + + int c; + int tmp; + + while ((c = get_opts()) != -1) + { + int parse_error = 0; + + switch (c) + { + case 'p': + this->ior_filename_ = get_opts.opt_arg(); + break; + + case 's': + tmp = ACE_OS::atoi(get_opts.opt_arg()); + if (tmp < 1) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Error. -s must be followed by an integer " + "value greater than 0.\n")); + parse_error = 1; + } + + this->num_servants_ = tmp; + break; + + case 'c': + tmp = ACE_OS::atoi(get_opts.opt_arg()); + if (tmp < 1) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Error. -c must be followed by an integer " + "value greater than 0.\n")); + parse_error = 1; + } + + this->num_clients_ = tmp; + break; + + case 't': + tmp = ACE_OS::atoi(get_opts.opt_arg()); + if (tmp < 1) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Error. -t must be followed by an integer " + "value greater than 0.\n")); + parse_error = 1; + } + + this->num_orb_threads_ = tmp; + break; + + case 'n': + tmp = ACE_OS::atoi(get_opts.opt_arg()); + if (tmp < 1) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Error. -n must be followed by an integer " + "value greater than 0.\n")); + parse_error = 1; + } + + this->num_csd_threads_ = tmp; + break; + + case 'l': + tmp = ACE_OS::atoi(get_opts.opt_arg()); + if (tmp < 0) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Error. -l must be followed by an integer " + "value greater than -1.\n")); + parse_error = 1; + } + + this->collocated_test_ = tmp; + break; + + case 'd': + tmp = ACE_OS::atoi(get_opts.opt_arg()); + if (tmp < 0) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Error. -d must be followed by an integer " + "value >= 0.\n")); + parse_error = 1; + } + + this->servant_to_deactivate_ = tmp; + break; + + case '?': + this->usage_statement(); + return 1; + + default: + this->usage_statement(); + return -1; + } + + if (parse_error != 0) + { + this->usage_statement(); + return parse_error; + } + } + + // The deadlock will happen with the collocated callback test + // when we have one working thread, so create at least one more + // working thread would resolve the deadlock. + if (this->collocated_test_ == 1 && this->num_csd_threads_ == 1) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Error. The num_csd_threads_ should be " + ">= 1.\n")); + return -1; + } + + return 0; +} + + +void +ServerApp::usage_statement() +{ + ACE_ERROR((LM_ERROR, + "(%P|%t) usage: %s \n" + "\t[-p <ior_filename_prefix>] \n" + "\t[-s <num_servants>] \n" + "\t[-c <num_clients>] \n" + "\t[-n <num_csd_threads>] \n" + "\t[-t <num_orb_threads>] \n" + "\t[-l <collocation_test>] \n" + "\t[-d <servant_to_deactivate>] \n" + "Default ior_filename_prefix is 'foo'.\n" + "Default num_servants is 1.\n" + "Default num_clients is 1.\n" + "Default num_orb_threads is 1.\n" + "Default collocation_test flag is 0.\n" + "Default servant_to_deactivate is -1 means not deactivate servant.\n" + " 0 means deactivate all servant. \n" + " >0 means the index (servant_to_deactivate-1) of the servant in the servant list.\n", + this->exe_name_.c_str ())); +} diff --git a/TAO/examples/CSD_Strategy/ThreadPool5/ServerApp.h b/TAO/examples/CSD_Strategy/ThreadPool5/ServerApp.h new file mode 100644 index 00000000000..8b461a3e299 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool5/ServerApp.h @@ -0,0 +1,34 @@ +// $Id$ +#ifndef SERVERAPP_H +#define SERVERAPP_H + +#include "ace/SString.h" +#include "ace/CORBA_macros.h" +#include "tao/Environment.h" + +class ServerApp +{ + public: + + ServerApp(); + ~ServerApp(); + + int run(int argc, char* argv[] ACE_ENV_ARG_DECL); + + + private: + + int parse_args(int argc, char* argv[]); + void usage_statement(); + + ACE_CString exe_name_; + ACE_CString ior_filename_; + unsigned num_servants_; + unsigned num_csd_threads_; + unsigned num_clients_; + unsigned num_orb_threads_; + int collocated_test_; + int servant_to_deactivate_; +}; + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool5/client_main.cpp b/TAO/examples/CSD_Strategy/ThreadPool5/client_main.cpp new file mode 100644 index 00000000000..1f9c337ae54 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool5/client_main.cpp @@ -0,0 +1,45 @@ +// $Id$ +#include "ClientApp.h" +#include "ace/Log_Msg.h" +#include "ace/SString.h" +#include "tao/Exception.h" + + +int +main(int argc, char* argv[]) +{ + ACE_LOG_MSG->priority_mask(LM_TRACE | + LM_DEBUG | + LM_INFO | + LM_NOTICE | + LM_WARNING | + LM_ERROR | + LM_CRITICAL | + LM_ALERT | + LM_EMERGENCY, + ACE_Log_Msg::PROCESS); + + + ClientApp app; + + ACE_TRY_NEW_ENV + { + int ret = app.run(argc,argv ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + return ret == 1 ? 0 : ret; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "Caught exception:"); + } + ACE_CATCHALL + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Unknown (...) exception caught in main() " + "for ClientApp\n")); + } + ACE_ENDTRY; + + return 1; +} diff --git a/TAO/examples/CSD_Strategy/ThreadPool5/run_test.pl b/TAO/examples/CSD_Strategy/ThreadPool5/run_test.pl new file mode 100755 index 00000000000..4ea3513ac50 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool5/run_test.pl @@ -0,0 +1,126 @@ +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; + + +$iorfname_prefix = "server"; +$num_servants=1; +$num_clients_per_servant=40; +$num_orb_threads=1; +$num_csd_threads=1; +$collocated_test=0; +$servant_cancellation_option=""; + +if ($ARGV[0] eq 'collocated') { + # 1 servant, 1 collocated client, 1 orb thread, 2 strategy working threads + $num_clients_per_servant=1; + $collocated_test=1; + $num_csd_threads=2; +} +elsif ($ARGV[0] eq 'multiple_servants') { + # multiple servants and single orb thread. + # 10 servant, 40 client, 1 orb thread, 10 strategy working threads + $num_servants=10; + $num_csd_threads=10; + $num_clients_per_servant=4; +} +elsif ($ARGV[0] eq 'multiple_orb_threads') { + # multiple servants and multiple orb threads. + # 10 servant, 40 client, 4 orb thread, 10 strategy working threads + $num_servants=10; + $num_csd_threads=10; + $num_clients_per_servant=4; + $num_orb_threads=4; +} +elsif ($ARGV[0] eq 'cancel_servant') { + # Cancel one servant and leave the other alive. + # 2 servant, 10 client, 5 orb thread, 1 strategy working threads + $num_clients_per_servant=5; + $num_servants=2; + $num_csd_threads=2; + $num_orb_threads=5; + $servant_cancellation_option = " -d 1 "; +} +elsif ($ARGV[0] eq '') { + # default test - 1 servant, 40 clients , 1 orb thread, 1 csd thread +} +else { + print STDERR "ERROR: invalid parameter $ARGV[0] \n"; + exit 1; +} + +$num_clients=$num_servants * $num_clients_per_servant; + +#Delete old ior files. +for (my $i = 0; $i < $num_servants; $i++) { + $servant_id = sprintf("%02d", ($i + 1)); + $iorfile[$i] = PerlACE::LocalFile($iorfname_prefix . "_$servant_id.ior"); + + unlink $iorfile[$i]; +} + +$SV = new PerlACE::Process ("server_main", + "-p $iorfname_prefix -s $num_servants " + . "-c $num_clients -t $num_orb_threads -n $num_csd_threads " + . "-l $collocated_test $servant_cancellation_option"); + +$SV->Spawn (); + +# Wait for the servant ior files created by server. +for (my $i = 0; $i < $num_servants; $i++) { + $servant_id = sprintf("%02d", ($i + 1)); + $iorfile[$i] = PerlACE::LocalFile($iorfname_prefix . "_$servant_id.ior"); + + if (PerlACE::waitforfile_timed ($iorfile[$i], + $PerlACE::wait_interval_for_process_creation) == -1) { + print STDERR "ERROR: cannot find file <$iorfile[$i]>\n"; + $SV->Kill (); $SV->TimedWait (1); + exit 1; + } +} + +$count = 0; + +if ($collocated_test == 0) { + for (my $i = 0; $i < $num_servants; $i++) { + for ($j = 0; $j < $num_clients_per_servant; $j++) { + $CLS[$count] = new PerlACE::Process ("client_main", " -i file://$iorfile[$i]"); + $CLS[$count]->Spawn (); + $count ++; + } + } + + for (my $i = 0; $i < $num_clients; $i++) { + $client = $CLS[$i]->WaitKill (60); + + if ($client != 0) { + print STDERR "ERROR: client $i returned $client\n"; + $status = 1; + } + } +} + +$server = $SV->WaitKill (60); + +if ($server != 0) { + print STDERR "ERROR: server returned $server\n"; + $status = 1; +} + +#Delete ior files generated by this run. +for (my $i = 0; $i < $num_servants; $i++) { + $servant_id = sprintf("%02d", ($i + 1)); + $iorfile[$i] = PerlACE::LocalFile($iorfname_prefix . "_$servant_id.ior"); + + unlink $iorfile[$i]; +} + +exit $status; diff --git a/TAO/examples/CSD_Strategy/ThreadPool5/server_main.cpp b/TAO/examples/CSD_Strategy/ThreadPool5/server_main.cpp new file mode 100644 index 00000000000..ba16e928f63 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool5/server_main.cpp @@ -0,0 +1,45 @@ +// $Id$ +#include "ServerApp.h" +#include "ace/Log_Msg.h" +#include "ace/CORBA_macros.h" +#include "tao/Environment.h" +#include "tao/Exception.h" + + +int +main(int argc, char* argv[]) +{ + ACE_LOG_MSG->priority_mask(LM_TRACE | + LM_DEBUG | + LM_INFO | + LM_NOTICE | + LM_WARNING | + LM_ERROR | + LM_CRITICAL | + LM_ALERT | + LM_EMERGENCY, + ACE_Log_Msg::PROCESS); + + ServerApp app; + + ACE_TRY_NEW_ENV + { + int ret = app.run(argc,argv ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + return ret == 1 ? 0 : ret; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "Caught exception:"); + } + ACE_CATCHALL + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Unknown (...) exception caught in main() " + "for ServerApp\n")); + } + ACE_ENDTRY; + + return 1; +} diff --git a/TAO/examples/CSD_Strategy/ThreadPool6/CSD_Test_ThreadPool6.mpc b/TAO/examples/CSD_Strategy/ThreadPool6/CSD_Test_ThreadPool6.mpc new file mode 100644 index 00000000000..fc53a3a81c2 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool6/CSD_Test_ThreadPool6.mpc @@ -0,0 +1,25 @@ +// -*- MPC -*- +// $Id$ + +project(*Server): csd_threadpool, taoexe, portableserver, minimum_corba { + exename = server_main + idlflags -= -Sc + + Source_Files { + Foo_i.cpp + ServerApp.cpp + server_main.cpp + OrbShutdownTask.cpp + } +} + +project(*Client): taoexe, anytypecode { + exename = client_main + + Source_Files { + FooC.cpp + ClientApp.cpp + client_main.cpp + } +} + diff --git a/TAO/examples/CSD_Strategy/ThreadPool6/ClientApp.cpp b/TAO/examples/CSD_Strategy/ThreadPool6/ClientApp.cpp new file mode 100644 index 00000000000..74e97209295 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool6/ClientApp.cpp @@ -0,0 +1,143 @@ +// $Id$ +#include "ClientApp.h" +#include "FooC.h" +#include "ace/Get_Opt.h" +#include "ace/Log_Msg.h" + + +ClientApp::ClientApp() +{ +} + + +ClientApp::~ClientApp() +{ +} + + +int +ClientApp::run(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + CORBA::ORB_var orb + = CORBA::ORB_init(argc, argv, "" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Parse the command-line args for this application. + // * Raises -1 if problems are encountered. + // * Returns 1 if the usage statement was explicitly requested. + // * Returns 0 otherwise. + int result = this->parse_args(argc, argv); + if (result != 0) + { + return result; + } + + CORBA::Object_var obj + = orb->string_to_object(this->ior_.c_str() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(obj.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to convert IOR string to obj ref.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + Foo_var foo = Foo::_narrow(obj.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(foo.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to narrow obj ref to Foo interface.\n")); + ACE_THROW_RETURN (TestException(), -1); + } + + + for (CORBA::Long i = 1; i <= 100; i++) + { + foo->op1(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + foo->op2(i ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + CORBA::Long value = foo->op3(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ===> Value retrieved from op3() == %d\n", + value)); + + for (CORBA::Long j = 1; j <= 5; j++) + { + foo->op4(495 + (i * 5) + j ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + } + + ACE_TRY_NEW_ENV + { + foo->op5(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCH (FooException, ex) + { + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ===> Caught FooException - as expected.\n")); + + } + ACE_ENDTRY; + } + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ===> Tell server that we are done().\n")); + + foo->done(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ===> Back from done().\n")); + + return 0; +} + + +int +ClientApp::parse_args(int argc, char* argv[]) +{ + this->exe_name_ = argv[0]; + + ACE_Get_Opt get_opts(argc, argv, "i:"); + + int c; + + while ((c = get_opts()) != -1) + { + switch (c) + { + case 'i': + this->ior_ = get_opts.opt_arg(); + break; + + case '?': + this->usage_statement(); + return 1; + default: + this->usage_statement(); + return -1; + } + } + + return 0; +} + + +void +ClientApp::usage_statement() +{ + ACE_ERROR((LM_ERROR, + "Usage: %s [options]\n\n" + "OPTIONS:\n\n" + "\t[-i <ior>]\n" + "\t[-?]\n\n", + this->exe_name_.c_str())); +} + diff --git a/TAO/examples/CSD_Strategy/ThreadPool6/ClientApp.h b/TAO/examples/CSD_Strategy/ThreadPool6/ClientApp.h new file mode 100644 index 00000000000..7dc57bb78dc --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool6/ClientApp.h @@ -0,0 +1,30 @@ +// $Id$ +#ifndef CLIENTAPP_H +#define CLIENTAPP_H + +#include "ace/SString.h" +#include "ace/CORBA_macros.h" +#include "tao/Environment.h" + + +class ClientApp +{ + public: + + ClientApp(); + ~ClientApp(); + + int run(int argc, char* argv[] ACE_ENV_ARG_DECL); + + + private: + + int parse_args(int argc, char* argv[]); + void usage_statement(); + + ACE_CString ior_; + + ACE_CString exe_name_; +}; + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool6/Foo.idl b/TAO/examples/CSD_Strategy/ThreadPool6/Foo.idl new file mode 100644 index 00000000000..f4a756a31b1 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool6/Foo.idl @@ -0,0 +1,29 @@ +// $Id$ +#ifndef FOO_IDL +#define FOO_IDL + +exception FooException {}; +exception TestException {}; + +interface Foo +{ + /// void return-type, no arguments + void op1(); + + /// void return-type, 1 "in" argument + void op2(in long value); + + /// long return-type, no arguments + long op3(); + + /// one-way version of op2 + oneway void op4(in long value); + + /// Operation that always raises an exception. + void op5() raises (FooException); + + /// Client calls this last. It will shutdown the server. + void done(); +}; + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool6/Foo_i.cpp b/TAO/examples/CSD_Strategy/ThreadPool6/Foo_i.cpp new file mode 100644 index 00000000000..8201c889f88 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool6/Foo_i.cpp @@ -0,0 +1,113 @@ +// $Id$ +#include "Foo_i.h" +#include "OrbShutdownTask.h" +#include "ace/OS.h" + +Foo_i::Foo_i(unsigned num_clients) + : value_(0), + num_clients_(num_clients), + count_op1_(0), + count_op2_(0), + count_op3_(0), + count_op4_(0), + count_op5_(0) + +{ + ACE_DEBUG((LM_DEBUG, + "(%P|%t) Number of clients for Foo_i servant: %d\n", + num_clients)); +} + + +Foo_i::~Foo_i() +{ +} + + +void +Foo_i::op1(ACE_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + ++this->count_op1_; + // Sleep for 10 milliseconds (10,000 microseconds) + //ACE_OS::sleep(ACE_Time_Value(0,10000)); +} + + +void +Foo_i::op2(CORBA::Long value ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + ++this->count_op2_; + this->value_ = value; +} + + +CORBA::Long +Foo_i::op3(ACE_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + ++this->count_op3_; + return this->value_; +} + + +void +Foo_i::op4(CORBA::Long value ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + ++this->count_op4_; + this->value_ = value; + + if (this->count_op4_ % 500 == 0) + { + ACE_DEBUG((LM_DEBUG, + "(%P|%t) op4() has been called %d times now. value == %d\n", + this->count_op4_, this->value_)); + } + + // Sleep for 10 milliseconds (10,000 microseconds) + //ACE_OS::sleep(ACE_Time_Value(0,10000)); +} + + +void +Foo_i::op5(ACE_ENV_SINGLE_ARG_DECL) + ACE_THROW_SPEC((CORBA::SystemException, FooException)) +{ + ++this->count_op5_; + ACE_THROW (FooException()); +} + + +void +Foo_i::done(ACE_ENV_SINGLE_ARG_DECL) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + unsigned num_left = --this->num_clients_; + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) A client has reported that it is done(). " + "There are %d clients left.\n", num_left)); + + if (num_left == 0) + { + ACE_DEBUG((LM_DEBUG, "(%P|%t) Stats:\n" + "op1() count: %d\n" + "op2() count: %d\n" + "op3() count: %d\n" + "op4() count: %d\n" + "op5() count: %d\n", + this->count_op1_, + this->count_op2_, + this->count_op3_, + this->count_op4_, + this->count_op5_)); + + if (TheOrbShutdownTask::instance()->open(0) != 0) + { + ACE_ERROR((LM_ERROR, "(%P|%t)Foo_i::done: " + "failed to create orb shutdown thread.\n")); + } + } +} diff --git a/TAO/examples/CSD_Strategy/ThreadPool6/Foo_i.h b/TAO/examples/CSD_Strategy/ThreadPool6/Foo_i.h new file mode 100644 index 00000000000..ab50cc5589a --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool6/Foo_i.h @@ -0,0 +1,48 @@ +// $Id$ +#ifndef FOO_I_H +#define FOO_I_H + +#include "FooS.h" + + +class Foo_i +{ + public: + + Foo_i(unsigned num_clients); + virtual ~Foo_i(); + + virtual void op1(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void op2(CORBA::Long value ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual CORBA::Long op3(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void op4(CORBA::Long value ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void op5(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException, FooException)); + + virtual void done(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + + private: + + CORBA::Long value_; + unsigned num_clients_; + + CORBA::ORB_var orb_; + + unsigned count_op1_; + unsigned count_op2_; + unsigned count_op3_; + unsigned count_op4_; + unsigned count_op5_; +}; + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool6/OrbShutdownTask.cpp b/TAO/examples/CSD_Strategy/ThreadPool6/OrbShutdownTask.cpp new file mode 100644 index 00000000000..f9d551e8aee --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool6/OrbShutdownTask.cpp @@ -0,0 +1,77 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file OrbShutdownTask.cpp + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#include "OrbShutdownTask.h" +#include "ace/CORBA_macros.h" +#include "ace/OS_NS_unistd.h" + + +OrbShutdownTask::OrbShutdownTask() +{ +} + + +OrbShutdownTask::~OrbShutdownTask() +{ +} + + +void +OrbShutdownTask::orb(CORBA::ORB_ptr orb) +{ + this->orb_ = CORBA::ORB::_duplicate (orb); +} + + +int +OrbShutdownTask::open(void*) +{ + if (this->activate(THR_NEW_LWP | THR_JOINABLE, 1) != 0) + { + // Assumes that when activate returns non-zero return code that + // no threads were activated. + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) OrbShutdownTask failed to open().\n"), + -1); + } + + return 0; +} + + +int +OrbShutdownTask::svc() +{ + ACE_OS::sleep (2); + ACE_DEBUG ((LM_DEBUG, "(%P|%t)OrbShutdownTask::svc shutdown orb \n")); + ACE_TRY_NEW_ENV + { + this->orb_->shutdown(0 ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHALL + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Exception raised by ORB::shutdown() call " + "in OrbShutdownTask::svc().\n")); + } + ACE_ENDTRY; + + return 0; +} + + +int +OrbShutdownTask::close(u_long) +{ + return 0; +} diff --git a/TAO/examples/CSD_Strategy/ThreadPool6/OrbShutdownTask.h b/TAO/examples/CSD_Strategy/ThreadPool6/OrbShutdownTask.h new file mode 100644 index 00000000000..3795d12c3c9 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool6/OrbShutdownTask.h @@ -0,0 +1,41 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file OrbShutdownTask.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef ORB_SHUTDOWN_TASK_H +#define ORB_SHUTDOWN_TASK_H + +#include "ace/Task.h" +#include "tao/ORB.h" + + +class OrbShutdownTask : public ACE_Task_Base +{ + public: + + OrbShutdownTask(); + virtual ~OrbShutdownTask(); + + void orb(CORBA::ORB_ptr orb); + + virtual int open(void*); + virtual int svc(); + virtual int close(u_long); + + + private: + + CORBA::ORB_var orb_; +}; + +typedef ACE_Singleton<OrbShutdownTask, ACE_Thread_Mutex> TheOrbShutdownTask; + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool6/README b/TAO/examples/CSD_Strategy/ThreadPool6/README new file mode 100644 index 00000000000..5c90da80c6b --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool6/README @@ -0,0 +1,14 @@ +# $Id$ + +Description: + +This is the simple "ThreadPool" test modified to use the TIE approach. + + +To run the test use the run_test.pl script: + +$ ./run_test.pl + + The script returns 0 if the test was successful. + + diff --git a/TAO/examples/CSD_Strategy/ThreadPool6/ServerApp.cpp b/TAO/examples/CSD_Strategy/ThreadPool6/ServerApp.cpp new file mode 100644 index 00000000000..08584619c8a --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool6/ServerApp.cpp @@ -0,0 +1,240 @@ +// $Id$ +#include "ServerApp.h" +#include "Foo_i.h" +#include "FooS_T.h" +#include "OrbShutdownTask.h" +#include "ace/Get_Opt.h" +#include "tao/CSD_ThreadPool/CSD_TP_Strategy.h" +#include "tao/Intrusive_Ref_Count_Handle_T.h" + + +ServerApp::ServerApp() +: ior_filename_ ("server.ior") +{ +} + + +ServerApp::~ServerApp() +{ +} + + +int +ServerApp::run(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + CORBA::ORB_var orb = CORBA::ORB_init(argc, argv, "" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Parse the command-line args for this application. + // * Raises -1 if problems are encountered. + // * Returns 1 if the usage statement was explicitly requested. + // * Returns 0 otherwise. + int result = this->parse_args(argc, argv); + if (result != 0) + { + return result; + } + + TheOrbShutdownTask::instance()->orb (orb.in ()); + + CORBA::Object_var obj + = orb->resolve_initial_references("RootPOA" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(obj.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to resolve initial ref for 'RootPOA'.\n")); + ACE_THROW_RETURN (TestException(), -1);; + } + + PortableServer::POA_var root_poa + = PortableServer::POA::_narrow(obj.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(root_poa.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to narrow obj ref to POA interface.\n")); + ACE_THROW_RETURN (TestException(), -1);; + } + + PortableServer::POAManager_var poa_manager + = root_poa->the_POAManager(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Create the child POA. + CORBA::PolicyList policies(1); + policies.length(1); + + policies[0] = + root_poa->create_implicit_activation_policy (PortableServer::IMPLICIT_ACTIVATION + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + PortableServer::POA_var child_poa + = root_poa->create_POA("ChildPoa", + poa_manager.in(), + policies + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(child_poa.in())) + { + ACE_ERROR((LM_ERROR, "(%P|%t) ERROR [ServerApp::run()]: " + "Failed to create the child POA.\n")); + ACE_THROW_RETURN (TestException(), -1);; + } + + policies[0]->destroy (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Create the thread pool servant dispatching strategy object, and + // hold it in a (local) smart pointer variable. + TAO_Intrusive_Ref_Count_Handle<TAO::CSD::TP_Strategy> csd_tp_strategy = + new TAO::CSD::TP_Strategy(); + + // Tell the strategy to apply itself to the child poa. + if (csd_tp_strategy->apply_to(child_poa.in() ACE_ENV_ARG_PARAMETER) == false) + { + ACE_ERROR((LM_ERROR, "(%P|%t) ERROR [ServerApp::run()]: " + "Failed to apply custom dispatching strategy to child poa.\n")); + ACE_THROW_RETURN (TestException(), -1);; + } + ACE_CHECK_RETURN (-1); + + // Create the Foo_i object. + Foo_i foo_i (this->num_clients_); + + // Create tie object with the Foo_i object. + POA_Foo_tie<Foo_i> foo_tie_i (foo_i, child_poa.in ()); + + // Get Object Reference for the foo_tie_i object. + Foo_var foo = foo_tie_i._this (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + if (CORBA::is_nil(foo.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to activate servant foo_tie_i.\n")); + ACE_THROW_RETURN (TestException(), -1);; + } + + // Stringify the object reference + CORBA::String_var ior + = orb->object_to_string(foo.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Write the stringified object reference to the ior file. + FILE* ior_file = ACE_OS::fopen(this->ior_filename_.c_str(), "w"); + + if (ior_file == 0) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Cannot open output file for writing IOR: %s", + this->ior_filename_.c_str())); + ACE_THROW_RETURN (TestException(), -1);; + } + + ACE_OS::fprintf(ior_file, "%s", ior.in ()); + ACE_OS::fclose(ior_file); + + // Activate the POA Manager + poa_manager->activate(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp is ready. Running the ORB event loop.\n")); + + // Run the ORB event loop. + orb->run(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp ORB has stopped running. " + "Stop the CSD strategy.\n")); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp is waiting for OrbShutdownTask.\n")); + TheOrbShutdownTask::instance()->wait (); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp is destroying the Root POA.\n")); + + // Sleep for 2 second to let the done() two-way call complete + // before cleanup. + ACE_OS::sleep (2); + + // Tear-down the root poa and orb. + root_poa->destroy(1, 1 ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp is destroying the ORB.\n")); + + orb->destroy(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp has completed running successfully.\n")); + + return 0; +} + + +int +ServerApp::parse_args(int argc, char* argv[]) +{ + this->exe_name_ = argv[0]; + + ACE_Get_Opt get_opts(argc, argv, "o:n:"); + + int c; + + while ((c = get_opts()) != -1) + { + switch (c) + { + case 'o': + this->ior_filename_ = get_opts.opt_arg(); + break; + + case 'n': + { + int tmp = ACE_OS::atoi(get_opts.opt_arg()); + if (tmp < 1) + { + this->usage_statement (); + return -1; + } + + this->num_clients_ = tmp; + } + break; + + case '?': + this->usage_statement(); + return 1; + + default: + this->usage_statement(); + return -1; + } + } + + return 0; +} + + +void +ServerApp::usage_statement() +{ + ACE_ERROR((LM_ERROR, + "Usage: %s [options]\n\n" + "OPTIONS:\n\n" + "\t[-o <ior_filename>]\n" + "\t[-n <num_clients>]\n" + "\t[-?]\n\n", + this->exe_name_.c_str())); +} + diff --git a/TAO/examples/CSD_Strategy/ThreadPool6/ServerApp.h b/TAO/examples/CSD_Strategy/ThreadPool6/ServerApp.h new file mode 100644 index 00000000000..ad89b43c972 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool6/ServerApp.h @@ -0,0 +1,30 @@ +// $Id$ +#ifndef SERVERAPP_H +#define SERVERAPP_H + +#include "ace/SString.h" +#include "ace/CORBA_macros.h" +#include "tao/Environment.h" + + +class ServerApp +{ + public: + + ServerApp(); + ~ServerApp(); + + int run(int argc, char* argv[] ACE_ENV_ARG_DECL); + + + private: + + int parse_args(int argc, char* argv[]); + void usage_statement(); + + ACE_CString exe_name_; + ACE_CString ior_filename_; + unsigned num_clients_; +}; + +#endif diff --git a/TAO/examples/CSD_Strategy/ThreadPool6/client_main.cpp b/TAO/examples/CSD_Strategy/ThreadPool6/client_main.cpp new file mode 100644 index 00000000000..1f9c337ae54 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool6/client_main.cpp @@ -0,0 +1,45 @@ +// $Id$ +#include "ClientApp.h" +#include "ace/Log_Msg.h" +#include "ace/SString.h" +#include "tao/Exception.h" + + +int +main(int argc, char* argv[]) +{ + ACE_LOG_MSG->priority_mask(LM_TRACE | + LM_DEBUG | + LM_INFO | + LM_NOTICE | + LM_WARNING | + LM_ERROR | + LM_CRITICAL | + LM_ALERT | + LM_EMERGENCY, + ACE_Log_Msg::PROCESS); + + + ClientApp app; + + ACE_TRY_NEW_ENV + { + int ret = app.run(argc,argv ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + return ret == 1 ? 0 : ret; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "Caught exception:"); + } + ACE_CATCHALL + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Unknown (...) exception caught in main() " + "for ClientApp\n")); + } + ACE_ENDTRY; + + return 1; +} diff --git a/TAO/examples/CSD_Strategy/ThreadPool6/run_test.pl b/TAO/examples/CSD_Strategy/ThreadPool6/run_test.pl new file mode 100755 index 00000000000..ded41bfc848 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool6/run_test.pl @@ -0,0 +1,55 @@ +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; + +$iorfile = PerlACE::LocalFile ("server.ior"); +unlink $iorfile; +$status = 0; + +$num_clients=1; + +$SV = new PerlACE::Process ("server_main", "-o $iorfile -n $num_clients"); + +$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; +} + +for ($i = 0; $i < $num_clients; $i++) { + + @CLS[$i] = new PerlACE::Process ("client_main", " -i file://$iorfile"); + + @CLS[$i]->Spawn (); +} + +for ($i = 0; $i < $num_clients; $i++) { + + $client = @CLS[$i]->WaitKill (60); + + if ($client != 0) { + print STDERR "ERROR: client $i returned $client\n"; + $status = 1; + } +} + + +$server = $SV->WaitKill (60); + +if ($server != 0) { + print STDERR "ERROR: server returned $server\n"; + $status = 1; +} + +unlink $iorfile; + +exit $status; diff --git a/TAO/examples/CSD_Strategy/ThreadPool6/server_main.cpp b/TAO/examples/CSD_Strategy/ThreadPool6/server_main.cpp new file mode 100644 index 00000000000..ba16e928f63 --- /dev/null +++ b/TAO/examples/CSD_Strategy/ThreadPool6/server_main.cpp @@ -0,0 +1,45 @@ +// $Id$ +#include "ServerApp.h" +#include "ace/Log_Msg.h" +#include "ace/CORBA_macros.h" +#include "tao/Environment.h" +#include "tao/Exception.h" + + +int +main(int argc, char* argv[]) +{ + ACE_LOG_MSG->priority_mask(LM_TRACE | + LM_DEBUG | + LM_INFO | + LM_NOTICE | + LM_WARNING | + LM_ERROR | + LM_CRITICAL | + LM_ALERT | + LM_EMERGENCY, + ACE_Log_Msg::PROCESS); + + ServerApp app; + + ACE_TRY_NEW_ENV + { + int ret = app.run(argc,argv ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + return ret == 1 ? 0 : ret; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "Caught exception:"); + } + ACE_CATCHALL + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Unknown (...) exception caught in main() " + "for ServerApp\n")); + } + ACE_ENDTRY; + + return 1; +} diff --git a/TAO/performance-tests/CSD_Strategy/TestApps/ClientApp.cpp b/TAO/performance-tests/CSD_Strategy/TestApps/ClientApp.cpp new file mode 100644 index 00000000000..f01b5c7570d --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestApps/ClientApp.cpp @@ -0,0 +1,200 @@ +// $Id$ +#include "ClientApp.h" +#include "TestInf/AppHelper.h" +#include "TestInf/TestAppExceptionC.h" +#include "TestServant/Foo_ClientEngine.h" +#include "ace/Get_Opt.h" + + +ClientApp::ClientApp() + : TestAppBase("CSD_PT_ClientApp"), + ior_("Not Set"), + client_id_(0), + num_loops_(1) +{ +} + + +ClientApp::~ClientApp() +{ +} + + +int +ClientApp::run_i(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + int result = this->init(argc, argv ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + if (result != 0) + { + return result; + } + + this->client_setup(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + result = this->run_engine(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + this->cleanup(); + return result; +} + + +int +ClientApp::init(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + this->orb_ = CORBA::ORB_init(argc, argv, "" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Parse the command-line args for this application. + // * Returns -1 if problems are encountered. + // * Returns 1 if the usage statement was explicitly requested. + // * Returns 0 otherwise. + return this->parse_args(argc, argv); +} + + +void +ClientApp::client_setup(ACE_ENV_SINGLE_ARG_DECL) +{ + // Turn the ior_ into a Foo obj ref. + Foo_var foo = RefHelper<Foo>::string_to_ref(this->orb_.in(), + this->ior_.c_str() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + // Create the ClientEngine object, and give it the Foo obj ref. + this->engine_ = new Foo_ClientEngine(foo.in(), this->client_id_); +} + + +int +ClientApp::run_engine(ACE_ENV_SINGLE_ARG_DECL) +{ + bool result = this->engine_->execute(this->num_loops_ + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + return result ? 0 : -1; +} + + +void +ClientApp::cleanup() +{ +} + + +int +ClientApp::parse_args(int argc, char* argv[]) +{ + this->exe_name_ = argv[0]; + + ACE_Get_Opt get_opts(argc, argv, "i:n:l:"); + + int c; + + while ((c = get_opts()) != -1) + { + int result = 0; + switch (c) + { + case 'i': + this->ior_ = get_opts.opt_arg(); + break; + + case 'n': + result = this->set_arg(this->client_id_, + get_opts.opt_arg(), + c, + "client_id", + 1); + break; + + case 'l': + result = this->set_arg(this->num_loops_, + get_opts.opt_arg(), + c, + "num_loops", + 1); + break; + + case '?': + this->usage_statement(); + return 1; + + default: + this->usage_statement(); + return -1; + } + + if (result != 0) + { + return result; + } + } + + return this->arg_dependency_checks(); +} + +void +ClientApp::usage_statement() +{ + ACE_ERROR((LM_ERROR, + "Usage: %s [options]\n\n" + "OPTIONS:\n\n" + "\t[-i <ior>]\n" + "\t[-n <client_id>]\n" + "\t[-l <num_loops>]\n" + "\t[-?]\n\n", + this->exe_name_.c_str())); +} + + +int +ClientApp::arg_dependency_checks() +{ + if (this->ior_ == "Not Set") + { + ACE_ERROR((LM_ERROR, + "Error: Missing required command-line option (-i <ior>).\n")); + this->usage_statement(); + return -1; + } + + if (this->client_id_ <= 0) + { + ACE_ERROR((LM_ERROR, + "Error: Required command-line option (-n <client id>).\n" + " The client id should be positive integer. \n")); + this->usage_statement(); + return -1; + } + + return 0; +} + + +int +ClientApp::set_arg(unsigned& value, + const char* arg, + char opt, + const char* name, + int min) +{ + int tmp = ACE_OS::atoi(arg); + + if (tmp < min) + { + ACE_ERROR((LM_ERROR, + "Error: -%c <%s> must be integer type with a value of, " + "at least, %d.\n", opt, name, min)); + this->usage_statement(); + return -1; + } + + value = tmp; + return 0; +} + + diff --git a/TAO/performance-tests/CSD_Strategy/TestApps/ClientApp.h b/TAO/performance-tests/CSD_Strategy/TestApps/ClientApp.h new file mode 100644 index 00000000000..9136ff9d27e --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestApps/ClientApp.h @@ -0,0 +1,63 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file ClientApp.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= +#ifndef CLIENTAPP_H +#define CLIENTAPP_H + +#include "TestInf/TestAppBase.h" +#include "TestInf/ClientEngine.h" +#include "tao/ORB.h" +#include "ace/SString.h" + + +class ClientApp : public TestAppBase +{ + public: + + ClientApp(); + virtual ~ClientApp(); + + + protected: + + virtual int run_i(int argc, char* argv[] ACE_ENV_ARG_DECL); + + + private: + + // These are all called, in order, by the run_i() method. + int init(int argc, char* argv[] ACE_ENV_ARG_DECL); + void client_setup(ACE_ENV_SINGLE_ARG_DECL); + int run_engine(ACE_ENV_SINGLE_ARG_DECL); + void cleanup(); + + // Helper methods used by the methods above. + int parse_args(int argc, char* argv[]); + + int set_arg(unsigned& value, + const char* arg, + char opt, + const char* name, + int min = 0); + + void usage_statement(); + int arg_dependency_checks(); + + + CORBA::ORB_var orb_; + ACE_CString exe_name_; + ACE_CString ior_; + ClientEngine_Handle engine_; + unsigned client_id_; + unsigned num_loops_; +}; + +#endif diff --git a/TAO/performance-tests/CSD_Strategy/TestApps/README b/TAO/performance-tests/CSD_Strategy/TestApps/README new file mode 100644 index 00000000000..61ddc725de5 --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestApps/README @@ -0,0 +1,64 @@ +/** + +@page CSD_Strategy TestApp README File + + This directory contains the test applications. This test tries to +estimate how fast the CSD strategy can handle requests. + + To run the test use the run_test.pl script as below. The number +parameter is the trail id for the server used to identify the test +results when running same test multiple times using single script. +The id should be positive integer. + + +$ ./run_test.pl 1 + + 1 remote client, 1 servant, 1 orb thread (main thread), 1 csd strategy thread + +$ ./run_test.pl remote 1 + + 40 remote clients, 1 servant, 1 orb thread (main thread), 1 csd strategy thread + +$ ./run_test.pl collocated 1 + + 10 collocated clients, 1 servant, 1 orb thread (main thread), 1 csd strategy thread + +$ ./run_test.pl remote_orbthreads 1 + + 40 remote clients, 1 servant, 5 orb threads, 1 csd strategy thread + +$ ./run_test.pl remote_servants 1 + + 40 remote clients, 5 servants, 5 orb threads, 1 csd strategy thread + +$ ./run_test.pl remote_csdthreads 1 + + 40 remote clients, 5 servants, 1 orb thread (main thread), 5 csd strategy threads + +$ ./run_test.pl remote_big 1 + + 40 remote clients, 10 servants, 4 orb threads, 5 csd strategy threads + +$ ./run_test.pl collocated_big 1 + + 40 collocated clients, 10 servants, 1 orb thread (main thread), 5 csd strategy threads + +$ ./run_test.pl big 1 + + 40 remote clients, 40 collocated clients, 10 servants, 4 orb threads, 5 csd strategy threads + +$ ./run_test.pl remote_huge 1 + + 400 remote clients, 10 servants, 4 orb threads, 5 csd strategy threads + +$ ./run_test.pl collocated_huge 1 + + 40 collocated clients, 10 servants, 1 orb thread (main thread), 20 csd strategy threads + + + The script returns 0 if the test was successful, and prints +out the number of requests, the total time to dispatch these requests +and the average number of requests the CSD strategy dispatched +per millisecond. + +*/ diff --git a/TAO/performance-tests/CSD_Strategy/TestApps/ServerApp.cpp b/TAO/performance-tests/CSD_Strategy/TestApps/ServerApp.cpp new file mode 100644 index 00000000000..2a01df0f410 --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestApps/ServerApp.cpp @@ -0,0 +1,421 @@ +// $Id$ +#include "ServerApp.h" +#include "TestInf/AppHelper.h" +#include "TestInf/OrbRunner.h" +#include "TestInf/AppShutdown.h" +#include "TestInf/TestAppExceptionC.h" +#include "TestServant/Foo_ClientEngine.h" +#include "ace/OS.h" +#include "ace/Get_Opt.h" +#include "ace/Time_Value.h" +#include "ace/High_Res_Timer.h" + + +ServerApp::ServerApp() + : TestAppBase("CSD_PT_ServerApp"), + ior_filename_prefix_("foo"), + num_servants_(1), + num_csd_threads_(1), + num_orb_threads_(1), + num_remote_clients_(1), + num_collocated_clients_(0), + num_loops_(1), + use_csd_(1), + scenario_id_("UnknownScenarioId"), + trial_id_(0) +{ +} + + +ServerApp::~ServerApp() +{ +} + + +int +ServerApp::run_i(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + int result = this->init(argc, argv ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + if (result != 0) + { + return result; + } + + this->poa_setup(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->csd_setup(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->servant_setup(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->collocated_setup(); + this->poa_activate(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_High_Res_Timer timer; + timer.start(); + + this->run_collocated_clients(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->run_orb_event_loop(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + + timer.stop(); + + ACE_Time_Value tv; + timer.elapsed_time(tv); + + unsigned num_operations = this->stats_.total(); + + double ops_per_msec = (1.0 * num_operations) / tv.msec(); + + ACE_DEBUG((LM_DEBUG, "%s,%d,%d,%d,%.2f\n", + this->scenario_id_.c_str(), + this->trial_id_, + num_operations, + tv.msec(), + ops_per_msec)); + + this->cleanup(); + return this->check_results () ? 0 : -1; +} + + +int +ServerApp::init(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + this->orb_ = CORBA::ORB_init(argc, argv, "" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Parse the command-line args for this application. + // * Raises -1 if problems are encountered. + // * Returns 1 if the usage statement was explicitly requested. + // * Returns 0 otherwise. + int result = this->parse_args(argc, argv); + + if (result != 0) + { + return result; + } + + TheAppShutdown->init(this->orb_.in(), + this->num_remote_clients_ + + this->num_collocated_clients_ + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + return 0; +} + + +void +ServerApp::poa_setup(ACE_ENV_SINGLE_ARG_DECL) +{ + this->poa_ = this->create_poa(this->orb_.in(), + "ChildPoa" + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; +} + + +void +ServerApp::csd_setup(ACE_ENV_SINGLE_ARG_DECL) +{ + this->tp_strategy_ = new TAO::CSD::TP_Strategy(this->num_csd_threads_); + + if (this->use_csd_ > 0) + { + if (!this->tp_strategy_->apply_to(this->poa_.in() ACE_ENV_ARG_PARAMETER)) + { + ACE_ERROR((LM_ERROR, + "Failed to apply CSD strategy to poa.\n")); + ACE_THROW(TestAppException()); + } + ACE_CHECK; + } +} + + +void +ServerApp::servant_setup(ACE_ENV_SINGLE_ARG_DECL) +{ + this->servants_.create_and_activate(this->num_servants_, + this->orb_.in (), + this->poa_.in (), + this->ior_filename_prefix_.c_str() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; +} + + +void +ServerApp::collocated_setup() +{ + int client_id = this->num_remote_clients_; + + for (unsigned i = 0; i < this->num_collocated_clients_; i++) + { + ++client_id; + + // Dole out the servant object references in a round-robin fashion. + unsigned servant_index = i % this->num_servants_; + + ServantListType::T_stub_var obj = this->servants_.objref(servant_index); + + ClientEngine_Handle engine = new Foo_ClientEngine(obj.in(), client_id); + + this->collocated_client_task_.add_engine(engine.in()); + } + + this->collocated_client_task_.num_loops(this->num_loops_); +} + + +void +ServerApp::poa_activate(ACE_ENV_SINGLE_ARG_DECL) +{ + PortableServer::POAManager_var poa_manager + = this->poa_->the_POAManager(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + + poa_manager->activate(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; +} + + +void +ServerApp::run_collocated_clients(ACE_ENV_SINGLE_ARG_DECL) +{ + if (this->num_collocated_clients_ > 0) + { + if (this->collocated_client_task_.open() == -1) + { + ACE_THROW (TestAppException ()); + } + } +} + + +void +ServerApp::run_orb_event_loop(ACE_ENV_SINGLE_ARG_DECL) +{ + OrbRunner orb_runner(this->orb_.in(), this->num_orb_threads_); + orb_runner.run(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + TheAppShutdown->wait (); +} + + +void +ServerApp::cleanup() +{ +} + + +int +ServerApp::parse_args(int argc, char* argv[]) +{ + this->exe_name_ = argv[0]; + + ACE_Get_Opt get_opts(argc, argv, "p:s:n:t:r:c:l:u:x:z:"); + + int c; + + while ((c = get_opts()) != -1) + { + int result = 0; + switch (c) + { + case 'p': + this->ior_filename_prefix_ = get_opts.opt_arg(); + break; + + case 's': + result = this->set_arg(this->num_servants_, + get_opts.opt_arg(), + c, + "num_servants", + 1); + break; + + case 'n': + result = this->set_arg(this->num_csd_threads_, + get_opts.opt_arg(), + c, + "num_servants", + 1); + break; + + case 't': + result = this->set_arg(this->num_orb_threads_, + get_opts.opt_arg(), + c, + "num_orb_threads", + 1); + break; + + case 'r': + result = this->set_arg(this->num_remote_clients_, + get_opts.opt_arg(), + c, + "num_remote_clients"); + break; + + case 'c': + result = this->set_arg(this->num_collocated_clients_, + get_opts.opt_arg(), + c, + "num_collocated_clients"); + break; + + case 'l': + result = this->set_arg(this->num_loops_, + get_opts.opt_arg(), + c, + "num_loops", + 1); + break; + + case 'u': + result = this->set_arg(this->use_csd_, + get_opts.opt_arg(), + c, + "use_csd_flag"); + break; + + case 'x': + this->scenario_id_ = get_opts.opt_arg(); + break; + + case 'z': + result = this->set_arg(this->trial_id_, + get_opts.opt_arg(), + c, + "trial_id_number", + 1); + break; + + case '?': + this->usage_statement(); + return 1; + + default: + this->usage_statement(); + return -1; + } + + if (result != 0) + { + return result; + } + } + + return this->arg_dependency_checks(); +} + +void +ServerApp::usage_statement() +{ + ACE_ERROR((LM_ERROR, + "Usage: %s [options]\n\n" + "OPTIONS:\n\n" + "\t[-p <ior_filename_prefix>]\n" + "\t[-s <num_servants>]\n" + "\t[-n <num_csd_threads>]\n" + "\t[-t <num_orb_threads>]\n" + "\t[-r <num_remote_clients>]\n" + "\t[-c <num_collocated_clients>]\n" + "\t[-l <num_loops>]\n" + "\t[-u <use_csd_flag>]\n" + "\t[-x <scenario_id_string>]\n" + "\t[-z <trial_id_number>]\n" + "\t[-?]\n\n", + this->exe_name_.c_str())); +} + + +int +ServerApp::arg_dependency_checks() +{ + return (this->num_remote_clients_ + + this->num_collocated_clients_) > 0 ? 0 : -1; +} + + +int +ServerApp::set_arg(unsigned& value, + const char* arg, + char opt, + const char* name, + int min) +{ + int tmp = ACE_OS::atoi(arg); + + if (tmp < min) + { + ACE_ERROR((LM_ERROR, + "Error: -%c <%s> must be integer type with a value of, " + "at least, %d.\n", opt, name, min)); + this->usage_statement(); + return -1; + } + + value = tmp; + return 0; +} + + +PortableServer::POA_ptr +ServerApp::create_poa(CORBA::ORB_ptr orb, + const char* poa_name + ACE_ENV_ARG_DECL) +{ + // Get the Root POA. + PortableServer::POA_var root_poa + = RefHelper<PortableServer::POA>::resolve_initial_ref(orb, + "RootPOA" + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + // Get the POAManager from the Root POA. + PortableServer::POAManager_var poa_manager + = root_poa->the_POAManager(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + // Create the child POA Policies. + CORBA::PolicyList policies(0); + policies.length(0); + + // Create the child POA + PortableServer::POA_var poa = AppHelper::create_poa(poa_name, + root_poa.in(), + poa_manager.in(), + policies + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + // Give away the child POA_ptr from the POA_var variable. + return poa._retn(); +} + + +bool +ServerApp::check_results() +{ + + this->stats_.init(this->num_remote_clients_ + + this->num_collocated_clients_, + this->num_loops_); + + Foo_ClientEngine::expected_results(this->stats_); + + for (unsigned i = 0; i < this->num_servants_; i++) + { + this->servants_.servant(i)->gather_stats(this->stats_); + } + + this->stats_.actual_vs_expected(); + + return true; +} diff --git a/TAO/performance-tests/CSD_Strategy/TestApps/ServerApp.h b/TAO/performance-tests/CSD_Strategy/TestApps/ServerApp.h new file mode 100644 index 00000000000..a9029d65703 --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestApps/ServerApp.h @@ -0,0 +1,95 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file ServerApp.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= +#ifndef SERVERAPP_H +#define SERVERAPP_H + +#include "TestInf/TestAppBase.h" +#include "TestInf/ServantList_T.h" +#include "TestInf/ClientTask.h" +#include "TestServant/Foo_i.h" +#include "TestServant/Foo_Statistics.h" +#include "tao/CSD_ThreadPool/CSD_TP_Strategy.h" +#include "ace/SString.h" + + +class ServerApp : public TestAppBase +{ + public: + + ServerApp(); + virtual ~ServerApp(); + + + protected: + + virtual int run_i(int argc, char* argv[] ACE_ENV_ARG_DECL); + + + private: + + // These are all called, in order, by the run_i() method. + int init(int argc, char* argv[] ACE_ENV_ARG_DECL); + void poa_setup(ACE_ENV_SINGLE_ARG_DECL); + void csd_setup(ACE_ENV_SINGLE_ARG_DECL); + void servant_setup(ACE_ENV_SINGLE_ARG_DECL); + void collocated_setup(); + void poa_activate(ACE_ENV_SINGLE_ARG_DECL); + void run_collocated_clients(ACE_ENV_SINGLE_ARG_DECL); + void run_orb_event_loop(ACE_ENV_SINGLE_ARG_DECL); + bool check_results(); + void cleanup(); + + + // Helper methods used by the methods above. + int parse_args(int argc, char* argv[]); + + int set_arg(unsigned& value, + const char* arg, + char opt, + const char* name, + int min = 0); + + void usage_statement(); + int arg_dependency_checks(); + + + PortableServer::POA_ptr create_poa(CORBA::ORB_ptr orb, + const char* poa_name + ACE_ENV_ARG_DECL); + + typedef ServantList<Foo_i> ServantListType; + + CORBA::ORB_var orb_; + PortableServer::POA_var poa_; + TAO::CSD::TP_Strategy_Handle tp_strategy_; + + ServantListType servants_; + + ClientTask collocated_client_task_; + + ACE_CString exe_name_; + ACE_CString ior_filename_prefix_; + unsigned num_servants_; + unsigned num_csd_threads_; + unsigned num_orb_threads_; + unsigned num_remote_clients_; + unsigned num_collocated_clients_; + unsigned num_loops_; + unsigned use_csd_; + + ACE_CString scenario_id_; + unsigned trial_id_; + + Foo_Statistics stats_; +}; + +#endif diff --git a/TAO/performance-tests/CSD_Strategy/TestApps/client_main.cpp b/TAO/performance-tests/CSD_Strategy/TestApps/client_main.cpp new file mode 100644 index 00000000000..3481f7068f7 --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestApps/client_main.cpp @@ -0,0 +1,7 @@ +// $Id$ +#include "TestInf/TestAppMain.h" +#include "ClientApp.h" + +TEST_APP_MAIN(ClientApp) + + diff --git a/TAO/performance-tests/CSD_Strategy/TestApps/csd_pt_testapps.mpc b/TAO/performance-tests/CSD_Strategy/TestApps/csd_pt_testapps.mpc new file mode 100644 index 00000000000..330fcd4afc5 --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestApps/csd_pt_testapps.mpc @@ -0,0 +1,21 @@ +// -*- MPC -*- +// $Id$ + +project(csd_test_server): csd_pt_test_exe { + exename=server_main + + Source_Files { + ServerApp.cpp + server_main.cpp + } +} + +project(csd_test_client): csd_pt_test_exe { + exename=client_main + + Source_Files { + ClientApp.cpp + client_main.cpp + } +} + diff --git a/TAO/performance-tests/CSD_Strategy/TestApps/run_test.pl b/TAO/performance-tests/CSD_Strategy/TestApps/run_test.pl new file mode 100755 index 00000000000..42469543ce0 --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestApps/run_test.pl @@ -0,0 +1,227 @@ +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; + +# 5 Minute server timeout. +my $server_timeout_secs = 300; + +my $status = 0; + +my $iorfname_prefix = "servant"; +my $num_servants = 1; +my $num_orb_threads = 1; +my $num_remote_clients = 1; +my $num_csd_threads = 1; +my $num_collocated_clients = 0; +my $num_loops = 100; +my $use_csd = 1; +my $scenario_id = "UnsetScenarioId"; +my $trial_id = 1; + +my $i; +my $j; +my @iorfile; + +my $ARGC = @ARGV; + +if ($ARGC > 0) +{ + if ($ARGC > 3) + { + print STDERR "ERROR: Too many command-line arguments for $0.\n"; + exit 1; + } + + if ($ARGC < 2) + { + print STDERR "ERROR: Too few command-line arguments for $0.\n"; + exit 1; + } + + if ($ARGC > 2) + { + $num_loops = $ARGV[2]; + } + + $scenario_id = $ARGV[0]; + $trial_id = $ARGV[1]; + + my $subtest = $scenario_id; + + if ($subtest =~ /^x_(.+)$/) + { + $subtest = $1; + $use_csd = 0; + } + + if ($subtest eq 'remote') + { + $num_remote_clients = 40; + } + elsif ($subtest eq 'collocated') + { + $num_remote_clients = 0; + $num_collocated_clients = 10; + } + elsif ($subtest eq 'remote_orbthreads') + { + $num_orb_threads = 5; + $num_remote_clients = 40; + } + elsif ($subtest eq 'remote_servants') + { + $num_servants = 5; + $num_remote_clients = 40; + } + elsif ($subtest eq 'remote_csdthreads') + { + $num_csd_threads = 5; + $num_servants = 5; + $num_remote_clients = 40; + } + elsif ($subtest eq 'remote_big') + { + $num_csd_threads = 5; + $num_servants = 10; + $num_orb_threads = 4; + $num_remote_clients = 40; + } + elsif ($subtest eq 'collocated_big') + { + $num_csd_threads = 5; + $num_servants = 10; + $num_remote_clients = 0; + $num_collocated_clients = 40; + } + elsif ($subtest eq 'big') + { + $num_csd_threads = 5; + $num_servants = 10; + $num_orb_threads = 4; + $num_remote_clients = 40; + $num_collocated_clients = 40; + } + elsif ($subtest eq 'remote_huge') + { + $num_csd_threads = 5; + $num_servants = 10; + $num_orb_threads = 4; + $num_remote_clients = 400; + $num_loops = $num_loops / 10; + # 15 minute server timeout + $server_timeout_secs = 1800; + } + elsif ($subtest eq 'collocated_huge') + { + $num_csd_threads = 20; + $num_servants = 10; + $num_remote_clients = 0; + $num_collocated_clients = 40; + } + elsif ($subtest eq 'usage') + { + print STDOUT "Usage: $0 [<subtest>]\n" . + "\n" . + "Supported <subtest> values:\n" . + "\n" . + "\tremote\n" . + "\tcollocated\n" . + "\tremote_orbthreads\n" . + "\tremote_servants\n" . + "\tremote_csdthreads\n" . + "\tremote_big\n" . + "\tcollocated_big\n" . + "\tbig\n" . + "\tremote_huge\n" . + "\tusage\n" . + "\n"; + exit 0; + } + else + { + print STDERR "ERROR: invalid subtest argument for $0: $subtest\n"; + exit 1; + } +} + +#Delete old ior files. +for ($i = 0; $i < $num_servants; $i++) { + my $servant_id = sprintf("%02d", ($i + 1)); + $iorfile[$i] = PerlACE::LocalFile($iorfname_prefix . "_$servant_id.ior"); + unlink $iorfile[$i]; +} + +$SV = new PerlACE::Process("server_main", + "-p $iorfname_prefix " . + "-s $num_servants " . + "-n $num_csd_threads " . + "-t $num_orb_threads " . + "-r $num_remote_clients " . + "-c $num_collocated_clients " . + "-l $num_loops " . + "-u $use_csd " . + "-x $scenario_id " . + "-z $trial_id"); + +$SV->Spawn(); + +# Wait for the servant ior files created by server. +for ($i = 0; $i < $num_servants; $i++) { + if (PerlACE::waitforfile_timed + ($iorfile[$i], + $PerlACE::wait_interval_for_process_creation) == -1) { + print STDERR "ERROR: cannot find file <$iorfile[$i]>\n"; + $SV->Kill(); + $SV->TimedWait(1); + exit 1; + } +} + +my $count = 0; + +for ($i = 0; $i < $num_remote_clients; $i++) +{ + $client_id = $i+1; + + # Round-robin assignment of servants to clients. + $j = $i % $num_servants; + + $CLS[$i] = new PerlACE::Process("client_main", + "-i file://$iorfile[$j] ". + "-n $client_id " . + "-l $num_loops"); + + $CLS[$i]->Spawn(); +} + +for ($i = 0; $i < $num_remote_clients; $i++) +{ + $client = $CLS[$i]->WaitKill(600); + + if ($client != 0) + { + print STDERR "ERROR: client $i returned $client\n"; + $status = 1; + } +} + + +$server = $SV->WaitKill(600); + +if ($server != 0) { + print STDERR "ERROR: server returned $server\n"; + $status = 1; +} + +#Delete ior files generated by this run. +for ($i = 0; $i < $num_servants; $i++) { + unlink $iorfile[$i]; +} + +exit $status; diff --git a/TAO/performance-tests/CSD_Strategy/TestApps/server_main.cpp b/TAO/performance-tests/CSD_Strategy/TestApps/server_main.cpp new file mode 100644 index 00000000000..d0d2aa30fff --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestApps/server_main.cpp @@ -0,0 +1,5 @@ +// $Id$ +#include "TestInf/TestAppMain.h" +#include "ServerApp.h" + +TEST_APP_MAIN(ServerApp) diff --git a/TAO/performance-tests/CSD_Strategy/TestInf/AppHelper.cpp b/TAO/performance-tests/CSD_Strategy/TestInf/AppHelper.cpp new file mode 100644 index 00000000000..0f60191a9bd --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestInf/AppHelper.cpp @@ -0,0 +1,102 @@ +// $Id$ +#include "AppHelper.h" + +void +AppHelper::ref_to_file(CORBA::ORB_ptr orb, + CORBA::Object_ptr obj, + const char* filename + ACE_ENV_ARG_DECL) +{ + CORBA::String_var ior = orb->object_to_string(obj); + + FILE* ior_file = ACE_OS::fopen(filename, "w"); + + if (ior_file == 0) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Cannot open output file [%s] to write IOR.", + filename)); + ACE_THROW (TestAppException()); + } + + ACE_OS::fprintf(ior_file, "%s", ior.in()); + ACE_OS::fclose(ior_file); +} + + +PortableServer::POA_ptr +AppHelper::create_poa(const char* name, + PortableServer::POA_ptr root_poa, + PortableServer::POAManager_ptr mgr, + CORBA::PolicyList& policies + ACE_ENV_ARG_DECL) +{ + PortableServer::POA_var child_poa = root_poa->create_POA(name, + mgr, + policies + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + if (CORBA::is_nil(child_poa.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to create child POA: %s.\n", name)); + ACE_THROW_RETURN (TestAppException(), PortableServer::POA::_nil ()); + } + + return child_poa._retn(); +} + + +CORBA::Object_ptr +AppHelper::activate_servant(PortableServer::POA_ptr poa, + PortableServer::Servant servant + ACE_ENV_ARG_DECL) +{ + // Activate the servant using the Child POA. + PortableServer::ObjectId_var oid + = poa->activate_object(servant ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (CORBA::Object::_nil ()); + + CORBA::Object_var obj + = poa->servant_to_reference(servant ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (CORBA::Object::_nil ()); + + if (CORBA::is_nil(obj.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to convert servant_to_ref.\n")); + ACE_THROW_RETURN (TestAppException(), CORBA::Object::_nil ()); + } + + return obj._retn(); +} + + +bool +AppHelper::validate_connection (CORBA::Object_ptr obj) +{ + for (CORBA::ULong j = 0; j != 100; ++j) + { + ACE_TRY_NEW_ENV + { +#if (TAO_HAS_CORBA_MESSAGING == 1) + CORBA::PolicyList_var unused; + obj->_validate_connection (unused + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; +#else + obj->_is_a ("Not_An_IDL_Type" + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; +#endif /* TAO_HAS_MESSAGING == 1 */ + return true; + } + ACE_CATCHANY + { + } + ACE_ENDTRY; + } + + return false; +} diff --git a/TAO/performance-tests/CSD_Strategy/TestInf/AppHelper.h b/TAO/performance-tests/CSD_Strategy/TestInf/AppHelper.h new file mode 100644 index 00000000000..bdc6c2ab5b3 --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestInf/AppHelper.h @@ -0,0 +1,114 @@ +// $Id$ +#ifndef APPHELPER_H +#define APPHELPER_H + +#include "CSD_PT_TestInf_Export.h" +#include "TestAppExceptionC.h" +#include "tao/PortableServer/PortableServer.h" +#include "tao/ORB.h" +#include "ace/OS.h" +#include "ace/Log_Msg.h" + + +template <typename T> +struct RefHelper +{ + typedef typename T::_ptr_type T_ptr; + typedef typename T::_var_type T_var; + + static T_ptr string_to_ref(CORBA::ORB_ptr orb, + const char* ior + ACE_ENV_ARG_DECL) + { + CORBA::Object_var obj = orb->string_to_object(ior ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN(T::_nil ()); + + if (CORBA::is_nil(obj.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to convert IOR string to obj ref.\n")); + ACE_THROW_RETURN (TestAppException(), T::_nil ()); + } + + T_var t_obj = T::_narrow(obj.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN(T::_nil ()); + + if (CORBA::is_nil(t_obj.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to narrow obj ref to T interface.\n")); + ACE_THROW_RETURN (TestAppException(), T::_nil ()); + } + + return t_obj._retn(); + } + + static T_ptr resolve_initial_ref(CORBA::ORB_ptr orb, + const char* name + ACE_ENV_ARG_DECL) + { + CORBA::Object_var obj + = orb->resolve_initial_references(name ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (T::_nil ()); + + if (CORBA::is_nil(obj.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to resolve initial ref for '%s'.\n", + name)); + ACE_THROW_RETURN (TestAppException(), T::_nil ()); + } + + T_var t_obj = T::_narrow(obj.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (T::_nil ()); + + + if (CORBA::is_nil(t_obj.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to narrow resolved initial ref '%s'.\n", + name)); + ACE_THROW_RETURN (TestAppException(), T::_nil ()); + } + + return t_obj._retn(); + } + +}; + +struct CSD_PT_TestInf_Export AppHelper +{ + + static void ref_to_file(CORBA::ORB_ptr orb, + CORBA::Object_ptr obj, + const char* filename + ACE_ENV_ARG_DECL); + + static PortableServer::POA_ptr create_poa + (const char* name, + PortableServer::POA_ptr root_poa, + PortableServer::POAManager_ptr mgr, + CORBA::PolicyList& policies + ACE_ENV_ARG_DECL); + + static CORBA::Object_ptr activate_servant(PortableServer::POA_ptr poa, + PortableServer::Servant servant + ACE_ENV_ARG_DECL); + + // This helper method is used because there is a chance that the + // initial CORBA request made to the target ORB will fail during + // connection establishment with a TRANSIENT CORBA SystemException. + // This occurs for some platforms (ie, windows) when several clients + // make their initial CORBA request to the same ORB at the same time, + // causing the ORB to attempt to handle several connection establishments + // at one time. Apparently, under certain conditions, it will throw the + // TRANSIENT exception to tell the client application to "try again later". + // The analogy is making a phone call. Sometimes you get a busy tone. + // This means "try again later". + // This helper function will retry until the connection establishment + // works - or until it decides that enough is enough. + static bool validate_connection (CORBA::Object_ptr obj); +}; + +#endif + diff --git a/TAO/performance-tests/CSD_Strategy/TestInf/AppShutdown.cpp b/TAO/performance-tests/CSD_Strategy/TestInf/AppShutdown.cpp new file mode 100644 index 00000000000..79d7f28c0d9 --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestInf/AppShutdown.cpp @@ -0,0 +1,84 @@ +// $Id$ +#include "AppShutdown.h" +#include "TestAppExceptionC.h" +#include "ace/Log_Msg.h" +#include "ace/OS_NS_unistd.h" + +AppShutdown::AppShutdown() + : num_clients_(0), + num_clients_shutdown_(0) +{ +} + + +AppShutdown::~AppShutdown() +{ +} + + +void +AppShutdown::init(CORBA::ORB_ptr orb, + unsigned num_clients + ACE_ENV_ARG_DECL) +{ + if ((!CORBA::is_nil(this->orb_.in())) || + (CORBA::is_nil(orb)) || + (num_clients == 0)) + { + // Already init()'ed, or bad argument values. + ACE_THROW(TestAppException()); + } + else + { + this->orb_ = CORBA::ORB::_duplicate(orb); + this->num_clients_ = num_clients; + this->num_clients_shutdown_ = 0; + } +} + + +void +AppShutdown::wait () +{ + this->orb_shutdown_task_.wait(); +} + + +void +AppShutdown::client_done() +{ + if ((this->num_clients_ == 0) || (CORBA::is_nil(this->orb_.in()))) + { + ACE_ERROR((LM_ERROR, "(%P|%t) AppShutdown was never initialized.\n")); + return; + } + + unsigned cur_shutdown; + + { + GuardType guard(this->lock_); + cur_shutdown = ++this->num_clients_shutdown_; + } + + if (cur_shutdown == this->num_clients_) + { + // Sleep for one second before shutting down the ORB. This + // is a poor-man version of "wait until the CSD request queue drains". + ACE_OS::sleep(1); + this->orb_shutdown_task_.orb(this->orb_.in()); + if (this->orb_shutdown_task_.open(0) != 0) + { + ACE_ERROR((LM_ERROR, "(%P|%t) AppShutdown failed to create orb "\ + "shutdown thread.\n")); + return; + } + } +} + + +AppShutdown* +AppShutdown::instance () +{ + static AppShutdown app_shutdown; + return &app_shutdown; +} diff --git a/TAO/performance-tests/CSD_Strategy/TestInf/AppShutdown.h b/TAO/performance-tests/CSD_Strategy/TestInf/AppShutdown.h new file mode 100644 index 00000000000..481659d734e --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestInf/AppShutdown.h @@ -0,0 +1,42 @@ +// $Id$ +#ifndef APP_SHUTDOWN_H +#define APP_SHUTDOWN_H + +#include "CSD_PT_TestInf_Export.h" +#include "OrbShutdownTask.h" +#include "tao/ORB.h" + +class CSD_PT_TestInf_Export AppShutdown +{ + public: + + AppShutdown(); + virtual ~AppShutdown(); + + void init(CORBA::ORB_ptr orb, + unsigned num_clients + ACE_ENV_ARG_DECL); + + void wait (); + + void client_done(); + + static AppShutdown* instance (); + + private: + + typedef ACE_SYNCH_MUTEX LockType; + typedef ACE_Guard<LockType> GuardType; + + LockType lock_; + CORBA::ORB_var orb_; + unsigned num_clients_; + unsigned num_clients_shutdown_; + + OrbShutdownTask orb_shutdown_task_; +}; + + +#define TheAppShutdown AppShutdown::instance() + +#endif diff --git a/TAO/performance-tests/CSD_Strategy/TestInf/CSD_PT_TestInf_Export.h b/TAO/performance-tests/CSD_Strategy/TestInf/CSD_PT_TestInf_Export.h new file mode 100644 index 00000000000..91f36276272 --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestInf/CSD_PT_TestInf_Export.h @@ -0,0 +1,58 @@ + +// -*- C++ -*- +// $Id$ +// Definition for Win32 Export directives. +// This file is generated automatically by generate_export_file.pl -s CSD_PT_TestInf +// ------------------------------ +#ifndef CSD_PT_TESTINF_EXPORT_H +#define CSD_PT_TESTINF_EXPORT_H + +#include "ace/config-all.h" + +#if defined (ACE_AS_STATIC_LIBS) && !defined (CSD_PT_TESTINF_HAS_DLL) +# define CSD_PT_TESTINF_HAS_DLL 0 +#endif /* ACE_AS_STATIC_LIBS && CSD_PT_TESTINF_HAS_DLL */ + +#if !defined (CSD_PT_TESTINF_HAS_DLL) +# define CSD_PT_TESTINF_HAS_DLL 1 +#endif /* ! CSD_PT_TESTINF_HAS_DLL */ + +#if defined (CSD_PT_TESTINF_HAS_DLL) && (CSD_PT_TESTINF_HAS_DLL == 1) +# if defined (CSD_PT_TESTINF_BUILD_DLL) +# define CSD_PT_TestInf_Export ACE_Proper_Export_Flag +# define CSD_PT_TESTINF_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T) +# define CSD_PT_TESTINF_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# else /* CSD_PT_TESTINF_BUILD_DLL */ +# define CSD_PT_TestInf_Export ACE_Proper_Import_Flag +# define CSD_PT_TESTINF_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T) +# define CSD_PT_TESTINF_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# endif /* CSD_PT_TESTINF_BUILD_DLL */ +#else /* CSD_PT_TESTINF_HAS_DLL == 1 */ +# define CSD_PT_TestInf_Export +# define CSD_PT_TESTINF_SINGLETON_DECLARATION(T) +# define CSD_PT_TESTINF_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +#endif /* CSD_PT_TESTINF_HAS_DLL == 1 */ + +// Set CSD_PT_TESTINF_NTRACE = 0 to turn on library specific tracing even if +// tracing is turned off for ACE. +#if !defined (CSD_PT_TESTINF_NTRACE) +# if (ACE_NTRACE == 1) +# define CSD_PT_TESTINF_NTRACE 1 +# else /* (ACE_NTRACE == 1) */ +# define CSD_PT_TESTINF_NTRACE 0 +# endif /* (ACE_NTRACE == 1) */ +#endif /* !CSD_PT_TESTINF_NTRACE */ + +#if (CSD_PT_TESTINF_NTRACE == 1) +# define CSD_PT_TESTINF_TRACE(X) +#else /* (CSD_PT_TESTINF_NTRACE == 1) */ +# if !defined (ACE_HAS_TRACE) +# define ACE_HAS_TRACE +# endif /* ACE_HAS_TRACE */ +# define CSD_PT_TESTINF_TRACE(X) ACE_TRACE_IMPL(X) +# include "ace/Trace.h" +#endif /* (CSD_PT_TESTINF_NTRACE == 1) */ + +#endif /* CSD_PT_TESTINF_EXPORT_H */ + +// End of auto generated file. diff --git a/TAO/performance-tests/CSD_Strategy/TestInf/CancelledException.idl b/TAO/performance-tests/CSD_Strategy/TestInf/CancelledException.idl new file mode 100644 index 00000000000..8f9afcf68de --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestInf/CancelledException.idl @@ -0,0 +1,7 @@ +// $Id$ +#ifndef CANCELAPPXCEPTION_IDL +#define CANCELAPPXCEPTION_IDL + +exception CancelledException {}; + +#endif diff --git a/TAO/performance-tests/CSD_Strategy/TestInf/ClientEngine.cpp b/TAO/performance-tests/CSD_Strategy/TestInf/ClientEngine.cpp new file mode 100644 index 00000000000..361bb3cd465 --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestInf/ClientEngine.cpp @@ -0,0 +1,12 @@ +// $Id$ +#include "ClientEngine.h" + + +ClientEngine::ClientEngine() +{ +} + + +ClientEngine::~ClientEngine() +{ +} diff --git a/TAO/performance-tests/CSD_Strategy/TestInf/ClientEngine.h b/TAO/performance-tests/CSD_Strategy/TestInf/ClientEngine.h new file mode 100644 index 00000000000..93acb571cdc --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestInf/ClientEngine.h @@ -0,0 +1,39 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file ClientEngine.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef CLIENT_ENGINE_H +#define CLIENT_ENGINE_H + +#include "CSD_PT_TestInf_Export.h" +#include "tao/Intrusive_Ref_Count_Base_T.h" +#include "tao/Intrusive_Ref_Count_Handle_T.h" +#include "tao/Environment.h" +#include "ace/Synch.h" +#include "ace/CORBA_macros.h" + + +class ClientEngine; +typedef TAO_Intrusive_Ref_Count_Handle<ClientEngine> ClientEngine_Handle; + + +class CSD_PT_TestInf_Export ClientEngine : public TAO_Intrusive_Ref_Count_Base<ACE_SYNCH_MUTEX> +{ + public: + + ClientEngine(); + virtual ~ClientEngine(); + + virtual bool execute(unsigned num_loops + ACE_ENV_ARG_DECL) = 0; +}; + +#endif diff --git a/TAO/performance-tests/CSD_Strategy/TestInf/ClientTask.cpp b/TAO/performance-tests/CSD_Strategy/TestInf/ClientTask.cpp new file mode 100644 index 00000000000..9b5ad8bc3cd --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestInf/ClientTask.cpp @@ -0,0 +1,117 @@ +// $Id$ +// This may look like C, but it's really -*- C++ -*- +#include "ClientTask.h" +#include "tao/Exception.h" +#include "ace/SString.h" + + +ClientTask::ClientTask() + : failure_count_(0), + num_loops_(1) +{ +} + + +ClientTask::~ClientTask() +{ +} + + +void +ClientTask::add_engine(ClientEngine* engine) +{ + // Pass in false so that _add_ref() is called. + ClientEngine_Handle engine_handle(engine,false); + this->engines_.push_back(engine_handle); +} + + +void +ClientTask::num_loops(unsigned num_loops) +{ + this->num_loops_ = num_loops; +} + + +int +ClientTask::open(void*) +{ + unsigned num_threads = this->engines_.size(); + + if (num_threads == 0) + { + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) ClientTask cannot activate 0 threads.\n"), + -1); + } + + if (this->activate(THR_NEW_LWP | THR_JOINABLE, num_threads) != 0) + { + // Assumes that when activate returns non-zero return code that + // no threads were activated. + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) ClientTask failed to activate " + "the %d client threads.\n", num_threads), + -1); + } + + return 0; +} + + +int +ClientTask::svc() +{ + ClientEngine_Handle engine; + unsigned num_loops; + + { + GuardType guard(this->lock_); + this->engines_.get(engine, this->engines_.size() - 1); + this->engines_.pop_back(); + num_loops = this->num_loops_; + } + + ACE_TRY_NEW_ENV + { + if (engine->execute(num_loops ACE_ENV_ARG_PARAMETER) == false) + { + GuardType guard(this->lock_); + this->failure_count_++; + } + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "ClientTask::svc Caught exception from execute():"); + + GuardType guard(this->lock_); + this->failure_count_ ++; + } + ACE_CATCHALL + { + ACE_ERROR((LM_ERROR, + "(%P|%t) ClientTask::svc caught unknown (...) exception "\ + "in execute() " )); + GuardType guard(this->lock_); + this->failure_count_++; + } + ACE_ENDTRY; + + return 0; +} + + +int +ClientTask::close(u_long) +{ + return 0; +} + + +unsigned +ClientTask::failure_count() const +{ + return this->failure_count_; +} diff --git a/TAO/performance-tests/CSD_Strategy/TestInf/ClientTask.h b/TAO/performance-tests/CSD_Strategy/TestInf/ClientTask.h new file mode 100644 index 00000000000..a99ccc6ad43 --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestInf/ClientTask.h @@ -0,0 +1,53 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file ClientTask.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef CLIENT_TASK_H +#define CLIENT_TASK_H + +#include "CSD_PT_TestInf_Export.h" +#include "ClientEngine.h" +#include "ace/Task.h" +#include "ace/Vector_T.h" +#include "ace/Synch.h" + + +class CSD_PT_TestInf_Export ClientTask : public ACE_Task_Base +{ + public: + + ClientTask(); + virtual ~ClientTask(); + + void add_engine(ClientEngine* engine); + void num_loops(unsigned num_loops); + + virtual int open(void* arg = 0); + virtual int svc(); + virtual int close(u_long); + + unsigned failure_count() const; + + + private: + + typedef ACE_SYNCH_MUTEX LockType; + typedef ACE_Guard<LockType> GuardType; + + typedef ACE_Vector<ClientEngine_Handle> EngineVector; + + LockType lock_; + EngineVector engines_; + unsigned failure_count_; + unsigned num_loops_; +}; + +#endif diff --git a/TAO/performance-tests/CSD_Strategy/TestInf/CustomException.idl b/TAO/performance-tests/CSD_Strategy/TestInf/CustomException.idl new file mode 100644 index 00000000000..794900c41ce --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestInf/CustomException.idl @@ -0,0 +1,7 @@ +// $Id$ +#ifndef CUSTOMEXCEPTION_IDL +#define CUSTOMEXCEPTION_IDL + +exception CustomException {}; + +#endif diff --git a/TAO/performance-tests/CSD_Strategy/TestInf/FooException.idl b/TAO/performance-tests/CSD_Strategy/TestInf/FooException.idl new file mode 100644 index 00000000000..4f76953e24c --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestInf/FooException.idl @@ -0,0 +1,7 @@ +// $Id$ +#ifndef FOOEXCEPTION_IDL +#define FOOEXCEPTION_IDL + +exception FooException {}; + +#endif diff --git a/TAO/performance-tests/CSD_Strategy/TestInf/OrbRunner.cpp b/TAO/performance-tests/CSD_Strategy/TestInf/OrbRunner.cpp new file mode 100644 index 00000000000..fc2ddbdec04 --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestInf/OrbRunner.cpp @@ -0,0 +1,57 @@ +// $Id$ +#include "OrbRunner.h" +#include "OrbTask.h" +#include "TestAppExceptionC.h" + + +OrbRunner::OrbRunner(CORBA::ORB_ptr orb, unsigned num_orb_threads) + : orb_(CORBA::ORB::_duplicate(orb)), + num_orb_threads_(num_orb_threads) +{ +} + + +OrbRunner::~OrbRunner() +{ +} + + +void +OrbRunner::run(ACE_ENV_SINGLE_ARG_DECL) +{ + ACE_ASSERT(this->num_orb_threads_ > 0); + + // If the num_orb_threads_ is exactly one, then just use the current + // (mainline) thread to run the ORB event loop. + if (this->num_orb_threads_ == 1) + { + // Since the num_orb_threads_ is exactly one, we just use the current + // (mainline) thread to run the ORB event loop. + this->orb_->run(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + } + else + { + // The num_orb_threads_ is greater than 1, so we will use an OrbTask + // (active object) to run the ORB event loop in (num_orb_threads_ - 1) + // threads. We use the current (mainline) thread as the other thread + // running the ORB event loop. + OrbTask orb_task(this->orb_.in(), this->num_orb_threads_ - 1); + + // Activate the OrbTask worker threads + if (orb_task.open(0) != 0) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to open the OrbTask.\n")); + ACE_THROW(TestAppException()); + } + + // This will use the current (mainline) thread to run the ORB event loop. + this->orb_->run(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + + // Now that the current thread has unblocked from running the orb, + // make sure to wait for all of the worker threads to complete. + orb_task.wait(); + } +} diff --git a/TAO/performance-tests/CSD_Strategy/TestInf/OrbRunner.h b/TAO/performance-tests/CSD_Strategy/TestInf/OrbRunner.h new file mode 100644 index 00000000000..cdbbcfea222 --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestInf/OrbRunner.h @@ -0,0 +1,24 @@ +// $Id$ +#ifndef ORB_RUNNER_H +#define ORB_RUNNER_H + +#include "CSD_PT_TestInf_Export.h" +#include "tao/ORB.h" + +class CSD_PT_TestInf_Export OrbRunner +{ + public: + + OrbRunner(CORBA::ORB_ptr orb, unsigned num_orb_threads = 1); + virtual ~OrbRunner(); + + void run(ACE_ENV_SINGLE_ARG_DECL); + + + private: + + CORBA::ORB_var orb_; + unsigned num_orb_threads_; +}; + +#endif diff --git a/TAO/performance-tests/CSD_Strategy/TestInf/OrbShutdownTask.cpp b/TAO/performance-tests/CSD_Strategy/TestInf/OrbShutdownTask.cpp new file mode 100644 index 00000000000..79ba1ba3f5e --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestInf/OrbShutdownTask.cpp @@ -0,0 +1,75 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file OrbShutdownTask.cpp + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#include "OrbShutdownTask.h" +#include "ace/CORBA_macros.h" +#include "ace/OS_NS_unistd.h" + + +OrbShutdownTask::OrbShutdownTask() +{ +} + + +OrbShutdownTask::~OrbShutdownTask() +{ +} + + +void +OrbShutdownTask::orb(CORBA::ORB_ptr orb) +{ + this->orb_ = CORBA::ORB::_duplicate(orb); +} + + +int +OrbShutdownTask::open(void*) +{ + if (this->activate(THR_NEW_LWP | THR_JOINABLE, 1) != 0) + { + // Assumes that when activate returns non-zero return code that + // no threads were activated. + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) OrbShutdownTask failed to open().\n"), + -1); + } + + return 0; +} + + +int +OrbShutdownTask::svc() +{ + ACE_TRY_NEW_ENV + { + this->orb_->shutdown(0 ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHALL + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Exception raised by ORB::shutdown() call " + "in OrbShutdownTask::svc().\n")); + } + ACE_ENDTRY; + + return 0; +} + + +int +OrbShutdownTask::close(u_long) +{ + return 0; +} diff --git a/TAO/performance-tests/CSD_Strategy/TestInf/OrbShutdownTask.h b/TAO/performance-tests/CSD_Strategy/TestInf/OrbShutdownTask.h new file mode 100644 index 00000000000..11f2bbd341a --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestInf/OrbShutdownTask.h @@ -0,0 +1,40 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file OrbShutdownTask.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef ORB_SHUTDOWN_TASK_H +#define ORB_SHUTDOWN_TASK_H + +#include "CSD_PT_TestInf_Export.h" +#include "ace/Task.h" +#include "tao/ORB.h" + + +class CSD_PT_TestInf_Export OrbShutdownTask : public ACE_Task_Base +{ + public: + + OrbShutdownTask(); + virtual ~OrbShutdownTask(); + + void orb(CORBA::ORB_ptr orb); + + virtual int open(void*); + virtual int svc(); + virtual int close(u_long); + + + private: + + CORBA::ORB_var orb_; +}; + +#endif diff --git a/TAO/performance-tests/CSD_Strategy/TestInf/OrbTask.cpp b/TAO/performance-tests/CSD_Strategy/TestInf/OrbTask.cpp new file mode 100644 index 00000000000..bca9d522e94 --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestInf/OrbTask.cpp @@ -0,0 +1,98 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file OrbTask.cpp + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#include "OrbTask.h" + +namespace { enum { MAX_ORB_TASK_WORKER_THREADS = 20 }; } + + +OrbTask::OrbTask(CORBA::ORB_ptr orb, unsigned num_threads) + : orb_(CORBA::ORB::_duplicate(orb)), + num_threads_(num_threads) +{ +} + + +OrbTask::~OrbTask() +{ +} + + +int +OrbTask::open(void*) +{ + if (this->num_threads_ < 1) + { + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) OrbTask failed to open. " + "num_threads_ (%d) is less-than 1.\n", + this->num_threads_), + -1); + } + + if (this->num_threads_ > MAX_ORB_TASK_WORKER_THREADS) + { + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) OrbTask failed to open. " + "num_threads_ (%d) is too large. Max is %d.\n", + this->num_threads_, MAX_ORB_TASK_WORKER_THREADS), + -1); + } + + if (CORBA::is_nil(this->orb_.in())) + { + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) OrbTask failed to open. " + "ORB object reference is nil.\n"), + -1); + } + + if (this->activate(THR_NEW_LWP | THR_JOINABLE, this->num_threads_) != 0) + { + // Assumes that when activate returns non-zero return code that + // no threads were activated. + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) OrbTask failed to activate " + "(%d) worker threads.\n", + this->num_threads_), + -1); + } + + return 0; +} + + +int +OrbTask::svc() +{ + ACE_TRY_NEW_ENV + { + this->orb_->run(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHALL + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Exception raised by ORB::run() method. " + "OrbTask is stopping.\n")); + } + ACE_ENDTRY; + + return 0; +} + + +int +OrbTask::close(u_long) +{ + return 0; +} diff --git a/TAO/performance-tests/CSD_Strategy/TestInf/OrbTask.h b/TAO/performance-tests/CSD_Strategy/TestInf/OrbTask.h new file mode 100644 index 00000000000..3631273c548 --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestInf/OrbTask.h @@ -0,0 +1,39 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file OrbTask.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef ORB_TASK_H +#define ORB_TASK_H + +#include "CSD_PT_TestInf_Export.h" +#include "ace/Task.h" +#include "tao/ORB.h" + + +class CSD_PT_TestInf_Export OrbTask : public ACE_Task_Base +{ + public: + + OrbTask(CORBA::ORB_ptr orb, unsigned num_threads = 1); + virtual ~OrbTask(); + + virtual int open(void*); + virtual int svc(); + virtual int close(u_long); + + + private: + + CORBA::ORB_var orb_; + unsigned num_threads_; +}; + +#endif diff --git a/TAO/performance-tests/CSD_Strategy/TestInf/README b/TAO/performance-tests/CSD_Strategy/TestInf/README new file mode 100644 index 00000000000..1d7f59a5c47 --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestInf/README @@ -0,0 +1,13 @@ +/** + +@page CSD_Strategy TestInf README File + + This is the test infrastructure library. It contains the common shared +code such as test exception idl files, the helper functions that wrap multiple +TAO operations and the classes provide the basic test functionalities. Adding +this library is to simplify the development of the new tests. + +*/ + + + diff --git a/TAO/performance-tests/CSD_Strategy/TestInf/ServantList_T.cpp b/TAO/performance-tests/CSD_Strategy/TestInf/ServantList_T.cpp new file mode 100644 index 00000000000..22133fa9868 --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestInf/ServantList_T.cpp @@ -0,0 +1,102 @@ +// $Id$ +#include "ServantList_T.h" +#include "AppHelper.h" +#include "TestAppExceptionC.h" + + +template <typename T> +ServantList<T>::ServantList() +{ +} + + +template <typename T> +ServantList<T>::~ServantList() +{ +} + + +template <typename T> +void +ServantList<T>::create_and_activate(unsigned num_servants, + CORBA::ORB_ptr orb, + PortableServer::POA_ptr poa, + const char* ior_fname_prefix + ACE_ENV_ARG_DECL) +{ + for (unsigned i = 0; i < num_servants; i++) + { + char buf[32]; + ACE_OS::sprintf(buf, "%02d", i + 1); + ACE_CString filename = ACE_CString(ior_fname_prefix) + "_" + buf + ".ior"; + ServantRecord record; + record.servant_ = new T(); + record.safe_servant_ = record.servant_; + + CORBA::Object_var obj + = AppHelper::activate_servant(poa, + record.safe_servant_.in() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + AppHelper::ref_to_file(orb, obj.in(), filename.c_str() ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + record.obj_ = T_stub::_narrow(obj.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + if (CORBA::is_nil(record.obj_.in())) + { + ACE_THROW (TestAppException()); + } + + this->servant_records_.push_back(record); + } +} + + +template <typename T> +void +ServantList<T>::create_and_activate(unsigned num_servants, + PortableServer::POA_ptr poa + ACE_ENV_ARG_DECL) +{ + for (unsigned i = 0; i < num_servants; i++) + { + ServantRecord record; + record.servant_ = new T(); + record.safe_servant_ = record.servant_; + + CORBA::Object_var obj + = AppHelper::activate_servant(poa, + record.safe_servant_.in() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + record.obj_ = T_stub::_narrow(obj.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + if (CORBA::is_nil(record.obj_.in())) + { + ACE_THROW (TestAppException()); + } + + this->servant_records_.push_back(record); + } +} + + +template <typename T> +typename ServantList<T>::T_stub_ptr +ServantList<T>::objref(unsigned index) +{ + return T_stub::_duplicate(this->servant_records_[index].obj_.in()); +} + + +template <typename T> +T* +ServantList<T>::servant(unsigned index) +{ + return this->servant_records_[index].servant_; +} diff --git a/TAO/performance-tests/CSD_Strategy/TestInf/ServantList_T.h b/TAO/performance-tests/CSD_Strategy/TestInf/ServantList_T.h new file mode 100644 index 00000000000..57143d889c1 --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestInf/ServantList_T.h @@ -0,0 +1,67 @@ +// $Id$ +#ifndef SERVANTLIST_T_H +#define SERVANTLIST_T_H + +#include "tao/PortableServer/PortableServer.h" +#include "tao/PortableServer/Servant_Base.h" +#include "ace/Vector_T.h" + + +// The T type is a concrete servant type. +template <class T> +class ServantList +{ + public: + + typedef typename T::_stub_type T_stub; + typedef typename T::_stub_ptr_type T_stub_ptr; + typedef typename T::_stub_var_type T_stub_var; + + ServantList(); + ~ServantList(); + + /// Activate servant and output ior to a file. + void create_and_activate(unsigned num_servants, + CORBA::ORB_ptr orb, + PortableServer::POA_ptr poa, + const char* ior_fname_prefix + ACE_ENV_ARG_DECL); + + /// Activate servant and not output ior to a file. + void create_and_activate(unsigned num_servants, + PortableServer::POA_ptr poa + ACE_ENV_ARG_DECL); + + + /// Get a (copy) of one of the object references (for a specific servant). + T_stub_ptr objref(unsigned index); + + /// This doesn't return a copy. + T* servant(unsigned index); + + + private: + + struct ServantRecord + { + T* servant_; + PortableServer::ServantBase_var safe_servant_; + T_stub_var obj_; + }; + + typedef ACE_Vector<ServantRecord> ServantRecordVector; + + ServantRecordVector servant_records_; +}; + + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ServantList_T.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("ServantList_T.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#endif /* SERVANTLIST_T_H */ + diff --git a/TAO/performance-tests/CSD_Strategy/TestInf/TestAppBase.cpp b/TAO/performance-tests/CSD_Strategy/TestInf/TestAppBase.cpp new file mode 100644 index 00000000000..f2a2e97b7a2 --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestInf/TestAppBase.cpp @@ -0,0 +1,30 @@ +// $Id$ +#include "TestAppBase.h" + +TestAppBase::TestAppBase(const char* name) + : name_(name) +{ +} + + +TestAppBase::~TestAppBase() +{ +} + + +const char* +TestAppBase::name() const +{ + return this->name_.c_str(); +} + + +int +TestAppBase::run(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + int rc = this->run_i(argc, argv ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Convert 1 to 0. Leave 0 and -1 as they are. + return (rc == 1) ? 0 : rc; +} diff --git a/TAO/performance-tests/CSD_Strategy/TestInf/TestAppBase.h b/TAO/performance-tests/CSD_Strategy/TestInf/TestAppBase.h new file mode 100644 index 00000000000..b14436b623c --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestInf/TestAppBase.h @@ -0,0 +1,36 @@ +// $Id$ +#ifndef TESTAPPBASE_H +#define TESTAPPBASE_H + +#include "CSD_PT_TestInf_Export.h" +#include "ace/SString.h" +#include "tao/Environment.h" +#include "ace/CORBA_macros.h" + + +class CSD_PT_TestInf_Export TestAppBase +{ + public: + + virtual ~TestAppBase(); + + // Returns 0 for success, and -1 for failure. + int run(int argc, char* argv[] ACE_ENV_ARG_DECL); + + const char* name() const; + + + protected: + + TestAppBase(const char* name); + + // Returns -1 for failure, 0 for success + virtual int run_i(int argc, char* argv[] ACE_ENV_ARG_DECL) = 0; + + + private: + + ACE_CString name_; +}; + +#endif diff --git a/TAO/performance-tests/CSD_Strategy/TestInf/TestAppException.idl b/TAO/performance-tests/CSD_Strategy/TestInf/TestAppException.idl new file mode 100644 index 00000000000..2ac53939b77 --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestInf/TestAppException.idl @@ -0,0 +1,7 @@ +// $Id$ +#ifndef TESTAPPXCEPTION_IDL +#define TESTAPPXCEPTION_IDL + +exception TestAppException {}; + +#endif diff --git a/TAO/performance-tests/CSD_Strategy/TestInf/TestAppMain.h b/TAO/performance-tests/CSD_Strategy/TestInf/TestAppMain.h new file mode 100644 index 00000000000..062b6fc0c8e --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestInf/TestAppMain.h @@ -0,0 +1,49 @@ +// $Id$ +#ifndef TESTAPPMAIN_H +#define TESTAPPMAIN_H + +#include "ace/Log_Msg.h" +#include "ace/SString.h" +#include "tao/Exception.h" +#include "tao/Environment.h" + +#define TEST_APP_MAIN(APP_TYPE) \ +int \ +main(int argc, char* argv[]) \ +{ \ + ACE_LOG_MSG->priority_mask(LM_TRACE | \ + LM_DEBUG | \ + LM_INFO | \ + LM_NOTICE | \ + LM_WARNING | \ + LM_ERROR | \ + LM_CRITICAL | \ + LM_ALERT | \ + LM_EMERGENCY, \ + ACE_Log_Msg::PROCESS); \ +\ + APP_TYPE app; \ +\ + ACE_TRY_NEW_ENV \ + { \ + int ret = app.run(argc,argv ACE_ENV_ARG_PARAMETER); \ + ACE_TRY_CHECK; \ + return ret; \ + } \ + ACE_CATCHANY \ + { \ + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, \ + "Caught exception:"); \ + } \ + ACE_CATCHALL \ + { \ + ACE_ERROR((LM_ERROR, \ + "(%P|%t) Unknown (...) exception caught in main() " \ + "for App [%d].\n", app.name())); \ + } \ + ACE_ENDTRY; \ + \ + return 1; \ +} + +#endif diff --git a/TAO/performance-tests/CSD_Strategy/TestInf/csd_pt_testinf.mpc b/TAO/performance-tests/CSD_Strategy/TestInf/csd_pt_testinf.mpc new file mode 100644 index 00000000000..39bea8a0c18 --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestInf/csd_pt_testinf.mpc @@ -0,0 +1,38 @@ +//$Id$ +project : taolib_with_idl, csd_threadpool { + sharedname = CSD_PT_TestInf + dynamicflags = CSD_PT_TESTINF_BUILD_DLL + idlflags += -Wb,export_macro=CSD_PT_TestInf_Export -Wb,export_include=CSD_PT_TestInf_Export.h + includes += $(TAO_ROOT)/tao + + IDL_Files { + FooException.idl + TestAppException.idl + CancelledException.idl + CustomException.idl + } + + Source_Files { + AppHelper.cpp + AppShutdown.cpp + ClientEngine.cpp + ClientTask.cpp + OrbRunner.cpp + OrbShutdownTask.cpp + OrbTask.cpp + TestAppBase.cpp + FooExceptionC.cpp + FooExceptionS.cpp + TestAppExceptionC.cpp + TestAppExceptionS.cpp + CancelledExceptionC.cpp + CancelledExceptionS.cpp + CustomExceptionC.cpp + CustomExceptionS.cpp + } + + Template_Files { + ServantList_T.cpp + } + +} diff --git a/TAO/performance-tests/CSD_Strategy/TestServant/CSD_PT_TestServant_Export.h b/TAO/performance-tests/CSD_Strategy/TestServant/CSD_PT_TestServant_Export.h new file mode 100644 index 00000000000..6d33bdbe291 --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestServant/CSD_PT_TestServant_Export.h @@ -0,0 +1,58 @@ + +// -*- C++ -*- +// $Id$ +// Definition for Win32 Export directives. +// This file is generated automatically by generate_export_file.pl -s CSD_PT_TestServant +// ------------------------------ +#ifndef CSD_PT_TESTSERVANT_EXPORT_H +#define CSD_PT_TESTSERVANT_EXPORT_H + +#include "ace/config-all.h" + +#if defined (ACE_AS_STATIC_LIBS) && !defined (CSD_PT_TESTSERVANT_HAS_DLL) +# define CSD_PT_TESTSERVANT_HAS_DLL 0 +#endif /* ACE_AS_STATIC_LIBS && CSD_PT_TESTSERVANT_HAS_DLL */ + +#if !defined (CSD_PT_TESTSERVANT_HAS_DLL) +# define CSD_PT_TESTSERVANT_HAS_DLL 1 +#endif /* ! CSD_PT_TESTSERVANT_HAS_DLL */ + +#if defined (CSD_PT_TESTSERVANT_HAS_DLL) && (CSD_PT_TESTSERVANT_HAS_DLL == 1) +# if defined (CSD_PT_TESTSERVANT_BUILD_DLL) +# define CSD_PT_TestServant_Export ACE_Proper_Export_Flag +# define CSD_PT_TESTSERVANT_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T) +# define CSD_PT_TESTSERVANT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# else /* CSD_PT_TESTSERVANT_BUILD_DLL */ +# define CSD_PT_TestServant_Export ACE_Proper_Import_Flag +# define CSD_PT_TESTSERVANT_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T) +# define CSD_PT_TESTSERVANT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# endif /* CSD_PT_TESTSERVANT_BUILD_DLL */ +#else /* CSD_PT_TESTSERVANT_HAS_DLL == 1 */ +# define CSD_PT_TestServant_Export +# define CSD_PT_TESTSERVANT_SINGLETON_DECLARATION(T) +# define CSD_PT_TESTSERVANT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +#endif /* CSD_PT_TESTSERVANT_HAS_DLL == 1 */ + +// Set CSD_PT_TESTSERVANT_NTRACE = 0 to turn on library specific tracing even if +// tracing is turned off for ACE. +#if !defined (CSD_PT_TESTSERVANT_NTRACE) +# if (ACE_NTRACE == 1) +# define CSD_PT_TESTSERVANT_NTRACE 1 +# else /* (ACE_NTRACE == 1) */ +# define CSD_PT_TESTSERVANT_NTRACE 0 +# endif /* (ACE_NTRACE == 1) */ +#endif /* !CSD_PT_TESTSERVANT_NTRACE */ + +#if (CSD_PT_TESTSERVANT_NTRACE == 1) +# define CSD_PT_TESTSERVANT_TRACE(X) +#else /* (CSD_PT_TESTSERVANT_NTRACE == 1) */ +# if !defined (ACE_HAS_TRACE) +# define ACE_HAS_TRACE +# endif /* ACE_HAS_TRACE */ +# define CSD_PT_TESTSERVANT_TRACE(X) ACE_TRACE_IMPL(X) +# include "ace/Trace.h" +#endif /* (CSD_PT_TESTSERVANT_NTRACE == 1) */ + +#endif /* CSD_PT_TESTSERVANT_EXPORT_H */ + +// End of auto generated file. diff --git a/TAO/performance-tests/CSD_Strategy/TestServant/Foo.idl b/TAO/performance-tests/CSD_Strategy/TestServant/Foo.idl new file mode 100644 index 00000000000..41663869082 --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestServant/Foo.idl @@ -0,0 +1,29 @@ +// $Id$ +#ifndef FOO_IDL +#define FOO_IDL + +#include "TestInf/FooException.idl" + +interface Foo +{ + /// void return-type, no arguments + void op1(); + + /// void return-type, 1 "in" argument + void op2(in long value); + + /// long return-type, 1 "in" argument + long op3(in long value); + + /// one-way version of op2 + oneway void op4(in long value); + + /// Operation that always raises an exception. + void op5() raises (FooException); + + /// Client calls this last. The last client to claim that it is + /// done will cause the server to shutdown. + void done(); +}; + +#endif diff --git a/TAO/performance-tests/CSD_Strategy/TestServant/Foo_ClientEngine.cpp b/TAO/performance-tests/CSD_Strategy/TestServant/Foo_ClientEngine.cpp new file mode 100644 index 00000000000..a5f4212e47e --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestServant/Foo_ClientEngine.cpp @@ -0,0 +1,88 @@ +// $Id$ +#include "Foo_ClientEngine.h" +#include "Foo_Statistics.h" +#include "TestInf/TestAppExceptionC.h" +#include "TestInf/AppHelper.h" +#include "ace/Log_Msg.h" + + +Foo_ClientEngine::Foo_ClientEngine(Foo_ptr obj, unsigned client_id) + : obj_(Foo::_duplicate(obj)), + client_id_(client_id) +{ +} + + +Foo_ClientEngine::~Foo_ClientEngine() +{ +} + + +bool +Foo_ClientEngine::execute(unsigned num_loops ACE_ENV_ARG_DECL) +{ + // Make sure the connection is established before making + // remote invocations. + if (AppHelper::validate_connection(this->obj_.in()) == false) + { + ACE_ERROR((LM_ERROR, + "(%P|%t)Foo_ClientEngine::execute - " + "client %d connect failed.\n", this->client_id_)); + return false; + } + + // Verify the return values and return the results. + bool success = true; + + for (unsigned loop = 0; loop < num_loops; loop++) + { + CORBA::Long i = this->client_id_; + + this->obj_->op1(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + this->obj_->op2(i ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + + CORBA::Long value = this->obj_->op3(i ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + success = (value != i) ? false : success; + + for (CORBA::Long j = 1; j <= 5; j++) + { + this->obj_->op4(495 + (i * 5) + j ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + } + + bool caught_exception = false; + + ACE_TRY_NEW_ENV + { + this->obj_->op5(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCH (FooException, ex) + { + // Expected + caught_exception = true; + } + ACE_ENDTRY; + + success = (!caught_exception) ? false : success; + } + + this->obj_->done(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + return success; +} + + +void +Foo_ClientEngine::expected_results(Foo_Statistics& stats) +{ + stats.expected(1, 1); + stats.expected(2, 1); + stats.expected(3, 1); + stats.expected(4, 0); + stats.expected(4, 5); + stats.expected(5, 1); +} diff --git a/TAO/performance-tests/CSD_Strategy/TestServant/Foo_ClientEngine.h b/TAO/performance-tests/CSD_Strategy/TestServant/Foo_ClientEngine.h new file mode 100644 index 00000000000..c704a9a65cb --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestServant/Foo_ClientEngine.h @@ -0,0 +1,41 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file Foo_ClientEngine.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef FOO_CLIENT_ENGINE_H +#define FOO_CLIENT_ENGINE_H + +#include "CSD_PT_TestServant_Export.h" +#include "TestInf/ClientEngine.h" +#include "FooC.h" + +class Foo_Statistics; + + +class CSD_PT_TestServant_Export Foo_ClientEngine : public ClientEngine +{ + public: + + Foo_ClientEngine(Foo_ptr obj, unsigned client_id = 0); + virtual ~Foo_ClientEngine(); + + virtual bool execute(unsigned num_loops ACE_ENV_ARG_DECL); + + static void expected_results(Foo_Statistics& stats); + + + private: + + Foo_var obj_; + unsigned client_id_; +}; + +#endif diff --git a/TAO/performance-tests/CSD_Strategy/TestServant/Foo_Statistics.cpp b/TAO/performance-tests/CSD_Strategy/TestServant/Foo_Statistics.cpp new file mode 100644 index 00000000000..6fe6e95fcff --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestServant/Foo_Statistics.cpp @@ -0,0 +1,75 @@ +// $Id$ +#include "Foo_Statistics.h" +#include "Foo_ClientEngine.h" + + +Foo_Statistics::Foo_Statistics() + : num_clients_(0), + num_loops_(0) +{ + for (unsigned i = 0; i < 5; i++) + { + this->expected_[i] = 0; + this->actual_[i] = 0; + } +} + + +Foo_Statistics::~Foo_Statistics() +{ +} + + +void +Foo_Statistics::init(unsigned num_clients, unsigned num_loops) +{ + this->num_clients_ = num_clients; + this->num_loops_ = num_loops; +} + + +void +Foo_Statistics::expected(unsigned op_num, unsigned count) +{ + this->expected_[op_num-1] = count * this->num_clients_ * this->num_loops_; +} + + +void +Foo_Statistics::actual(unsigned op_num, unsigned count) +{ + this->actual_[op_num-1] += count; +} + + +bool +Foo_Statistics::actual_vs_expected() +{ + for (unsigned i = 0; i < 5; i++) + { + if (this->expected_[i] != this->actual_[i]) + { + ACE_DEBUG((LM_DEBUG, + "Actual vs. Expected Results Failure: " + "op%d() expected: %d, got: %d\n", + i, this->expected_[i], this->actual_[i])); + return false; + } + } + + return true; +} + + +unsigned +Foo_Statistics::total() const +{ + unsigned t = 0; + + for (unsigned i = 0 ; i < 5; i++) + { + t += this->expected_[i]; + } + + return t; +} diff --git a/TAO/performance-tests/CSD_Strategy/TestServant/Foo_Statistics.h b/TAO/performance-tests/CSD_Strategy/TestServant/Foo_Statistics.h new file mode 100644 index 00000000000..e864489f9b3 --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestServant/Foo_Statistics.h @@ -0,0 +1,33 @@ +// $Id$ +#ifndef FOO_STATISTICS_H +#define FOO_STATISTICS_H + +#include "CSD_PT_TestServant_Export.h" + + +class CSD_PT_TestServant_Export Foo_Statistics +{ + public: + + Foo_Statistics(); + virtual ~Foo_Statistics(); + + void init(unsigned num_clients, unsigned num_loops); + + void expected(unsigned op_num, unsigned count); + void actual(unsigned op_num, unsigned count); + + bool actual_vs_expected(); + + unsigned total() const; + + + private: + + unsigned num_clients_; + unsigned num_loops_; + unsigned expected_[5]; + unsigned actual_[5]; +}; + +#endif diff --git a/TAO/performance-tests/CSD_Strategy/TestServant/Foo_i.cpp b/TAO/performance-tests/CSD_Strategy/TestServant/Foo_i.cpp new file mode 100644 index 00000000000..cbe2721a94d --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestServant/Foo_i.cpp @@ -0,0 +1,83 @@ +// $Id$ +#include "Foo_i.h" +#include "TestInf/AppShutdown.h" +#include "ace/OS.h" +#include "ace/Time_Value.h" + + + + +Foo_i::Foo_i() +{ + for (unsigned i = 0; i < 5; i++) + { + this->op_count_[i] = 0; + } +} + + +Foo_i::~Foo_i() +{ +} + + +void +Foo_i::op1(ACE_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + this->op_count_[0]++; +} + + +void +Foo_i::op2(CORBA::Long value ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + ACE_UNUSED_ARG(value); + this->op_count_[1]++; +} + + +CORBA::Long +Foo_i::op3(CORBA::Long value ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + this->op_count_[2]++; + return value; +} + + +void +Foo_i::op4(CORBA::Long value ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + ACE_UNUSED_ARG(value); + this->op_count_[3]++; +} + + +void +Foo_i::op5(ACE_ENV_SINGLE_ARG_DECL) + ACE_THROW_SPEC((CORBA::SystemException, FooException)) +{ + this->op_count_[4]++; + ACE_THROW (FooException()); +} + + +void +Foo_i::done(ACE_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + TheAppShutdown->client_done(); +} + + +void +Foo_i::gather_stats(Foo_Statistics& stats) +{ + for (unsigned i = 0; i < 5; i++) + { + stats.actual(i + 1, this->op_count_[i]); + } +} diff --git a/TAO/performance-tests/CSD_Strategy/TestServant/Foo_i.h b/TAO/performance-tests/CSD_Strategy/TestServant/Foo_i.h new file mode 100644 index 00000000000..b6270ecf0e3 --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestServant/Foo_i.h @@ -0,0 +1,46 @@ +// $Id$ +#ifndef FOO_I_H +#define FOO_I_H + +#include "CSD_PT_TestServant_Export.h" +#include "FooS.h" +#include "Foo_Statistics.h" + + +class CSD_PT_TestServant_Export Foo_i : public virtual POA_Foo, + public virtual PortableServer::RefCountServantBase +{ + public: + + Foo_i(); + virtual ~Foo_i(); + + virtual void op1(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void op2(CORBA::Long value ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual CORBA::Long op3(CORBA::Long value ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void op4(CORBA::Long value ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void op5(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException, + FooException)); + + virtual void done(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + + void gather_stats(Foo_Statistics& stats); + + + private: + + unsigned op_count_[5]; +}; + +#endif diff --git a/TAO/performance-tests/CSD_Strategy/TestServant/README b/TAO/performance-tests/CSD_Strategy/TestServant/README new file mode 100644 index 00000000000..b8ccf09aaf1 --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestServant/README @@ -0,0 +1,10 @@ +/** + +@page CSD_Strategy TestServant README File + + This is a library for the specific test. It contains test idl files, the +servant implementaions, test statistics and the client task with sequence +of remote invocations. Adding this library is to simplify the tests with +multiple clients or collocated tests. + +*/ diff --git a/TAO/performance-tests/CSD_Strategy/TestServant/csd_pt_testservant.mpc b/TAO/performance-tests/CSD_Strategy/TestServant/csd_pt_testservant.mpc new file mode 100644 index 00000000000..543180258f2 --- /dev/null +++ b/TAO/performance-tests/CSD_Strategy/TestServant/csd_pt_testservant.mpc @@ -0,0 +1,20 @@ +//$Id$ +project : csd_pt_testinf_lib { + sharedname = CSD_PT_TestServant + dynamicflags = CSD_PT_TESTSERVANT_BUILD_DLL + idlflags += -Wb,export_macro=CSD_PT_TestServant_Export -Wb,export_include=CSD_PT_TestServant_Export.h + includes += $(TAO_ROOT)/tao + + IDL_Files { + Foo.idl + } + + Source_Files { + FooC.cpp + FooS.cpp + Foo_ClientEngine.cpp + Foo_i.cpp + Foo_Statistics.cpp + } + +} diff --git a/TAO/tao/CSD_Framework.mpc b/TAO/tao/CSD_Framework.mpc new file mode 100644 index 00000000000..d80d59483e5 --- /dev/null +++ b/TAO/tao/CSD_Framework.mpc @@ -0,0 +1,34 @@ +//$Id$ +project : taolib, portableserver, core, pi { + sharedname = TAO_CSD_Framework + dynamicflags = TAO_CSD_FW_BUILD_DLL + includes += $(TAO_ROOT)/tao + + Source_Files { + CSD_Framework + } + + Header_Files { + CSD_Framework + } + + Inline_Files { + CSD_Framework + } + + Template_Files { + CSD_Framework + } + + Resource_Files { + CSD_Framework + } + + IDL_Files { + CSD_Framework + } + + PIDL_Files { + CSD_Framework + } +} diff --git a/TAO/tao/CSD_Framework/CSD_Default_Servant_Dispatcher.cpp b/TAO/tao/CSD_Framework/CSD_Default_Servant_Dispatcher.cpp new file mode 100644 index 00000000000..63513ba304d --- /dev/null +++ b/TAO/tao/CSD_Framework/CSD_Default_Servant_Dispatcher.cpp @@ -0,0 +1,56 @@ +// @(#) $Id$ + +#include "CSD_Default_Servant_Dispatcher.h" +#include "CSD_POA.h" +#include "CSD_Strategy_Repository.h" +#include "ace/Dynamic_Service.h" + +ACE_RCSID(CSD_Framework, + CSD_Default_Servant_Dispatcher, + "$Id$") + + +TAO_CSD_Default_Servant_Dispatcher::~TAO_CSD_Default_Servant_Dispatcher (void) +{ +} + + +TAO_Root_POA * +TAO_CSD_Default_Servant_Dispatcher::create_Root_POA (const ACE_CString &name, + TAO_POA_Manager &poa_manager, + const TAO_POA_Policy_Set &policies, + ACE_Lock &lock, + TAO_SYNCH_MUTEX &thread_lock, + TAO_ORB_Core &orb_core, + TAO_Object_Adapter *object_adapter + ACE_ENV_ARG_DECL) +{ + TAO_CSD_POA *poa = 0; + + ACE_NEW_THROW_EX (poa, + TAO_CSD_POA (name, + poa_manager, + policies, + 0, + lock, + thread_lock, + orb_core, + object_adapter + ACE_ENV_ARG_PARAMETER), + CORBA::NO_MEMORY ()); + ACE_CHECK_RETURN (0); + + + TAO_CSD_Strategy_Repository *repo = + ACE_Dynamic_Service<TAO_CSD_Strategy_Repository>::instance ("TAO_CSD_Strategy_Repository"); + + CSD_Framework::Strategy_var strategy = repo->find (name); + + if (! CORBA::is_nil (strategy.in ())) + { + poa->set_csd_strategy (strategy.in () ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (0); + } + + return poa; +} diff --git a/TAO/tao/CSD_Framework/CSD_Default_Servant_Dispatcher.h b/TAO/tao/CSD_Framework/CSD_Default_Servant_Dispatcher.h new file mode 100644 index 00000000000..120630c123b --- /dev/null +++ b/TAO/tao/CSD_Framework/CSD_Default_Servant_Dispatcher.h @@ -0,0 +1,49 @@ +/* -*- C++ -*- */ + +//============================================================================= +/** + * @file CSD_Default_Servant_Dispatcher.h + * + * $Id$ + * + * @author Yan Dai (dai_y@ociweb.com) + */ +//============================================================================= + +#ifndef TAO_CSD_DEFAULT_SERVANT_DISPATCHER_H +#define TAO_CSD_DEFAULT_SERVANT_DISPATCHER_H +#include /**/ "ace/pre.h" + +#include "CSD_FW_Export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "tao/PortableServer/Default_Servant_Dispatcher.h" + +/** + * @class TAO_CSD_Default_Servant_Dispatcher + * + * @brief Interface for CSD_POA servant dispatching strategies. + */ +class TAO_CSD_FW_Export TAO_CSD_Default_Servant_Dispatcher + : public virtual TAO_Default_Servant_Dispatcher +{ +public: + virtual ~TAO_CSD_Default_Servant_Dispatcher (void); + + + /// Factory method for creating new CSD Root POA. + virtual TAO_Root_POA *create_Root_POA (const ACE_CString &name, + TAO_POA_Manager &poa_manager, + const TAO_POA_Policy_Set &policies, + ACE_Lock &lock, + TAO_SYNCH_MUTEX &thread_lock, + TAO_ORB_Core &orb_core, + TAO_Object_Adapter *object_adapter + ACE_ENV_ARG_DECL); +}; + +#include /**/ "ace/post.h" +#endif /* TAO_CSD_DEFAULT_SERVANT_DISPATCHER_H */ diff --git a/TAO/tao/CSD_Framework/CSD_FW_Export.h b/TAO/tao/CSD_Framework/CSD_FW_Export.h new file mode 100644 index 00000000000..edeb9119dc4 --- /dev/null +++ b/TAO/tao/CSD_Framework/CSD_FW_Export.h @@ -0,0 +1,58 @@ + +// -*- C++ -*- +// $Id$ +// Definition for Win32 Export directives. +// This file is generated automatically by generate_export_file.pl -s TAO_CSD_FW +// ------------------------------ +#ifndef TAO_CSD_FW_EXPORT_H +#define TAO_CSD_FW_EXPORT_H + +#include "ace/config-all.h" + +#if defined (ACE_AS_STATIC_LIBS) && !defined (TAO_CSD_FW_HAS_DLL) +# define TAO_CSD_FW_HAS_DLL 0 +#endif /* ACE_AS_STATIC_LIBS && TAO_CSD_FW_HAS_DLL */ + +#if !defined (TAO_CSD_FW_HAS_DLL) +# define TAO_CSD_FW_HAS_DLL 1 +#endif /* ! TAO_CSD_FW_HAS_DLL */ + +#if defined (TAO_CSD_FW_HAS_DLL) && (TAO_CSD_FW_HAS_DLL == 1) +# if defined (TAO_CSD_FW_BUILD_DLL) +# define TAO_CSD_FW_Export ACE_Proper_Export_Flag +# define TAO_CSD_FW_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T) +# define TAO_CSD_FW_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# else /* TAO_CSD_FW_BUILD_DLL */ +# define TAO_CSD_FW_Export ACE_Proper_Import_Flag +# define TAO_CSD_FW_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T) +# define TAO_CSD_FW_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# endif /* TAO_CSD_FW_BUILD_DLL */ +#else /* TAO_CSD_FW_HAS_DLL == 1 */ +# define TAO_CSD_FW_Export +# define TAO_CSD_FW_SINGLETON_DECLARATION(T) +# define TAO_CSD_FW_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +#endif /* TAO_CSD_FW_HAS_DLL == 1 */ + +// Set TAO_CSD_FW_NTRACE = 0 to turn on library specific tracing even if +// tracing is turned off for ACE. +#if !defined (TAO_CSD_FW_NTRACE) +# if (ACE_NTRACE == 1) +# define TAO_CSD_FW_NTRACE 1 +# else /* (ACE_NTRACE == 1) */ +# define TAO_CSD_FW_NTRACE 0 +# endif /* (ACE_NTRACE == 1) */ +#endif /* !TAO_CSD_FW_NTRACE */ + +#if (TAO_CSD_FW_NTRACE == 1) +# define TAO_CSD_FW_TRACE(X) +#else /* (TAO_CSD_FW_NTRACE == 1) */ +# if !defined (ACE_HAS_TRACE) +# define ACE_HAS_TRACE +# endif /* ACE_HAS_TRACE */ +# define TAO_CSD_FW_TRACE(X) ACE_TRACE_IMPL(X) +# include "ace/Trace.h" +#endif /* (TAO_CSD_FW_NTRACE == 1) */ + +#endif /* TAO_CSD_FW_EXPORT_H */ + +// End of auto generated file. diff --git a/TAO/tao/CSD_Framework/CSD_FW_Server_Request_Wrapper.cpp b/TAO/tao/CSD_Framework/CSD_FW_Server_Request_Wrapper.cpp new file mode 100644 index 00000000000..94d71cb86af --- /dev/null +++ b/TAO/tao/CSD_Framework/CSD_FW_Server_Request_Wrapper.cpp @@ -0,0 +1,462 @@ +// $Id$ +#include "CSD_FW_Server_Request_Wrapper.h" +#include "tao/debug.h" +#include "tao/ORB_Constants.h" +#include "ORB_Core.h" +#include "tao/Transport.h" +#include "tao/CDR.h" + + +ACE_RCSID (CSD_Framework, + FW_Server_Request_Wrapper, + "$Id$") + +#if !defined (__ACE_INLINE__) +# include "CSD_FW_Server_Request_Wrapper.inl" +#endif /* ! __ACE_INLINE__ */ + + +TAO::CSD::FW_Server_Request_Wrapper::~FW_Server_Request_Wrapper() +{ + // Only delete the request if we cloned it. + if (this->is_clone_) + { + // Since this TAO_ServerRequest object is a clone, it + // "owns" the input and output CDR objects held by the + // incoming_ and outgoing_ data members, respectfully. + // Thus, for the clone case, the TAO_ServerRequest dtor + // needs to release (aka, delete) the CDR objects. + delete this->request_->incoming_; + + // Get the start message block that reference to the data allocated + // on the heap. + if (this->request_->outgoing_ != 0) + { + char* buffer = this->request_->outgoing_->begin ()->base (); + delete [] buffer; + delete this->request_->outgoing_; + } + if (this->request_->operation_details_ != 0) + { + char* opname = (char*)this->request_->operation_details_->opname_; + delete [] opname; + } + delete this->request_; + } +} + + +// Assumes that the servant argument is not a NULL pointer. +void +TAO::CSD::FW_Server_Request_Wrapper::dispatch + (PortableServer::Servant servant + ACE_ENV_ARG_DECL) +{ + ACE_TRY + { + servant->_dispatch(*this->request_, 0 ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + } + // Only CORBA exceptions are caught here. + ACE_CATCHANY + { + if (this->request_->collocated()) + { + // For collocated requests, we re-throw the exception. + ACE_RE_THROW; + } + else if (!this->request_->sync_with_server() && + this->request_->response_expected() && + !this->request_->deferred_reply()) + { + // The request is a remote request that is expecting a reply. + this->request_->tao_send_reply_exception(ACE_ANY_EXCEPTION); + } + else if (TAO_debug_level > 0) + { + // It is unfortunate that an exception (probably a system + // exception) was thrown by the dispatch code (even by the + // user) when the client was not expecting a response. + // However, in this case, we cannot close the connection + // down, since it really isn't the client's fault. + + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) exception thrown ") + ACE_TEXT ("but client is not waiting a response\n"))); + + ACE_PRINT_EXCEPTION ( + ACE_ANY_EXCEPTION, + "FW_Server_Request_Wrapper::dispatch ()"); + } + } +#if defined (TAO_HAS_EXCEPTIONS) + ACE_CATCHALL + { + // @@ TODO some c++ exception or another, but what do we do with + // it? + // We are supposed to map it into a CORBA::UNKNOWN exception. + // BTW, this cannot be detected if using the <env> mapping. If + // we have native exceptions but no support for them in the ORB + // we should still be able to catch it. If we don't have native + // exceptions it couldn't have been raised in the first place! + CORBA::UNKNOWN exception (CORBA::SystemException::_tao_minor_code + (TAO_UNHANDLED_SERVER_CXX_EXCEPTION, 0), + CORBA::COMPLETED_MAYBE); + + if (this->request_->collocated()) + { + // For collocated requests, we re-throw the exception. + ACE_RE_THROW; + } + else if (!this->request_->sync_with_server() && + this->request_->response_expected() && + !this->request_->deferred_reply()) + { + // The request is a remote request that is expecting a reply. + this->request_->tao_send_reply_exception(exception); + } + else if (TAO_debug_level > 0) + { + // It is unfortunate that an exception (probably a system + // exception) was thrown by the dispatch code (even by the + // user) when the client was not expecting a response. + // However, in this case, we cannot close the connection + // down, since it really isn't the client's fault. + + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) exception thrown ") + ACE_TEXT ("but client is not waiting a response\n"))); + + ACE_PRINT_EXCEPTION ( + exception, + "FW_Server_Request_Wrapper::dispatch ()"); + } + } +#endif /* TAO_HAS_EXCEPTIONS */ + + ACE_ENDTRY; +} + + +TAO_ServerRequest* +TAO::CSD::FW_Server_Request_Wrapper::clone (TAO_ServerRequest*& request) +{ + // TBD-CSD: Ultimately add an argument for an allocator. + TAO_ServerRequest* clone_obj = this->create_new_request (); + + if (clone_obj == 0) + { + return 0; + } + + // TYPE: TAO_Pluggable_Messaging* + // ACTION: Assuming that a shallow-copy is ok here. + clone_obj->mesg_base_ = request->mesg_base_; + + // TYPE: ACE_CString + // ACTION: Assignment performs deep-copy of string contents. + clone_obj->operation_ = request->operation_; + + // TYPE: CORBA::Object_var + // ACTION: Assignment performs reference-counted copy of object ref. + clone_obj->forward_location_ = request->forward_location_; + + // TYPE: TAO_InputCDR* + // ACTION: This *must* be "cloned". + if (request->incoming_ != 0) + { + clone_obj->incoming_ = this->clone (request->incoming_); + } + + // TYPE: TAO_OutputCDR* + // ACTION: This *must* be "cloned". + if (request->outgoing_ != 0) + { + clone_obj->outgoing_ = this->create_new_output_cdr (); + } + + // TYPE: TAO_Transport* + // ACTION: Assuming that a shallow-copy is ok here. + clone_obj->transport_ = request->transport_; + + // TYPE: CORBA::Boolean + // ACTION: Primitive data type assignment. + clone_obj->response_expected_ = request->response_expected_; + + // TYPE: CORBA::Boolean + // ACTION: Primitive data type assignment. + clone_obj->deferred_reply_ = request->deferred_reply_; + + // TYPE: CORBA::Boolean + // ACTION: Primitive data type assignment. + clone_obj->sync_with_server_ = request->sync_with_server_; + + // TYPE: CORBA::Boolean + // ACTION: Primitive data type assignment. + clone_obj->is_dsi_ = request->is_dsi_; + + // TYPE: CORBA::ULong + // ACTION: Primitive data type assignment. + clone_obj->exception_type_ = request->exception_type_; + + // TYPE: TAO_ORB_Core* + // ACTION: Assuming that a shallow-copy is ok here. + clone_obj->orb_core_ = request->orb_core_; + + // TYPE: TAO_Service_Context + // ACTION: No copy/assignment operator, so adding/using a clone operation. + this->clone (request->request_service_context_, clone_obj->request_service_context_); + + // TYPE: TAO_Service_Context + // ACTION: No copy/assignment operator, so adding/using a clone operation. + this->clone (request->reply_service_context_, clone_obj->reply_service_context_); + + // TYPE: CORBA::ULong + // ACTION: Primitive data type assignment. + clone_obj->request_id_ = request->request_id_; + + // TYPE: TAO_Tagged_Profile + // ACTION: No copy/assignment operator, so adding/using a clone operation. + this->clone (request->profile_, clone_obj->profile_); + + // TYPE: CORBA::OctetSeq_var + // ACTION: Assignment performs reference-counted copy of sequence. + clone_obj->requesting_principal_ = request->requesting_principal_; + + // TYPE: ptrdiff_t + // ACTION: Primitive data type assignment (unsigned integral type). + clone_obj->dsi_nvlist_align_ = request->dsi_nvlist_align_; + + // TYPE: TAO_Operation_Details const * const + // ACTION: Need to clone this. + if (request->operation_details_ != 0) + { + ACE_ASSERT (request->incoming_ == 0); + if (this->clone (request->operation_details_, + clone_obj->operation_details_, + clone_obj->incoming_) == false) + { + return 0; + } + } + + // TYPE: CORBA::Boolean + // ACTION: Primitive data type assignment. + clone_obj->argument_flag_ = request->argument_flag_; + +#if TAO_HAS_INTERCEPTORS == 1 + // TYPE: size_t + // ACTION: Primitive data type assignment. + // Just leave this alone for a clone. + // + //clone_obj->interceptor_count_ = request->interceptor_count_; + + // TYPE: TAO::PICurrent_Impl + // ACTION: Copy/assignment operator disabled on purpose. + // Just leave this alone for a clone. + // + // clone_obj->rs_pi_current_ + + // TYPE: TAO::PICurrent_Copy_Callback + // ACTION: No copy/assignment operator. + // Just leave this alone for a clone. + // + // clone_obj->pi_current_copy_callback_ + + // TYPE: CORBA::OctetSeq_var + // ACTION: Assignment performs reference-counted copy of sequence. + // Assuming that this is ok. + // Just leave this alone for a clone. + // + //clone_obj->result_seq_ = request->result_seq_; +#endif /* TAO_HAS_INTERCEPTORS == 1 */ + + if (clone_obj->transport_ != 0) + { + clone_obj->transport_->assign_translators(clone_obj->incoming_, + clone_obj->outgoing_); + } + return clone_obj; +} + + +TAO_InputCDR* +TAO::CSD::FW_Server_Request_Wrapper::clone (TAO_InputCDR*& from) +{ + TAO_InputCDR* clone_ptr = 0; + ACE_NEW_RETURN (clone_ptr, + TAO_InputCDR(*from), + 0); + return clone_ptr; +} + + +bool +TAO::CSD::FW_Server_Request_Wrapper::clone (TAO_Operation_Details const *& from, + TAO_Operation_Details const *& to, + TAO_InputCDR*& cdr) +{ + TAO_Operation_Details* from_non_const + = const_cast <TAO_Operation_Details *>(from); + + char* cloned_op_name = new char[from_non_const->opname_len_ + 1]; + ACE_OS::strncpy(cloned_op_name, from_non_const->opname_, from_non_const->opname_len_); + cloned_op_name[from_non_const->opname_len_] = '\0'; + + TAO_OutputCDR outcdr; + + if (! from_non_const->marshal_args (outcdr)) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT("(%P|%T) TAO::CSD::FW_Server_Request_Wrapper::") + ACE_TEXT("clone TAO_Operation_Details failed\n"))); + return false; + } + + ACE_NEW_RETURN (cdr, + TAO_InputCDR (outcdr), + false); + + + // CSD-TBD: Eventually need to use allocators. + + // CSD-TBD: Assert that this->ex_data_ and this->ex_count_ are both == 0 + TAO_Operation_Details* to_non_const; + ACE_NEW_RETURN (to_non_const, + TAO_Operation_Details(cloned_op_name, + from_non_const->opname_len_, + from_non_const->argument_flag_, + 0, + 0, + 0, + 0), + false); + + + // DATA MEMBER: const char *opname_; + // DATA MEMBER: CORBA::ULong opname_len_; + // DATA MEMBER: CORBA::Boolean argument_flag_; + // DATA MEMBER: TAO::Argument **args_; + // DATA MEMBER: CORBA::ULong num_args_; + // DATA MEMBER: TAO::Exception_Data *ex_data_; + // DATA MEMBER: CORBA::ULong ex_count_; + // + // ACTION: None - handled in ctor + // + + // DATA MEMBER: CORBA::ULong request_id_; + // DATA MEMBER: CORBA::Octet response_flags_; + // DATA MEMBER: TAO_Target_Specification::TAO_Target_Address addressing_mode_; + // DATA MEMBER: TAO_Service_Context request_service_info_; + // DATA MEMBER: TAO_Service_Context reply_service_info_; + // + // ACTION: Use assignment op to copy from "this" object to the clone. + // + to_non_const->request_id_ = from->request_id_; + to_non_const->response_flags_ = from->response_flags_; + to_non_const->addressing_mode_ = from->addressing_mode_; + + // DATA MEMBER: TAO_Service_Context request_service_info_; + // DATA MEMBER: TAO_Service_Context reply_service_info_; + // + // ACTION: Use the TAO_Service_Context clone() method. + // + this->clone (from_non_const->request_service_info_, to_non_const->request_service_info_); + this->clone (from_non_const->reply_service_info_, to_non_const->reply_service_info_); + + to = to_non_const; + + return true; +} + + +void +TAO::CSD::FW_Server_Request_Wrapper::clone (TAO_Tagged_Profile& from, + TAO_Tagged_Profile& to) +{ + to.orb_core_ = from.orb_core_; + to.discriminator_ = from.discriminator_; + to.object_key_extracted_ = from.object_key_extracted_; + to.object_key_ = from.object_key_; + to.profile_ = from.profile_; + to.profile_index_ = from.profile_index_; + to.type_id_ = from.type_id_; +} + + +void +TAO::CSD::FW_Server_Request_Wrapper::clone (TAO_Service_Context& from, + TAO_Service_Context& to) +{ + to.service_context_ = from.service_context_; +} + +TAO_ServerRequest* +TAO::CSD::FW_Server_Request_Wrapper::create_new_request () +{ + // Use one of constructor to create the TAO_ServerRequest object then + // reset the data members. This reduces the footprint due to a default + // TAO_ServerRequest constructor. + // + //TAO_ServerRequest (TAO_Pluggable_Messaging *mesg_base, + // TAO_InputCDR &input, + // TAO_OutputCDR &output, + // TAO_Transport *transport, + // TAO_ORB_Core *orb_core); + + TAO_ServerRequest* request = 0; + + TAO_InputCDR dummy_input ((ACE_Message_Block *)0); // empty input cdr stream + TAO_OutputCDR dummy_output ((char *)0, (size_t) 0); // empty output cdr stream + ACE_NEW_RETURN (request, + TAO_ServerRequest (0, + dummy_input, + dummy_output, + 0, + 0), + 0); + + request->incoming_ = 0; + request->outgoing_ = 0; + + return request; +} + + +TAO_OutputCDR* +TAO::CSD::FW_Server_Request_Wrapper::create_new_output_cdr () +{ + TAO_OutputCDR* cdr = 0; + + // A buffer that we will use to initialise the CDR stream + char* repbuf = new char[ACE_CDR::DEFAULT_BUFSIZE]; + + ACE_CDR::Octet major; + ACE_CDR::Octet minor; + this->request_->outgoing_->get_version (major, minor); + + // Initialze an output CDR on the stack + // NOTE: Don't jump to a conclusion as to why we are using the + // input_cdr and hence the global pool here. These pools will move + // to the lanes anyway at some point of time. Further, it would have + // been awesome to have this in TSS. But for some reason the cloning + // that happens when the ORB gets flow controlled while writing a + // reply is messing things up. We crash horribly. Doing this adds a + // lock, we need to set things like this -- put stuff in TSS here + // and transfer to global memory when we get flow controlled. We + // need to work on the message block to get it right! + ACE_NEW_RETURN (cdr, + TAO_OutputCDR (repbuf, + ACE_CDR::DEFAULT_BUFSIZE, + TAO_ENCAP_BYTE_ORDER, + this->request_->orb_core_->input_cdr_buffer_allocator (), + this->request_->orb_core_->input_cdr_dblock_allocator (), + this->request_->orb_core_->input_cdr_msgblock_allocator (), + this->request_->orb_core_->orb_params ()->cdr_memcpy_tradeoff (), + major, + minor), + 0); + + return cdr; +} + diff --git a/TAO/tao/CSD_Framework/CSD_FW_Server_Request_Wrapper.h b/TAO/tao/CSD_Framework/CSD_FW_Server_Request_Wrapper.h new file mode 100644 index 00000000000..945a921ca99 --- /dev/null +++ b/TAO/tao/CSD_Framework/CSD_FW_Server_Request_Wrapper.h @@ -0,0 +1,127 @@ +/* -*- C++ -*- */ + +//============================================================================= +/** + * @file CSD_FW_Server_Request_Wrapper.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_CSD_FW_SERVER_REQUEST_WRAPPER_H +#define TAO_CSD_FW_SERVER_REQUEST_WRAPPER_H + +#include /**/ "ace/pre.h" + +#include "CSD_FW_Export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "tao/TAO_Server_Request.h" +#include "tao/operation_details.h" +#include "tao/PortableServer/Servant_Base.h" + +namespace TAO +{ + namespace CSD + { + + /** + * @class FW_Server_Request_Wrapper + * + * @brief Wrapper around a TAO_Server_Request that will be cloned + * at the proper time. + * + * This CSD Framework class is used to provide an interface to a + * TAO_ServerRequest object such that it can be used for CSD strategies + * that need to clone TAO_Server_Requests (ie, so that they may be + * placed on a queue to be dispatched by another thread). + * + * There are several purposes for this class, with the main thing being + * that the TAO_ServerRequest object is not used directly by the + * CSD Strategies since it is, after all, an internal TAO class that was + * never meant to be exposed. Future changes to TAO's internal design + * may cause disruption in the TAO_ServerRequest class. These changes + * would only need to be accounted for here in this + * FW_Server_Request_Wrapper class' implementation, and all CSD + * Strategies will work again. It's a maintenance issue. + * + * @note: The CSD namespace is inside of TAO namespace in current + * implementation. This can be changed but, at least for now, it's + * already been delivered to some customs, we leave it as-is. If it + * needs to change, we will make this change. + */ + class TAO_CSD_FW_Export FW_Server_Request_Wrapper + { + public: + + /// Constructor. + FW_Server_Request_Wrapper(TAO_ServerRequest& server_request); + + /// Destructor. + ~FW_Server_Request_Wrapper(); + + /// Perform the clone operation. + void clone(); + + /// Dispatch the request to the servant. + void dispatch(PortableServer::Servant servant ACE_ENV_ARG_DECL); + + /// Cancel the request. + void cancel(); + + + private: + + /// Create a deep copy of the request_ object. + /// The other clone methods are used to support the TAO_ServerRequest clone. + TAO_ServerRequest* clone (TAO_ServerRequest*& from); + + /// Clone an input cdr stream. + TAO_InputCDR* clone (TAO_InputCDR*& from); + + /// Create a deep copy of a TAO_Operation_Details object and marshall + /// the arguments into a TAO_InputCDR stream. The cloned TAO_Operation_Details + /// object is created without any arguments. This would help the skeleton + /// code to determine whether the arguments are in the operation_details_ + /// object or should be demarshalled from the incoming_ stream in the request_ + /// object. + bool clone (TAO_Operation_Details const *& from, + TAO_Operation_Details const *& to, + TAO_InputCDR* & cdr); + + /// Clone the TAO_Tagged_Profile object. + void clone (TAO_Tagged_Profile& from, TAO_Tagged_Profile& to); + + /// Clone the TAO_Service_Context object. + void clone (TAO_Service_Context& from, TAO_Service_Context& to); + + /// Create a new TAO_ServerRequest with default initial values. + TAO_ServerRequest* create_new_request (); + + /// Create a TAO_OutputCDR stream initialized with a heap allocated + /// buffer. + TAO_OutputCDR* create_new_output_cdr (); + + /// A flag that indicates that the TAO_ServerRequest object + /// is already cloned. + bool is_clone_; + + /// Pointer to the underlying TAO_ServerRequest object. + TAO_ServerRequest* request_; + }; + + } +} + +#if defined (__ACE_INLINE__) +# include "CSD_FW_Server_Request_Wrapper.inl" +#endif /* __ACE_INLINE__ */ + +#include /**/ "ace/post.h" + +#endif /* TAO_CSD_FW_SERVER_REQUEST_WRAPPER_H */ diff --git a/TAO/tao/CSD_Framework/CSD_FW_Server_Request_Wrapper.inl b/TAO/tao/CSD_Framework/CSD_FW_Server_Request_Wrapper.inl new file mode 100644 index 00000000000..a259de116ab --- /dev/null +++ b/TAO/tao/CSD_Framework/CSD_FW_Server_Request_Wrapper.inl @@ -0,0 +1,42 @@ +// $Id$ + + +ACE_INLINE +TAO::CSD::FW_Server_Request_Wrapper::FW_Server_Request_Wrapper + (TAO_ServerRequest& server_request) + : is_clone_(false), + request_(&server_request) +{ +} + + +ACE_INLINE +void +TAO::CSD::FW_Server_Request_Wrapper::clone() +{ + // Only clone the TAO_Server_Request object if we have not performed the + // clone already. This really should only be called once, but this code + // makes sure that we do not introduce a leak. + if (!this->is_clone_) + { + this->request_ = this->clone (this->request_); + this->is_clone_ = true; + } +} + + +ACE_INLINE +void +TAO::CSD::FW_Server_Request_Wrapper::cancel() +{ + // We only need to handle remote requests that are expecting a reply. + if (!this->request_->collocated() && + !this->request_->sync_with_server() && + this->request_->response_expected() && + !this->request_->deferred_reply()) + { + CORBA::NO_IMPLEMENT ex; + this->request_->tao_send_reply_exception(ex); + } +} + diff --git a/TAO/tao/CSD_Framework/CSD_Framework.pidl b/TAO/tao/CSD_Framework/CSD_Framework.pidl new file mode 100644 index 00000000000..ba1940df02e --- /dev/null +++ b/TAO/tao/CSD_Framework/CSD_Framework.pidl @@ -0,0 +1,75 @@ +// -*- IDL -*- +/** + * @file CSD_Framework.pidl + * + * $Id$ + * + * @brief Pre-compiled IDL source for the CSD_Framework module. + * + * This file was used to generate the code in + * CSD_FrameworkC.{h,inl,cpp}, using the following command: + * + $ACE_ROOT/bin/tao_idl \ + -o orig -Gp -Gd -Ge 1 -Gt -Sc -GA -I$TAO_ROOT \ + -Wb,export_macro=TAO_CSD_FW_Export \ + -Wb,export_include="CSD_FW_Export.h" \ + -Wb,pre_include="ace/pre.h" \ + -Wb,post_include="ace/post.h" \ + CSD_Framework.pidl + * + * After the file is generated a patch from the diffs directory must + * be applied. The patch: + * + * - Disables parts of the code under certain configurations. + * + * - Eliminates cycles in the include dependencies. + * + * - Adds non-idl components of CSD_Framework to the namespace. + * This includes (a) Servant (b) ServantBase (c) RefCountServantBase + * (d) Cookie (e) ObjectId_to_string (f) string_to_ObjectId (g) + * ObjectId_to_wstring (h) wstring_to_ObjectId (i) ServantBase_var + * (j) DynamicImplementation (k) LocalServantBase + * + * Apply patches using the following command: + * + * patch < diffs/CSD_Framework.diff + * + * Note: The diffs were generated using: + * + * rm diffs/CSD_Framework.diff + * for i in CSD_FrameworkC.{h,i,cpp}; do + * diff -wub orig/$i $i >> diffs/CSD_Framework.diff + * done + */ + +#ifndef _CSD_FRAMEWORK_IDL_ +#define _CSD_FRAMEWORK_IDL_ + +#include <tao/PortableServer/PortableServer.pidl> + +module CSD_Framework { + + //# pragma version CSD_Framework 2.3 + + // This is a common base interface for all CSD strategy + // implementations + local interface Strategy { + + //# pragma version Strategy 2.3 + + // This is support for a legacy method of supplying a strategy to a + // POA. + boolean apply_to(in PortableServer::POA p); + }; + + // Specialized POA providing a method to supply a strategy object to + // the POA. + local interface POA : PortableServer::POA { + + //# pragma version POA 2.3 + + void set_csd_strategy (in Strategy s); + }; +}; + +#endif //_CSD_FRAMEWORK_IDL_ diff --git a/TAO/tao/CSD_Framework/CSD_FrameworkA.cpp b/TAO/tao/CSD_Framework/CSD_FrameworkA.cpp new file mode 100644 index 00000000000..9045084e4bc --- /dev/null +++ b/TAO/tao/CSD_Framework/CSD_FrameworkA.cpp @@ -0,0 +1,73 @@ +// -*- C++ -*- +// +// $Id$ + +// **** Code generated by the The ACE ORB (TAO) IDL Compiler **** +// TAO and the TAO IDL Compiler have been developed by: +// Center for Distributed Object Computing +// Washington University +// St. Louis, MO +// USA +// http://www.cs.wustl.edu/~schmidt/doc-center.html +// and +// Distributed Object Computing Laboratory +// University of California at Irvine +// Irvine, CA +// USA +// http://doc.ece.uci.edu/ +// and +// Institute for Software Integrated Systems +// Vanderbilt University +// Nashville, TN +// USA +// http://www.isis.vanderbilt.edu/ +// +// Information about TAO is available at: +// http://www.cs.wustl.edu/~schmidt/TAO.html + +#include "CSD_FrameworkA.h" +#include "tao/AnyTypeCode/Null_RefCount_Policy.h" +#include "tao/AnyTypeCode/TypeCode_Constants.h" +#include "tao/AnyTypeCode/Alias_TypeCode_Static.h" +#include "tao/AnyTypeCode/Objref_TypeCode_Static.h" +#include "tao/AnyTypeCode/String_TypeCode_Static.h" +#include "tao/AnyTypeCode/Any.h" +#include "tao/CDR.h" +#include "tao/AnyTypeCode/Any.h" +#include "tao/AnyTypeCode/Any_Impl_T.h" + +// TAO_IDL - Generated from +// c:\csd\code\doc\ace_wrappers\tao\tao_idl\be\be_visitor_typecode/objref_typecode.cpp:76 + +static TAO::TypeCode::Objref<char const *, + TAO::Null_RefCount_Policy> + _tao_tc_CSD_Framework_Strategy ( + ::CORBA::tk_local_interface, + "IDL:CSD_Framework/Strategy:1.0", + "Strategy"); + +namespace CSD_Framework +{ + ::CORBA::TypeCode_ptr const _tc_Strategy = + &_tao_tc_CSD_Framework_Strategy; +} + + + +// TAO_IDL - Generated from +// c:\csd\code\doc\ace_wrappers\tao\tao_idl\be\be_visitor_typecode/objref_typecode.cpp:76 + +static TAO::TypeCode::Objref<char const *, + TAO::Null_RefCount_Policy> + _tao_tc_CSD_Framework_POA ( + ::CORBA::tk_local_interface, + "IDL:CSD_Framework/POA:1.0", + "POA"); + +namespace CSD_Framework +{ + ::CORBA::TypeCode_ptr const _tc_POA = + &_tao_tc_CSD_Framework_POA; +} + + diff --git a/TAO/tao/CSD_Framework/CSD_FrameworkA.h b/TAO/tao/CSD_Framework/CSD_FrameworkA.h new file mode 100644 index 00000000000..db88e7a79d6 --- /dev/null +++ b/TAO/tao/CSD_Framework/CSD_FrameworkA.h @@ -0,0 +1,64 @@ +// -*- C++ -*- +// +// $Id$ + +// **** Code generated by the The ACE ORB (TAO) IDL Compiler **** +// TAO and the TAO IDL Compiler have been developed by: +// Center for Distributed Object Computing +// Washington University +// St. Louis, MO +// USA +// http://www.cs.wustl.edu/~schmidt/doc-center.html +// and +// Distributed Object Computing Laboratory +// University of California at Irvine +// Irvine, CA +// USA +// http://doc.ece.uci.edu/ +// and +// Institute for Software Integrated Systems +// Vanderbilt University +// Nashville, TN +// USA +// http://www.isis.vanderbilt.edu/ +// +// Information about TAO is available at: +// http://www.cs.wustl.edu/~schmidt/TAO.html + +// TAO_IDL - Generated from +// .\be\be_codegen.cpp:754 + +#ifndef _TAO_IDL_ORIG_CSD_FRAMEWORKA_H_ +#define _TAO_IDL_ORIG_CSD_FRAMEWORKA_H_ + +#include /**/ "ace/pre.h" + +#include "CSD_FW_Export.h" +#include "CSD_FrameworkC.h" +//#include "tao/PortableServer/PortableServerA.h" + + +// TAO_IDL - Generated from +// c:\csd\code\doc\ace_wrappers\tao\tao_idl\be\be_visitor_module/module_ch.cpp:59 + +namespace CSD_Framework +{ + + // TAO_IDL - Generated from + // c:\csd\code\doc\ace_wrappers\tao\tao_idl\be\be_visitor_typecode/typecode_decl.cpp:49 + + extern TAO_CSD_FW_Export ::CORBA::TypeCode_ptr const _tc_Strategy; + + // TAO_IDL - Generated from + // c:\csd\code\doc\ace_wrappers\tao\tao_idl\be\be_visitor_typecode/typecode_decl.cpp:49 + + extern TAO_CSD_FW_Export ::CORBA::TypeCode_ptr const _tc_POA; + +// TAO_IDL - Generated from +// c:\csd\code\doc\ace_wrappers\tao\tao_idl\be\be_visitor_module/module_ch.cpp:86 + +} // module CSD_Framework + +#include /**/ "ace/post.h" + +#endif /* ifndef */ diff --git a/TAO/tao/CSD_Framework/CSD_FrameworkC.cpp b/TAO/tao/CSD_Framework/CSD_FrameworkC.cpp new file mode 100644 index 00000000000..12b91dd79cc --- /dev/null +++ b/TAO/tao/CSD_Framework/CSD_FrameworkC.cpp @@ -0,0 +1,293 @@ +// -*- C++ -*- +// +// $Id$ + +// **** Code generated by the The ACE ORB (TAO) IDL Compiler **** +// TAO and the TAO IDL Compiler have been developed by: +// Center for Distributed Object Computing +// Washington University +// St. Louis, MO +// USA +// http://www.cs.wustl.edu/~schmidt/doc-center.html +// and +// Distributed Object Computing Laboratory +// University of California at Irvine +// Irvine, CA +// USA +// http://doc.ece.uci.edu/ +// and +// Institute for Software Integrated Systems +// Vanderbilt University +// Nashville, TN +// USA +// http://www.isis.vanderbilt.edu/ +// +// Information about TAO is available at: +// http://www.cs.wustl.edu/~schmidt/TAO.html + +// TAO_IDL - Generated from +// .\be\be_codegen.cpp:277 + + +#include "CSD_FrameworkC.h" +#include "tao/CDR.h" +#include "ace/OS_NS_string.h" + +#if !defined (__ACE_INLINE__) +#include "CSD_FrameworkC.inl" +#endif /* !defined INLINE */ + +// TAO_IDL - Generated from +// .\be\be_visitor_arg_traits.cpp:70 + +// Arg traits specializations. +namespace TAO +{ +} + + +// TAO_IDL - Generated from +// c:\csd\code\doc\ace_wrappers\tao\tao_idl\be\be_visitor_interface/interface_cs.cpp:60 + +// Traits specializations for CSD_Framework::Strategy. + +CSD_Framework::Strategy_ptr +TAO::Objref_Traits<CSD_Framework::Strategy>::duplicate ( + CSD_Framework::Strategy_ptr p + ) +{ + return CSD_Framework::Strategy::_duplicate (p); +} + +void +TAO::Objref_Traits<CSD_Framework::Strategy>::release ( + CSD_Framework::Strategy_ptr p + ) +{ + CORBA::release (p); +} + +CSD_Framework::Strategy_ptr +TAO::Objref_Traits<CSD_Framework::Strategy>::nil (void) +{ + return CSD_Framework::Strategy::_nil (); +} + +::CORBA::Boolean +TAO::Objref_Traits<CSD_Framework::Strategy>::marshal ( + CSD_Framework::Strategy_ptr p, + TAO_OutputCDR & cdr + ) +{ + return ::CORBA::Object::marshal (p, cdr); +} + +CSD_Framework::Strategy::Strategy (void) +{} + +CSD_Framework::Strategy::~Strategy (void) +{} + +CSD_Framework::Strategy_ptr +CSD_Framework::Strategy::_narrow ( + ::CORBA::Object_ptr _tao_objref + ACE_ENV_ARG_DECL_NOT_USED + ) +{ + return Strategy::_duplicate ( + dynamic_cast<Strategy_ptr> (_tao_objref) + ); +} + +CSD_Framework::Strategy_ptr +CSD_Framework::Strategy::_unchecked_narrow ( + ::CORBA::Object_ptr _tao_objref + ACE_ENV_ARG_DECL_NOT_USED + ) +{ + return Strategy::_duplicate ( + dynamic_cast<Strategy_ptr> (_tao_objref) + ); +} + +CSD_Framework::Strategy_ptr +CSD_Framework::Strategy::_duplicate (Strategy_ptr obj) +{ + if (! CORBA::is_nil (obj)) + { + obj->_add_ref (); + } + + return obj; +} + +void +CSD_Framework::Strategy::_tao_release (Strategy_ptr obj) +{ + CORBA::release (obj); +} + +::CORBA::Boolean +CSD_Framework::Strategy::_is_a ( + const char *value + ACE_ENV_ARG_DECL_NOT_USED + ) +{ + if ( + !ACE_OS::strcmp ( + value, + "IDL:CSD_Framework/Strategy:1.0" + ) || + !ACE_OS::strcmp ( + value, + "IDL:omg.org/CORBA/LocalObject:1.0" + ) || + !ACE_OS::strcmp ( + value, + "IDL:omg.org/CORBA/Object:1.0" + ) + ) + { + return true; // success using local knowledge + } + else + { + return false; + } +} + +const char* CSD_Framework::Strategy::_interface_repository_id (void) const +{ + return "IDL:CSD_Framework/Strategy:1.0"; +} + +::CORBA::Boolean +CSD_Framework::Strategy::marshal (TAO_OutputCDR &) +{ + return false; +} + +// TAO_IDL - Generated from +// c:\csd\code\doc\ace_wrappers\tao\tao_idl\be\be_visitor_interface/interface_cs.cpp:60 + +// Traits specializations for CSD_Framework::POA. + +CSD_Framework::POA_ptr +TAO::Objref_Traits<CSD_Framework::POA>::duplicate ( + CSD_Framework::POA_ptr p + ) +{ + return CSD_Framework::POA::_duplicate (p); +} + +void +TAO::Objref_Traits<CSD_Framework::POA>::release ( + CSD_Framework::POA_ptr p + ) +{ + CORBA::release (p); +} + +CSD_Framework::POA_ptr +TAO::Objref_Traits<CSD_Framework::POA>::nil (void) +{ + return CSD_Framework::POA::_nil (); +} + +::CORBA::Boolean +TAO::Objref_Traits<CSD_Framework::POA>::marshal ( + CSD_Framework::POA_ptr p, + TAO_OutputCDR & cdr + ) +{ + return ::CORBA::Object::marshal (p, cdr); +} + +CSD_Framework::POA::POA (void) +{} + +CSD_Framework::POA::~POA (void) +{} + +CSD_Framework::POA_ptr +CSD_Framework::POA::_narrow ( + ::CORBA::Object_ptr _tao_objref + ACE_ENV_ARG_DECL_NOT_USED + ) +{ + return POA::_duplicate ( + dynamic_cast<POA_ptr> (_tao_objref) + ); +} + +CSD_Framework::POA_ptr +CSD_Framework::POA::_unchecked_narrow ( + ::CORBA::Object_ptr _tao_objref + ACE_ENV_ARG_DECL_NOT_USED + ) +{ + return POA::_duplicate ( + dynamic_cast<POA_ptr> (_tao_objref) + ); +} + +CSD_Framework::POA_ptr +CSD_Framework::POA::_duplicate (POA_ptr obj) +{ + if (! CORBA::is_nil (obj)) + { + obj->_add_ref (); + } + + return obj; +} + +void +CSD_Framework::POA::_tao_release (POA_ptr obj) +{ + CORBA::release (obj); +} + +::CORBA::Boolean +CSD_Framework::POA::_is_a ( + const char *value + ACE_ENV_ARG_DECL_NOT_USED + ) +{ + if ( + !ACE_OS::strcmp ( + value, + "IDL:omg.org/PortableServer/POA:1.0" + ) || + !ACE_OS::strcmp ( + value, + "IDL:CSD_Framework/POA:1.0" + ) || + !ACE_OS::strcmp ( + value, + "IDL:omg.org/CORBA/LocalObject:1.0" + ) || + !ACE_OS::strcmp ( + value, + "IDL:omg.org/CORBA/Object:1.0" + ) + ) + { + return true; // success using local knowledge + } + else + { + return false; + } +} + +const char* CSD_Framework::POA::_interface_repository_id (void) const +{ + return "IDL:CSD_Framework/POA:1.0"; +} + +::CORBA::Boolean +CSD_Framework::POA::marshal (TAO_OutputCDR &) +{ + return false; +} diff --git a/TAO/tao/CSD_Framework/CSD_FrameworkC.h b/TAO/tao/CSD_Framework/CSD_FrameworkC.h new file mode 100644 index 00000000000..832eae8ffe0 --- /dev/null +++ b/TAO/tao/CSD_Framework/CSD_FrameworkC.h @@ -0,0 +1,312 @@ +// -*- C++ -*- +// +// $Id$ + +// **** Code generated by the The ACE ORB (TAO) IDL Compiler **** +// TAO and the TAO IDL Compiler have been developed by: +// Center for Distributed Object Computing +// Washington University +// St. Louis, MO +// USA +// http://www.cs.wustl.edu/~schmidt/doc-center.html +// and +// Distributed Object Computing Laboratory +// University of California at Irvine +// Irvine, CA +// USA +// http://doc.ece.uci.edu/ +// and +// Institute for Software Integrated Systems +// Vanderbilt University +// Nashville, TN +// USA +// http://www.isis.vanderbilt.edu/ +// +// Information about TAO is available at: +// http://www.cs.wustl.edu/~schmidt/TAO.html + +// TAO_IDL - Generated from +// .\be\be_codegen.cpp:154 + +#ifndef _TAO_IDL_ORIG_CSD_FRAMEWORKC_H_ +#define _TAO_IDL_ORIG_CSD_FRAMEWORKC_H_ + +#include /**/ "ace/pre.h" + + +#include "ace/config-all.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "CSD_FW_Export.h" +#include "tao/ORB.h" +#include "tao/SystemException.h" +#include "tao/Environment.h" +#include "tao/Object.h" +#include "tao/Objref_VarOut_T.h" + +#include "tao/PortableServer/PortableServer.h" + +#if defined (TAO_EXPORT_MACRO) +#undef TAO_EXPORT_MACRO +#endif +#define TAO_EXPORT_MACRO TAO_CSD_FW_Export + +// TAO_IDL - Generated from +// c:\csd\code\doc\ace_wrappers\tao\tao_idl\be\be_visitor_module/module_ch.cpp:49 + +namespace CSD_Framework +{ + + // TAO_IDL - Generated from + // .\be\be_interface.cpp:646 + +#if !defined (_CSD_FRAMEWORK_STRATEGY__VAR_OUT_CH_) +#define _CSD_FRAMEWORK_STRATEGY__VAR_OUT_CH_ + + class Strategy; + typedef Strategy *Strategy_ptr; + + typedef + TAO_Objref_Var_T< + Strategy + > + Strategy_var; + + typedef + TAO_Objref_Out_T< + Strategy + > + Strategy_out; + +#endif /* end #if !defined */ + + // TAO_IDL - Generated from + // c:\csd\code\doc\ace_wrappers\tao\tao_idl\be\be_visitor_interface/interface_ch.cpp:54 + +#if !defined (_CSD_FRAMEWORK_STRATEGY_CH_) +#define _CSD_FRAMEWORK_STRATEGY_CH_ + + class TAO_CSD_FW_Export Strategy + : public virtual ::CORBA::Object + { + public: + typedef Strategy_ptr _ptr_type; + typedef Strategy_var _var_type; + + // The static operations. + static Strategy_ptr _duplicate (Strategy_ptr obj); + + static void _tao_release (Strategy_ptr obj); + + static Strategy_ptr _narrow ( + ::CORBA::Object_ptr obj + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ); + + static Strategy_ptr _unchecked_narrow ( + ::CORBA::Object_ptr obj + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ); + + static Strategy_ptr _nil (void) + { + return static_cast<Strategy_ptr> (0); + } + + + + // TAO_IDL - Generated from + // c:\csd\code\doc\ace_wrappers\tao\tao_idl\be\be_visitor_operation/operation_ch.cpp:46 + + virtual ::CORBA::Boolean apply_to ( + ::PortableServer::POA_ptr p + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + ::CORBA::SystemException + )) = 0; + + // TAO_IDL - Generated from + // c:\csd\code\doc\ace_wrappers\tao\tao_idl\be\be_visitor_interface/interface_ch.cpp:210 + + virtual ::CORBA::Boolean _is_a ( + const char *type_id + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ); + + virtual const char* _interface_repository_id (void) const; + virtual ::CORBA::Boolean marshal (TAO_OutputCDR &cdr); + + protected: + // Abstract or local interface only. + Strategy (void); + + virtual ~Strategy (void); + + private: + // Private and unimplemented for concrete interfaces. + Strategy (const Strategy &); + + void operator= (const Strategy &); + }; + +#endif /* end #if !defined */ + + // TAO_IDL - Generated from + // .\be\be_interface.cpp:646 + +#if !defined (_CSD_FRAMEWORK_POA__VAR_OUT_CH_) +#define _CSD_FRAMEWORK_POA__VAR_OUT_CH_ + + class POA; + typedef POA *POA_ptr; + + typedef + TAO_Objref_Var_T< + POA + > + POA_var; + + typedef + TAO_Objref_Out_T< + POA + > + POA_out; + +#endif /* end #if !defined */ + + // TAO_IDL - Generated from + // c:\csd\code\doc\ace_wrappers\tao\tao_idl\be\be_visitor_interface/interface_ch.cpp:54 + +#if !defined (_CSD_FRAMEWORK_POA_CH_) +#define _CSD_FRAMEWORK_POA_CH_ + + class TAO_CSD_FW_Export POA + : public virtual ::PortableServer::POA + { + public: + typedef POA_ptr _ptr_type; + typedef POA_var _var_type; + + // The static operations. + static POA_ptr _duplicate (POA_ptr obj); + + static void _tao_release (POA_ptr obj); + + static POA_ptr _narrow ( + ::CORBA::Object_ptr obj + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ); + + static POA_ptr _unchecked_narrow ( + ::CORBA::Object_ptr obj + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ); + + static POA_ptr _nil (void) + { + return static_cast<POA_ptr> (0); + } + + + + // TAO_IDL - Generated from + // c:\csd\code\doc\ace_wrappers\tao\tao_idl\be\be_visitor_operation/operation_ch.cpp:46 + + virtual void set_csd_strategy ( + ::CSD_Framework::Strategy_ptr s + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + ::CORBA::SystemException + )) = 0; + + // TAO_IDL - Generated from + // c:\csd\code\doc\ace_wrappers\tao\tao_idl\be\be_visitor_interface/interface_ch.cpp:210 + + virtual ::CORBA::Boolean _is_a ( + const char *type_id + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ); + + virtual const char* _interface_repository_id (void) const; + virtual ::CORBA::Boolean marshal (TAO_OutputCDR &cdr); + + protected: + // Abstract or local interface only. + POA (void); + + virtual ~POA (void); + + private: + // Private and unimplemented for concrete interfaces. + POA (const POA &); + + void operator= (const POA &); + }; + +#endif /* end #if !defined */ + +// TAO_IDL - Generated from +// c:\csd\code\doc\ace_wrappers\tao\tao_idl\be\be_visitor_module/module_ch.cpp:78 + +} // module CSD_Framework + +// TAO_IDL - Generated from +// .\be\be_visitor_traits.cpp:61 + +// Traits specializations. +namespace TAO +{ + +#if !defined (_CSD_FRAMEWORK_STRATEGY__TRAITS_) +#define _CSD_FRAMEWORK_STRATEGY__TRAITS_ + + template<> + struct TAO_CSD_FW_Export Objref_Traits< ::CSD_Framework::Strategy> + { + static ::CSD_Framework::Strategy_ptr duplicate ( + ::CSD_Framework::Strategy_ptr + ); + static void release ( + ::CSD_Framework::Strategy_ptr + ); + static ::CSD_Framework::Strategy_ptr nil (void); + static ::CORBA::Boolean marshal ( + ::CSD_Framework::Strategy_ptr p, + TAO_OutputCDR & cdr + ); + }; + +#endif /* end #if !defined */ + +#if !defined (_CSD_FRAMEWORK_POA__TRAITS_) +#define _CSD_FRAMEWORK_POA__TRAITS_ + + template<> + struct TAO_CSD_FW_Export Objref_Traits< ::CSD_Framework::POA> + { + static ::CSD_Framework::POA_ptr duplicate ( + ::CSD_Framework::POA_ptr + ); + static void release ( + ::CSD_Framework::POA_ptr + ); + static ::CSD_Framework::POA_ptr nil (void); + static ::CORBA::Boolean marshal ( + ::CSD_Framework::POA_ptr p, + TAO_OutputCDR & cdr + ); + }; + +#endif /* end #if !defined */ +} + +#include /**/ "ace/post.h" + +#endif /* ifndef */ + + diff --git a/TAO/tao/CSD_Framework/CSD_FrameworkC.inl b/TAO/tao/CSD_Framework/CSD_FrameworkC.inl new file mode 100644 index 00000000000..c944d806c1f --- /dev/null +++ b/TAO/tao/CSD_Framework/CSD_FrameworkC.inl @@ -0,0 +1,27 @@ +// -*- C++ -*- +// +// $Id$ + +// **** Code generated by the The ACE ORB (TAO) IDL Compiler **** +// TAO and the TAO IDL Compiler have been developed by: +// Center for Distributed Object Computing +// Washington University +// St. Louis, MO +// USA +// http://www.cs.wustl.edu/~schmidt/doc-center.html +// and +// Distributed Object Computing Laboratory +// University of California at Irvine +// Irvine, CA +// USA +// http://doc.ece.uci.edu/ +// and +// Institute for Software Integrated Systems +// Vanderbilt University +// Nashville, TN +// USA +// http://www.isis.vanderbilt.edu/ +// +// Information about TAO is available at: +// http://www.cs.wustl.edu/~schmidt/TAO.html + diff --git a/TAO/tao/CSD_Framework/CSD_Framework_Loader.cpp b/TAO/tao/CSD_Framework/CSD_Framework_Loader.cpp new file mode 100644 index 00000000000..9163e6995dc --- /dev/null +++ b/TAO/tao/CSD_Framework/CSD_Framework_Loader.cpp @@ -0,0 +1,26 @@ +// $Id$ + +#include "CSD_Framework_Loader.h" +#include "CSD_Object_Adapter_Factory.h" +#include "CSD_Strategy_Repository.h" +#include "ace/Dynamic_Service.h" + +ACE_RCSID (CSD_Framework, + CSD_Framework_Loader, + "$Id$") + +#include "tao/ORB_Core.h" + +int +TAO_CSD_Framework_Loader::init (void) +{ + ACE_Service_Config::process_directive (ace_svc_desc_TAO_CSD_Object_Adapter_Factory); + + TAO_ORB_Core::set_poa_factory ("TAO_CSD_Object_Adapter_Factory", + "dynamic TAO_CSD_Object_Adapter_Factory Service_Object * _make_TAO_CSD_Object_Adapter_Factory()"); + + + ACE_Service_Config::process_directive (ace_svc_desc_TAO_CSD_Strategy_Repository); + + return 0; +} diff --git a/TAO/tao/CSD_Framework/CSD_Framework_Loader.h b/TAO/tao/CSD_Framework/CSD_Framework_Loader.h new file mode 100644 index 00000000000..5a13ed5f13f --- /dev/null +++ b/TAO/tao/CSD_Framework/CSD_Framework_Loader.h @@ -0,0 +1,41 @@ +/* -*- C++ -*- */ + +//============================================================================= +/** + * @file CSD_Framework_Loader.h + * + * $Id$ + * + * Header file for loading CSD framework service objects. + * + * @author Yan Dai (dai_y@ociweb.com) + */ +//============================================================================= + +#ifndef TAO_CSD_FRAMEWORK_LOADER_H +#define TAO_CSD_FRAMEWORK_LOADER_H +#include /**/ "ace/pre.h" + +#include "CSD_FW_Export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +/** + * @class TAO_CSD_Framework_Loader + * + * @brief TAO_CSD_Framework_Loader. + * + * This class acts as a facade for the CSD_Framework library to the + * ORB. + */ +class TAO_CSD_FW_Export TAO_CSD_Framework_Loader +{ + public: + /// Used to force the initialization of the ORB code. + static int init (void); +}; + +#include /**/ "ace/post.h" +#endif /* TAO_CSD_FRAMEWORK_LOADER_H */ diff --git a/TAO/tao/CSD_Framework/CSD_ORBInitializer.cpp b/TAO/tao/CSD_Framework/CSD_ORBInitializer.cpp new file mode 100644 index 00000000000..56a46b61c18 --- /dev/null +++ b/TAO/tao/CSD_Framework/CSD_ORBInitializer.cpp @@ -0,0 +1,33 @@ +// $Id$ +#include "CSD_ORBInitializer.h" + +#if defined (TAO_HAS_CORBA_MESSAGING) && TAO_HAS_CORBA_MESSAGING != 0 + +ACE_RCSID (CSD_Framework, + CSD_ORBInitializer, + "$Id$") + +#include "CSD_Object_Adapter_Factory.h" + +TAO_CSD_ORBInitializer::TAO_CSD_ORBInitializer () +{ +} + +void +TAO_CSD_ORBInitializer::pre_init ( + PortableInterceptor::ORBInitInfo_ptr + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ +} + +void +TAO_CSD_ORBInitializer::post_init ( + PortableInterceptor::ORBInitInfo_ptr + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ +} + + +#endif /* TAO_HAS_CORBA_MESSAGING && TAO_HAS_CORBA_MESSAGING != 0 */ diff --git a/TAO/tao/CSD_Framework/CSD_ORBInitializer.h b/TAO/tao/CSD_Framework/CSD_ORBInitializer.h new file mode 100644 index 00000000000..0b661e2dd7c --- /dev/null +++ b/TAO/tao/CSD_Framework/CSD_ORBInitializer.h @@ -0,0 +1,66 @@ +/* -*- C++ -*- */ + +//============================================================================= +/** + * @file CSD_ORBInitializer.h + * + * $Id$ + * + * @author Yan Dai (dai_y@ociweb.com) + */ +//============================================================================= + + +#ifndef TAO_CSD_ORB_INITIALIZER_H +#define TAO_CSD_ORB_INITIALIZER_H + +#include /**/ "ace/pre.h" + +#include "tao/orbconf.h" + +#if defined (TAO_HAS_CORBA_MESSAGING) && TAO_HAS_CORBA_MESSAGING != 0 + +#include "CSD_FW_Export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +//#include "tao/PortableInterceptorC.h" +#include "tao/LocalObject.h" +#include "tao/PI/ORBInitializerC.h" + +// This is to remove "inherits via dominance" warnings from MSVC. +// MSVC is being a little too paranoid. +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable:4250) +#endif /* _MSC_VER */ + +/// CSD ORB initializer. +class TAO_CSD_FW_Export TAO_CSD_ORBInitializer : + public virtual PortableInterceptor::ORBInitializer, + public virtual TAO_Local_RefCounted_Object +{ +public: + + TAO_CSD_ORBInitializer (); + + 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)); +}; + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif /* _MSC_VER */ + +#endif /* TAO_HAS_CORBA_MESSAGING && TAO_HAS_CORBA_MESSAGING != 0 */ + +#include /**/ "ace/post.h" + +#endif /* TAO_CSD_ORB_INITIALIZER_H */ diff --git a/TAO/tao/CSD_Framework/CSD_Object_Adapter.cpp b/TAO/tao/CSD_Framework/CSD_Object_Adapter.cpp new file mode 100644 index 00000000000..cd599fd37e2 --- /dev/null +++ b/TAO/tao/CSD_Framework/CSD_Object_Adapter.cpp @@ -0,0 +1,42 @@ +// $Id$ + +#include "CSD_Object_Adapter.h" +#include "CSD_Strategy_Proxy.h" +#include "CSD_POA.h" + +ACE_RCSID (CSD_Framework, + CSD_Object_Adapter, + "$Id$") + +TAO_CSD_Object_Adapter::TAO_CSD_Object_Adapter ( + const TAO_Server_Strategy_Factory::Active_Object_Map_Creation_Parameters &creation_parameters, + TAO_ORB_Core &orb_core) + : TAO_Object_Adapter (creation_parameters, orb_core) +{ + +} + +TAO_CSD_Object_Adapter::~TAO_CSD_Object_Adapter () +{ +} + +void +TAO_CSD_Object_Adapter::do_dispatch ( + TAO_ServerRequest& req, + TAO::Portable_Server::Servant_Upcall& upcall + ACE_ENV_ARG_DECL) +{ + TAO_Root_POA& poa = upcall.poa (); + TAO_CSD_POA* csd_poa = dynamic_cast<TAO_CSD_POA*> (&poa); + + if (csd_poa == 0) + { + ACE_THROW (CORBA::BAD_PARAM ()); + } + + TAO::CSD::Strategy_Proxy& proxy + = csd_poa->servant_dispatching_strategy_proxy (); + proxy.dispatch_request (req, upcall ACE_ENV_ARG_PARAMETER); + ACE_CHECK; +} + diff --git a/TAO/tao/CSD_Framework/CSD_Object_Adapter.h b/TAO/tao/CSD_Framework/CSD_Object_Adapter.h new file mode 100644 index 00000000000..83deb3c96b6 --- /dev/null +++ b/TAO/tao/CSD_Framework/CSD_Object_Adapter.h @@ -0,0 +1,54 @@ +/* -*- C++ -*- */ + +//============================================================================= +/** + * @file CSD_Object_Adapter.h + * + * $Id$ + * + * @author Yan Dai (dai_y@ociweb.com) + */ +//============================================================================= + + +#ifndef TAO_CSD_OBJECT_ADAPTER_H +#define TAO_CSD_OBJECT_ADAPTER_H +#include /**/ "ace/pre.h" + +#include "CSD_FW_Export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "tao/PortableServer/Object_Adapter.h" + +/** + * @class TAO_CSD_Object_Adapter + * + * @brief Defines the CSD version Object Adapter which overrides + * default dispatch implementation. + * + * This class will be used as a facade for the CSD POAs in a server + */ +class TAO_CSD_FW_Export TAO_CSD_Object_Adapter : public TAO_Object_Adapter +{ +public: + + /// Constructor + TAO_CSD_Object_Adapter (const TAO_Server_Strategy_Factory::Active_Object_Map_Creation_Parameters &creation_parameters, + TAO_ORB_Core &orb_core); + + /// Destructor + virtual ~TAO_CSD_Object_Adapter (void); + + /// Hand the request to the Service_Dispatching_Strategy_Proxy for + /// dispatching. + virtual void do_dispatch (TAO_ServerRequest& req, + TAO::Portable_Server::Servant_Upcall& upcall + ACE_ENV_ARG_DECL); +}; + + +#include /**/ "ace/post.h" +#endif /* TAO_CSD_OBJECT_ADAPTER_H */ diff --git a/TAO/tao/CSD_Framework/CSD_Object_Adapter_Factory.cpp b/TAO/tao/CSD_Framework/CSD_Object_Adapter_Factory.cpp new file mode 100644 index 00000000000..7943eda6a5d --- /dev/null +++ b/TAO/tao/CSD_Framework/CSD_Object_Adapter_Factory.cpp @@ -0,0 +1,93 @@ +// $Id$ + +#include "CSD_Object_Adapter_Factory.h" +#include "CSD_Strategy_Repository.h" +#include "CSD_Object_Adapter.h" +#include "CSD_ORBInitializer.h" +#include "CSD_Default_Servant_Dispatcher.h" +#include "tao/ORB_Core.h" +#include "tao/ORBInitializer_Registry.h" +#include "ace/Dynamic_Service.h" + +ACE_RCSID (CSD_Framework, + CSD_Object_Adapter_Factory, + "$Id$") + + +TAO_CSD_Object_Adapter_Factory::TAO_CSD_Object_Adapter_Factory (void) +{ +} + +TAO_Adapter* +TAO_CSD_Object_Adapter_Factory::create (TAO_ORB_Core *oc) +{ + // Create the CSD object adapter. + TAO_CSD_Object_Adapter *object_adapter = 0; + ACE_NEW_RETURN (object_adapter, + TAO_CSD_Object_Adapter (oc->server_factory ()-> + active_object_map_creation_parameters (), + *oc), + 0); + + // Create and register the CSD servant dispatcher. + TAO_CSD_Default_Servant_Dispatcher * csd_servant_dispatcher = 0; + ACE_NEW_RETURN (csd_servant_dispatcher, + TAO_CSD_Default_Servant_Dispatcher, + 0); + object_adapter->servant_dispatcher (csd_servant_dispatcher); + + return object_adapter; +} + +int +TAO_CSD_Object_Adapter_Factory::init (int /* argc */, + ACE_TCHAR* /* argv */ []) +{ + TAO_CSD_Strategy_Repository *repo = + ACE_Dynamic_Service<TAO_CSD_Strategy_Repository>::instance ("TAO_CSD_Strategy_Repository"); + + if (repo != 0) + repo->init(0,0); + + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + /// Register the Messaging ORBInitializer. + PortableInterceptor::ORBInitializer_ptr temp_orb_initializer = + PortableInterceptor::ORBInitializer::_nil (); + + ACE_NEW_THROW_EX (temp_orb_initializer, + TAO_CSD_ORBInitializer, + CORBA::NO_MEMORY ( + CORBA::SystemException::_tao_minor_code ( + TAO::VMCID, + ENOMEM), + CORBA::COMPLETED_NO)); + ACE_TRY_CHECK; + + PortableInterceptor::ORBInitializer_var orb_initializer = + temp_orb_initializer; + + PortableInterceptor::register_orb_initializer (orb_initializer.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "(%P | %t) Caught exception:"); + return -1; + } + ACE_ENDTRY; + + return 0; +} + + +ACE_FACTORY_DEFINE (TAO_CSD_FW, TAO_CSD_Object_Adapter_Factory) +ACE_STATIC_SVC_DEFINE (TAO_CSD_Object_Adapter_Factory, + ACE_TEXT ("TAO_CSD_Object_Adapter_Factory"), + ACE_SVC_OBJ_T, + &ACE_SVC_NAME (TAO_CSD_Object_Adapter_Factory), + ACE_Service_Type::DELETE_THIS | ACE_Service_Type::DELETE_OBJ, + 0) diff --git a/TAO/tao/CSD_Framework/CSD_Object_Adapter_Factory.h b/TAO/tao/CSD_Framework/CSD_Object_Adapter_Factory.h new file mode 100644 index 00000000000..9deab152daf --- /dev/null +++ b/TAO/tao/CSD_Framework/CSD_Object_Adapter_Factory.h @@ -0,0 +1,46 @@ +/* -*- C++ -*- */ + +//============================================================================= +/** + * @file CSD_Object_Adapter_Factory.h + * + * $Id$ + * + * @author Yan Dai (dai_y@ociweb.com) + */ +//============================================================================= + + +#ifndef TAO_CSD_OBJECT_ADAPTER_FACTORY_H +#define TAO_CSD_OBJECT_ADAPTER_FACTORY_H +#include /**/ "ace/pre.h" + +#include "CSD_FW_Export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "tao/Adapter_Factory.h" +#include "ace/Service_Config.h" + + +class TAO_CSD_FW_Export TAO_CSD_Object_Adapter_Factory : public TAO_Adapter_Factory +{ +public: + /// Constructor + TAO_CSD_Object_Adapter_Factory (void); + + // = The TAO_Adapter_Factory methods, please read tao/Adapter.h for + // details. + virtual TAO_Adapter *create (TAO_ORB_Core *orb_core); + + virtual int init (int argc, + ACE_TCHAR* argv[]); +}; + +ACE_STATIC_SVC_DECLARE_EXPORT (TAO_CSD_FW, TAO_CSD_Object_Adapter_Factory) +ACE_FACTORY_DECLARE (TAO_CSD_FW, TAO_CSD_Object_Adapter_Factory) + +#include /**/ "ace/post.h" +#endif /* TAO_CSD_OBJECT_ADAPTER_FACTORY_H */ diff --git a/TAO/tao/CSD_Framework/CSD_POA.cpp b/TAO/tao/CSD_Framework/CSD_POA.cpp new file mode 100644 index 00000000000..98ec63d864e --- /dev/null +++ b/TAO/tao/CSD_Framework/CSD_POA.cpp @@ -0,0 +1,131 @@ +// $Id$ + + +#include "CSD_POA.h" +#include "CSD_Strategy_Repository.h" +#include "CSD_Strategy_Base.h" + +#include "ace/Dynamic_Service.h" + +ACE_RCSID (CSD_Framework, + CSD_POA, + "$Id$") + +#if !defined (__ACE_INLINE__) +# include "CSD_POA.inl" +#endif /* ! __ACE_INLINE__ */ + +// Implementation skeleton constructor +TAO_CSD_POA::TAO_CSD_POA (const String &name, + TAO_POA_Manager &poa_manager, + const TAO_POA_Policy_Set &policies, + TAO_Root_POA *parent, + ACE_Lock &lock, + TAO_SYNCH_MUTEX &thread_lock, + TAO_ORB_Core &orb_core, + TAO_Object_Adapter *object_adapter + ACE_ENV_ARG_DECL) +: TAO_Regular_POA (name, + poa_manager, + policies, + parent, + lock, + thread_lock, + orb_core, + object_adapter + ACE_ENV_ARG_PARAMETER) +{ + ACE_NEW_THROW_EX (this->sds_proxy_, + TAO::CSD::Strategy_Proxy (), + CORBA::NO_MEMORY ()); + ACE_CHECK; +} + + +// Implementation skeleton destructor +TAO_CSD_POA::~TAO_CSD_POA (void) +{ + delete this->sds_proxy_; +} + +void TAO_CSD_POA::set_csd_strategy ( + ::CSD_Framework::Strategy_ptr strategy + ACE_ENV_ARG_DECL + ) + ACE_THROW_SPEC (( + CORBA::SystemException + )) +{ + if (CORBA::is_nil (strategy)) + { + ACE_THROW (CORBA::BAD_PARAM ()); + } + this->sds_proxy_->custom_strategy (strategy); +} + +TAO_Root_POA * +TAO_CSD_POA::new_POA (const String &name, + TAO_POA_Manager &poa_manager, + const TAO_POA_Policy_Set &policies, + TAO_Root_POA *parent, + ACE_Lock &lock, + TAO_SYNCH_MUTEX &thread_lock, + TAO_ORB_Core &orb_core, + TAO_Object_Adapter *object_adapter + ACE_ENV_ARG_DECL) +{ + TAO_CSD_POA *poa = 0; + + ACE_NEW_THROW_EX (poa, + TAO_CSD_POA (name, + poa_manager, + policies, + parent, + lock, + thread_lock, + orb_core, + object_adapter + ACE_ENV_ARG_PARAMETER), + CORBA::NO_MEMORY ()); + ACE_CHECK_RETURN (0); + + TAO_CSD_Strategy_Repository *repo = + ACE_Dynamic_Service<TAO_CSD_Strategy_Repository>::instance ("TAO_CSD_Strategy_Repository"); + + + CSD_Framework::Strategy_var strategy = repo->find (name); + + if (! CORBA::is_nil (strategy.in ())) + { + poa->set_csd_strategy (strategy.in () ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (0); + } + + return poa; +} + +void TAO_CSD_POA::poa_activated_hook () +{ + this->sds_proxy_->poa_activated_event (); +} + +void TAO_CSD_POA::poa_deactivated_hook () +{ + this->sds_proxy_->poa_deactivated_event (); +} + +void TAO_CSD_POA::servant_activated_hook (PortableServer::Servant servant, + const PortableServer::ObjectId& oid + ACE_ENV_ARG_DECL) +{ + this->sds_proxy_->servant_activated_event (servant, oid ACE_ENV_ARG_PARAMETER); + ACE_CHECK; +} + +void TAO_CSD_POA::servant_deactivated_hook (PortableServer::Servant servant, + const PortableServer::ObjectId& oid + ACE_ENV_ARG_DECL) +{ + this->sds_proxy_->servant_deactivated_event (servant, oid ACE_ENV_ARG_PARAMETER); + ACE_CHECK; +} diff --git a/TAO/tao/CSD_Framework/CSD_POA.h b/TAO/tao/CSD_Framework/CSD_POA.h new file mode 100644 index 00000000000..8038537b45d --- /dev/null +++ b/TAO/tao/CSD_Framework/CSD_POA.h @@ -0,0 +1,108 @@ +/* -*- C++ -*- */ + +//============================================================================= +/** + * @file CSD_POA.h + * + * $Id$ + * + * @author Yan Dai (dai_y@ociweb.com) + */ +//============================================================================= + +#ifndef TAO_CSD_POA_H +#define TAO_CSD_POA_H + +#include /**/ "ace/pre.h" + +#include "CSD_FW_Export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +#pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "tao/PortableServer/Regular_POA.h" +#include "CSD_Strategy_Proxy.h" + + +/** + * @class TAO_CSD_POA + * + * @brief Implementation of the CSD_Framework::POA interface. + * + * Implementation of the CSD_Framework::POA interface. + */ +class TAO_CSD_FW_Export TAO_CSD_POA + : public virtual CSD_Framework::POA, + public virtual TAO_Regular_POA +{ +public: + //Constructor + TAO_CSD_POA (const String &name, + TAO_POA_Manager &poa_manager, + const TAO_POA_Policy_Set &policies, + TAO_Root_POA *parent, + ACE_Lock &lock, + TAO_SYNCH_MUTEX &thread_lock, + TAO_ORB_Core &orb_core, + TAO_Object_Adapter *object_adapter + ACE_ENV_ARG_DECL); + + //Destructor + virtual ~TAO_CSD_POA (void); + + /// Pass the Strategy object reference to the CSD poa. + virtual + void set_csd_strategy ( + ::CSD_Framework::Strategy_ptr s + ACE_ENV_ARG_DECL + ) + ACE_THROW_SPEC (( + CORBA::SystemException + )); + + /// Hook - The POA has been (or is being) activated. + virtual void poa_activated_hook (); + + /// Hook - The POA has been deactivated. + virtual void poa_deactivated_hook (); + + /// Hook - A servant has been activated. + virtual void servant_activated_hook (PortableServer::Servant servant, + const PortableServer::ObjectId& oid + ACE_ENV_ARG_DECL); + + /// Hook - A servant has been deactivated. + virtual void servant_deactivated_hook (PortableServer::Servant servant, + const PortableServer::ObjectId& oid + ACE_ENV_ARG_DECL); + + ///Method for creating new CSD POA. + TAO_Root_POA * new_POA (const String &name, + TAO_POA_Manager &poa_manager, + const TAO_POA_Policy_Set &policies, + TAO_Root_POA *parent, + ACE_Lock &lock, + TAO_SYNCH_MUTEX &thread_lock, + TAO_ORB_Core &orb_core, + TAO_Object_Adapter *object_adapter + ACE_ENV_ARG_DECL); + + /// Servant Dispatching Strategy proxy accessor. + TAO::CSD::Strategy_Proxy& + servant_dispatching_strategy_proxy (void) const; + +private: + + TAO::CSD::Strategy_Proxy* sds_proxy_; +}; + + +#if defined (__ACE_INLINE__) +# include "CSD_POA.inl" +#endif /* __ACE_INLINE__ */ + +#include /**/ "ace/post.h" + +#endif /* TAO_CSD_POA_H */ + diff --git a/TAO/tao/CSD_Framework/CSD_POA.inl b/TAO/tao/CSD_Framework/CSD_POA.inl new file mode 100644 index 00000000000..7a9aef6f63a --- /dev/null +++ b/TAO/tao/CSD_Framework/CSD_POA.inl @@ -0,0 +1,11 @@ +// $Id$ + + + +ACE_INLINE +TAO::CSD::Strategy_Proxy& +TAO_CSD_POA::servant_dispatching_strategy_proxy (void) const +{ + return *sds_proxy_; +} + diff --git a/TAO/tao/CSD_Framework/CSD_Strategy_Base.cpp b/TAO/tao/CSD_Framework/CSD_Strategy_Base.cpp new file mode 100644 index 00000000000..de6524c3b04 --- /dev/null +++ b/TAO/tao/CSD_Framework/CSD_Strategy_Base.cpp @@ -0,0 +1,133 @@ +// $Id$ + +#include "CSD_Strategy_Base.h" +#include "CSD_POA.h" +#include "CSD_Strategy_Proxy.h" +#include "tao/PortableServer/Root_POA.h" +#include "tao/PortableServer/POAManager.h" +#include "tao/PortableServer/Servant_Base.h" +#include "tao/TAO_Server_Request.h" + +ACE_RCSID (CSD_Framework, + CSD_Strategy_Base, + "$Id$") + +#if !defined (__ACE_INLINE__) +# include "CSD_Strategy_Base.inl" +#endif /* ! __ACE_INLINE__ */ + + +TAO::CSD::Strategy_Base::~Strategy_Base() +{ +} + +CORBA::Boolean +TAO::CSD::Strategy_Base::apply_to (PortableServer::POA_ptr poa + ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + if (CORBA::is_nil(poa)) + { + if (TAO_debug_level > 0) + ACE_ERROR((LM_ERROR, + ACE_TEXT("(%P|%t) CSD Strategy cannot ") + ACE_TEXT("be applied to a nil POA.\n"))); + return false; + } + + if (!CORBA::is_nil(this->poa_.in())) + { + if (TAO_debug_level > 0) + ACE_ERROR((LM_ERROR, + ACE_TEXT("(%P|%t) CSD Strategy already ") + ACE_TEXT("applied to a POA.\n"))); + return false; + } + + // The POA is a local interface (IDL terminology), and thus we know that + // we can downcast the POA_ptr to its (TAO) implementation type. + TAO_CSD_POA* poa_impl = dynamic_cast<TAO_CSD_POA*>(poa); + + if (poa_impl == 0) + { + if (TAO_debug_level > 0) + ACE_ERROR((LM_ERROR, + ACE_TEXT("(%P|%t) CSD Strategy cannot ") + ACE_TEXT("be applied to a non CSD POA.\n"))); + return false; + } + + // We need to check to see if the POA is already "active". If this is + // the case, then we need to handle the poa_activated_event() right now. + // If the POA is not already "active", then we can just wait until it + // does get activated, and we (the strategy) will be informed of the + // poa_activated_event() at that time. + if (poa_impl->tao_poa_manager().get_state() == + PortableServer::POAManager::ACTIVE) + { + // The POA is already "active" (since its POAManager is active). + // We need to "raise" the poa_activated_event() now. Otherwise, + // the event will be raised when the POAManager does become active. + if (!this->poa_activated_event()) + { + // An error has been already been reported to the log with + // the detailed reason for the failure to handle the event. + return false; + } + } + + // Set the CSD Strategy_Base on the strategy proxy object owned by the POA. + bool strategy_set = false; + ACE_TRY_NEW_ENV + { + poa_impl->set_csd_strategy (this ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + strategy_set = true; + } + ACE_CATCHANY + { + } + ACE_ENDTRY; + + if (! strategy_set) + { + // We need to make sure that we raise a poa_deactivated_event() if + // we earlier raised a poa_activated_event(). + this->poa_deactivated_event(); + + // An error has been already been reported to the log with + // the detailed reason why the proxy will not accept the + // custom strategy. + return false; + } + + // Save a duplicate of the poa into our data member. + this->poa_ = PortableServer::POA::_duplicate (poa); + + // Success + return true; +} + + +void +TAO::CSD::Strategy_Base::servant_activated_event_i + (PortableServer::Servant servant, + const PortableServer::ObjectId& oid + ACE_ENV_ARG_DECL) +{ + ACE_UNUSED_ARG(servant); + ACE_UNUSED_ARG(oid); + // do nothing. +} + + +void +TAO::CSD::Strategy_Base::servant_deactivated_event_i + (PortableServer::Servant servant, + const PortableServer::ObjectId& oid + ACE_ENV_ARG_DECL) +{ + ACE_UNUSED_ARG(servant); + ACE_UNUSED_ARG(oid); + // do nothing. +} diff --git a/TAO/tao/CSD_Framework/CSD_Strategy_Base.h b/TAO/tao/CSD_Framework/CSD_Strategy_Base.h new file mode 100644 index 00000000000..9650a914a45 --- /dev/null +++ b/TAO/tao/CSD_Framework/CSD_Strategy_Base.h @@ -0,0 +1,172 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file Custom_Servant_Dispatching_Strategy.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_CSD_FW_CUSTOM_SERVANT_DISPATCHING_STRATEGY_H +#define TAO_CSD_FW_CUSTOM_SERVANT_DISPATCHING_STRATEGY_H + +#include /**/ "ace/pre.h" + +#include "CSD_FW_Export.h" + +#include "tao/PortableServer/PortableServer.h" +#include "tao/PortableServer/Servant_Upcall.h" +#include "tao/PortableServer/Servant_Base.h" +#include "tao/TAO_Server_Request.h" +#include "tao/LocalObject.h" + + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "CSD_FrameworkC.h" + +class TAO_Root_POA; +namespace PortableServer +{ + class POAManager; +}; + + +namespace TAO +{ + namespace CSD + { + /** + * @class Strategy_Base + * + * @brief Base class for all Custom Servant Dispatching Strategies. + * + * This class serves as the base class for all "custom" strategies that + * perform servant dispatching. An instance of (a subclass of) this class + * can be applied to a POA object. Any servant requests for the POA will + * be "dispatched" to this strategy object. + * + */ + class TAO_CSD_FW_Export Strategy_Base + : public CSD_Framework::Strategy, + public TAO_Local_RefCounted_Object + { + public: + + /// Result Type for dispatching method(s). + enum DispatchResult + { + // The request dispatching has been handled. + DISPATCH_HANDLED, + + // The request dispatching has been rejected. + DISPATCH_REJECTED, + + // Defer to "default" dispatching strategy (use the caller's thread). + DISPATCH_DEFERRED + }; + + /// Virtual Destructor. + virtual ~Strategy_Base(); + + /// This method is invoked to "attach" this strategy object to + /// the supplied POA. Returns true for success, and false for failure. + CORBA::Boolean apply_to(PortableServer::POA_ptr poa ACE_ENV_ARG_DECL) + ACE_THROW_SPEC((CORBA::SystemException)); + + protected: + /// Default Constructor. + Strategy_Base(); + + /// Subclass provides implementation to dispatch a remote request. + virtual DispatchResult dispatch_remote_request_i + (TAO_ServerRequest& server_request, + const PortableServer::ObjectId& object_id, + PortableServer::POA_ptr poa, + const char* operation, + PortableServer::Servant servant + ACE_ENV_ARG_DECL) = 0; + + /// Subclass provides implementation to dispatch a collocated request. + virtual DispatchResult dispatch_collocated_request_i + (TAO_ServerRequest& server_request, + const PortableServer::ObjectId& object_id, + PortableServer::POA_ptr poa, + const char* operation, + PortableServer::Servant servant + ACE_ENV_ARG_DECL) = 0; + + /// Event - The POA has been activated. + virtual bool poa_activated_event_i() = 0; + + /// Event - The POA has been deactivated. + virtual void poa_deactivated_event_i() = 0; + + /// Event - A servant has been activated. + virtual void servant_activated_event_i + (PortableServer::Servant servant, + const PortableServer::ObjectId& oid + ACE_ENV_ARG_DECL); + + /// Event - A servant has been deactivated. + virtual void servant_deactivated_event_i + (PortableServer::Servant servant, + const PortableServer::ObjectId& oid + ACE_ENV_ARG_DECL); + + private: + + /// Only our friend, the proxy, is allowed to invoke our private operations. + /// This allows us to not pollute the public interface of the CSD Strategy_Base + /// subclasses with methods that should never be called (except by the + /// proxy, of course). + friend class Strategy_Proxy; + + /// This CSD Strategy_Base has been asked to dispatch a (collocated or remote) + /// request. + void dispatch_request(TAO_ServerRequest& server_request, + ::TAO::Portable_Server::Servant_Upcall& upcall + ACE_ENV_ARG_DECL); + + /// Event - The POA has been activated. This happens when the POA_Manager + /// is activated. + bool poa_activated_event(); + + /// Event - The POA has been deactivated. This happens when the + /// POAManager is deactivated, or when the POA is destroyed. + void poa_deactivated_event(); + + /// Event - A servant has been activated. + void servant_activated_event(PortableServer::Servant servant, + const PortableServer::ObjectId& oid + ACE_ENV_ARG_DECL); + + /// Event - A servant has been deactivated. This also occurs when + /// the POA is destroyed. + void servant_deactivated_event(PortableServer::Servant servant, + const PortableServer::ObjectId& oid + ACE_ENV_ARG_DECL); + + /// The POA to which this strategy has been applied. + ::PortableServer::POA_var poa_; + + /// This flag indicates that the POA is currently active (true) or + /// currently inactive (false). + bool poa_activated_; + }; + } +} + + +#if defined (__ACE_INLINE__) +# include "CSD_Strategy_Base.inl" +#endif /* __ACE_INLINE__ */ + +#include /**/ "ace/post.h" + +#endif /* TAO_CSD_FW_CUSTOM_SERVANT_DISPATCHING_STRATEGY_H */ diff --git a/TAO/tao/CSD_Framework/CSD_Strategy_Base.inl b/TAO/tao/CSD_Framework/CSD_Strategy_Base.inl new file mode 100644 index 00000000000..1f31a6cdcf4 --- /dev/null +++ b/TAO/tao/CSD_Framework/CSD_Strategy_Base.inl @@ -0,0 +1,138 @@ +// -*- C++ -*- +// $Id$ +#include "tao/debug.h" + +ACE_INLINE +TAO::CSD::Strategy_Base::Strategy_Base() + : poa_activated_(false) +{ +} + +ACE_INLINE +void +TAO::CSD::Strategy_Base::dispatch_request + (TAO_ServerRequest& server_request, + TAO::Portable_Server::Servant_Upcall& upcall + ACE_ENV_ARG_DECL) +{ + DispatchResult result; + + if (server_request.collocated()) + { + result = this->dispatch_collocated_request_i(server_request, + upcall.user_id(), + this->poa_.in(), + server_request.operation(), + upcall.servant() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + } + else + { + result = this->dispatch_remote_request_i(server_request, + upcall.user_id(), + this->poa_.in(), + server_request.operation(), + upcall.servant() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + } + + switch (result) + { + case DISPATCH_HANDLED: + // Do nothing. Everything has been handled. + break; + + case DISPATCH_REJECTED: + if (server_request.collocated ()) + { + CORBA::NO_IMPLEMENT ex; + ex._raise (); + } + else + { + // Raise an appropriate SystemException if the request is expecting + // a reply. + if (!server_request.sync_with_server() && + server_request.response_expected() && + !server_request.deferred_reply()) + { + CORBA::NO_IMPLEMENT ex; + server_request.tao_send_reply_exception(ex); + } + } + break; + + case DISPATCH_DEFERRED: + // Perform the "default" dispatching strategy logic for this request + // right now, using the current thread. + upcall.servant()->_dispatch(server_request, + (void*)&upcall + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + break; + + default: + if (TAO_debug_level > 0) + ACE_ERROR((LM_ERROR, + ACE_TEXT("(%P|%t) Unknown result (%d) from call to ") + ACE_TEXT("dispatch_remote_request_i().\n"), result)); + // Since we do not know what to do here, just do the minimum, which + // treats this case just like the DISPATCH_HANDLED case, for better + // or worse. Hitting this default case means a coding error. + break; + } +} + + +ACE_INLINE +bool +TAO::CSD::Strategy_Base::poa_activated_event() +{ + // Notify the subclass of the event, saving the result. + this->poa_activated_ = this->poa_activated_event_i(); + + // Return the result + return this->poa_activated_; +} + +ACE_INLINE +void +TAO::CSD::Strategy_Base::poa_deactivated_event() +{ + if (this->poa_activated_) + { + this->poa_activated_ = false; + + // Notify the subclass of the event. + this->poa_deactivated_event_i(); + + // Reset the poa to nil to decrement the reference count. + // This will break the circular dependency of the deletion + // of the CSD POA. + this->poa_ = 0; + } +} + +ACE_INLINE +void +TAO::CSD::Strategy_Base::servant_activated_event + (PortableServer::Servant servant, + const PortableServer::ObjectId& oid + ACE_ENV_ARG_DECL) +{ + this->servant_activated_event_i(servant, oid ACE_ENV_ARG_PARAMETER); + ACE_CHECK; +} + +ACE_INLINE +void +TAO::CSD::Strategy_Base::servant_deactivated_event + (PortableServer::Servant servant, + const PortableServer::ObjectId& oid + ACE_ENV_ARG_DECL) +{ + this->servant_deactivated_event_i(servant, oid ACE_ENV_ARG_PARAMETER); + ACE_CHECK; +} diff --git a/TAO/tao/CSD_Framework/CSD_Strategy_Proxy.cpp b/TAO/tao/CSD_Framework/CSD_Strategy_Proxy.cpp new file mode 100644 index 00000000000..063ec14f9aa --- /dev/null +++ b/TAO/tao/CSD_Framework/CSD_Strategy_Proxy.cpp @@ -0,0 +1,47 @@ +// $Id$ + +#include "CSD_Strategy_Proxy.h" +#include "tao/TAO_Server_Request.h" +#include "tao/debug.h" + +ACE_RCSID (CSD_Framework, + CSD_Strategy_Base, + "$Id$") + + +#if !defined (__ACE_INLINE__) +# include "CSD_Strategy_Proxy.inl" +#endif /* ! __ACE_INLINE__ */ + + +bool +TAO::CSD::Strategy_Proxy::custom_strategy + (CSD_Framework::Strategy_ptr strategy) +{ + if (this->strategy_impl_) + { + if (TAO_debug_level > 0) + ACE_ERROR((LM_ERROR, + ACE_TEXT("(%P|%t) Error - TAO::CSD::Strategy_Proxy ") + ACE_TEXT("object already has a custom strategy.\n"))); + + return false; + } + + if (CORBA::is_nil(strategy)) + { + if (TAO_debug_level > 0) + ACE_ERROR((LM_ERROR, + ACE_TEXT("(%P|%t) Error - TAO::CSD::Strategy_Proxy ") + ACE_TEXT("supplied with a NIL custom strategy.\n"))); + + return false; + } + + // We need to bump up the reference count of the strategy before saving + // it off into our handle (smart pointer) data member. + this->strategy_ = CSD_Framework::Strategy::_duplicate(strategy); + this->strategy_impl_ = dynamic_cast <TAO::CSD::Strategy_Base*> (strategy); + + return true; +} diff --git a/TAO/tao/CSD_Framework/CSD_Strategy_Proxy.h b/TAO/tao/CSD_Framework/CSD_Strategy_Proxy.h new file mode 100644 index 00000000000..78ffea92778 --- /dev/null +++ b/TAO/tao/CSD_Framework/CSD_Strategy_Proxy.h @@ -0,0 +1,110 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file CSD_Strategy_Proxy.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_SERVANT_DISPATCHING_STRATEGY_PROXY_H +#define TAO_SERVANT_DISPATCHING_STRATEGY_PROXY_H + +#include /**/ "ace/pre.h" + +#include "CSD_FW_Export.h" + +#include "tao/PortableServer/PortableServer.h" +#include "tao/PortableServer/Servant_Upcall.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "CSD_Strategy_Base.h" + +class TAO_ServerRequest; + + +namespace TAO +{ + namespace CSD + { + /** + * @class Strategy_Proxy + * + * @brief Proxy class for the Custom Servant Dispatching Strategy. + * + * If no custom servant dispatching strategy is provided to the proxy, + * then the "default servant dispatching strategy" logic is used. + */ + class TAO_CSD_FW_Export Strategy_Proxy + { + public: + + /// Default Constructor. + Strategy_Proxy(); + + /// Destructor. + ~Strategy_Proxy(); + + /// Mutator to provide the proxy with a CSD Strategy object. + /// A return value of true indicates success, and false indicates + /// failure to set the custom strategy on the proxy object. + bool custom_strategy(CSD_Framework::Strategy_ptr strategy); + + /// Invoked by the Object_Adapter using an ORB thread. + /// + /// If the proxy object holds a custom strategy object, then this method + /// will simply delegate to the custom strategy object. Otherwise, + /// this method will perform the "default servant dispatching strategy" + /// logic, preserving the original logic path as it was prior to the + /// introduction of the Custom Servant Dispatching feature. + /// + /// This method will be inlined (if inlining is turned on during the build). + /// + /// The added cost to the original logic path will be this method + /// invocation + one conditional (an is_nil() call/comparison for truth on + /// the smart pointer to the custom dispatching strategy object). + void dispatch_request(TAO_ServerRequest& server_request, + TAO::Portable_Server::Servant_Upcall& upcall + ACE_ENV_ARG_DECL); + + + /// Event - The POA has been (or is being) activated. + bool poa_activated_event(); + + /// Event - The POA has been deactivated. + void poa_deactivated_event(); + + /// Event - A servant has been activated. + void servant_activated_event(PortableServer::Servant servant, + const PortableServer::ObjectId& oid + ACE_ENV_ARG_DECL); + + /// Event - A servant has been deactivated. + void servant_deactivated_event(PortableServer::Servant servant, + const PortableServer::ObjectId& oid + ACE_ENV_ARG_DECL); + + private: + + /// Smart Pointer to a custom servant dispatching strategy object. + /// This smart pointer will be in the "nil" state when the "default" + /// strategy is to be applied. + CSD_Framework::Strategy_var strategy_; + TAO::CSD::Strategy_Base *strategy_impl_; + }; + } +} + +#if defined (__ACE_INLINE__) +# include "CSD_Strategy_Proxy.inl" +#endif /* __ACE_INLINE__ */ + +#include /**/ "ace/post.h" + +#endif diff --git a/TAO/tao/CSD_Framework/CSD_Strategy_Proxy.inl b/TAO/tao/CSD_Framework/CSD_Strategy_Proxy.inl new file mode 100644 index 00000000000..320fd6dca8f --- /dev/null +++ b/TAO/tao/CSD_Framework/CSD_Strategy_Proxy.inl @@ -0,0 +1,104 @@ +// -*- C++ -*- +// $Id$ + + +ACE_INLINE +TAO::CSD::Strategy_Proxy::Strategy_Proxy() + : strategy_impl_(0) +{ +} + + +ACE_INLINE +TAO::CSD::Strategy_Proxy::~Strategy_Proxy() +{ + strategy_impl_ = 0; // don't delete it! The var will do it for us. +} + +ACE_INLINE +void +TAO::CSD::Strategy_Proxy::dispatch_request + (TAO_ServerRequest& server_request, + TAO::Portable_Server::Servant_Upcall& upcall + ACE_ENV_ARG_DECL) +{ + + if (this->strategy_impl_ == 0) + { + // This is the "default" strategy implementation. + upcall.servant()->_dispatch(server_request, + (void*)&upcall + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + } + else + { + // Delegate to the custom strategy object. + this->strategy_impl_->dispatch_request(server_request, + upcall + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + } +} + + +ACE_INLINE +bool +TAO::CSD::Strategy_Proxy::poa_activated_event() +{ + // Delegate to the custom strategy object (or return true if this proxy + // is not holding a custom strategy). + return (this->strategy_impl_ == 0) ? true + : this->strategy_impl_->poa_activated_event(); +} + + +ACE_INLINE +void +TAO::CSD::Strategy_Proxy::poa_deactivated_event() +{ + // We only need to do something if this proxy holds a custom strategy. + if (this->strategy_impl_) + { + // Delegate to the custom strategy object. + this->strategy_impl_->poa_deactivated_event(); + } +} + + +ACE_INLINE +void +TAO::CSD::Strategy_Proxy::servant_activated_event + (PortableServer::Servant servant, + const PortableServer::ObjectId& oid + ACE_ENV_ARG_DECL) +{ + // We only need to do something if this proxy holds a custom strategy. + if (this->strategy_impl_) + { + // Delegate to the custom strategy object. + this->strategy_impl_->servant_activated_event(servant, + oid + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + } +} + + +ACE_INLINE +void +TAO::CSD::Strategy_Proxy::servant_deactivated_event + (PortableServer::Servant servant, + const PortableServer::ObjectId& oid + ACE_ENV_ARG_DECL) +{ + // We only need to do something if this proxy holds a custom strategy. + if (this->strategy_impl_) + { + // Delegate to the custom strategy object. + this->strategy_impl_->servant_deactivated_event(servant, + oid + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + } +} diff --git a/TAO/tao/CSD_Framework/CSD_Strategy_Repository.cpp b/TAO/tao/CSD_Framework/CSD_Strategy_Repository.cpp new file mode 100644 index 00000000000..2a98495e301 --- /dev/null +++ b/TAO/tao/CSD_Framework/CSD_Strategy_Repository.cpp @@ -0,0 +1,114 @@ +// $Id$ + +#include "CSD_Strategy_Repository.h" +#include "tao/debug.h" + +ACE_RCSID (CSD_Framework, + CSD_Strategy_Factory, + "$Id$") + + +TAO_CSD_Strategy_Repository::TAO_CSD_Strategy_Repository() +{ +} + + +TAO_CSD_Strategy_Repository::~TAO_CSD_Strategy_Repository() +{ + delete this->strategy_list_head_; +} + +int +TAO_CSD_Strategy_Repository::init(int, ACE_TCHAR **) +{ + + static int initialized = 0; + + // Only allow initialization once. + if (initialized) + return 0; + + initialized = 1; + this->strategy_list_head_ = 0; + return 0; +} + +CSD_Framework::Strategy_ptr +TAO_CSD_Strategy_Repository::find (const ACE_CString& name) +{ + + if (this->strategy_list_head_ != 0) + { + Strategy_Node *node = this->strategy_list_head_->find(name); + if (node != 0) + return CSD_Framework::Strategy::_duplicate (node->strategy_.in()); + } + + return CSD_Framework::Strategy::_nil(); +} + + +int +TAO_CSD_Strategy_Repository::add_strategy (const ACE_CString& name, + CSD_Framework::Strategy_ptr strat) +{ + Strategy_Node *node = 0; + ACE_NEW_RETURN (node, Strategy_Node(name,strat),-1); + if (this->strategy_list_head_ == 0) + this->strategy_list_head_ = node; + else + this->strategy_list_head_->add_node(node); + + if (TAO_debug_level > 3) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT("Strategy_Repository::add_strategy for %s \n"), + name.c_str ())); + } + return 0; +} + +TAO_CSD_Strategy_Repository::Strategy_Node::Strategy_Node (const ACE_CString& name, + CSD_Framework::Strategy_ptr strat) + : poa_name_(name), + strategy_(CSD_Framework::Strategy::_duplicate(strat)), + next_(0) +{ +} + +TAO_CSD_Strategy_Repository::Strategy_Node::~Strategy_Node () +{ + if (this->next_) + delete this->next_; +} + +void +TAO_CSD_Strategy_Repository::Strategy_Node::add_node(Strategy_Node *node) +{ + if (this->next_) + this->next_->add_node(node); + else + this->next_ = node; +} + +TAO_CSD_Strategy_Repository::Strategy_Node * +TAO_CSD_Strategy_Repository::Strategy_Node::find(const ACE_CString &name) +{ + if (this->poa_name_ == name) + return this; + if (this->next_) + return this->next_->find(name); + return 0; +} + + +///////////////////////////////////////////////////////////////////// + +ACE_FACTORY_DEFINE (TAO_CSD_FW, TAO_CSD_Strategy_Repository) +ACE_STATIC_SVC_DEFINE (TAO_CSD_Strategy_Repository, + ACE_TEXT ("TAO_CSD_Strategy_Repository"), + ACE_SVC_OBJ_T, + &ACE_SVC_NAME (TAO_CSD_Strategy_Repository), + ACE_Service_Type::DELETE_THIS + | ACE_Service_Type::DELETE_OBJ, + 0) diff --git a/TAO/tao/CSD_Framework/CSD_Strategy_Repository.h b/TAO/tao/CSD_Framework/CSD_Strategy_Repository.h new file mode 100644 index 00000000000..d9b1ef773d0 --- /dev/null +++ b/TAO/tao/CSD_Framework/CSD_Strategy_Repository.h @@ -0,0 +1,75 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file CSD_Strategy_Repository.h + * + * $Id$ + * + * @author Yan Dai <dai_y@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_CSD_STRATEGY_FACTORY_H +#define TAO_CSD_STRATEGY_FACTORY_H + +#include /**/ "ace/pre.h" + +#include "CSD_FW_Export.h" +#include "CSD_FrameworkC.h" +#include "ace/Service_Object.h" +#include "ace/Service_Config.h" +#include "ace/Synch.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + + +/** + * @class TAO_CSD_Strategy_Factory + * + * @brief An ACE_Service_Object capable of creating TP_Strategy objects. + * + * TBD - Explain in more detail. + * + */ +class TAO_CSD_FW_Export TAO_CSD_Strategy_Repository : public ACE_Service_Object +{ +public: + + /// Constructor. + TAO_CSD_Strategy_Repository(); + + /// Virtual Destructor. + virtual ~TAO_CSD_Strategy_Repository(); + + int init (int argc, ACE_TCHAR ** argv); + + /// Factory method used to create a CSD_Strategy object. + CSD_Framework::Strategy_ptr find (const ACE_CString& poa_name); + + int add_strategy (const ACE_CString& poa_name, + CSD_Framework::Strategy_ptr strategy); + +private: + struct Strategy_Node { + Strategy_Node(const ACE_CString& poa_name, + CSD_Framework::Strategy_ptr strategy); + ~Strategy_Node(); + void add_node (Strategy_Node *); + Strategy_Node *find(const ACE_CString& name); + + ACE_CString poa_name_; + CSD_Framework::Strategy_var strategy_; + Strategy_Node * next_; + }; + Strategy_Node * strategy_list_head_; +}; + +ACE_STATIC_SVC_DECLARE_EXPORT (TAO_CSD_FW, TAO_CSD_Strategy_Repository) +ACE_FACTORY_DECLARE (TAO_CSD_FW, TAO_CSD_Strategy_Repository) + +#include /**/ "ace/post.h" + +#endif /* TAO_CSD_STRATEGY_FACTORY_H */ diff --git a/TAO/tao/CSD_Framework/diffs/CSD_Framework.diff b/TAO/tao/CSD_Framework/diffs/CSD_Framework.diff new file mode 100644 index 00000000000..4d5e2989f73 --- /dev/null +++ b/TAO/tao/CSD_Framework/diffs/CSD_Framework.diff @@ -0,0 +1,38 @@ +--- CSD_FrameworkA.h 2005-10-03 16:07:54.484375000 -0700 ++++ orig/CSD_FrameworkA.h 2005-10-03 13:11:38.312500000 -0700 +@@ -34,8 +34,8 @@ + #include /**/ "ace/pre.h" + + #include "CSD_FW_Export.h" +-#include "CSD_FrameworkC.h" +-//#include "tao/PortableServer/PortableServerA.h" ++#include "tao/orig/CSD_FrameworkC.h" ++#include "tao/PortableServer/PortableServerA.h" + + + // TAO_IDL - Generated from +--- CSD_FrameworkC.h 2005-10-03 16:08:02.500000000 -0700 ++++ orig/CSD_FrameworkC.h 2005-10-03 13:11:38.312500000 -0700 +@@ -47,7 +47,7 @@ + #include "tao/Object.h" + #include "tao/Objref_VarOut_T.h" + +-#include "tao/PortableServer/PortableServer.h" ++#include "tao/PortableServer/PortableServerC.h" + + #if defined (TAO_EXPORT_MACRO) + #undef TAO_EXPORT_MACRO +@@ -305,6 +305,13 @@ + #endif /* end #if !defined */ + } + ++// TAO_IDL - Generated from ++// .\be\be_codegen.cpp:1040 ++ ++#if defined (__ACE_INLINE__) ++#include "CSD_FrameworkC.inl" ++#endif /* defined INLINE */ ++ + #include /**/ "ace/post.h" + + #endif /* ifndef */ diff --git a/TAO/tao/CSD_ThreadPool.mpc b/TAO/tao/CSD_ThreadPool.mpc new file mode 100644 index 00000000000..54a6dffc681 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool.mpc @@ -0,0 +1,34 @@ +//$Id$ +project : csd_framework { + sharedname = TAO_CSD_ThreadPool + dynamicflags = TAO_CSD_TP_BUILD_DLL + includes += $(TAO_ROOT)/tao + + Source_Files { + CSD_ThreadPool + } + + Header_Files { + CSD_ThreadPool + } + + Inline_Files { + CSD_ThreadPool + } + + Template_Files { + CSD_ThreadPool + } + + Resource_Files { + CSD_ThreadPool + } + + IDL_Files { + CSD_ThreadPool + } + + PIDL_Files { + CSD_ThreadPool + } +} diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Cancel_Visitor.cpp b/TAO/tao/CSD_ThreadPool/CSD_TP_Cancel_Visitor.cpp new file mode 100644 index 00000000000..9117ad0b690 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Cancel_Visitor.cpp @@ -0,0 +1,44 @@ +// $Id$ + +#include "CSD_TP_Cancel_Visitor.h" +#include "CSD_TP_Request.h" + +ACE_RCSID (CSD_TP, + Cancel_Visitor, + "$Id$") + +#if !defined (__ACE_INLINE__) +# include "CSD_TP_Cancel_Visitor.inl" +#endif /* ! __ACE_INLINE__ */ + + +TAO::CSD::TP_Cancel_Visitor::~TP_Cancel_Visitor() +{ +} + + +bool +TAO::CSD::TP_Cancel_Visitor::visit_request(TP_Request* request, + bool& remove_flag) +{ + // If our servant_ data member is in the 'nil' state, then + // we are supposed to cancel *ALL* requests that we visit. + // + // Otherwise, if our servant_ data member is not in the 'nil' state, + // we are supposed to cancel only requests that target our specific + // servant_. + + if ((this->servant_.in() == 0) || (request->is_target(this->servant_.in()))) + { + // Set the remove_flag to true so that this request is removed + // (and released) from the queue when we finish our visit. + remove_flag = true; + + // Cancel the request + request->cancel(); + } + + // Since we are either cancelling requests to any servant or a + // specific servant, always continue visitation. + return true; +} diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Cancel_Visitor.h b/TAO/tao/CSD_ThreadPool/CSD_TP_Cancel_Visitor.h new file mode 100644 index 00000000000..538f6899979 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Cancel_Visitor.h @@ -0,0 +1,85 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file CSD_TP_Cancel_Visitor.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_CSD_TP_CANCEL_VISITOR_H +#define TAO_CSD_TP_CANCEL_VISITOR_H + +#include /**/ "ace/pre.h" + +#include "CSD_TP_Export.h" +#include "tao/PortableServer/Servant_Base.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "CSD_TP_Queue_Visitor.h" + + +namespace TAO +{ + namespace CSD + { + + /** + * @class TP_Cancel_Visitor + * + * @brief Used to extract/cancel request(s) from the queue. + * + * This visitor is used to cancel certain requests in the queue + * as they are visited. + * + * Note that this is currently implemented to cancel *all* + * requests in the queue, or requests that are targeted for a specific + * servant. This could be extended in the future to perhaps + * cancel all requests that have the same operation name, or something + * else. + * + */ + class TAO_CSD_TP_Export TP_Cancel_Visitor : public TP_Queue_Visitor + { + public: + + /// Default Constructor - cancel *all* requests. + TP_Cancel_Visitor(); + + /// Constructor with provided servant - cancel requests that + /// target the supplied servant. + TP_Cancel_Visitor(PortableServer::Servant servant); + + /// Virtual Destructor. + virtual ~TP_Cancel_Visitor(); + + /// Returns true to continue visitation. Returns false to stop + /// visitation. Sets the remove_flag to true if the request should + /// be removed from the queue as a result of the visit. Leaves the + /// remove_flag alone otherwise. + virtual bool visit_request(TP_Request* request, bool& remove_flag); + + + private: + + /// Left as nil if we are to cancel all requests, or set to a specific + /// servant if only requests targeting that servant should be cancelled. + PortableServer::ServantBase_var servant_; + }; + + } +} + +#if defined (__ACE_INLINE__) +# include "CSD_TP_Cancel_Visitor.inl" +#endif /* __ACE_INLINE__ */ + +#include /**/ "ace/post.h" + +#endif /* TAO_CSD_TP_DISPATCHABLE_VISITOR_H */ diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Cancel_Visitor.inl b/TAO/tao/CSD_ThreadPool/CSD_TP_Cancel_Visitor.inl new file mode 100644 index 00000000000..b5d698f1f7a --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Cancel_Visitor.inl @@ -0,0 +1,28 @@ +// $Id$ + + +ACE_INLINE +TAO::CSD::TP_Cancel_Visitor::TP_Cancel_Visitor() +{ +} + + +ACE_INLINE +TAO::CSD::TP_Cancel_Visitor::TP_Cancel_Visitor(PortableServer::Servant servant) + : servant_(servant) +{ + // This try-catch block is not really necessary for current implementation + // since the _add_ref does not throw exception, but we have to add it to + // satisfy the non-exception builds. If _add_ref really throws an exception + // then this constructor needs deal with the exception. + ACE_TRY_NEW_ENV + { + this->servant_->_add_ref (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHALL + { + } + ACE_ENDTRY; +} + diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Collocated_Asynch_Request.cpp b/TAO/tao/CSD_ThreadPool/CSD_TP_Collocated_Asynch_Request.cpp new file mode 100644 index 00000000000..b43ec670d51 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Collocated_Asynch_Request.cpp @@ -0,0 +1,57 @@ +// $Id$ + +#include "CSD_TP_Collocated_Asynch_Request.h" + +ACE_RCSID (CSD_ThreadPool, + TP_Collocated_Asynch_Request, + "$Id$") + +#if !defined (__ACE_INLINE__) +# include "CSD_TP_Collocated_Asynch_Request.inl" +#endif /* ! __ACE_INLINE__ */ + + +TAO::CSD::TP_Collocated_Asynch_Request::~TP_Collocated_Asynch_Request() +{ +} + + +void +TAO::CSD::TP_Collocated_Asynch_Request::prepare_for_queue_i() +{ + this->do_clone(); +} + + +void +TAO::CSD::TP_Collocated_Asynch_Request::dispatch_i() +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + this->do_dispatch(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + // Eat these. We probably should log these, but since we have already + // unblocked the requesting thread there is no point in saving it or + // doing anything with it. + } +#if defined (TAO_HAS_EXCEPTIONS) + ACE_CATCHALL + { + // Eat these. We probably should log these, but since we have already + // unblocked the requesting thread there is no point in saving it or + // doing anything with it. + } +#endif + ACE_ENDTRY; +} + + +void +TAO::CSD::TP_Collocated_Asynch_Request::cancel_i() +{ + this->do_cancel(); +} diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Collocated_Asynch_Request.h b/TAO/tao/CSD_ThreadPool/CSD_TP_Collocated_Asynch_Request.h new file mode 100644 index 00000000000..bf7b2a17b37 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Collocated_Asynch_Request.h @@ -0,0 +1,87 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file CSD_TP_Collocated_Asynch_Request.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_CSD_TP_COLLOCATED_ASYNCH_REQUEST_H +#define TAO_CSD_TP_COLLOCATED_ASYNCH_REQUEST_H + +#include /**/ "ace/pre.h" + +#include "CSD_TP_Export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "CSD_TP_Corba_Request.h" + + +namespace TAO +{ + namespace CSD + { + + class TP_Collocated_Asynch_Request; + typedef TAO_Intrusive_Ref_Count_Handle<TP_Collocated_Asynch_Request> + TP_Collocated_Asynch_Request_Handle; + + /** + * @class TP_Collocated_Asynch_Request + * + * @brief Represents a "queue-able", collocated, asynchronous, + * CORBA request. + * + * This kind request is one-way collocated request with the default + * SYNC_SCOPE policy (SYNC_WITH_TRANSPORT) applied. It is cloned + * before enqueuing and the "enqueuing" thread never blocks. + */ + class TAO_CSD_TP_Export TP_Collocated_Asynch_Request + : public TP_Corba_Request + { + public: + + /// Constructor. + TP_Collocated_Asynch_Request + (TAO_ServerRequest& server_request, + const PortableServer::ObjectId& object_id, + PortableServer::POA_ptr poa, + const char* operation, + PortableServer::Servant servant, + TP_Servant_State* servant_state); + + /// Virtual Destructor. + virtual ~TP_Collocated_Asynch_Request(); + + + protected: + + /// Prepare this TP_Collocated_Asynch_Request object to be placed + /// into the request queue. This will cause the underlying + /// TAO_ServerRequest object to be cloned. + virtual void prepare_for_queue_i(); + + /// Dispatch the request to the servant. + virtual void dispatch_i(); + + /// Cancel the request. + virtual void cancel_i(); + }; + + } +} + +#if defined (__ACE_INLINE__) +# include "CSD_TP_Collocated_Asynch_Request.inl" +#endif /* __ACE_INLINE__ */ + +#include /**/ "ace/post.h" + +#endif /* TAO_CSD_TP_COLLOCATED_ASYNCH_REQUEST_H */ diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Collocated_Asynch_Request.inl b/TAO/tao/CSD_ThreadPool/CSD_TP_Collocated_Asynch_Request.inl new file mode 100644 index 00000000000..94a7238bd46 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Collocated_Asynch_Request.inl @@ -0,0 +1,20 @@ +// $Id$ + + +ACE_INLINE +TAO::CSD::TP_Collocated_Asynch_Request::TP_Collocated_Asynch_Request + (TAO_ServerRequest& server_request, + const PortableServer::ObjectId& object_id, + PortableServer::POA_ptr poa, + const char* operation, + PortableServer::Servant servant, + TP_Servant_State* servant_state) + : TP_Corba_Request(object_id, + poa, + operation, + servant, + servant_state, + server_request) +{ +} + diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Collocated_Synch_Request.cpp b/TAO/tao/CSD_ThreadPool/CSD_TP_Collocated_Synch_Request.cpp new file mode 100644 index 00000000000..58e868c835a --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Collocated_Synch_Request.cpp @@ -0,0 +1,55 @@ +// $Id$ + +#include "CSD_TP_Collocated_Synch_Request.h" + +ACE_RCSID (CSD_ThreadPool, + TP_Collocated_Synch_Request, + "$Id$") + +#include "tao/ORB_Core.h" + +#if !defined (__ACE_INLINE__) +# include "CSD_TP_Collocated_Synch_Request.inl" +#endif /* ! __ACE_INLINE__ */ + + +TAO::CSD::TP_Collocated_Synch_Request::~TP_Collocated_Synch_Request() +{ +} + + +void +TAO::CSD::TP_Collocated_Synch_Request::dispatch_i() +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + this->do_dispatch(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + // We need to save off a copy of the exception. + this->exception_ = ACE_ANY_EXCEPTION._tao_duplicate(); + } +#if defined (TAO_HAS_EXCEPTIONS) + ACE_CATCHALL + { + this->exception_ + = new CORBA::UNKNOWN (CORBA::SystemException::_tao_minor_code + (TAO_UNHANDLED_SERVER_CXX_EXCEPTION, 0), + CORBA::COMPLETED_MAYBE); + } +#endif + ACE_ENDTRY; + + this->synch_helper_.dispatched(); +} + + +void +TAO::CSD::TP_Collocated_Synch_Request::cancel_i() +{ + this->synch_helper_.cancelled(); +} + diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Collocated_Synch_Request.h b/TAO/tao/CSD_ThreadPool/CSD_TP_Collocated_Synch_Request.h new file mode 100644 index 00000000000..732158e3c02 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Collocated_Synch_Request.h @@ -0,0 +1,106 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file CSD_TP_Collocated_Synch_Request.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_CSD_TP_COLLOCATED_SYNCH_REQUEST_H +#define TAO_CSD_TP_COLLOCATED_SYNCH_REQUEST_H + +#include /**/ "ace/pre.h" + +#include "CSD_TP_Export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "CSD_TP_Corba_Request.h" +#include "CSD_TP_Synch_Helper.h" +#include "tao/Exception.h" + + +namespace TAO +{ + namespace CSD + { + + class TP_Collocated_Synch_Request; + typedef TAO_Intrusive_Ref_Count_Handle<TP_Collocated_Synch_Request> + TP_Collocated_Synch_Request_Handle; + + /** + * @class TP_Collocated_Synch_Request + * + * @brief Represents a "queue-able", synchronous, collocated, + * CORBA request. + * + * This kind request is the two-way or oneway(with SYNC_WITH_TARGET + * policy applied) collocated request. It is NOT cloned before + * enqueuing and the "enqueuing" thread will block until the request + * is dispatched/handled or cancelled. + */ + class TAO_CSD_TP_Export TP_Collocated_Synch_Request + : public TP_Corba_Request + { + public: + + /// Constructor. + TP_Collocated_Synch_Request + (TAO_ServerRequest& server_request, + const PortableServer::ObjectId& object_id, + PortableServer::POA_ptr poa, + const char* operation, + PortableServer::Servant servant, + TP_Servant_State* servant_state); + + /// Virtual Destructor. + virtual ~TP_Collocated_Synch_Request(); + + /// Wait until the request has been dispatched (and completed), or + /// until it has been cancelled. + /// Returns true if the request has been dispatched, and returns + /// false if the request has been cancelled. + bool wait(ACE_ENV_SINGLE_ARG_DECL); + + + protected: + + /// Note that we do not override our base class implementation of + /// prepare_for_queue_i() (which does nothing), because we don't + /// need to clone the Server Request object. + + /// Dispatch the request to the servant. + virtual void dispatch_i(); + + /// Cancel the request. + virtual void cancel_i(); + + + private: + + /// Helper used to block and unblock the thread that invokes our + /// wait() method. + TP_Synch_Helper synch_helper_; + + /// Set to NULL initially, and will only be set thereafter if an + /// exception is raised from the dispatch() call on the server_request_. + CORBA::Exception* exception_; + }; + + } +} + +#if defined (__ACE_INLINE__) +# include "CSD_TP_Collocated_Synch_Request.inl" +#endif /* __ACE_INLINE__ */ + +#include /**/ "ace/post.h" + +#endif /* TAO_CSD_TP_COLLOCATED_SYNCH_REQUEST_H */ diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Collocated_Synch_Request.inl b/TAO/tao/CSD_ThreadPool/CSD_TP_Collocated_Synch_Request.inl new file mode 100644 index 00000000000..4481a463c1e --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Collocated_Synch_Request.inl @@ -0,0 +1,52 @@ +// $Id$ + + +ACE_INLINE +TAO::CSD::TP_Collocated_Synch_Request::TP_Collocated_Synch_Request + (TAO_ServerRequest& server_request, + const PortableServer::ObjectId& object_id, + PortableServer::POA_ptr poa, + const char* operation, + PortableServer::Servant servant, + TP_Servant_State* servant_state) + : TP_Corba_Request(object_id, + poa, + operation, + servant, + servant_state, + server_request), + exception_(0) +{ +} + + +ACE_INLINE +bool +TAO::CSD::TP_Collocated_Synch_Request::wait(ACE_ENV_SINGLE_ARG_DECL) +{ + bool dispatched = this->synch_helper_.wait_while_pending(); + + if (dispatched) + { + // Check to see if the dispatching caused an exception to be raised. + if (this->exception_ != 0) + { + // An exception was raised during the actual dispatching to + // the servant. We need to raise the exception to our caller, + // which is the thread that made the collocated request in the + // first place. + CORBA::Exception* ex = this->exception_; + this->exception_ = 0; + +#if defined (TAO_HAS_EXCEPTIONS) + ACE_Auto_Basic_Ptr<CORBA::Exception> ex_holder(ex); + ex->_raise (); +#else + ACE_TRY_ENV.exception (ex); +#endif /* ACE_HAS_EXCEPTIONS */ + } + } + + return dispatched; + +} diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Collocated_Synch_With_Server_Request.cpp b/TAO/tao/CSD_ThreadPool/CSD_TP_Collocated_Synch_With_Server_Request.cpp new file mode 100644 index 00000000000..657cac81be0 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Collocated_Synch_With_Server_Request.cpp @@ -0,0 +1,71 @@ +// $Id$ + +#include "CSD_TP_Collocated_Synch_With_Server_Request.h" + +ACE_RCSID (CSD_ThreadPool, + TP_Collocated_Synch_With_Server_Request, + "$Id$") + +#include "tao/Exception.h" + +#if !defined (__ACE_INLINE__) +# include "CSD_TP_Collocated_Synch_With_Server_Request.inl" +#endif /* ! __ACE_INLINE__ */ + + +TAO::CSD::TP_Collocated_Synch_With_Server_Request::~TP_Collocated_Synch_With_Server_Request() +{ +} + + +void +TAO::CSD::TP_Collocated_Synch_With_Server_Request::prepare_for_queue_i() +{ + // NOTE: We *NEED* clone the TAO_ServerRequest for a collocated, + // one-way SYNC_WITH_SERVER request. This is because the + // calling thread is signalled just *before* the request is + // dispatched. It's (very) possible that the calling thread + // will destroy the underlying TAO_ServerRequest object while + // the request is dispatching to servant. This is why we make + // a clone - so that we have our own copy that won't be destroyed + // while we are using it. + this->do_clone(); +} + + +void +TAO::CSD::TP_Collocated_Synch_With_Server_Request::dispatch_i() +{ + // This is done *before* we do_dispatch(). + this->synch_helper_.dispatched(); + + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + this->do_dispatch(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + // Eat these. We probably should log these, but since we have already + // unblocked the requesting thread there is no point in saving it or + // doing anything with it. + } +#if defined (TAO_HAS_EXCEPTIONS) + ACE_CATCHALL + { + // Eat these. We probably should log these, but since we have already + // unblocked the requesting thread there is no point in saving it or + // doing anything with it. + } +#endif + ACE_ENDTRY; +} + + +void +TAO::CSD::TP_Collocated_Synch_With_Server_Request::cancel_i() +{ + this->synch_helper_.cancelled(); +} + diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Collocated_Synch_With_Server_Request.h b/TAO/tao/CSD_ThreadPool/CSD_TP_Collocated_Synch_With_Server_Request.h new file mode 100644 index 00000000000..39748db1853 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Collocated_Synch_With_Server_Request.h @@ -0,0 +1,107 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file CSD_TP_Collocated_Synch_With_Server_Request.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_CSD_TP_COLLOCATED_SYNCH_WITH_SERVER_REQUEST_H +#define TAO_CSD_TP_COLLOCATED_SYNCH_WITH_SERVER_REQUEST_H + +#include /**/ "ace/pre.h" + +#include "CSD_TP_Export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "CSD_TP_Corba_Request.h" +#include "CSD_TP_Synch_Helper.h" + + +namespace TAO +{ + namespace CSD + { + + class TP_Collocated_Synch_With_Server_Request; + typedef TAO_Intrusive_Ref_Count_Handle + <TP_Collocated_Synch_With_Server_Request> + TP_Collocated_Synch_With_Server_Request_Handle; + + /** + * @class TP_Collocated_Synch_With_Server_Request + * + * @brief Represents a "queue-able", one-way, collocated, CORBA + * request with a "Synch Scope" policy of SYNC_WITH_SERVER. + * + * This kind of request is one-way request with the SYNC_WITH_SERVER + * policy applied. It is cloned before enqueuing and the "enqueuing" + * thread will block until it is signalled by the TP_Task thread that + * will happen just before the request is dispatched or the request + * is cancelled. + */ + class TAO_CSD_TP_Export TP_Collocated_Synch_With_Server_Request + : public TP_Corba_Request + { + public: + + /// Constructor. + TP_Collocated_Synch_With_Server_Request + (TAO_ServerRequest& server_request, + const PortableServer::ObjectId& object_id, + PortableServer::POA_ptr poa, + const char* operation, + PortableServer::Servant servant, + TP_Servant_State* servant_state); + + /// Virtual Destructor. + virtual ~TP_Collocated_Synch_With_Server_Request(); + + /// Wait until the request has been dispatched (but not completed), or + /// until it has been cancelled. Note that this will wait until just + /// *before* the request is dispatched by a worker thread. This is + /// different than the TP_Collocated_Synch_Request which waits until + /// just *after* the request is dispatched by a worker thread. + /// Returns true if the request has been dispatched, and returns + /// false if the request has been cancelled. + bool wait(ACE_ENV_SINGLE_ARG_DECL); + + + protected: + + /// Prepare this TP_Collocated_Synch_With_Server_Request object to be + /// placed into the request queue. This will cause the underlying + /// TAO_ServerRequest object to be cloned. + virtual void prepare_for_queue_i(); + + /// Dispatch the request to the servant. + virtual void dispatch_i(); + + /// Cancel the request. + virtual void cancel_i(); + + + private: + + /// Helper used to block and unblock the thread that invokes our + /// wait() method. + TP_Synch_Helper synch_helper_; + }; + + } +} + +#if defined (__ACE_INLINE__) +# include "CSD_TP_Collocated_Synch_With_Server_Request.inl" +#endif /* __ACE_INLINE__ */ + +#include /**/ "ace/post.h" + +#endif /* TAO_CSD_TP_COLLOCATED_SYNCH_WITH_SERVER_REQUEST_H */ diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Collocated_Synch_With_Server_Request.inl b/TAO/tao/CSD_ThreadPool/CSD_TP_Collocated_Synch_With_Server_Request.inl new file mode 100644 index 00000000000..08dc5141fae --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Collocated_Synch_With_Server_Request.inl @@ -0,0 +1,27 @@ +// $Id$ + +ACE_INLINE +TAO::CSD::TP_Collocated_Synch_With_Server_Request::TP_Collocated_Synch_With_Server_Request + (TAO_ServerRequest& server_request, + const PortableServer::ObjectId& object_id, + PortableServer::POA_ptr poa, + const char* operation, + PortableServer::Servant servant, + TP_Servant_State* servant_state) + : TP_Corba_Request(object_id, + poa, + operation, + servant, + servant_state, + server_request) +{ +} + + +ACE_INLINE +bool +TAO::CSD::TP_Collocated_Synch_With_Server_Request::wait(ACE_ENV_SINGLE_ARG_DECL_NOT_USED) +{ + return this->synch_helper_.wait_while_pending(); +} + diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Corba_Request.cpp b/TAO/tao/CSD_ThreadPool/CSD_TP_Corba_Request.cpp new file mode 100644 index 00000000000..a4a40ba6091 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Corba_Request.cpp @@ -0,0 +1,16 @@ +// $Id$ + +#include "CSD_TP_Corba_Request.h" + +ACE_RCSID (CSD_ThreadPool, + TP_Corba_Request, + "$Id$") + +#if !defined (__ACE_INLINE__) +# include "CSD_TP_Corba_Request.inl" +#endif /* ! __ACE_INLINE__ */ + + +TAO::CSD::TP_Corba_Request::~TP_Corba_Request() +{ +} diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Corba_Request.h b/TAO/tao/CSD_ThreadPool/CSD_TP_Corba_Request.h new file mode 100644 index 00000000000..d6343e20935 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Corba_Request.h @@ -0,0 +1,100 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file CSD_TP_Corba_Request.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_CSD_TP_CORBA_REQUEST_H +#define TAO_CSD_TP_CORBA_REQUEST_H + +#include /**/ "ace/pre.h" + +#include "CSD_TP_Export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "CSD_TP_Request.h" +#include "tao/CSD_Framework/CSD_FW_Server_Request_Wrapper.h" +#include "tao/PortableServer/PortableServer.h" +#include "tao/PortableServer/Servant_Base.h" +#include "ace/SString.h" + + +namespace TAO +{ + namespace CSD + { + + class TP_Corba_Request; + typedef TAO_Intrusive_Ref_Count_Handle<TP_Corba_Request> + TP_Corba_Request_Handle; + + /** + * @class TP_Corba_Request + * + * @brief Base class for "queue-able" CORBA requests. + * + * TBD - Add description + * + */ + class TAO_CSD_TP_Export TP_Corba_Request : public TP_Request + { + public: + + /// Virtual Destructor. + virtual ~TP_Corba_Request(); + + + protected: + + /// Constructor. + TP_Corba_Request(const PortableServer::ObjectId& object_id, + PortableServer::POA_ptr poa, + const char* operation, + PortableServer::Servant servant, + TP_Servant_State* servant_state, + TAO_ServerRequest& server_request); + + /// Delegate to the FW_Server_Request_Wrapper clone() method. + void do_clone(); + + /// Delegate to the FW_Server_Request_Wrapper dispatch() method. + void do_dispatch(ACE_ENV_SINGLE_ARG_DECL); + + /// Delegate to the FW_Server_Request_Wrapper cancel() method. + void do_cancel(); + + + private: + + /// The ObjectId for the target servant. + PortableServer::ObjectId object_id_; + + /// The POA. + PortableServer::POA_var poa_; + + /// The name of the IDL operation. + ACE_CString operation_; + + /// The TAO_ServerRequest object wrapper. + FW_Server_Request_Wrapper server_request_; + }; + + } +} + +#if defined (__ACE_INLINE__) +# include "CSD_TP_Corba_Request.inl" +#endif /* __ACE_INLINE__ */ + +#include /**/ "ace/post.h" + +#endif /* TAO_CSD_TP_CORBA_REQUEST_H */ diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Corba_Request.inl b/TAO/tao/CSD_ThreadPool/CSD_TP_Corba_Request.inl new file mode 100644 index 00000000000..2047ad845d3 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Corba_Request.inl @@ -0,0 +1,42 @@ +// $Id$ + + +ACE_INLINE +TAO::CSD::TP_Corba_Request::TP_Corba_Request + (const PortableServer::ObjectId& object_id, + PortableServer::POA_ptr poa, + const char* operation, + PortableServer::Servant servant, + TP_Servant_State* servant_state, + TAO_ServerRequest& server_request) + : TP_Request(servant,servant_state), + object_id_(object_id), + operation_(operation), + server_request_(server_request) +{ + this->poa_ = PortableServer::POA::_duplicate(poa); +} + + +ACE_INLINE +void +TAO::CSD::TP_Corba_Request::do_clone() +{ + this->server_request_.clone(); +} + +ACE_INLINE +void +TAO::CSD::TP_Corba_Request::do_dispatch(ACE_ENV_SINGLE_ARG_DECL) +{ + this->server_request_.dispatch(this->servant() ACE_ENV_ARG_PARAMETER); + ACE_CHECK; +} + + +ACE_INLINE +void +TAO::CSD::TP_Corba_Request::do_cancel() +{ + this->server_request_.cancel(); +} diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Asynch_Request.cpp b/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Asynch_Request.cpp new file mode 100644 index 00000000000..4ac59c6f1fa --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Asynch_Request.cpp @@ -0,0 +1,50 @@ +// $Id$ + +#include "CSD_TP_Custom_Asynch_Request.h" + +ACE_RCSID (CSD_ThreadPool, + TP_Custom_Asynch_Request, + "$Id$") + +#if !defined (__ACE_INLINE__) +# include "CSD_TP_Custom_Asynch_Request.inl" +#endif /* ! __ACE_INLINE__ */ + + +TAO::CSD::TP_Custom_Asynch_Request::~TP_Custom_Asynch_Request() +{ +} + + +void +TAO::CSD::TP_Custom_Asynch_Request::dispatch_i() +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + this->execute_op(); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + // Eat these. We probably should log these, but since we have already + // unblocked the requesting thread there is no point in saving it or + // doing anything with it. + } +#if defined (TAO_HAS_EXCEPTIONS) + ACE_CATCHALL + { + // Eat these. We probably should log these, but since we have already + // unblocked the requesting thread there is no point in saving it or + // doing anything with it. + } +#endif + ACE_ENDTRY; +} + + +void +TAO::CSD::TP_Custom_Asynch_Request::cancel_i() +{ + this->cancel_op(); +} diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Asynch_Request.h b/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Asynch_Request.h new file mode 100644 index 00000000000..ee3479c2e9c --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Asynch_Request.h @@ -0,0 +1,76 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file CSD_TP_Custom_Asynch_Request.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_CSD_TP_CUSTOM_ASYNCH_REQUEST_H +#define TAO_CSD_TP_CUSTOM_ASYNCH_REQUEST_H + +#include /**/ "ace/pre.h" + +#include "CSD_TP_Export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "CSD_TP_Custom_Request.h" + + +namespace TAO +{ + namespace CSD + { + + class TP_Custom_Asynch_Request; + typedef TAO_Intrusive_Ref_Count_Handle<TP_Custom_Asynch_Request> + TP_Custom_Asynch_Request_Handle; + + /** + * @class TP_Custom_Asynch_Request + * + * @brief Base class for "queue-able", Custom (non-CORBA), + * Synchronous requests. + * + * TBD - Add description + * + */ + class TAO_CSD_TP_Export TP_Custom_Asynch_Request + : public TP_Custom_Request + { + public: + + /// Constructor. + TP_Custom_Asynch_Request(TP_Custom_Request_Operation* op, + TP_Servant_State* servant_state); + + /// Virtual Destructor. + virtual ~TP_Custom_Asynch_Request(); + + + protected: + + /// Dispatch the request to the servant. + virtual void dispatch_i(); + + /// Cancel the request. + virtual void cancel_i(); + }; + + } +} + +#if defined (__ACE_INLINE__) +# include "CSD_TP_Custom_Asynch_Request.inl" +#endif /* __ACE_INLINE__ */ + +#include /**/ "ace/post.h" + +#endif /* TAO_CSD_TP_CUSTOM_ASYNCH_REQUEST_H */ diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Asynch_Request.inl b/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Asynch_Request.inl new file mode 100644 index 00000000000..7281af45b9a --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Asynch_Request.inl @@ -0,0 +1,11 @@ +// $Id$ + + +ACE_INLINE +TAO::CSD::TP_Custom_Asynch_Request::TP_Custom_Asynch_Request + (TP_Custom_Request_Operation* op, + TP_Servant_State* servant_state) + : TP_Custom_Request(op,servant_state) +{ +} + diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Request.cpp b/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Request.cpp new file mode 100644 index 00000000000..810858cca79 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Request.cpp @@ -0,0 +1,16 @@ +// $Id$ + +#include "CSD_TP_Custom_Request.h" + +ACE_RCSID (CSD_ThreadPool, + TP_Custom_Request, + "$Id$") + +#if !defined (__ACE_INLINE__) +# include "CSD_TP_Custom_Request.inl" +#endif /* ! __ACE_INLINE__ */ + + +TAO::CSD::TP_Custom_Request::~TP_Custom_Request() +{ +} diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Request.h b/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Request.h new file mode 100644 index 00000000000..e4d89f40e15 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Request.h @@ -0,0 +1,78 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file CSD_TP_Custom_Request.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_CSD_TP_CUSTOM_REQUEST_H +#define TAO_CSD_TP_CUSTOM_REQUEST_H + +#include /**/ "ace/pre.h" + +#include "CSD_TP_Export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "CSD_TP_Request.h" +#include "CSD_TP_Custom_Request_Operation.h" +#include "tao/PortableServer/Servant_Base.h" + + +namespace TAO +{ + namespace CSD + { + + class TP_Custom_Request; + typedef TAO_Intrusive_Ref_Count_Handle<TP_Custom_Request> + TP_Custom_Request_Handle; + + /** + * @class TP_Custom_Request + * + * @brief Base class for "queue-able" Custom (non-CORBA) requests. + * + * TBD - Add description + * + */ + class TAO_CSD_TP_Export TP_Custom_Request : public TP_Request + { + public: + + /// Virtual Destructor. + virtual ~TP_Custom_Request(); + + + protected: + + /// Constructor. + TP_Custom_Request(TP_Custom_Request_Operation* op, + TP_Servant_State* servant_state); + + void execute_op(); + void cancel_op(); + + + private: + + TP_Custom_Request_Operation_Handle op_; + }; + + } +} + +#if defined (__ACE_INLINE__) +# include "CSD_TP_Custom_Request.inl" +#endif /* __ACE_INLINE__ */ + +#include /**/ "ace/post.h" + +#endif /* TAO_CSD_TP_CUSTOM_REQUEST_H */ diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Request.inl b/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Request.inl new file mode 100644 index 00000000000..6b53f3cbf78 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Request.inl @@ -0,0 +1,44 @@ +// $Id$ + + +ACE_INLINE +TAO::CSD::TP_Custom_Request::TP_Custom_Request + (TP_Custom_Request_Operation* op, + TP_Servant_State* servant_state) + : TP_Request(op->servant(),servant_state), + op_(op, false) +{ +} + + +ACE_INLINE +void +TAO::CSD::TP_Custom_Request::execute_op() +{ + this->op_->execute(); + + // Now drop the reference to the custom operation object. + // This is necessary so that custom operation objects can be created + // on the stack for synchronous custom requests. If we do not do this, + // then there is a race condition which could result in the stack-created + // custom operation object having a reference count of 2 when it falls + // out of scope (and destructs). Our op_ data member would be the one + // that held the other reference, and when our op_ data member destructs, + // it attempts to perform a _remove_ref() on the underlying operation + // object - which has already been destructed! Thus, we reset the op_ + // data member here to the 'nil' state - causing the _remove_ref() to + // be performed now. + this->op_ = 0; +} + + +ACE_INLINE +void +TAO::CSD::TP_Custom_Request::cancel_op() +{ + this->op_->cancel(); + + // See comments in the execute_op() method. + this->op_ = 0; +} + diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Request_Operation.cpp b/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Request_Operation.cpp new file mode 100644 index 00000000000..49617f39ea3 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Request_Operation.cpp @@ -0,0 +1,16 @@ +// $Id$ + +#include "CSD_TP_Custom_Request_Operation.h" + +ACE_RCSID (CSD_ThreadPool, + TP_Custom_Request_Operation, + "$Id$") + +#if !defined (__ACE_INLINE__) +# include "CSD_TP_Custom_Request_Operation.inl" +#endif /* ! __ACE_INLINE__ */ + + +TAO::CSD::TP_Custom_Request_Operation::~TP_Custom_Request_Operation() +{ +} diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Request_Operation.h b/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Request_Operation.h new file mode 100644 index 00000000000..50673612536 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Request_Operation.h @@ -0,0 +1,96 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file CSD_TP_Custom_Request_Operation.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_CSD_TP_CUSTOM_REQUEST_OPERATION_H +#define TAO_CSD_TP_CUSTOM_REQUEST_OPERATION_H + +#include /**/ "ace/pre.h" + +#include "CSD_TP_Export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "tao/Intrusive_Ref_Count_Base_T.h" +#include "tao/Intrusive_Ref_Count_Handle_T.h" +#include "tao/PortableServer/Servant_Base.h" +#include "ace/Synch.h" + + +namespace TAO +{ + namespace CSD + { + + class TP_Custom_Request_Operation; + typedef TAO_Intrusive_Ref_Count_Handle<TP_Custom_Request_Operation> + TP_Custom_Request_Operation_Handle; + + + /** + * @class TP_Custom_Request_Operation + * + * @brief Base class for all custom request operations. + * + * @note The caller that creates a new TP_Custom_Request_Operation + * object needs call _add_ref () on the servant before + * constructing it and the TP_Custom_Request_Operation object + * is responsible to decrement the reference count. + * + * TBD - Add description + */ + class TAO_CSD_TP_Export TP_Custom_Request_Operation + : public TAO_Intrusive_Ref_Count_Base<ACE_SYNCH_MUTEX> + { + public: + + /// Virtual Destructor. + virtual ~TP_Custom_Request_Operation(); + + /// Invoked by a worker thread to perform the operation. + void execute(); + + /// Invoked when the request has been cancelled. + void cancel(); + + /// Used by the TP_Strategy to obtain the target servant in order + /// to construct the custom request object. Returns the servant as + /// an "in" argument (the caller does not get a new 'copy'). This + /// is useful for chaining. + PortableServer::Servant servant(); + + + protected: + + /// Constructor. + TP_Custom_Request_Operation(PortableServer::Servant servant); + + virtual void execute_i() = 0; + virtual void cancel_i() = 0; + + + private: + + PortableServer::ServantBase_var servant_; + }; + + } +} + +#if defined (__ACE_INLINE__) +# include "CSD_TP_Custom_Request_Operation.inl" +#endif /* __ACE_INLINE__ */ + +#include /**/ "ace/post.h" + +#endif /* TAO_CSD_TP_CUSTOM_REQUEST_OPERATION_H */ diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Request_Operation.inl b/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Request_Operation.inl new file mode 100644 index 00000000000..cfdcc74f1c6 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Request_Operation.inl @@ -0,0 +1,47 @@ +// -*- C++ -*- +// $Id$ + + +ACE_INLINE +TAO::CSD::TP_Custom_Request_Operation::TP_Custom_Request_Operation + (PortableServer::Servant servant) +: servant_ (servant) +{ + // This try-catch block is not really necessary for current implementation + // since the _add_ref does not throw exception, but we have to add it to + // satisfy the non-exception builds. If _add_ref really throws an exception + // then this constructor needs deal with the exception. + ACE_TRY_NEW_ENV + { + this->servant_->_add_ref (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHALL + { + } + ACE_ENDTRY; +} + + +ACE_INLINE +void +TAO::CSD::TP_Custom_Request_Operation::execute() +{ + this->execute_i(); +} + + +ACE_INLINE +void +TAO::CSD::TP_Custom_Request_Operation::cancel() +{ + this->cancel_i(); +} + + +ACE_INLINE +PortableServer::Servant +TAO::CSD::TP_Custom_Request_Operation::servant() +{ + return this->servant_.in(); +} diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Synch_Request.cpp b/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Synch_Request.cpp new file mode 100644 index 00000000000..dd9162bea02 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Synch_Request.cpp @@ -0,0 +1,32 @@ +// $Id$ + +#include "CSD_TP_Custom_Synch_Request.h" + +ACE_RCSID (CSD_ThreadPool, + TP_Custom_Synch_Request, + "$Id$") + +#if !defined (__ACE_INLINE__) +# include "CSD_TP_Custom_Synch_Request.inl" +#endif /* ! __ACE_INLINE__ */ + + +TAO::CSD::TP_Custom_Synch_Request::~TP_Custom_Synch_Request() +{ +} + + +void +TAO::CSD::TP_Custom_Synch_Request::dispatch_i() +{ + this->execute_op(); + this->synch_helper_.dispatched(); +} + + +void +TAO::CSD::TP_Custom_Synch_Request::cancel_i() +{ + this->cancel_op(); + this->synch_helper_.cancelled(); +} diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Synch_Request.h b/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Synch_Request.h new file mode 100644 index 00000000000..a4c5e059e40 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Synch_Request.h @@ -0,0 +1,89 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file CSD_TP_Custom_Synch_Request.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_CSD_TP_CUSTOM_SYNCH_REQUEST_H +#define TAO_CSD_TP_CUSTOM_SYNCH_REQUEST_H + +#include /**/ "ace/pre.h" + +#include "CSD_TP_Export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "CSD_TP_Custom_Request.h" +#include "CSD_TP_Synch_Helper.h" + + +namespace TAO +{ + namespace CSD + { + + class TP_Custom_Synch_Request; + typedef TAO_Intrusive_Ref_Count_Handle<TP_Custom_Synch_Request> + TP_Custom_Synch_Request_Handle; + + /** + * @class TP_Custom_Synch_Request + * + * @brief Base class for "queue-able", Custom (non-CORBA), + * Synchronous requests. + * + * TBD - Add description + * + */ + class TAO_CSD_TP_Export TP_Custom_Synch_Request : public TP_Custom_Request + { + public: + + /// Constructor. + TP_Custom_Synch_Request(TP_Custom_Request_Operation* op, + TP_Servant_State* servant_state); + + /// Virtual Destructor. + virtual ~TP_Custom_Synch_Request(); + + /// Wait until the request has been executed (and completes), or + /// until it has been cancelled. Returns true if the request has + /// been executed/completed, and returns false if the request has + /// been cancelled. + bool wait(); + + + protected: + + /// Dispatch the request to the servant. + virtual void dispatch_i(); + + /// Cancel the request. + virtual void cancel_i(); + + + private: + + /// Helper used to block and unblock the thread that invokes our + /// wait() method. + TP_Synch_Helper synch_helper_; + }; + + } +} + +#if defined (__ACE_INLINE__) +# include "CSD_TP_Custom_Synch_Request.inl" +#endif /* __ACE_INLINE__ */ + +#include /**/ "ace/post.h" + +#endif /* TAO_CSD_TP_CUSTOM_SYNCH_REQUEST_H */ diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Synch_Request.inl b/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Synch_Request.inl new file mode 100644 index 00000000000..18cb942160c --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Custom_Synch_Request.inl @@ -0,0 +1,18 @@ +// $Id$ + + +ACE_INLINE +TAO::CSD::TP_Custom_Synch_Request::TP_Custom_Synch_Request + (TP_Custom_Request_Operation* op, + TP_Servant_State* servant_state) + : TP_Custom_Request(op,servant_state) +{ +} + + +ACE_INLINE +bool +TAO::CSD::TP_Custom_Synch_Request::wait() +{ + return this->synch_helper_.wait_while_pending(); +} diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Dispatchable_Visitor.cpp b/TAO/tao/CSD_ThreadPool/CSD_TP_Dispatchable_Visitor.cpp new file mode 100644 index 00000000000..c10b11aa53b --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Dispatchable_Visitor.cpp @@ -0,0 +1,50 @@ +// $Id$ + +#include "CSD_TP_Dispatchable_Visitor.h" + +ACE_RCSID (CSD_TP, + Dispatchable_Visitor, + "$Id$") + +#if !defined (__ACE_INLINE__) +# include "CSD_TP_Dispatchable_Visitor.inl" +#endif /* ! __ACE_INLINE__ */ + + +TAO::CSD::TP_Dispatchable_Visitor::~TP_Dispatchable_Visitor() +{ +} + + +bool +TAO::CSD::TP_Dispatchable_Visitor::visit_request(TP_Request* request, + bool& remove_flag) +{ + // Ask the request object if the target servant is "ready" to accept + // a request being dispatched to it. + if (request->is_ready()) + { + // Ok. This request is a "dispatchable" request. It is what we were + // hoping to find. + + // Save a copy of the request in our handle data member. + request->_add_ref(); + this->request_ = request; + + // Make sure that the queue will extract the request from the queue + // upon our return. + remove_flag = true; + + // Mark the target servant as being "busy". + request->mark_as_busy(); + + // Stop the visitation by returning false. + return false; + } + + // The target servant object of the request isn't ready, so the request + // is not considered to be a "dispatchable" request. + + // Return true to visit the next request in the queue (if there is one). + return true; +} diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Dispatchable_Visitor.h b/TAO/tao/CSD_ThreadPool/CSD_TP_Dispatchable_Visitor.h new file mode 100644 index 00000000000..9f639a5e8a9 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Dispatchable_Visitor.h @@ -0,0 +1,91 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file CSD_TP_Dispatchable_Visitor.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_CSD_TP_DISPATCHABLE_VISITOR_H +#define TAO_CSD_TP_DISPATCHABLE_VISITOR_H + +#include /**/ "ace/pre.h" + +#include "CSD_TP_Export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "CSD_TP_Queue_Visitor.h" +#include "CSD_TP_Request.h" + + +namespace TAO +{ + namespace CSD + { + + /** + * @class TP_Dispatchable_Visitor + * + * @brief Used to extract the first "dispatchable" request from the queue. + * + * An instance of this visitor class is used by one of the worker + * threads to locate the first "dispatchable" request in the queue. If + * such a request is visited, then this visitor will save a "copy" of + * the request, indicate that the request should be removed from the + * queue, and indicate that visitation should stop. + * + * An method is provided to retrieve a "copy" of the "dispatchable" + * request that was saved off during visitation. A nil reference + * (ie, a NULL pointer) will be returned if no dispatchable request + * was found. + * + */ + class TAO_CSD_TP_Export TP_Dispatchable_Visitor : public TP_Queue_Visitor + { + public: + + /// Default Constructor. + TP_Dispatchable_Visitor(); + + /// Virtual Destructor. + virtual ~TP_Dispatchable_Visitor(); + + /// Reset this visitor object in order to re-use it for another + /// visitation of the request queue. This sets the vistor's "result" + /// (the TP_Request* data member) to its default value (a nil handle). + void reset(); + + /// Returns true to continue visitation. Returns false to stop + /// visitation. Sets the remove_flag to true if the request should + /// be removed from the queue as a result of the visit. Leaves the + /// remove_flag alone otherwise. + virtual bool visit_request(TP_Request* request, bool& remove_flag); + + /// This returns a "copy" of the located request, or 0 if no request + /// was located. + TP_Request* request(); + + + private: + + /// A handle to the located request. + TP_Request_Handle request_; + }; + + } +} + +#if defined (__ACE_INLINE__) +# include "CSD_TP_Dispatchable_Visitor.inl" +#endif /* __ACE_INLINE__ */ + +#include /**/ "ace/post.h" + +#endif /* TAO_CSD_TP_DISPATCHABLE_VISITOR_H */ diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Dispatchable_Visitor.inl b/TAO/tao/CSD_ThreadPool/CSD_TP_Dispatchable_Visitor.inl new file mode 100644 index 00000000000..ac66587e2a7 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Dispatchable_Visitor.inl @@ -0,0 +1,26 @@ +// $Id$ + + +ACE_INLINE +TAO::CSD::TP_Dispatchable_Visitor::TP_Dispatchable_Visitor() +{ +} + + +ACE_INLINE +void +TAO::CSD::TP_Dispatchable_Visitor::reset() +{ + // Set the handle to 0 to have it release any request it may currently + // be referencing. + this->request_ = 0; +} + + +ACE_INLINE +TAO::CSD::TP_Request* +TAO::CSD::TP_Dispatchable_Visitor::request() +{ + TP_Request_Handle handle(this->request_.in(), false); + return handle._retn(); +} diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Export.h b/TAO/tao/CSD_ThreadPool/CSD_TP_Export.h new file mode 100644 index 00000000000..1eeb556e4f8 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Export.h @@ -0,0 +1,58 @@ + +// -*- C++ -*- +// $Id$ +// Definition for Win32 Export directives. +// This file is generated automatically by generate_export_file.pl -s TAO_CSD_TP +// ------------------------------ +#ifndef TAO_CSD_TP_EXPORT_H +#define TAO_CSD_TP_EXPORT_H + +#include "ace/config-all.h" + +#if defined (ACE_AS_STATIC_LIBS) && !defined (TAO_CSD_TP_HAS_DLL) +# define TAO_CSD_TP_HAS_DLL 0 +#endif /* ACE_AS_STATIC_LIBS && TAO_CSD_TP_HAS_DLL */ + +#if !defined (TAO_CSD_TP_HAS_DLL) +# define TAO_CSD_TP_HAS_DLL 1 +#endif /* ! TAO_CSD_TP_HAS_DLL */ + +#if defined (TAO_CSD_TP_HAS_DLL) && (TAO_CSD_TP_HAS_DLL == 1) +# if defined (TAO_CSD_TP_BUILD_DLL) +# define TAO_CSD_TP_Export ACE_Proper_Export_Flag +# define TAO_CSD_TP_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T) +# define TAO_CSD_TP_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# else /* TAO_CSD_TP_BUILD_DLL */ +# define TAO_CSD_TP_Export ACE_Proper_Import_Flag +# define TAO_CSD_TP_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T) +# define TAO_CSD_TP_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# endif /* TAO_CSD_TP_BUILD_DLL */ +#else /* TAO_CSD_TP_HAS_DLL == 1 */ +# define TAO_CSD_TP_Export +# define TAO_CSD_TP_SINGLETON_DECLARATION(T) +# define TAO_CSD_TP_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +#endif /* TAO_CSD_TP_HAS_DLL == 1 */ + +// Set TAO_CSD_TP_NTRACE = 0 to turn on library specific tracing even if +// tracing is turned off for ACE. +#if !defined (TAO_CSD_TP_NTRACE) +# if (ACE_NTRACE == 1) +# define TAO_CSD_TP_NTRACE 1 +# else /* (ACE_NTRACE == 1) */ +# define TAO_CSD_TP_NTRACE 0 +# endif /* (ACE_NTRACE == 1) */ +#endif /* !TAO_CSD_TP_NTRACE */ + +#if (TAO_CSD_TP_NTRACE == 1) +# define TAO_CSD_TP_TRACE(X) +#else /* (TAO_CSD_TP_NTRACE == 1) */ +# if !defined (ACE_HAS_TRACE) +# define ACE_HAS_TRACE +# endif /* ACE_HAS_TRACE */ +# define TAO_CSD_TP_TRACE(X) ACE_TRACE_IMPL(X) +# include "ace/Trace.h" +#endif /* (TAO_CSD_TP_NTRACE == 1) */ + +#endif /* TAO_CSD_TP_EXPORT_H */ + +// End of auto generated file. diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Queue.cpp b/TAO/tao/CSD_ThreadPool/CSD_TP_Queue.cpp new file mode 100644 index 00000000000..7253794cf0b --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Queue.cpp @@ -0,0 +1,124 @@ +// $Id$ + +#include "CSD_TP_Queue.h" +#include "CSD_TP_Request.h" +#include "CSD_TP_Queue_Visitor.h" + +ACE_RCSID (CSD_ThreadPool, + TP_Queue, + "$Id$") + +#if !defined (__ACE_INLINE__) +# include "CSD_TP_Queue.inl" +#endif /* ! __ACE_INLINE__ */ + + +void +TAO::CSD::TP_Queue::put(TP_Request* request) +{ + // The request is passed in as an "in" argument, and we would like to + // hold on to a "copy" within the queue (the linked list). We will + // perform an _add_ref() on the request now to make the queue's "copy". + request->_add_ref(); + + if (this->tail_ == 0) + { + // The tail_ is a NULL pointer only when the queue is empty. + // Make the request be the only element in the queue. + this->head_ = this->tail_ = request; + + // Make sure the request's prev_ and next_ pointers are set to NULL. + request->prev_ = request->next_ = 0; + } + else + { + // There is at least one request already in the queue. "Append" the + // supplied request object to the end of the queue. + request->prev_ = this->tail_; + request->next_ = 0; + this->tail_->next_ = request; + this->tail_ = request; + } +} + + +void +TAO::CSD::TP_Queue::accept_visitor(TP_Queue_Visitor& visitor) +{ + TP_Request* cur = this->head_; + + while (cur != 0) + { + TP_Request* prev = cur->prev_; + TP_Request* next = cur->next_; + + // Pass the current request to the visitor. Also pass-in a reference + // to the remove_from_queue flag. The visitor may decide that it + // wants to keep the current request for itself, and desires that the + // request be (surgically) removed from the queue. The visitor also + // gets to decide, via its return value, whether or not visitation + // should continue (or cease to continue). + bool remove_from_queue = false; + + bool continue_visitation = visitor.visit_request(cur,remove_from_queue); + + if (remove_from_queue) + { + // Create a local handle to release the current request once + // the handle falls out of scope. We need to do this because the + // queue "owns" a "copy" of each request in the queue. + TP_Request_Handle handle = cur; + + if (this->head_ == cur) + { + // The current request is at the front (the head_) of the queue. + + // Move the head_ to the next request in the queue. + this->head_ = next; + + if (this->head_ == 0) + { + // Not only was the current request at the front of the + // queue - it was the *only* request in the queue. + // Update the tail_ pointer now that the queue is empty. + this->tail_ = 0; + } + else + { + // Set the (new) head_ request's prev_ pointer to be NULL. + this->head_->prev_ = 0; + } + } + else if (this->tail_ == cur) + { + // The current request is not at the front of the queue, + // but it is at the back of the queue. This implies that + // the queue currently contains at least two requests - + // the current request (cur), and the previous request (prev). + // The point is that we can now assume that the 'prev' pointer + // is never NULL in this case. + this->tail_ = prev; + this->tail_->next_ = 0; + } + else + { + // The current request is not at the front or at the back. + // This implies that there are at least three requests in + // the queue. We can assume that the 'next' and 'prev' + // pointers are never NULL in this case. + prev->next_ = next; + next->prev_ = prev; + } + } + + if (!continue_visitation) + { + // The visitor doesn't want to procede with any further visitation. + // Break out of the visitation loop now. + break; + } + + // Move on to the next request in the queue. + cur = next; + } +} diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Queue.h b/TAO/tao/CSD_ThreadPool/CSD_TP_Queue.h new file mode 100644 index 00000000000..7b42cfeda59 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Queue.h @@ -0,0 +1,96 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file CSD_TP_Queue.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_CSD_TP_QUEUE_H +#define TAO_CSD_TP_QUEUE_H + +#include /**/ "ace/pre.h" + +#include "CSD_TP_Export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + + +namespace TAO +{ + namespace CSD + { + + class TP_Request; + class TP_Queue_Visitor; + + /** + * @class TP_Queue + * + * @brief Queue of servant requests that need to be dispatched. + * + * This is the queue of pending servant requests that is "owned" + * by a TP_Strategy object. When an ORB thread dispatches + * a servant request to the strategy object, it will create the + * appropriate (subclass of) TP_Request object to "wrap" + * the servant request in a "queue-friendly" wrapper. The ORB thread + * will then place the TP_Request object on to the queue. Note that + * this scenario pertains to what are being called "remote requests". + * There are other scenarios in which other types of requests can + * get added to this queue. + * + * The strategy object will employ a set of worker threads that are + * responsible for "servicing" the servant requests in the queue. + * + * Note: In the future, support will be added to allow the client + * application inject "custom" TP_Request objects into + * a TP_Strategy object, causing them to be placed in + * the queue. + */ + class TAO_CSD_TP_Export TP_Queue + { + public: + + /// Default Constructor. + TP_Queue(); + + /// Destructor. + ~TP_Queue(); + + /// Place a request at the end of the queue. + void put(TP_Request* request); + + /// Returns true if the queue is empty. Returns false otherwise. + bool is_empty() const; + + /// Visitors will visit each request in the queue, from front to back, + /// and have the ability to stop visiting at any time (ie, before + /// visiting every request). + void accept_visitor(TP_Queue_Visitor& visitor); + + + private: + + /// The request at the front of the queue. + TP_Request* head_; + + /// The request at the end of the queue. + TP_Request* tail_; + }; + + } +} + +#if defined (__ACE_INLINE__) +# include "CSD_TP_Queue.inl" +#endif /* __ACE_INLINE__ */ + +#include /**/ "ace/post.h" + +#endif /* TAO_CSD_TP_QUEUE_H */ diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Queue.inl b/TAO/tao/CSD_ThreadPool/CSD_TP_Queue.inl new file mode 100644 index 00000000000..58adcec4744 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Queue.inl @@ -0,0 +1,23 @@ +// $Id$ + + +ACE_INLINE +TAO::CSD::TP_Queue::TP_Queue() + : head_(0), + tail_(0) +{ +} + + +ACE_INLINE +TAO::CSD::TP_Queue::~TP_Queue() +{ +} + + +ACE_INLINE +bool +TAO::CSD::TP_Queue::is_empty() const +{ + return (this->head_ == 0); +} diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Queue_Visitor.cpp b/TAO/tao/CSD_ThreadPool/CSD_TP_Queue_Visitor.cpp new file mode 100644 index 00000000000..95d3c39f750 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Queue_Visitor.cpp @@ -0,0 +1,16 @@ +// $Id$ + +#include "CSD_TP_Queue_Visitor.h" + +ACE_RCSID (CSD_ThreadPool, + TP_Queue_Visitor, + "$Id$") + +#if !defined (__ACE_INLINE__) +# include "CSD_TP_Queue_Visitor.inl" +#endif /* ! __ACE_INLINE__ */ + + +TAO::CSD::TP_Queue_Visitor::~TP_Queue_Visitor() +{ +} diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Queue_Visitor.h b/TAO/tao/CSD_ThreadPool/CSD_TP_Queue_Visitor.h new file mode 100644 index 00000000000..cece3e7ffbc --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Queue_Visitor.h @@ -0,0 +1,74 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file CSD_TP_Queue_Visitor.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_CSD_TP_QUEUE_VISITOR_H +#define TAO_CSD_TP_QUEUE_VISITOR_H + +#include /**/ "ace/pre.h" + +#include "CSD_TP_Export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + + +namespace TAO +{ + namespace CSD + { + + class TP_Request; + + + /** + * @class TP_Queue_Visitor + * + * @brief Base class for vistors of the elements in the TP_Queue. + * + * Provides a way to perform thread-safe iteration over the + * TP_Request objects contained within a TP_Queue object. + * + * This also provides a means to encapsulate each distinct algorithm + * within a distinct subclass of TP_Queue_Visitor. + * + */ + class TAO_CSD_TP_Export TP_Queue_Visitor + { + public: + + /// Virtual Destructor. + virtual ~TP_Queue_Visitor(); + + /// Returns true to continue visitation. Return false to stop + /// visitation. Sets the remove_flag to true if the request should + /// be removed from the queue as a result of the visit. Leaves the + /// remove_flag alone otherwise. + virtual bool visit_request(TP_Request* request, bool& remove_flag) = 0; + + + protected: + + /// Default Constructor. + TP_Queue_Visitor(); + }; + + } +} + +#if defined (__ACE_INLINE__) +# include "CSD_TP_Queue_Visitor.inl" +#endif /* __ACE_INLINE__ */ + +#include /**/ "ace/post.h" + +#endif /* TAO_CSD_TP_QUEUE_VISITOR_H */ diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Queue_Visitor.inl b/TAO/tao/CSD_ThreadPool/CSD_TP_Queue_Visitor.inl new file mode 100644 index 00000000000..77567843234 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Queue_Visitor.inl @@ -0,0 +1,7 @@ +// $Id$ + + +ACE_INLINE +TAO::CSD::TP_Queue_Visitor::TP_Queue_Visitor() +{ +} diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Remote_Request.cpp b/TAO/tao/CSD_ThreadPool/CSD_TP_Remote_Request.cpp new file mode 100644 index 00000000000..cf7f2642505 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Remote_Request.cpp @@ -0,0 +1,57 @@ +// $Id$ + +#include "CSD_TP_Remote_Request.h" + +ACE_RCSID (CSD_ThreadPool, + TP_Remote_Request, + "$Id$") + +#if !defined (__ACE_INLINE__) +# include "CSD_TP_Remote_Request.inl" +#endif /* ! __ACE_INLINE__ */ + + +TAO::CSD::TP_Remote_Request::~TP_Remote_Request() +{ +} + + +void +TAO::CSD::TP_Remote_Request::prepare_for_queue_i() +{ + this->do_clone(); +} + + +void +TAO::CSD::TP_Remote_Request::dispatch_i() +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + this->do_dispatch(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + // Eat these. We probably should log these, but since we have already + // unblocked the requesting thread there is no point in saving it or + // doing anything with it. + } +#if defined (TAO_HAS_EXCEPTIONS) + ACE_CATCHALL + { + // Eat these. We probably should log these, but since we have already + // unblocked the requesting thread there is no point in saving it or + // doing anything with it. + } +#endif + ACE_ENDTRY; +} + + +void +TAO::CSD::TP_Remote_Request::cancel_i() +{ + this->do_cancel(); +} diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Remote_Request.h b/TAO/tao/CSD_ThreadPool/CSD_TP_Remote_Request.h new file mode 100644 index 00000000000..c80dec5c992 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Remote_Request.h @@ -0,0 +1,99 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file CSD_TP_Remote_Request.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_CSD_TP_REMOTE_REQUEST_H +#define TAO_CSD_TP_REMOTE_REQUEST_H + +#include /**/ "ace/pre.h" + +#include "CSD_TP_Export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "CSD_TP_Corba_Request.h" + + +namespace TAO +{ + namespace CSD + { + + class TP_Remote_Request; + typedef TAO_Intrusive_Ref_Count_Handle<TP_Remote_Request> + TP_Remote_Request_Handle; + + /** + * @class TP_Remote_Request + * + * @brief Represents a "queue-able", remote, CORBA request. + * Both syncronous and asynchronous remote CORBA requests + * are represented by the class. + * + * TBD - Go over the following comments and clean up. + * + * Since this class derives from the TP_Request class, it can be + * added to a TP_Queue (ie, it is a "queueable" request). It + * represents a servant request that has been made by a remote + * CORBA client (as opposed to a collocated CORBA client). The + * term "CORBA client" is being used here to distinguish CORBA + * servant requests (those made thru a CORBA object reference), and + * "Custom" servant requests that can be "dispatched" to the strategy + * directly by the client application code (ie, not thru a CORBA + * object reference). Thus, there are "CORBA clients" and + * "Direct clients". + * + * In summary, this class represents a servant request made when a + * remote client invokes a method on a CORBA object reference. + * + */ + class TAO_CSD_TP_Export TP_Remote_Request : public TP_Corba_Request + { + public: + + /// Constructor. + TP_Remote_Request(TAO_ServerRequest& server_request, + const PortableServer::ObjectId& object_id, + PortableServer::POA_ptr poa, + const char* operation, + PortableServer::Servant servant, + TP_Servant_State* servant_state); + + /// Virtual Destructor. + virtual ~TP_Remote_Request(); + + + protected: + + /// Prepare this TP_Remote_Request object to be placed into the + /// request queue. This will cause the underlying TAO_ServerRequest + /// object to be cloned. + virtual void prepare_for_queue_i(); + + /// Dispatch the request to the servant. + virtual void dispatch_i(); + + /// Cancel the request. + virtual void cancel_i(); + }; + + } +} + +#if defined (__ACE_INLINE__) +# include "CSD_TP_Remote_Request.inl" +#endif /* __ACE_INLINE__ */ + +#include /**/ "ace/post.h" + +#endif /* TAO_CSD_TP_REMOTE_REQUEST_H */ diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Remote_Request.inl b/TAO/tao/CSD_ThreadPool/CSD_TP_Remote_Request.inl new file mode 100644 index 00000000000..baa56a9ea08 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Remote_Request.inl @@ -0,0 +1,20 @@ +// $Id$ + + +ACE_INLINE +TAO::CSD::TP_Remote_Request::TP_Remote_Request + (TAO_ServerRequest& server_request, + const PortableServer::ObjectId& object_id, + PortableServer::POA_ptr poa, + const char* operation, + PortableServer::Servant servant, + TP_Servant_State* servant_state) + : TP_Corba_Request(object_id, + poa, + operation, + servant, + servant_state, + server_request) +{ +} + diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Request.cpp b/TAO/tao/CSD_ThreadPool/CSD_TP_Request.cpp new file mode 100644 index 00000000000..a01d18f19dd --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Request.cpp @@ -0,0 +1,24 @@ +// $Id$ + +#include "CSD_TP_Request.h" + +ACE_RCSID (CSD_ThreadPool, + TP_Request, + "$Id$") + +#if !defined (__ACE_INLINE__) +# include "CSD_TP_Request.inl" +#endif /* ! __ACE_INLINE__ */ + + +TAO::CSD::TP_Request::~TP_Request() +{ +} + + +void +TAO::CSD::TP_Request::prepare_for_queue_i() +{ + // Default implementation is to do nothing. Subclasses can provide + // their own implementation if needed. +} diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Request.h b/TAO/tao/CSD_ThreadPool/CSD_TP_Request.h new file mode 100644 index 00000000000..4e7c61e9b09 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Request.h @@ -0,0 +1,133 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file CSD_TP_Request.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_CSD_TP_REQUEST_H +#define TAO_CSD_TP_REQUEST_H + +#include /**/ "ace/pre.h" + +#include "CSD_TP_Export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "CSD_TP_Servant_State.h" +#include "tao/PortableServer/Servant_Base.h" +#include "tao/Intrusive_Ref_Count_Base_T.h" +#include "tao/Intrusive_Ref_Count_Handle_T.h" + + +namespace TAO +{ + namespace CSD + { + + class TP_Request; + typedef TAO_Intrusive_Ref_Count_Handle<TP_Request> TP_Request_Handle; + + class TP_Queue; + + + /** + * @class TP_Request + * + * @brief Base class for "queue-able" requests. + * + * This class serves as the abstract base class for all types of + * "servant requests" that can be inserted into a TP_Queue + * object. + */ + class TAO_CSD_TP_Export TP_Request + : public TAO_Intrusive_Ref_Count_Base<ACE_SYNCH_MUTEX> + { + public: + + /// Virtual Destructor. + virtual ~TP_Request(); + + /// Prepare the request to be placed into the request queue. + void prepare_for_queue(); + + /// Invoked to dispatch the request to the servant. + void dispatch(); + + /// Invoked to cancel the request. + void cancel(); + + /// Is the target servant ready to accept a request? + bool is_ready() const; + + /// Mark the target servant as being busy. + void mark_as_busy(); + + /// Mark the target servant as being ready (ie, not busy). + void mark_as_ready(); + + /// This method returns true if this request targets the supplied + /// servant object. + bool is_target(PortableServer::Servant servant); + + + protected: + + /// Constructor. + TP_Request(PortableServer::Servant servant, + TP_Servant_State* servant_state); + + /// Accessor for the servant. Does not return a new (ref counted) + /// reference! This is used for chaining. + PortableServer::Servant servant(); + + /// The subclass knows if it needs to do anything in preparation + /// of being placed into the request queue. The default implementation + /// does nothing, so only subclasses that have something to do + /// need to provide their own implementation. + virtual void prepare_for_queue_i(); + + /// The subclass knows how to carry out its own way of dispatching + /// the request to the servant. + virtual void dispatch_i() = 0; + + /// Ask the subclass to perform its duties to carry out the cancellation. + virtual void cancel_i() = 0; + + + private: + + /// The TP_Queue class is our friend since it needs access to + /// the prev_ and next_ (private) data members. + friend class TP_Queue; + + /// The previous TP_Request object (in the queue). + TP_Request* prev_; + + /// The next TP_Request object (in the queue). + TP_Request* next_; + + /// Reference to the servant object. + PortableServer::ServantBase_var servant_; + + /// Reference to the servant "state" object (contains the busy flag). + TP_Servant_State::HandleType servant_state_; + }; + + } +} + +#if defined (__ACE_INLINE__) +# include "CSD_TP_Request.inl" +#endif /* __ACE_INLINE__ */ + +#include /**/ "ace/post.h" + +#endif /* TAO_CSD_TP_REQUEST_H */ diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Request.inl b/TAO/tao/CSD_ThreadPool/CSD_TP_Request.inl new file mode 100644 index 00000000000..7181678ecde --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Request.inl @@ -0,0 +1,92 @@ +// $Id$ + + +ACE_INLINE +TAO::CSD::TP_Request::TP_Request(PortableServer::Servant servant, + TP_Servant_State* servant_state) + : prev_(0), + next_(0), + servant_ (servant), + servant_state_(servant_state, false) +{ + // This try-catch block is not really necessary for current implementation + // since the _add_ref does not throw exception, but we have to add it to + // satisfy the non-exception builds. If _add_ref really throws an exception + // then this constructor needs deal with the exception. + ACE_TRY_NEW_ENV + { + this->servant_->_add_ref (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHALL + { + } + ACE_ENDTRY; +} + + +ACE_INLINE +void +TAO::CSD::TP_Request::prepare_for_queue() +{ + this->prepare_for_queue_i(); +} + + +ACE_INLINE +PortableServer::Servant +TAO::CSD::TP_Request::servant() +{ + // Used for chaining so we do not return a new "copy". + return this->servant_.in(); +} + + +ACE_INLINE +bool +TAO::CSD::TP_Request::is_ready() const +{ + return !this->servant_state_->busy_flag(); +} + + +ACE_INLINE +void +TAO::CSD::TP_Request::mark_as_busy() +{ + this->servant_state_->busy_flag(true); +} + + +ACE_INLINE +void +TAO::CSD::TP_Request::mark_as_ready() +{ + this->servant_state_->busy_flag(false); +} + + +ACE_INLINE +bool +TAO::CSD::TP_Request::is_target(PortableServer::Servant servant) +{ + // Compare pointers. Return true only if these are the exact same object. + return (servant == this->servant_.in()); +} + + +ACE_INLINE +void +TAO::CSD::TP_Request::dispatch() +{ + this->dispatch_i(); + +} + + +ACE_INLINE +void +TAO::CSD::TP_Request::cancel() +{ + this->cancel_i(); +} diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Servant_State.cpp b/TAO/tao/CSD_ThreadPool/CSD_TP_Servant_State.cpp new file mode 100644 index 00000000000..bd7413d3fd2 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Servant_State.cpp @@ -0,0 +1,16 @@ +// $Id$ + +#include "CSD_TP_Servant_State.h" + +ACE_RCSID (CSD_TP, + Servant_State, + "$Id$") + +#if !defined (__ACE_INLINE__) +# include "CSD_TP_Servant_State.inl" +#endif /* ! __ACE_INLINE__ */ + + +TAO::CSD::TP_Servant_State::~TP_Servant_State() +{ +} diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Servant_State.h b/TAO/tao/CSD_ThreadPool/CSD_TP_Servant_State.h new file mode 100644 index 00000000000..fca7d321f1d --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Servant_State.h @@ -0,0 +1,89 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file CSD_TP_Servant_State.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_CSD_TP_SERVANT_STATE_H +#define TAO_CSD_TP_SERVANT_STATE_H + +#include /**/ "ace/pre.h" + +#include "CSD_TP_Export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "tao/Intrusive_Ref_Count_Base_T.h" +#include "tao/Intrusive_Ref_Count_Handle_T.h" +#include "ace/Synch.h" + + +namespace TAO +{ + namespace CSD + { + + /** + * @class TP_Servant_State + * + * @brief Maintains state information for a particular servant. + * + * This TP_Servant_State class is an intrusively reference-counted + * class. This allows it to be held in a "smart pointer" (aka, handle) + * object that will manage the reference-counting automagically. + * + * One TP_Servant_State object is created for each servant object for + * which a request is to be dispatched. The servant state objects are + * held (via smart pointers) in a TP_Servant_State_Map object. In turn, + * the TP_Servant_State_Map object is a data member of the TP_Stategy + * class. Each request placed on to the request queue will hold a + * reference (via a smart pointer) to the servant state object. + * + * Currently, the only "state" info held in this TP_Servant_State class + * is the servant's busy flag. + * + */ + class TAO_CSD_TP_Export TP_Servant_State + : public TAO_Intrusive_Ref_Count_Base<ACE_SYNCH_MUTEX> + { + public: + + /// Handle Type (aka, Smart Pointer Type). + typedef TAO_Intrusive_Ref_Count_Handle<TP_Servant_State> HandleType; + + /// Default Constructor. + TP_Servant_State(); + + /// Virtual Destructor. + virtual ~TP_Servant_State(); + + /// Accessor for the servant busy flag. + bool busy_flag() const; + + /// Mutator for the servant busy flag. + void busy_flag(bool new_value); + + private: + + /// The servant's current "busy" state (true == busy, false == not busy) + bool busy_flag_; + }; + + } +} + +#if defined (__ACE_INLINE__) +# include "CSD_TP_Servant_State.inl" +#endif /* __ACE_INLINE__ */ + +#include /**/ "ace/post.h" + +#endif /* TAO_CSD_TP_SERVANT_STATE_H */ diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Servant_State.inl b/TAO/tao/CSD_ThreadPool/CSD_TP_Servant_State.inl new file mode 100644 index 00000000000..ba67f809131 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Servant_State.inl @@ -0,0 +1,24 @@ +// $Id$ + + +ACE_INLINE +TAO::CSD::TP_Servant_State::TP_Servant_State() + : busy_flag_(false) +{ +} + + +ACE_INLINE +bool +TAO::CSD::TP_Servant_State::busy_flag() const +{ + return this->busy_flag_; +} + + +ACE_INLINE +void +TAO::CSD::TP_Servant_State::busy_flag(bool new_value) +{ + this->busy_flag_ = new_value; +} diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Servant_State_Map.cpp b/TAO/tao/CSD_ThreadPool/CSD_TP_Servant_State_Map.cpp new file mode 100644 index 00000000000..d6d34c6c6c2 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Servant_State_Map.cpp @@ -0,0 +1,11 @@ +// $Id$ + +#include "CSD_TP_Servant_State_Map.h" + +ACE_RCSID (CSD_TP, + Servant_State_Map, + "$Id$") + +#if !defined (__ACE_INLINE__) +# include "CSD_TP_Servant_State_Map.inl" +#endif /* ! __ACE_INLINE__ */ diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Servant_State_Map.h b/TAO/tao/CSD_ThreadPool/CSD_TP_Servant_State_Map.h new file mode 100644 index 00000000000..667b836006c --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Servant_State_Map.h @@ -0,0 +1,92 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file CSD_TP_Servant_State_Map.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_CSD_TP_SERVANT_STATE_MAP_H +#define TAO_CSD_TP_SERVANT_STATE_MAP_H + +#include /**/ "ace/pre.h" + +#include "CSD_TP_Export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "CSD_TP_Servant_State.h" +#include "tao/PortableServer/PortableServer.h" +#include "ace/Hash_Map_Manager.h" +#include "ace/Synch.h" + + +namespace TAO +{ + namespace CSD + { + + /** + * @class TP_Servant_State_Map + * + * @brief Map of Servant_State objects - one per servant. + * + * A TP_Stategy object holds an instance of a TP_Servant_State_Map object + * as a (held-by-value) data member. The strategy uses this map to + * find or create the TP_Servant_State object for a particular servant + * object. + * + */ + class TAO_CSD_TP_Export TP_Servant_State_Map + { + public: + + /// Default Constructor. + TP_Servant_State_Map(); + + /// Destructor. + ~TP_Servant_State_Map(); + + /// Accessor for the servant busy flag. + TP_Servant_State* find(PortableServer::Servant servant + ACE_ENV_ARG_DECL); + + /// Insert the servant to map. + void insert(PortableServer::Servant servant + ACE_ENV_ARG_DECL); + + /// Remove the servant from map. + void remove(PortableServer::Servant servant + ACE_ENV_ARG_DECL); + + + private: + + /// Underlying Map Type - Hash-Based - + /// Key Type: void*, Value Type: TP_Servant_State::HandleType + typedef ACE_Hash_Map_Manager_Ex<void*, + TP_Servant_State::HandleType, + ACE_Hash<void*>, + ACE_Equal_To<void*>, + ACE_SYNCH_MUTEX> MapType; + + /// The underlying map of servant state objects. + MapType map_; + }; + + } +} + +#if defined (__ACE_INLINE__) +# include "CSD_TP_Servant_State_Map.inl" +#endif /* __ACE_INLINE__ */ + +#include /**/ "ace/post.h" + +#endif /* TAO_CSD_TP_SERVANT_STATE_MAP_H */ diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Servant_State_Map.inl b/TAO/tao/CSD_ThreadPool/CSD_TP_Servant_State_Map.inl new file mode 100644 index 00000000000..0d0e40f54f3 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Servant_State_Map.inl @@ -0,0 +1,66 @@ +// $Id$ + + +ACE_INLINE +TAO::CSD::TP_Servant_State_Map::TP_Servant_State_Map() +{ +} + + +ACE_INLINE +TAO::CSD::TP_Servant_State_Map::~TP_Servant_State_Map() +{ +} + + +ACE_INLINE +TAO::CSD::TP_Servant_State* +TAO::CSD::TP_Servant_State_Map::find(PortableServer::Servant servant + ACE_ENV_ARG_DECL) +{ + void* key = servant; + + TP_Servant_State::HandleType value; + + if (this->map_.find(key, value) != 0) + { + ACE_THROW_RETURN (PortableServer::POA::ServantNotActive (), 0); + } + + return value._retn(); +} + + +ACE_INLINE +void +TAO::CSD::TP_Servant_State_Map::insert(PortableServer::Servant servant + ACE_ENV_ARG_DECL) +{ + void* key = servant; + + TP_Servant_State::HandleType value = new TP_Servant_State (); + + int result = this->map_.bind(key, value); + + if (result == 1) + { + ACE_THROW (PortableServer::POA::ServantAlreadyActive ()); + } + + ACE_ASSERT (result == 0); +} + + +ACE_INLINE +void +TAO::CSD::TP_Servant_State_Map::remove(PortableServer::Servant servant + ACE_ENV_ARG_DECL) +{ + void* key = servant; + + if (this->map_.unbind(key) == -1) + { + ACE_THROW (PortableServer::POA::ServantNotActive ()); + } +} + diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Strategy.cpp b/TAO/tao/CSD_ThreadPool/CSD_TP_Strategy.cpp new file mode 100644 index 00000000000..6968234d673 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Strategy.cpp @@ -0,0 +1,270 @@ +// $Id$ + +#include "CSD_TP_Strategy.h" +#include "CSD_TP_Remote_Request.h" +#include "CSD_TP_Collocated_Synch_Request.h" +#include "CSD_TP_Collocated_Asynch_Request.h" +#include "CSD_TP_Custom_Synch_Request.h" +#include "CSD_TP_Custom_Asynch_Request.h" +#include "CSD_TP_Collocated_Synch_With_Server_Request.h" +#include "ace/Trace.h" + +ACE_RCSID (CSD_ThreadPool, + TP_Strategy, + "$Id$") + +#if !defined (__ACE_INLINE__) +# include "CSD_TP_Strategy.inl" +#endif /* ! __ACE_INLINE__ */ + + +TAO::CSD::TP_Strategy::~TP_Strategy() +{ +} + + + +TAO::CSD::TP_Strategy::CustomRequestOutcome +TAO::CSD::TP_Strategy::custom_synch_request(TP_Custom_Request_Operation* op + ACE_ENV_ARG_DECL) +{ + TP_Servant_State::HandleType servant_state + = this->servant_state_map_.find(op->servant() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (REQUEST_REJECTED); + + TP_Custom_Synch_Request_Handle request = new + TP_Custom_Synch_Request(op, servant_state.in()); + + if (!this->task_.add_request(request.in())) + { + // The request was rejected by the task. + return REQUEST_REJECTED; + } + + // Now we wait until the request is handled (executed or cancelled). + return (request->wait()) ? REQUEST_EXECUTED : REQUEST_CANCELLED; +} + + +TAO::CSD::TP_Strategy::CustomRequestOutcome +TAO::CSD::TP_Strategy::custom_asynch_request(TP_Custom_Request_Operation* op + ACE_ENV_ARG_DECL) +{ + TP_Servant_State::HandleType servant_state + = this->servant_state_map_.find(op->servant() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (REQUEST_REJECTED); + + TP_Custom_Asynch_Request_Handle request = new + TP_Custom_Asynch_Request(op, servant_state.in()); + + return (this->task_.add_request(request.in())) + ? REQUEST_DISPATCHED : REQUEST_REJECTED; +} + + +bool +TAO::CSD::TP_Strategy::poa_activated_event_i() +{ + // Activates the worker threads, and waits until all have been started. + return (this->task_.open(&(this->num_threads_)) == 0); +} + + +void +TAO::CSD::TP_Strategy::poa_deactivated_event_i() +{ + // Passing in a value of 1 means that we want to shutdown the task, which + // equates to causing all worker threads to shutdown. The worker threads + // themselves will also invoke the close() method, but the passed-in value + // will be 0. So, a 1 means "shutdown", and a 0 means "a single worker + // thread is going away". + this->task_.close(1); +} + + +TAO::CSD::Strategy_Base::DispatchResult +TAO::CSD::TP_Strategy::dispatch_remote_request_i + (TAO_ServerRequest& server_request, + const PortableServer::ObjectId& object_id, + PortableServer::POA_ptr poa, + const char* operation, + PortableServer::Servant servant + ACE_ENV_ARG_DECL) +{ + // Obtain the TP_Servant_State object associated with the servant object. + // The find() either return a non nil handle or already thrown + // ServantNotActive exception. + + TP_Servant_State::HandleType servant_state + = this->servant_state_map_.find(servant ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (DISPATCH_REJECTED); + + // Now we can create the TP_Remote_Request object, and then add it to our + // task_'s "request queue". + // + // TBD-CSD: Need to use a Cached Allocator to "create" the + // TP_Remote_Request objects. For now, use the heap. + TP_Remote_Request_Handle request = + new TP_Remote_Request(server_request, + object_id, + poa, + operation, + servant, + servant_state.in()); + + // Hand the request object to our task so that it can add the request + // to its "request queue". + if (!this->task_.add_request(request.in())) + { + // Return the DISPATCH_REJECTED return code so that the caller (our + // base class' dispatch_request() method) knows that we did + // not handle the request, and that it should be rejected. + return TAO::CSD::Strategy_Base::DISPATCH_REJECTED; + } + + return TAO::CSD::Strategy_Base::DISPATCH_HANDLED; +} + + +TAO::CSD::Strategy_Base::DispatchResult +TAO::CSD::TP_Strategy::dispatch_collocated_request_i + (TAO_ServerRequest& server_request, + const PortableServer::ObjectId& object_id, + PortableServer::POA_ptr poa, + const char* operation, + PortableServer::Servant servant + ACE_ENV_ARG_DECL) +{ + // Obtain the TP_Servant_State object associated with the servant object. + // The find() either return a non nil handle or already thrown + // ServantNotActive exception. + + TP_Servant_State::HandleType servant_state + = this->servant_state_map_.find(servant ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (DISPATCH_REJECTED); + + bool is_sync_with_server = server_request.sync_with_server(); + bool is_synchronous = server_request.response_expected(); + + TP_Collocated_Synch_Request_Handle synch_request; + TP_Collocated_Synch_With_Server_Request_Handle synch_with_server_request; + TP_Request_Handle request; + + // Create the request object using the appropriate concrete type. + if (is_sync_with_server) + { + synch_with_server_request = + new TP_Collocated_Synch_With_Server_Request + (server_request, + object_id, + poa, + operation, + servant, + servant_state.in()); + + // Give the request handle its own "copy". + synch_with_server_request->_add_ref(); + request = synch_with_server_request.in(); + } + else if (is_synchronous) + { + synch_request = new TP_Collocated_Synch_Request(server_request, + object_id, + poa, + operation, + servant, + servant_state.in()); + + // Give the request handle its own "copy". + synch_request->_add_ref(); + request = synch_request.in(); + } + else + { + // Just use the (base) request handle to hold the request object. + request = new TP_Collocated_Asynch_Request(server_request, + object_id, + poa, + operation, + servant, + servant_state.in()); + } + + // Hand the request object to our task so that it can add the request + // to its "request queue". + if (!this->task_.add_request(request.in())) + { + // Return the DISPATCH_REJECTED return code so that the caller (our + // base class' dispatch_request() method) knows that we did + // not handle the request, and that it should be rejected. + return DISPATCH_REJECTED; + } + + // We need to wait on the request object if the request type is a + // synchronous request. + if (!synch_request.is_nil()) + { + int srw = synch_request->wait(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (DISPATCH_REJECTED); + if (srw == false) + { + // Raise exception when request was cancelled. + ACE_THROW_RETURN(CORBA::NO_IMPLEMENT(), DISPATCH_REJECTED); + } + } + else if (!synch_with_server_request.is_nil()) + { + bool swsr = synch_with_server_request->wait(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (DISPATCH_REJECTED); + if (swsr == false) + { + // Raise exception when request was cancelled. + ACE_THROW_RETURN(CORBA::NO_IMPLEMENT(), DISPATCH_REJECTED); + } + } + + return DISPATCH_HANDLED; +} + + +void +TAO::CSD::TP_Strategy::servant_activated_event_i + (PortableServer::Servant servant, + const PortableServer::ObjectId& oid + ACE_ENV_ARG_DECL) +{ + ACE_UNUSED_ARG(oid); + + // Add the servant to the servant state map. + this->servant_state_map_.insert(servant ACE_ENV_ARG_PARAMETER); + ACE_CHECK; +} + + +void +TAO::CSD::TP_Strategy::servant_deactivated_event_i + (PortableServer::Servant servant, + const PortableServer::ObjectId& oid + ACE_ENV_ARG_DECL) +{ + ACE_UNUSED_ARG(oid); + + // Cancel all requests stuck in the queue for the specified servant. + this->task_.cancel_servant(servant ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + // Remove the servant from the servant state map. + this->servant_state_map_.remove(servant ACE_ENV_ARG_PARAMETER); + ACE_CHECK; +} + + +void +TAO::CSD::TP_Strategy::cancel_requests(PortableServer::Servant servant + ACE_ENV_ARG_DECL) +{ + // Cancel all requests stuck in the queue for the specified servant. + this->task_.cancel_servant(servant ACE_ENV_ARG_PARAMETER); + ACE_CHECK; +} + diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Strategy.h b/TAO/tao/CSD_ThreadPool/CSD_TP_Strategy.h new file mode 100644 index 00000000000..ff96daa2788 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Strategy.h @@ -0,0 +1,180 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file CSD_TP_Strategy.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_CSD_TP_STRATEGY_H +#define TAO_CSD_TP_STRATEGY_H + +#include /**/ "ace/pre.h" + +#include "CSD_TP_Export.h" + +#include "CSD_TP_Task.h" +#include "CSD_TP_Servant_State_Map.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "tao/CSD_Framework/CSD_Strategy_Base.h" +#include "tao/Intrusive_Ref_Count_Handle_T.h" + + + +namespace TAO +{ + namespace CSD + { + + class TP_Strategy; + typedef TAO_Intrusive_Ref_Count_Handle<TP_Strategy> TP_Strategy_Handle; + + class TP_Custom_Request_Operation; + + /** + * @class TP_Strategy + * + * @brief A simple custom Thread-Pool servant dispatching strategy class. + * + * This class represents a concrete implementation of a "Custom + * Servant Dispatching Strategy". This implementation is being called + * the "Thread Pool Strategy" reference implementation. + * + * A custom servant dispatching strategy object can be applied to a + * POA object in order to carry out the servant dispatching duties + * for that POA. + * + */ + class TAO_CSD_TP_Export TP_Strategy + : public Strategy_Base + { + public: + + /// Constructor. + TP_Strategy(unsigned num_threads = 1); + + /// Virtual Destructor. + virtual ~TP_Strategy(); + + /// Set the number of threads in the pool (must be > 0). + void set_num_threads(unsigned num_threads); + + /// Return codes for the custom dispatch_request() methods. + enum CustomRequestOutcome + { + /// The request was successfully put on the request queue. + REQUEST_DISPATCHED, + /// The request has been executed/completed by a worker thread. + REQUEST_EXECUTED, + /// The request was removed from the queue and cancelled. + REQUEST_CANCELLED, + /// The request queue rejected the request + REQUEST_REJECTED + }; + + /// Inject a synchronous, custom request into the request queue. + /// This will block the calling thread until the request is handled + /// (dispatched or cancelled) or rejected. + /// Will return REQUEST_EXECUTED, REQUEST_CANCELLED, or REQUEST_REJECTED. + CustomRequestOutcome custom_synch_request + (TP_Custom_Request_Operation* op + ACE_ENV_ARG_DECL); + + /// Inject an asynchronous, custom request into the request queue. + /// This will return control to the calling thread once the request + /// has been placed into the queue (or rejected). + /// Will return REQUEST_DISPATCHED or REQUEST_REJECTED. + CustomRequestOutcome custom_asynch_request + (TP_Custom_Request_Operation* op + ACE_ENV_ARG_DECL); + + /// Cancel all requests that are targeted for the provided servant. + /// This is requested on the user application level. + void cancel_requests(PortableServer::Servant servant + ACE_ENV_ARG_DECL); + + protected: + + /// Handle the dispatching of a remote request. + /// + /// This will cause a new "request" object to be created and pushed + /// on to a "request queue". The worker threads are responsible for + /// servicing the queue, and performing the actual dispatch logic. + virtual Strategy_Base::DispatchResult dispatch_remote_request_i + (TAO_ServerRequest& server_request, + const PortableServer::ObjectId& object_id, + PortableServer::POA_ptr poa, + const char* operation, + PortableServer::Servant servant + ACE_ENV_ARG_DECL); + + /// Handle the dispatching of a collocated request. + /// + /// This will cause a new "request" object to be created and pushed + /// on to a "request queue". The worker threads are responsible for + /// servicing the queue, and performing the actual dispatch logic. + virtual Strategy_Base::DispatchResult dispatch_collocated_request_i + (TAO_ServerRequest& server_request, + const PortableServer::ObjectId& object_id, + PortableServer::POA_ptr poa, + const char* operation, + PortableServer::Servant servant + ACE_ENV_ARG_DECL); + + /// Event - The POA has been activated. + /// This will activate the worker thread(s). + /// Returns true if the worker threads were activated successfully. + /// Otherwise, returns false. + virtual bool poa_activated_event_i(); + + /// Event - The POA has been deactivated. + /// This will shutdown the worker thread(s). + virtual void poa_deactivated_event_i(); + + /// Event - A servant has been activated + virtual void servant_activated_event_i + (PortableServer::Servant servant, + const PortableServer::ObjectId& oid + ACE_ENV_ARG_DECL); + + /// Event - A servant has been deactivated + virtual void servant_deactivated_event_i + (PortableServer::Servant servant, + const PortableServer::ObjectId& oid + ACE_ENV_ARG_DECL); + + + private: + + /// This is the active object used by the worker threads. + /// The request queue is owned/managed by the task object. + /// The strategy object puts requests into the task's request + /// queue, and the worker threads service the queued requests + /// by performing the actual servant request dispatching logic. + TP_Task task_; + + /// The number of worker threads to use for the task. + unsigned num_threads_; + + /// The map of servant state objects. + TP_Servant_State_Map servant_state_map_; + }; + + } +} + +#if defined (__ACE_INLINE__) +# include "CSD_TP_Strategy.inl" +#endif /* __ACE_INLINE__ */ + +#include /**/ "ace/post.h" + +#endif /* TAO_CSD_TP_STRATEGY_H */ diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Strategy.inl b/TAO/tao/CSD_ThreadPool/CSD_TP_Strategy.inl new file mode 100644 index 00000000000..ac2f95e3586 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Strategy.inl @@ -0,0 +1,17 @@ +// $Id$ + +ACE_INLINE +TAO::CSD::TP_Strategy::TP_Strategy(unsigned num_threads) + : num_threads_(num_threads) +{ + // Assumes that num_threads > 0. +} + + +ACE_INLINE +void +TAO::CSD::TP_Strategy::set_num_threads(unsigned num_threads) +{ + // Simple Mutator. Assumes that num_threads > 0. + this->num_threads_ = num_threads; +} diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Strategy_Factory.cpp b/TAO/tao/CSD_ThreadPool/CSD_TP_Strategy_Factory.cpp new file mode 100644 index 00000000000..0ec186f2f6d --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Strategy_Factory.cpp @@ -0,0 +1,108 @@ +// $Id$ + +#include "CSD_TP_Strategy_Factory.h" +#include "CSD_TP_Strategy.h" +#include "CSD_ThreadPool.h" +#include "tao/CSD_Framework/CSD_Strategy_Repository.h" +#include "tao/debug.h" +#include "ace/Dynamic_Service.h" +#include "ace/OS_NS_strings.h" + +ACE_RCSID (CSD_ThreadPool, + TP_Strategy_Factory, + "$Id$") + + +TAO::CSD::TP_Strategy_Factory::TP_Strategy_Factory() +{ +} + + +TAO::CSD::TP_Strategy_Factory::~TP_Strategy_Factory() +{ +} + + +int +TAO::CSD::TP_Strategy_Factory::init (int argc, + ACE_TCHAR* argv[]) +{ + ACE_TRACE ("TAO::CSD::TP_Strategy_Factory::init"); + + static int initialized = 0; + + // Only allow initialization once. + if (initialized) + return 0; + + initialized = 1; + TAO_CSD_Strategy_Repository *repo = + ACE_Dynamic_Service<TAO_CSD_Strategy_Repository>::instance ("TAO_CSD_Strategy_Repository"); + + if (repo != 0) + repo->init(0,0); + + ACE_CString poa_name; + unsigned num_threads = 1; + + // Parse any service configurator parameters. + for (int curarg = 0; curarg < argc; curarg++) + if (ACE_OS::strcasecmp (argv[curarg], + ACE_TEXT("-CSDtp")) == 0) + { + curarg++; + if (curarg < argc) + { + // Parse the parameter + ACE_CString arg ((const char *)argv[curarg]); + ssize_t pos = arg.find (':'); + poa_name = arg.substr (0, pos); + ACE_CString num_thread_str = arg.substr (pos + 1, arg.length () - pos); + num_threads = ACE_OS::strtoul (num_thread_str.c_str (), 0, 10); + + // Create the ThreadPool strategy for each named poa. + TP_Strategy* strategy = 0; + ACE_NEW_RETURN (strategy, TP_Strategy (num_threads), -1); + CSD_Framework::Strategy_var objref = strategy; + + TAO_CSD_Strategy_Repository *repo = + ACE_Dynamic_Service<TAO_CSD_Strategy_Repository>::instance + ("TAO_CSD_Strategy_Repository"); + + if (repo == 0) + { + TAO_CSD_ThreadPool::init (); + repo = ACE_Dynamic_Service<TAO_CSD_Strategy_Repository>::instance ( + "TAO_CSD_Strategy_Repository" + ); + } + + + repo->add_strategy (poa_name, strategy); + } + } + else + { + if (TAO_debug_level > 0) + { + ACE_DEBUG ((LM_ERROR, + ACE_TEXT("CSD_ORB_Loader: Unknown option ") + ACE_TEXT("<%s>.\n"), + argv[curarg])); + } + } + + + return 0; +} + +ACE_FACTORY_NAMESPACE_DEFINE(TAO_CSD_TP, + TAO_CSD_TP_Strategy_Factory, + TAO::CSD::TP_Strategy_Factory) + +ACE_STATIC_SVC_DEFINE(TAO_CSD_TP_Strategy_Factory, + ACE_TEXT("TAO_CSD_TP_Strategy_Factory"), + ACE_SVC_OBJ_T, + &ACE_SVC_NAME(TAO_CSD_TP_Strategy_Factory), + ACE_Service_Type::DELETE_THIS | ACE_Service_Type::DELETE_OBJ, + 0) diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Strategy_Factory.h b/TAO/tao/CSD_ThreadPool/CSD_TP_Strategy_Factory.h new file mode 100644 index 00000000000..e51346befbf --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Strategy_Factory.h @@ -0,0 +1,61 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file CSD_TP_Strategy_Factory.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_CSD_TP_STRATEGY_FACTORY_H +#define TAO_CSD_TP_STRATEGY_FACTORY_H + +#include /**/ "ace/pre.h" + +#include "CSD_TP_Export.h" +#include "ace/Service_Object.h" +#include "ace/Service_Config.h" + + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + + +namespace TAO +{ + namespace CSD + { + + /** + * @class TP_Strategy_Factory + * + * @brief An ACE_Service_Object capable of creating TP_Strategy objects. + * + * TBD - Explain in more detail. + * + */ + class TAO_CSD_TP_Export TP_Strategy_Factory : public ACE_Service_Object + { + public: + + /// Constructor. + TP_Strategy_Factory(); + + /// Virtual Destructor. + virtual ~TP_Strategy_Factory(); + + int init (int argc, ACE_TCHAR* argv[]); + }; + } +} + +ACE_STATIC_SVC_DECLARE_EXPORT(TAO_CSD_TP, TAO_CSD_TP_Strategy_Factory) +ACE_FACTORY_DECLARE(TAO_CSD_TP, TAO_CSD_TP_Strategy_Factory) + +#include /**/ "ace/post.h" + +#endif /* TAO_CSD_TP_STRATEGY_FACTORY_H */ diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Synch_Helper.cpp b/TAO/tao/CSD_ThreadPool/CSD_TP_Synch_Helper.cpp new file mode 100644 index 00000000000..b3b241ec8f8 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Synch_Helper.cpp @@ -0,0 +1,11 @@ +// $Id$ + +#include "CSD_TP_Synch_Helper.h" + +ACE_RCSID (CSD_ThreadPool, + TP_Synch_Helper, + "$Id$") + +#if !defined (__ACE_INLINE__) +# include "CSD_TP_Synch_Helper.inl" +#endif /* ! __ACE_INLINE__ */ diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Synch_Helper.h b/TAO/tao/CSD_ThreadPool/CSD_TP_Synch_Helper.h new file mode 100644 index 00000000000..80c8aaff2ec --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Synch_Helper.h @@ -0,0 +1,107 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file CSD_TP_Synch_Helper.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_CSD_TP_SYNCH_HELPER_H +#define TAO_CSD_TP_SYNCH_HELPER_H + +#include /**/ "ace/pre.h" + +#include "CSD_TP_Export.h" +#include "tao/Condition.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/Synch.h" + + +namespace TAO +{ + namespace CSD + { + + /** + * @class TP_Synch_Helper + * + * @brief Helper class for synchronous requests to block the requesting + * thread until the appropriate time (when it will be un-blocked). + * + * TBD - Description here + * + */ + class TAO_CSD_TP_Export TP_Synch_Helper + { + public: + + /// Constructor. Sets initial state to PENDING. + TP_Synch_Helper(); + + /// Destructor. + ~TP_Synch_Helper(); + + /// Returns true if the helper state is DISPATCHED, and false if + /// the helper state is CANCELLED. However, if the helper state + /// is PENDING, then this method will block the calling thread + /// until the state changes to something other than PENDING + /// (ie, DISPATCHED or CANCELLED). + bool wait_while_pending(); + + /// Change the state of this helper to DISPATCHED, which will cause + /// wait_while_pending() to unblock. + void dispatched(); + + /// Change the state of this helper to CANCELLED, which will cause + /// wait_while_pending() to unblock. + void cancelled(); + + + private: + + /// Enumeration Type for all possible states of this helper object. + enum HelperState + { + PENDING, + DISPATCHED, + CANCELLED + }; + + /// Thread lock type + typedef ACE_SYNCH_MUTEX LockType; + + /// Thread guard type + typedef ACE_Guard<LockType> GuardType; + + /// Thread condition type + typedef TAO_Condition<LockType> ConditionType; + + /// Lock used to protect the state and condition. + LockType lock_; + + /// Used to denote the state of the request dispatching. + HelperState state_; + + /// The condition used to block the calling thread until the + /// state is something other than the PENDING state. + ConditionType condition_; + }; + + } +} + +#if defined (__ACE_INLINE__) +# include "CSD_TP_Synch_Helper.inl" +#endif /* __ACE_INLINE__ */ + +#include /**/ "ace/post.h" + +#endif /* TAO_CSD_TP_SYNCH_HELPER_H */ diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Synch_Helper.inl b/TAO/tao/CSD_ThreadPool/CSD_TP_Synch_Helper.inl new file mode 100644 index 00000000000..8a54320afb4 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Synch_Helper.inl @@ -0,0 +1,50 @@ +// $Id$ + + +ACE_INLINE +TAO::CSD::TP_Synch_Helper::TP_Synch_Helper() + : state_(PENDING), + condition_(this->lock_) +{ +} + + +ACE_INLINE +TAO::CSD::TP_Synch_Helper::~TP_Synch_Helper() +{ +} + + +ACE_INLINE +bool +TAO::CSD::TP_Synch_Helper::wait_while_pending() +{ + GuardType guard(this->lock_); + + while (this->state_ == PENDING) + { + this->condition_.wait(); + } + + return (this->state_ == DISPATCHED); +} + + +ACE_INLINE +void +TAO::CSD::TP_Synch_Helper::dispatched() +{ + GuardType guard(this->lock_); + this->state_ = DISPATCHED; + this->condition_.signal(); +} + + +ACE_INLINE +void +TAO::CSD::TP_Synch_Helper::cancelled() +{ + GuardType guard(this->lock_); + this->state_ = CANCELLED; + this->condition_.signal(); +} diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Task.cpp b/TAO/tao/CSD_ThreadPool/CSD_TP_Task.cpp new file mode 100644 index 00000000000..4a3874a4b82 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Task.cpp @@ -0,0 +1,310 @@ +// $Id$ + +#include "CSD_TP_Task.h" +#include "CSD_TP_Request.h" +#include "CSD_TP_Dispatchable_Visitor.h" +#include "CSD_TP_Cancel_Visitor.h" + +ACE_RCSID (CSD_ThreadPool, + TP_Task, + "$Id$") + +#if !defined (__ACE_INLINE__) +# include "CSD_TP_Task.inl" +#endif /* ! __ACE_INLINE__ */ + +TAO::CSD::TP_Task::~TP_Task() +{ +} + + +bool +TAO::CSD::TP_Task::add_request(TP_Request* request) +{ + GuardType guard(this->lock_); + + if (!this->accepting_requests_) + { + ACE_DEBUG((LM_DEBUG,"(%P|%t) TP_Task::add_request() - " + "not accepting requests\n")); + return false; + } + + // We have made the decision that the request is going to be placed upon + // the queue_. Inform the request that it is about to be placed into + // a request queue. Some requests may not need to do anything in + // preparation of being placed into a queue. Others, however, may need + // to perfom a "clone" operation on some underlying request data before + // the request can be properly placed into a queue. + request->prepare_for_queue(); + + this->queue_.put(request); + + this->work_available_.signal(); + + return true; +} + + +int +TAO::CSD::TP_Task::open(void* num_threads_ptr) +{ + unsigned num = 1; + + if (num_threads_ptr != 0) + { + unsigned* tmp = ACE_static_cast(unsigned*, num_threads_ptr); + + if (tmp == 0) + { + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) TP_Task failed to open. " + "Invalid argument type passed to open().\n"), + -1); + } + + num = *tmp; + } + + // We can't activate 0 threads. Make sure this isn't the case. + if (num < 1) + { + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) TP_Task failed to open. " + "num_threads_ (%u) is less-than 1.\n", + num), + -1); + } + + // Likewise, we can't activate too many. Make sure this isn't the case. + if (num > MAX_THREADPOOL_TASK_WORKER_THREADS) + { + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) TP_Task failed to open. " + "num_threads_ (%u) is too large. Max is %d.\n", + num, MAX_THREADPOOL_TASK_WORKER_THREADS), + -1); + } + + // We need the lock acquired from here on out. + GuardType guard(this->lock_); + + // We can assume that we are in the proper state to handle this open() + // call as long as we haven't been open()'ed before. + if (this->opened_) + { + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) TP_Task failed to open. " + "Task has previously been open()'ed.\n"), + -1); + } + + // Activate this task object with 'num' worker threads. + if (this->activate(THR_NEW_LWP | THR_JOINABLE, num) != 0) + { + // Assumes that when activate returns non-zero return code that + // no threads were activated. + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) TP_Task failed to activate " + "(%d) worker threads.\n", + num), + -1); + } + + // Now we have past the point where we can say we've been open()'ed before. + this->opened_ = true; + + // Now we wait until all of the threads have started. + while (this->num_threads_ != num) + { + this->active_workers_.wait(); + } + + // We can now accept requests (via our add_request() method). + this->accepting_requests_ = true; + + return 0; +} + + +int +TAO::CSD::TP_Task::svc() +{ + // Account for this current worker thread having started the + // execution of this svc() method. + { + GuardType guard(this->lock_); + // Put the thread id into a collection which is used to check whether + // the orb shutdown is called by one of the threads in the pool. + ACE_thread_t thr_id = ACE_OS::thr_self (); + if (this->activated_threads_.set(thr_id, this->num_threads_) == -1) + { + ACE_ERROR_RETURN((LM_ERROR, + ACE_TEXT("(%P|%t)TP_Task::svc: number of threads is out of range \n")), + 0); + } + ++this->num_threads_; + this->active_workers_.signal(); + } + + // This visitor object will be re-used over and over again as part of + // the "GetWork" logic below. + TP_Dispatchable_Visitor dispatchable_visitor; + + // Start the "GetWork-And-PerformWork" loop for the current worker thread. + while (1) + { + TP_Request_Handle request; + + // Do the "GetWork" step. + { + // Acquire the lock until just before we decide to "PerformWork". + GuardType guard(this->lock_); + + // Start the "GetWork" loop. + while (request.is_nil()) + { + if (this->shutdown_initiated_) + { + // This breaks us out of all loops with one fell swoop. + return 0; + } + + // There is no need to visit the queue if it is empty. + if (!this->queue_.is_empty()) + { + // Reset the visitor since we use it over and over. This + // will cause the visitor to drop any reference to + // a request that it may still be holding from a prior + // call to accept_visitor(). + dispatchable_visitor.reset(); + + // Visit the requests in the queue in hopes of + // locating the first "dispatchable" (ie, not busy) request. + // If a dispatchable request is located, it is extracted + // from the queue and saved in a handle data member in the + // visitor object. + this->queue_.accept_visitor(dispatchable_visitor); + + // If a dispatchable request is located, it is extracted + // from the queue and saved in a handle data member in the + // visitor object. Let's get a "copy" (or a NULL pointer + // if the visitor didn't locate/extract one). + request = dispatchable_visitor.request(); + } + + // Either the queue is empty or we couldn't find any dispatchable + // requests in the queue at this time. + if (request.is_nil()) + { + // Let's wait until we hear about the possibility of + // work before we go look again. + this->work_available_.wait(); + } + } + + // We have dropped out of the "while (request.is_nil())" loop. + // We only get here is we located/extracted a dispatchable request + // from the queue. Note that the visitor will have already + // marked the target servant as now being busy (because of us). + // We can now safely release the lock. + } + + // Do the "PerformWork" step. We don't need the lock_ to do this. + request->dispatch(); + + // Now that the request has been dispatched, we need to mark the target + // servant as no longer being busy, and we need to signal any wait()'ing + // worker threads that there may be some dispatchable requests in the + // queue now for this not-busy servant. We need the lock_ to do this. + { + GuardType guard(this->lock_); + request->mark_as_ready(); + this->work_available_.signal(); + } + + // Note that the request will be "released" here when the request + // handle falls out of scope and its destructor performs the + // _remove_ref() call on the underlying TP_Request object. + } + + // This will never get executed. + return 0; +} + + +int +TAO::CSD::TP_Task::close(u_long flag) +{ + GuardType guard(this->lock_); + + if (flag == 0) + { + // Worker thread is closing. + --this->num_threads_; + this->active_workers_.signal(); + } + else + { + // Strategy object is shutting down the task. + + // Do nothing if this task has never been open()'ed. + if (!this->opened_) + { + return 0; + } + + // Set the shutdown flag to true. + this->shutdown_initiated_ = true; + + // Stop accepting requests. + this->accepting_requests_ = false; + + // Signal all worker threads waiting on the work_available_ condition. + this->work_available_.broadcast(); + + size_t num_waiting_threads = 0; + + ACE_thread_t my_thr_id = ACE_OS::thr_self (); + + // Check whether the calling thread(calling orb shutdown) is one of the + // threads in the pool. If it is then it should not wait itself. + size_t size = this->activated_threads_.size (); + + for (size_t i = 0; i < size; i ++) + { + ACE_thread_t thr_id = 0; + if (activated_threads_.get (thr_id, i) == 0 && thr_id == my_thr_id) + { + num_waiting_threads = 1; + break; + } + } + + // Wait until all worker threads have shutdown. + while (this->num_threads_ != num_waiting_threads) + { + this->active_workers_.wait(); + } + + // Cancel all requests. + TP_Cancel_Visitor cancel_visitor; + this->queue_.accept_visitor(cancel_visitor); + } + + return 0; +} + + + +void +TAO::CSD::TP_Task::cancel_servant (PortableServer::Servant servant + ACE_ENV_ARG_DECL) +{ + GuardType guard(this->lock_); + + // Cancel the requests targeted for the provided servant. + TP_Cancel_Visitor cancel_visitor(servant); + this->queue_.accept_visitor(cancel_visitor); +} + diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Task.h b/TAO/tao/CSD_ThreadPool/CSD_TP_Task.h new file mode 100644 index 00000000000..25fa02f2fda --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Task.h @@ -0,0 +1,158 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file CSD_TP_Task.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_CSD_TP_TASK_H +#define TAO_CSD_TP_TASK_H + +#include /**/ "ace/pre.h" + +#include "CSD_TP_Export.h" + +#include "CSD_TP_Queue.h" +#include "tao/PortableServer/PortableServer.h" +#include "tao/Condition.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/Task.h" +#include "ace/Synch.h" +#include "ace/Containers_T.h" + +namespace TAO +{ + namespace CSD + { + + /** + * @class TP_Task + * + * @brief Active Object managing a queue of request objects. + * + * There are two types of "users" of a TP_Task object: + * + * 1) The TP_Strategy object that "owns" this task object. + * 2) The worker threads that "run" this task object as an + * "active object". + * + * The TP_Strategy object that "owns" this task object dictates + * when the worker threads are activated and when they are shutdown. It + * also injects requests into this task's queue via calls to the + * add_request() method. It is also the TP_Strategy object that + * dictates the number of worker threads to be activated via a call to + * the set_num_threads() method. + * + * The active object pattern is implemented via the use of the + * the ACE_Task_Base base class, and each worker thread will + * invoke this task's svc() method, and when the svc() returns, the + * worker thread will invoke this task's close() method (with the + * flag argument equal to 0). + * + * @note I just wanted to document an idea... When the pool consists + * of only one worker thread, we could care less about checking + * if target servant objects are busy or not. The simple fact + * that only one thread will be dispatching all requests means + * that servant objects will never be busy when the thread + * tests to see if a request is "ready_for_dispatch()". I'm + * just wondering if this knowledge can be applied to the + * implementation such that the "pool with one worker thread" case + * performs more efficiently. This is STP vs SSTP. + * + */ + class TAO_CSD_TP_Export TP_Task : public ACE_Task_Base + { + public: + + /// Default Constructor. + TP_Task(); + + /// Virtual Destructor. + virtual ~TP_Task(); + + /// Put a request object on to the request queue. + /// Returns true if successful, false otherwise (it has been "rejected"). + bool add_request(TP_Request* request); + + /// Activate the worker threads + virtual int open(void* num_threads_ptr = 0); + + /// The "mainline" executed by each worker thread. + virtual int svc(); + + /// Multi-purpose: argument value is used to differentiate purpose. + /// + /// 0) Invoked by each worker thread after its invocation of the + /// svc() method has completed (ie, returned). + /// 1) Invoked by the strategy object to shutdown all worker threads. + virtual int close(u_long flag = 0); + + /// Cancel all requests that are targeted for the provided servant. + void cancel_servant (PortableServer::Servant servant + ACE_ENV_ARG_DECL); + + + private: + + typedef TAO_SYNCH_MUTEX LockType; + typedef ACE_Guard<LockType> GuardType; + typedef TAO_Condition<LockType> ConditionType; + + + /// Lock to protect the "state" (all of the data members) of this object. + LockType lock_; + + /// Condition used to signal worker threads that they may be able to + /// find a request in the queue_ that needs to be dispatched to a + /// servant that is currently "not busy". + /// This condition will be signal()'ed each time a new request is + /// added to the queue_, and also when a servant has become "not busy". + ConditionType work_available_; + + /// This condition will be signal()'ed each time the num_threads_ + /// data member has its value changed. This is used to keep the + /// close(1) invocation (ie, a shutdown request) blocked until all + /// of the worker threads have stopped running. + ConditionType active_workers_; + + /// Flag used to indicate when this task will (or will not) accept + /// requests via the the add_request() method. + bool accepting_requests_; + + /// Flag used to initiate a shutdown request to all worker threads. + bool shutdown_initiated_; + + /// Flag used to avoid multiple open() calls. + bool opened_; + + /// The number of currently active worker threads. + unsigned num_threads_; + + /// The queue of pending servant requests (a.k.a. the "request queue"). + TP_Queue queue_; + + typedef ACE_Array <ACE_thread_t> Thread_Ids; + + /// The list of ids for the threads launched by this task. + Thread_Ids activated_threads_; + }; + + } +} + +#if defined (__ACE_INLINE__) +# include "CSD_TP_Task.inl" +#endif /* __ACE_INLINE__ */ + +#include /**/ "ace/post.h" + +#endif /* TAO_CSD_TP_TASK_H */ diff --git a/TAO/tao/CSD_ThreadPool/CSD_TP_Task.inl b/TAO/tao/CSD_ThreadPool/CSD_TP_Task.inl new file mode 100644 index 00000000000..5d9744d2afb --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_TP_Task.inl @@ -0,0 +1,17 @@ +// $Id$ + +namespace { enum { MAX_THREADPOOL_TASK_WORKER_THREADS = 50 }; } +namespace { const ACE_thread_t default_thread_id = 0; } + + +ACE_INLINE +TAO::CSD::TP_Task::TP_Task() + : work_available_(this->lock_), + active_workers_(this->lock_), + accepting_requests_(false), + shutdown_initiated_(false), + opened_(false), + num_threads_(0), + activated_threads_ ((size_t)MAX_THREADPOOL_TASK_WORKER_THREADS, default_thread_id) +{ +} diff --git a/TAO/tao/CSD_ThreadPool/CSD_ThreadPool.cpp b/TAO/tao/CSD_ThreadPool/CSD_ThreadPool.cpp new file mode 100644 index 00000000000..6797bd315e9 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_ThreadPool.cpp @@ -0,0 +1,19 @@ +// $Id$ + +#include "CSD_ThreadPool.h" +#include "CSD_TP_Strategy_Factory.h" +#include "tao/CSD_Framework/CSD_Framework_Loader.h" +#include "tao/debug.h" +#include "ace/Dynamic_Service.h" + +int +TAO_CSD_ThreadPool::init (void) +{ + static int initialized = 0; + if (initialized == 1) + return 0; + initialized = 1; + + TAO_CSD_Framework_Loader::init(); + return ACE_Service_Config::process_directive (ace_svc_desc_TAO_CSD_TP_Strategy_Factory); +} diff --git a/TAO/tao/CSD_ThreadPool/CSD_ThreadPool.h b/TAO/tao/CSD_ThreadPool/CSD_ThreadPool.h new file mode 100644 index 00000000000..e227bce3023 --- /dev/null +++ b/TAO/tao/CSD_ThreadPool/CSD_ThreadPool.h @@ -0,0 +1,60 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file CSD_Threadpool.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_CSD_THREADPOOL_H +#define TAO_CSD_THREADPOOL_H + +#include /**/ "ace/pre.h" + +#include "CSD_TP_Export.h" +#include "ace/Service_Object.h" +#include "ace/Service_Config.h" + + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +/** + * @class TP_Strategy_Factory + * + * @brief An ACE_Service_Object capable of creating TP_Strategy objects. + * + * TBD - Explain in more detail. + * + */ +class TAO_CSD_TP_Export TAO_CSD_ThreadPool +{ + public: + /// Used to force the initialization of the ORB code. + static int init (void); +}; + +#if defined(ACE_HAS_BROKEN_STATIC_CONSTRUCTORS) + +typedef int (*TAO_CSD_Threadpool) (void); + +static TAO_CSD_Threadpool +TAO_Requires_CSD_Threadpool = + &TAO_CSD_ThreadPool::init; + +#else + +static int +TAO_Requires_CSD_Threadpool = + TAO_CSD_ThreadPool::init (); + +#endif /* ACE_HAS_BROKEN_STATIC_CONSTRUCTORS */ + +#include /**/ "ace/post.h" + +#endif /* TAO_CSD_THREADPOOL_H */ diff --git a/TAO/tao/Intrusive_Ref_Count_Base_T.cpp b/TAO/tao/Intrusive_Ref_Count_Base_T.cpp new file mode 100644 index 00000000000..e7776d3fd91 --- /dev/null +++ b/TAO/tao/Intrusive_Ref_Count_Base_T.cpp @@ -0,0 +1,21 @@ +// $Id$ + +#ifndef TAO_INTRUSIVE_REF_COUNT_BASE_T_C +#define TAO_INTRUSIVE_REF_COUNT_BASE_T_C + +#include "Intrusive_Ref_Count_Base_T.h" + +#if !defined (__ACE_INLINE__) +#include "tao/Intrusive_Ref_Count_Base_T.inl" +#endif /* __ACE_INLINE__ */ + +ACE_RCSID (tao, + Intrusive_Ref_Count_Base_T, + "$Id$") + +template <typename T> +TAO_Intrusive_Ref_Count_Base<T>::~TAO_Intrusive_Ref_Count_Base() +{ +} + +#endif /* TAO_INTRUSIVE_REF_COUNT_BASE_T_C */ diff --git a/TAO/tao/Intrusive_Ref_Count_Base_T.h b/TAO/tao/Intrusive_Ref_Count_Base_T.h new file mode 100644 index 00000000000..f37041bd02c --- /dev/null +++ b/TAO/tao/Intrusive_Ref_Count_Base_T.h @@ -0,0 +1,75 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file Intrusive_Ref_Count_Base_T.h + * + * $Id$ + * + * @authors Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_INTRUSIVE_REF_COUNT_BASE_T_H +#define TAO_INTRUSIVE_REF_COUNT_BASE_T_H + +#include /**/ "ace/pre.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/Atomic_Op.h" + + +/** + * @class TAO_Intrusive_Ref_Count_Base<ACE_LOCK> + * + * @brief Template base class to provide intrusive reference-counting + * to subclasses. This makes the subclass capable of using a + * TAO_Intrusive_Ref_Count_Handle<X> class as a smart-pointer + * to an X object. In this case, X is a sub-class of this class, + * TAO_Intrusive_Ref_Count_Base<ACE_LOCK>. The ACE_LOCK type is + * used to protect the atomic reference count data member. + * + */ +template <class ACE_LOCK> +class TAO_Intrusive_Ref_Count_Base +{ +public: + + virtual ~TAO_Intrusive_Ref_Count_Base(); + + void _add_ref(); + void _remove_ref(); + + +protected: + + TAO_Intrusive_Ref_Count_Base(); + + +private: + + ACE_Atomic_Op<ACE_LOCK, long> ref_count_; + + // Not implemented. + TAO_Intrusive_Ref_Count_Base(const TAO_Intrusive_Ref_Count_Base&); + TAO_Intrusive_Ref_Count_Base& operator=(const TAO_Intrusive_Ref_Count_Base&); +}; + +#if defined (__ACE_INLINE__) +#include "Intrusive_Ref_Count_Base_T.inl" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "Intrusive_Ref_Count_Base_T.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Intrusive_Ref_Count_Base_T.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#include /**/ "ace/post.h" + +#endif /* TAO_INTRUSIVE_REF_COUNT_BASE_T_H */ diff --git a/TAO/tao/Intrusive_Ref_Count_Base_T.inl b/TAO/tao/Intrusive_Ref_Count_Base_T.inl new file mode 100644 index 00000000000..448763b6c74 --- /dev/null +++ b/TAO/tao/Intrusive_Ref_Count_Base_T.inl @@ -0,0 +1,32 @@ +// $Id$ + +template <typename T> +ACE_INLINE +TAO_Intrusive_Ref_Count_Base<T>::TAO_Intrusive_Ref_Count_Base () + : ref_count_(1) +{} + + +template <typename T> +ACE_INLINE +void +TAO_Intrusive_Ref_Count_Base<T>::_add_ref() +{ + ++this->ref_count_; +} + + +template <typename T> +ACE_INLINE +void +TAO_Intrusive_Ref_Count_Base<T>::_remove_ref() +{ + long new_count = --this->ref_count_; + + if (new_count != 0) + { + return; + } + + delete this; +} diff --git a/TAO/tao/Intrusive_Ref_Count_Handle_T.cpp b/TAO/tao/Intrusive_Ref_Count_Handle_T.cpp new file mode 100644 index 00000000000..f66b1177c48 --- /dev/null +++ b/TAO/tao/Intrusive_Ref_Count_Handle_T.cpp @@ -0,0 +1,16 @@ +// $Id$ + +#ifndef TAO_INTRUSIVE_REF_COUNT_HANDLE_T_C +#define TAO_INTRUSIVE_REF_COUNT_HANDLE_T_C + +#include "Intrusive_Ref_Count_Handle_T.h" + +#if !defined (__ACE_INLINE__) +#include "tao/Intrusive_Ref_Count_Handle_T.inl" +#endif /* __ACE_INLINE__ */ + +ACE_RCSID (tao, + Intrusive_Ref_Count_Handle_T, + "$Id$") + +#endif /* TAO_INTRUSIVE_REF_COUNT_HANDLE_T_C */ diff --git a/TAO/tao/Intrusive_Ref_Count_Handle_T.h b/TAO/tao/Intrusive_Ref_Count_Handle_T.h new file mode 100644 index 00000000000..ce9a64dc694 --- /dev/null +++ b/TAO/tao/Intrusive_Ref_Count_Handle_T.h @@ -0,0 +1,152 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file Intrusive_Ref_Count_Handle_T.h + * + * $Id$ + * + * @authors Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef TAO_INTRUSIVE_REF_COUNT_HANDLE_T_H +#define TAO_INTRUSIVE_REF_COUNT_HANDLE_T_H + +#include /**/ "ace/pre.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + + +/** + * @class TAO_Intrusive_Ref_Count_Handle<T> + * + * @brief Template class for smart-pointer to (intrusively) ref-counted object. + * + * This class behaves just like a xxx_var type behaves. The only significant + * difference is that this class provides a "bool is_nil() const" method, + * and xxx_var types don't (they use the "bool CORBA::is_nil(xxx_ptr ptr)" + * method instead). For example, + * + * typedef TAO_Intrusive_Ref_Count_Handle<PortableServer::ServantBase> + * MyServantBase_var; + * + * The MyServantBase_var and the PortableServer::ServantBase_var are + * nearly idenitical. The only difference is that the MyServantBase_var + * has a "isNil()" method that indicates whether or not the smart pointer + * is in the 'nil' state or not. + * + * This class can be used to "safely" deal with an instance of a servant. + * For example, we can use a single variable + * TAO_Intrusive_Ref_Count_Handle<Foo_i> + * + * typedef TAO_Intrusive_Ref_Count_Handle<Foo_i> Foo_i_var; + * Foo_i_var servant_; + * + * instead of using two variables + * + * PortableServer::ServantBase_var servant_holder_; + * Foo_i* servant_; + + * to deal with the servant memory. + * + * The Foo_i_var type does everything that the PortableServer::ServantBase_var + * type does. In addition, the Foo_i_var type can provide access to the servant + * as derived class via the arrow operator. + */ +template <typename T> +class TAO_Intrusive_Ref_Count_Handle +{ +public: + + /// Default Ctor - enters the "nil" state. + TAO_Intrusive_Ref_Count_Handle(); + + /// Ctor - By default, takes ownership of passed-in "copy" of reference + /// to T. But the second argument (bool) can be changed from + /// the default value of 'true' to the non-default value of 'false'. + /// The second argument dictates whether or not this handle object + /// should take ownership of the passed-in pointer to the T object. + /// By default, it takes ownership, leaving the reference counter + /// of the T object unchanged. When it is instructed to not take + /// ownership (false value for second arg), then the reference + /// counter of the T object will be incremented so that this + /// handle object has its own "copy". + TAO_Intrusive_Ref_Count_Handle(T* p, bool take_ownership = true); + + /// Copy Ctor - claims a "copy" of rhs object's reference to T. + TAO_Intrusive_Ref_Count_Handle(const TAO_Intrusive_Ref_Count_Handle& b); + + /// Dtor + ~TAO_Intrusive_Ref_Count_Handle(); + + /// Assignment Operator with T* argument. + /// Takes ownership of passed-in "copy" of reference to T. + TAO_Intrusive_Ref_Count_Handle& operator=(T* p); + + /// Assignment Operator with const TAO_Smart_Ptr<T>& argument. + /// Claims a "copy" of rhs object's reference to T. + TAO_Intrusive_Ref_Count_Handle& operator= + (const TAO_Intrusive_Ref_Count_Handle& b); + + /// Const Accessor to underlying pointer (T*) using arrow (->) operator. + T* operator->() const; + + /// Returns true if underlying pointer is NULL (0). + /// Returns false otherwise. + bool is_nil() const; + + /// Used to pass the underlying pointer as an "IN" argument to a method. + T* in() const; + + /// Used to pass the underlying pointer as an "IN/OUT" argument to a method. + T*& inout(); + + /// Used to pass the underlying pointer as an "OUT" argument to a method. + T*& out(); + + /// Used to take-away the underlying pointer from this smart pointer object. + /// Caller becomes responsibe for the returned "copy" to the reference. + /// Always leaves the smart pointer in the "nil" state upon return. + T* _retn(); + + +private: + + /// Claim a "copy" of the reference-counted object by adding + /// one to its reference counter. Do nothing if this smart pointer + /// object is currently in the "nil" state. + void claim(); + + /// Drop our "copy" of the reference-counted object by removing + /// one from its reference counter. Do nothing if this smart pointer + /// object is currently in the "nil" state. + /// Note that this method will always leave this smart pointer + /// in the "nil" state upon its return. + void drop(); + + + /// The underlying pointer to the (intrusively) reference-counted object. + /// Set to 0 when this smart pointer is in the "nil" state. Otherwise, + /// this smart pointer always owns a (reference-counted) "copy" of the + /// object pointed to by the ptr_ data member. + T* ptr_; +}; + +#if defined (__ACE_INLINE__) +#include "Intrusive_Ref_Count_Handle_T.inl" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "Intrusive_Ref_Count_Handle_T.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Intrusive_Ref_Count_Handle_T.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#include /**/ "ace/post.h" + +#endif /* TAO_INTRUSIVE_REF_COUNT_HANDLE_T_H */ diff --git a/TAO/tao/Intrusive_Ref_Count_Handle_T.inl b/TAO/tao/Intrusive_Ref_Count_Handle_T.inl new file mode 100644 index 00000000000..9c3a1fbe48b --- /dev/null +++ b/TAO/tao/Intrusive_Ref_Count_Handle_T.inl @@ -0,0 +1,155 @@ +// $Id$ + + +template <typename T> +ACE_INLINE +TAO_Intrusive_Ref_Count_Handle<T>::TAO_Intrusive_Ref_Count_Handle() + : ptr_(0) +{ +} + + +template <typename T> +ACE_INLINE +TAO_Intrusive_Ref_Count_Handle<T>::TAO_Intrusive_Ref_Count_Handle + (T* p, + bool take_ownership) + : ptr_(p) +{ + if (!take_ownership) + { + this->claim(); + } +} + + +template <typename T> +ACE_INLINE +TAO_Intrusive_Ref_Count_Handle<T>::TAO_Intrusive_Ref_Count_Handle + (const TAO_Intrusive_Ref_Count_Handle<T>& b) + : ptr_(b.ptr_) +{ + this->claim(); +} + + +template <typename T> +ACE_INLINE +TAO_Intrusive_Ref_Count_Handle<T>::~TAO_Intrusive_Ref_Count_Handle() +{ + this->drop(); +} + + +template <typename T> +ACE_INLINE +TAO_Intrusive_Ref_Count_Handle<T>& +TAO_Intrusive_Ref_Count_Handle<T>::operator=(T* p) +{ + if (this->ptr_ != p) + { + this->drop(); + this->ptr_ = p; + } + + return *this; +} + + +template <typename T> +ACE_INLINE +TAO_Intrusive_Ref_Count_Handle<T>& +TAO_Intrusive_Ref_Count_Handle<T>::operator= + (const TAO_Intrusive_Ref_Count_Handle<T>& b) +{ + if (this->ptr_ != b.ptr_) + { + this->drop(); + this->ptr_ = b.ptr_; + this->claim(); + } + + return *this; +} + + +template <typename T> +ACE_INLINE +T* +TAO_Intrusive_Ref_Count_Handle<T>::operator->() const +{ + return this->ptr_; +} + + +template <typename T> +ACE_INLINE +bool +TAO_Intrusive_Ref_Count_Handle<T>::is_nil() const +{ + return this->ptr_ == 0; +} + + +template <typename T> +ACE_INLINE +T* +TAO_Intrusive_Ref_Count_Handle<T>::in() const +{ + return this->ptr_; +} + + +template <typename T> +ACE_INLINE +T*& +TAO_Intrusive_Ref_Count_Handle<T>::inout() +{ + return this->ptr_; +} + + +template <typename T> +ACE_INLINE +T*& +TAO_Intrusive_Ref_Count_Handle<T>::out() +{ + this->drop(); + return this->ptr_; +} + + +template <typename T> +ACE_INLINE +T* +TAO_Intrusive_Ref_Count_Handle<T>::_retn() +{ + T* retval = this->ptr_; + this->ptr_ = 0; + return retval; +} + + +template <typename T> +ACE_INLINE +void +TAO_Intrusive_Ref_Count_Handle<T>::claim() +{ + if (this->ptr_ != 0) + { + this->ptr_->_add_ref(); + } +} + + +template <typename T> +ACE_INLINE +void +TAO_Intrusive_Ref_Count_Handle<T>::drop() +{ + if (this->ptr_ != 0) + { + this->ptr_->_remove_ref(); + this->ptr_ = 0; + } +} diff --git a/TAO/tao/PortableServer/Object_Adapter.cpp b/TAO/tao/PortableServer/Object_Adapter.cpp index 6ad3cc7ad62..c1a6c27d759 100644 --- a/TAO/tao/PortableServer/Object_Adapter.cpp +++ b/TAO/tao/PortableServer/Object_Adapter.cpp @@ -355,9 +355,7 @@ TAO_Object_Adapter::dispatch_servant (const TAO::ObjectKey &key, { ACE_FUNCTION_TIMEPROBE (TAO_SERVANT_DISPATCH_START); - servant_upcall.servant ()->_dispatch (req, - &servant_upcall - ACE_ENV_ARG_PARAMETER); + do_dispatch (req, servant_upcall ACE_ENV_ARG_PARAMETER); ACE_CHECK_RETURN (result); } @@ -1242,3 +1240,14 @@ TAO_Object_Adapter::servant_dispatcher (TAO_Servant_Dispatcher *dispatcher) this->servant_dispatcher_ = dispatcher; } +void +TAO_Object_Adapter::do_dispatch (TAO_ServerRequest& req, + TAO::Portable_Server::Servant_Upcall& upcall + ACE_ENV_ARG_DECL) +{ + upcall.servant ()->_dispatch(req, + &upcall + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; +} + diff --git a/TAO/tao/PortableServer/Object_Adapter.h b/TAO/tao/PortableServer/Object_Adapter.h index a3605dc2f11..85587c99c0f 100644 --- a/TAO/tao/PortableServer/Object_Adapter.h +++ b/TAO/tao/PortableServer/Object_Adapter.h @@ -217,6 +217,10 @@ protected: static ACE_Lock *create_lock (int enable_locking, TAO_SYNCH_MUTEX &thread_lock); + virtual void do_dispatch (TAO_ServerRequest& req, + TAO::Portable_Server::Servant_Upcall& upcall + ACE_ENV_ARG_DECL); + public: /** diff --git a/TAO/tao/PortableServer/POAManager.cpp b/TAO/tao/PortableServer/POAManager.cpp index 539f5d0cd9d..186b51c9163 100644 --- a/TAO/tao/PortableServer/POAManager.cpp +++ b/TAO/tao/PortableServer/POAManager.cpp @@ -51,6 +51,15 @@ TAO_POA_Manager::activate_i (ACE_ENV_SINGLE_ARG_DECL) else { this->state_ = PortableServer::POAManager::ACTIVE; + // Find the poas that applied the custom servant dispatching + // strategy to launch the dispatching threads. + + for (POA_COLLECTION::iterator iterator = this->poa_collection_.begin (); + iterator != this->poa_collection_.end (); + ++iterator) + { + (*iterator)->poa_activated_hook (); + } } this->adapter_manager_state_changed (this->state_ @@ -117,6 +126,10 @@ TAO_POA_Manager::deactivate_i (CORBA::Boolean etherealize_objects, ++iterator) { TAO_Root_POA *poa = *iterator; + // Notify the poas that applied the custom servant dispatching + // strategy to stop the dispatching threads. + poa->poa_deactivated_hook (); + poa->deactivate_all_objects_i (etherealize_objects, wait_for_completion ACE_ENV_ARG_PARAMETER); diff --git a/TAO/tao/PortableServer/Root_POA.cpp b/TAO/tao/PortableServer/Root_POA.cpp index 4a132bd1766..4d51829d9e4 100644 --- a/TAO/tao/PortableServer/Root_POA.cpp +++ b/TAO/tao/PortableServer/Root_POA.cpp @@ -822,6 +822,10 @@ TAO_Root_POA::destroy_i (CORBA::Boolean etherealize_objects, this->cleanup_in_progress_ = 1; + // Inform the custom servant dispatching strategy to stop the working + // threads when the poa is destroyed. + this->poa_deactivated_hook (); + // This operation destroys the POA and all descendant POAs. The POA // so destroyed (that is, the POA with its name) may be re-created // later in the same process. (This differs from the @@ -2892,3 +2896,35 @@ TAO_POA_Static_Resources::TAO_POA_Static_Resources (void) { } +void +TAO_Root_POA::poa_activated_hook () +{ + //no-ops +} + +void +TAO_Root_POA::poa_deactivated_hook () +{ + //no-ops +} + +void +TAO_Root_POA::servant_activated_hook (PortableServer::Servant servant, + const PortableServer::ObjectId& oid + ACE_ENV_ARG_DECL) +{ + //no-ops + ACE_UNUSED_ARG (servant); + ACE_UNUSED_ARG (oid); +} + +void +TAO_Root_POA::servant_deactivated_hook (PortableServer::Servant servant, + const PortableServer::ObjectId& oid + ACE_ENV_ARG_DECL) +{ + //no-ops + ACE_UNUSED_ARG (servant); + ACE_UNUSED_ARG (oid); +} + diff --git a/TAO/tao/PortableServer/Root_POA.h b/TAO/tao/PortableServer/Root_POA.h index 7fcd071f9f7..313bd5bb093 100644 --- a/TAO/tao/PortableServer/Root_POA.h +++ b/TAO/tao/PortableServer/Root_POA.h @@ -561,6 +561,25 @@ public: ACE_ENV_SINGLE_ARG_DECL ); + /// These hooks are needed by the CSD strategy to override + /// and no-ops by default. + + /// Hook - The POA has been (or is being) activated. + virtual void poa_activated_hook (); + + /// Hook - The POA has been deactivated. + virtual void poa_deactivated_hook (); + + /// Hook - A servant has been activated. + virtual void servant_activated_hook (PortableServer::Servant servant, + const PortableServer::ObjectId& oid + ACE_ENV_ARG_DECL); + + /// Hook - A servant has been deactivated. + virtual void servant_deactivated_hook (PortableServer::Servant servant, + const PortableServer::ObjectId& oid + ACE_ENV_ARG_DECL); + protected: #if (TAO_HAS_MINIMUM_POA == 0) diff --git a/TAO/tao/PortableServer/ServantRetentionStrategyRetain.cpp b/TAO/tao/PortableServer/ServantRetentionStrategyRetain.cpp index 87cf5b4defe..3e054666f24 100644 --- a/TAO/tao/PortableServer/ServantRetentionStrategyRetain.cpp +++ b/TAO/tao/PortableServer/ServantRetentionStrategyRetain.cpp @@ -105,6 +105,18 @@ namespace TAO // Decrement the reference count. CORBA::UShort new_count = --active_object_map_entry->reference_count_; + // Inform the custom servant dispatching (CSD) strategy that the + // servant is deactivated. This would be called just once when the + // servant is deactivated the first time. + if (active_object_map_entry->deactivated_ == 0) + { + this->poa_->servant_deactivated_hook ( + active_object_map_entry->servant_, + active_object_map_entry->user_id_ + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + } + if (new_count == 0) { this->poa_->cleanup_servant (active_object_map_entry->servant_, @@ -557,6 +569,13 @@ namespace TAO // Everything is finally ok // + // Inform the custom servant dispatching (CSD) strategy that the + // sevant is activated. + this->poa_->servant_activated_hook (servant, + user_id.in () + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (0); + // ATTENTION: Trick locking here, see class header for details Non_Servant_Upcall non_servant_upcall (*this->poa_); ACE_UNUSED_ARG (non_servant_upcall); @@ -635,6 +654,13 @@ namespace TAO // Everything is finally ok // + // Inform the custom servant dispatching (CSD) strategy that the + // sevant is activated. + this->poa_->servant_activated_hook (servant, + system_id.in () + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (0); + // ATTENTION: Trick locking here, see class header for details Non_Servant_Upcall non_servant_upcall (*this->poa_); ACE_UNUSED_ARG (non_servant_upcall); @@ -758,6 +784,13 @@ namespace TAO // Everything is finally ok // + // Inform the custom servant dispatching (CSD) strategy that the + // sevant is activated. + this->poa_->servant_activated_hook (servant, + user_id.in () + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (0); + // ATTENTION: Trick locking here, see class header for details Non_Servant_Upcall non_servant_upcall (*this->poa_); ACE_UNUSED_ARG (non_servant_upcall); @@ -865,6 +898,13 @@ namespace TAO // Everything is finally ok // + // Inform the custom servant dispatching (CSD) strategy that the + // sevant is activated. + this->poa_->servant_activated_hook (servant, + id + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + // ATTENTION: Trick locking here, see class header for details Non_Servant_Upcall non_servant_upcall (*this->poa_); ACE_UNUSED_ARG (non_servant_upcall); diff --git a/TAO/tao/PortableServer/get_arg.h b/TAO/tao/PortableServer/get_arg.h index bf7a2fc892f..498035b3ed8 100644 --- a/TAO/tao/PortableServer/get_arg.h +++ b/TAO/tao/PortableServer/get_arg.h @@ -79,7 +79,7 @@ namespace TAO size_t i) { return - details + (details != 0 && details->args () != 0) ? static_cast<typename TAO::Arg_Traits<T>::in_arg_val *> ( details->args ()[i])->arg () : static_cast<typename TAO::SArg_Traits<T>::in_arg_val *> ( diff --git a/TAO/tao/Service_Context.h b/TAO/tao/Service_Context.h index 348bec7c061..b5ac3727b15 100644 --- a/TAO/tao/Service_Context.h +++ b/TAO/tao/Service_Context.h @@ -23,6 +23,14 @@ # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ +namespace TAO +{ + namespace CSD + { + class FW_Server_Request_Wrapper; + } +} + /** * @class TAO_Service_Context * @@ -52,6 +60,11 @@ class TAO_Export TAO_Service_Context { public: + /// Declare FW_Server_Request_Wrapper a friend + /// This friendship makes the FW_Server_Request_Wrapper be able to + /// clone the TAO_Service_Context data member in TAO_ServerRequest. + friend class TAO::CSD::FW_Server_Request_Wrapper; + /// Constructor TAO_Service_Context (void); diff --git a/TAO/tao/TAO_Server_Request.h b/TAO/tao/TAO_Server_Request.h index 288fd4a2723..29b11e2503a 100644 --- a/TAO/tao/TAO_Server_Request.h +++ b/TAO/tao/TAO_Server_Request.h @@ -52,6 +52,14 @@ namespace CORBA class Exception; } +namespace TAO +{ + namespace CSD + { + class FW_Server_Request_Wrapper; + } +} + class TAO_Operation_Details; /** @@ -65,6 +73,12 @@ class TAO_Operation_Details; class TAO_Export TAO_ServerRequest { public: + + /// Declare FW_Server_Request_Wrapper a friend + /// This friendship makes the FW_Server_Request_Wrapper be able to + /// clone the TAO_ServerRequest. + friend class TAO::CSD::FW_Server_Request_Wrapper; + /// Declare TAO_AMH_Response_Handler a friend /** * The TAO_AMH_Response_Handler class needs to copy part of the @@ -319,7 +333,7 @@ private: /// Used to pad CDR stream if we have used DSI. ptrdiff_t dsi_nvlist_align_; - TAO_Operation_Details const * const operation_details_; + TAO_Operation_Details const * operation_details_; /** * An argument flag to indicate whether there is any data that is diff --git a/TAO/tao/Tagged_Profile.h b/TAO/tao/Tagged_Profile.h index 5e9e10f8348..b7706dca0c7 100644 --- a/TAO/tao/Tagged_Profile.h +++ b/TAO/tao/Tagged_Profile.h @@ -24,6 +24,14 @@ #include "tao/Object_KeyC.h" #include "ace/SString.h" +namespace TAO +{ + namespace CSD + { + class FW_Server_Request_Wrapper; + } +} + /** * @class TAO_Tagged_Profile * @@ -34,6 +42,12 @@ class TAO_Export TAO_Tagged_Profile { public: + + /// Declare FW_Server_Request_Wrapper a friend + /// This friendship makes the FW_Server_Request_Wrapper be able to + /// clone the TAO_Tagged_Profile data member in TAO_ServerRequest. + friend class TAO::CSD::FW_Server_Request_Wrapper; + /// Ctor TAO_Tagged_Profile (TAO_ORB_Core *orb_core); diff --git a/TAO/tao/operation_details.h b/TAO/tao/operation_details.h index 8748d0f6147..55df7ee8328 100644 --- a/TAO/tao/operation_details.h +++ b/TAO/tao/operation_details.h @@ -37,6 +37,14 @@ namespace TAO struct Exception_Data; } +namespace TAO +{ + namespace CSD + { + class FW_Server_Request_Wrapper; + } +} + /** * @class TAO_Operation_Details * @@ -53,6 +61,11 @@ 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 + /// clone the TAO_Operation_Details data member in TAO_ServerRequest. + friend class TAO::CSD::FW_Server_Request_Wrapper; + /// Constructor TAO_Operation_Details (const char *name, CORBA::ULong len, diff --git a/TAO/tests/CSD_Strategy_Tests/Broken/CSD_TP_Broken.mpc b/TAO/tests/CSD_Strategy_Tests/Broken/CSD_TP_Broken.mpc new file mode 100644 index 00000000000..016caef75ef --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/Broken/CSD_TP_Broken.mpc @@ -0,0 +1,21 @@ +// -*- MPC -*- +// $Id$ + +project(*Server): csd_tp_test_exe_b { + exename=server_main + + Source_Files { + ServerApp.cpp + server_main.cpp + } +} + +project(*Client): csd_tp_test_exe_b { + exename=client_main + + Source_Files { + ClientApp.cpp + client_main.cpp + } +} + diff --git a/TAO/tests/CSD_Strategy_Tests/Broken/ClientApp.cpp b/TAO/tests/CSD_Strategy_Tests/Broken/ClientApp.cpp new file mode 100644 index 00000000000..f9d264a5ed7 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/Broken/ClientApp.cpp @@ -0,0 +1,318 @@ +// $Id$ +#include "ClientApp.h" +#include "AppHelper.h" +#include "OrbRunner.h" +#include "AppShutdown.h" +#include "TestAppExceptionC.h" +#include "Foo_B_ClientEngine.h" +#include "ace/Get_Opt.h" + + +ClientApp::ClientApp() +: TestAppBase("TP_Test_3_Client"), + client_task_ (true), // shutdown orb after client is done. + num_servants_ (1), + num_csd_threads_ (1), + num_orb_threads_ (1), + ior_("Not Set"), + client_kind_(0), + client_id_(0) +{ +} + + +ClientApp::~ClientApp() +{ +} + + +int +ClientApp::run_i(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + int result = this->init(argc, argv ACE_ENV_ARG_PARAMETER); + if (result != 0) + { + return result; + } + ACE_CHECK_RETURN (-1); + + this->poa_setup(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->csd_setup(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->client_setup(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->poa_activate(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->run_clients(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->run_orb_event_loop(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->cleanup(); + + return this->check_validity () ? 0 : -1; +} + + +int +ClientApp::init(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + this->orb_ = CORBA::ORB_init(argc, argv, "" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Parse the command-line args for this application. + // * Raises -1 if problems are encountered. + // * Returns 1 if the usage statement was explicitly requested. + // * Returns 0 otherwise. + int result = this->parse_args(argc, argv); + if (result != 0) + { + return result; + } + + TheAppShutdown->init(this->orb_.in(), num_servants_ ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + return 0; +} + + +void +ClientApp::poa_setup(ACE_ENV_SINGLE_ARG_DECL) +{ + this->poa_ = this->create_poa(this->orb_.in(), + "ChildPoa" + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; +} + + +void +ClientApp::csd_setup(ACE_ENV_SINGLE_ARG_DECL) +{ + this->tp_strategy_ = new TAO::CSD::TP_Strategy(this->num_csd_threads_); + + if (!this->tp_strategy_->apply_to(this->poa_.in() ACE_ENV_ARG_PARAMETER)) + { + ACE_ERROR((LM_ERROR, + "Failed to apply CSD strategy to poa.\n")); + ACE_THROW(TestAppException()); + } + ACE_CHECK; +} + + +void +ClientApp::client_setup(ACE_ENV_SINGLE_ARG_DECL) +{ + // Turn the ior_ into a Foo_B obj ref. + Foo_B_var foo = RefHelper<Foo_B>::string_to_ref(this->orb_.in(), + this->ior_.c_str() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + this->servants_.create_and_activate(1, // number of callback servants + this->poa_.in() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + ServantListType::T_stub_var cb = this->servants_.objref(0); + + // Create the ClientEngine object, and give it the Foo_B and Callback object + // references. + ClientEngine_Handle engine + = new Foo_B_ClientEngine(foo.in(), cb.in (), this->client_id_); + this->client_task_.add_engine(engine.in()); +} + + +void +ClientApp::poa_activate(ACE_ENV_SINGLE_ARG_DECL) +{ + PortableServer::POAManager_var poa_manager + = this->poa_->the_POAManager(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + poa_manager->activate(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; +} + + +void +ClientApp::run_clients(ACE_ENV_SINGLE_ARG_DECL) +{ + if (this->client_task_.open() != 0) + { + ACE_THROW (TestAppException ()); + } +} + + +void +ClientApp::run_orb_event_loop(ACE_ENV_SINGLE_ARG_DECL) +{ + OrbRunner orb_runner(this->orb_.in(), this->num_orb_threads_); + orb_runner.run(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + TheAppShutdown->wait (); +} + + +PortableServer::POA_ptr +ClientApp::create_poa(CORBA::ORB_ptr orb, const char* poa_name ACE_ENV_ARG_DECL) +{ + // Get the Root POA. + PortableServer::POA_var root_poa + = RefHelper<PortableServer::POA>::resolve_initial_ref(orb, + "RootPOA" + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + // Get the POAManager from the Root POA. + PortableServer::POAManager_var poa_manager + = root_poa->the_POAManager(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + // Create the child POA Policies. + CORBA::PolicyList policies(0); + policies.length(0); + + // Create the child POA + PortableServer::POA_var poa = AppHelper::create_poa(poa_name, + root_poa.in(), + poa_manager.in(), + policies + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + // Give away the child POA_ptr from the POA_var variable. + return poa._retn(); +} + + +void +ClientApp::cleanup() +{ +} + + +int +ClientApp::parse_args(int argc, char* argv[]) +{ + this->exe_name_ = argv[0]; + + ACE_Get_Opt get_opts(argc, argv, "i:k:n:"); + + int c; + + while ((c = get_opts()) != -1) + { + int result = 0; + switch (c) + { + case 'i': + this->ior_ = get_opts.opt_arg(); + break; + + case 'k': + result = set_arg(this->client_kind_, + get_opts.opt_arg(), + c, + "client_kind"); + break; + + case 'n': + result = set_arg(this->client_id_, + get_opts.opt_arg(), + c, + "client_id"); + break; + + case '?': + this->usage_statement(); + return 1; + + default: + this->usage_statement(); + return -1; + } + + if (result != 0) + { + return result; + } + } + + return this->arg_dependency_checks(); +} + +void +ClientApp::usage_statement() +{ + ACE_ERROR((LM_ERROR, + "Usage: %s [options]\n\n" + "OPTIONS:\n\n" + "\t[-i <ior>]\n" + "\t[-k <client_kind>]\n" + "\t[-n <client_id>]\n" + "\t[-?]\n\n", + this->exe_name_.c_str())); +} + + +int +ClientApp::arg_dependency_checks() +{ + if (this->ior_ == "Not Set") + { + ACE_ERROR((LM_ERROR, + "Error: Missing required command-line option (-i <ior>).\n")); + this->usage_statement(); + return -1; + } + if (this->client_id_ <= 0) + { + ACE_ERROR((LM_ERROR, + "Error: Invalid command-line option (-n <client id>). \n" + " The client id should be positive integer. \n")); + this->usage_statement(); + return -1; + } + + return 0; +} + + +int +ClientApp::set_arg(unsigned& value, + const char* arg, + char opt, + const char* name, + int min) +{ + int tmp = ACE_OS::atoi(arg); + + if (tmp < min) + { + ACE_ERROR((LM_ERROR, + "Error: -%c <%s> must be integer type with a value of, " + "at least, %d.\n", opt, name, min)); + this->usage_statement(); + return -1; + } + + value = tmp; + return 0; +} + + +bool +ClientApp::check_validity () +{ + // Check whether the clients return any errors. + if (this->client_task_.failure_count () > 0) + { + return false; + } + + return true; +} + diff --git a/TAO/tests/CSD_Strategy_Tests/Broken/ClientApp.h b/TAO/tests/CSD_Strategy_Tests/Broken/ClientApp.h new file mode 100644 index 00000000000..846384224f5 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/Broken/ClientApp.h @@ -0,0 +1,78 @@ +// $Id$ +#ifndef CLIENTAPP_H +#define CLIENTAPP_H + +#include "TestAppBase.h" +#include "ClientEngine.h" +#include "ServantList_T.h" +#include "Callback_i.h" +#include "ClientTask.h" +#include "tao/CSD_ThreadPool/CSD_TP_Strategy.h" +#include "tao/ORB.h" +#include "ace/SString.h" + + +class ClientApp : public TestAppBase +{ + public: + + ClientApp(); + virtual ~ClientApp(); + + protected: + + virtual int run_i(int argc, char* argv[] ACE_ENV_ARG_DECL); + + + private: + + // These are all called, in order, by the run_i() method. + int init(int argc, char* argv[] ACE_ENV_ARG_DECL); + void poa_setup(ACE_ENV_SINGLE_ARG_DECL); + void csd_setup(ACE_ENV_SINGLE_ARG_DECL); + void client_setup(ACE_ENV_SINGLE_ARG_DECL); + void poa_activate(ACE_ENV_SINGLE_ARG_DECL); + void run_clients(ACE_ENV_SINGLE_ARG_DECL); + void run_orb_event_loop(ACE_ENV_SINGLE_ARG_DECL); + bool check_validity (); + void cleanup(); + + // Helper methods used by the methods above. + int parse_args(int argc, char* argv[]); + + int set_arg(unsigned& value, + const char* arg, + char opt, + const char* name, + int min = 0); + + void usage_statement(); + int arg_dependency_checks(); + + PortableServer::POA_ptr create_poa(CORBA::ORB_ptr orb, + const char* poa_name + ACE_ENV_ARG_DECL); + + + typedef ServantList<Callback_i> ServantListType; + + CORBA::ORB_var orb_; + PortableServer::POA_var poa_; + TAO::CSD::TP_Strategy_Handle tp_strategy_; + + ServantListType servants_; + + ClientTask client_task_; + + ACE_CString exe_name_; + + unsigned num_servants_; + unsigned num_csd_threads_; + unsigned num_orb_threads_; + + ACE_CString ior_; + unsigned client_kind_; + unsigned client_id_; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/Broken/ServerApp.cpp b/TAO/tests/CSD_Strategy_Tests/Broken/ServerApp.cpp new file mode 100644 index 00000000000..e84221c8a35 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/Broken/ServerApp.cpp @@ -0,0 +1,417 @@ +// $Id$ +#include "ServerApp.h" +#include "AppHelper.h" +#include "OrbRunner.h" +#include "AppShutdown.h" +#include "TestAppExceptionC.h" +#include "Foo_B_SimpleClientEngine.h" +#include "Callback_i.h" +#include "ace/OS.h" +#include "ace/Get_Opt.h" + + +ServerApp::ServerApp() + : TestAppBase("TP_Test_3_Server"), + ior_filename_prefix_("foo"), + num_servants_(1), + num_csd_threads_(1), + num_orb_threads_(1), + num_remote_clients_(1), + num_collocated_clients_(0), + collocated_client_kind_(0) +{ +} + + +ServerApp::~ServerApp() +{ +} + + +int +ServerApp::run_i(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + int result = this->init(argc, argv ACE_ENV_ARG_PARAMETER); + if (result != 0) + { + return result; + } + ACE_CHECK_RETURN (-1); + + this->poa_setup(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->csd_setup(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->servant_setup(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->collocated_setup(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->poa_activate(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->run_collocated_clients(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->run_orb_event_loop(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->cleanup(); + return this->check_validity () ? 0 : -1; +} + + +int +ServerApp::init(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + this->orb_ = CORBA::ORB_init(argc, argv, "" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Parse the command-line args for this application. + // * Raises -1 if problems are encountered. + // * Returns 1 if the usage statement was explicitly requested. + // * Returns 0 otherwise. + int result = this->parse_args(argc, argv); + if (result != 0) + { + return result; + } + + unsigned num_clients = this->num_remote_clients_ + + this->num_collocated_clients_; + + TheAppShutdown->init(this->orb_.in(), num_clients ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + return 0; +} + + +void +ServerApp::poa_setup(ACE_ENV_SINGLE_ARG_DECL) +{ + this->poa_ = this->create_poa(this->orb_.in(), + "ChildPoa" + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + if (this->num_collocated_clients_ > 0) + { + this->cb_poa_ = this->create_poa(this->orb_.in(), + "CallbackPoa" + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + } +} + +void +ServerApp::csd_setup(ACE_ENV_SINGLE_ARG_DECL) +{ + this->tp_strategy_ = new TAO::CSD::TP_Strategy(this->num_csd_threads_); + +// We don't apply the strategy for this test to show that the bug isn't +// part of the CSD ThreadPool Strategy code. +#if 0 + if (!this->tp_strategy_->apply_to(this->poa_.in() ACE_ENV_ARG_PARAMETER)) + { + ACE_ERROR((LM_ERROR, + "Failed to apply CSD strategy to poa.\n")); + ACE_THROW(TestAppException()); + } + ACE_CHECK; +#endif + + // Use another poa and strategy for callbacks. This would resolve + // the deadlock situation that happens when having number of csd + // threads less than number of collocated clients. + if (this->num_collocated_clients_ > 0) + { + this->cb_tp_strategy_ = new TAO::CSD::TP_Strategy(); +// We don't apply the strategy for this test to show that the bug isn't +// part of the CSD ThreadPool Strategy code. +#if 0 + if (!this->cb_tp_strategy_->apply_to(this->cb_poa_.in() ACE_ENV_ARG_PARAMETER)) + { + ACE_ERROR((LM_ERROR, + "Failed to apply CSD strategy to callback poa.\n")); + ACE_THROW(TestAppException()); + } + ACE_CHECK; +#endif + } +} + + +void +ServerApp::servant_setup(ACE_ENV_SINGLE_ARG_DECL) +{ + this->foo_servants_.create_and_activate(this->num_servants_, + this->orb_.in (), + this->poa_.in (), + this->ior_filename_prefix_.c_str() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; +} + + +void +ServerApp::collocated_setup(ACE_ENV_SINGLE_ARG_DECL) +{ + if (this->num_collocated_clients_ == 0) + return; + + this->cb_servants_.create_and_activate(1, // number of callback servants + this->cb_poa_.in() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + CallbackServantListType::T_stub_var cb = this->cb_servants_.objref(0); + + unsigned client_id = this->num_remote_clients_; + + for (unsigned i = 0; i < this->num_collocated_clients_; i++) + { + client_id ++; + // Dole out the servant object references in a round-robin fashion. + unsigned servant_index = i % this->num_servants_; + + FooServantListType::T_stub_var foo + = this->foo_servants_.objref(servant_index); + ClientEngine_Handle engine + = new Foo_B_SimpleClientEngine(foo.in(), cb.in (), client_id, true); + this->collocated_client_task_.add_engine(engine.in()); + } +} + + +void +ServerApp::poa_activate(ACE_ENV_SINGLE_ARG_DECL) +{ + PortableServer::POAManager_var poa_manager + = this->poa_->the_POAManager(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + poa_manager->activate(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; +} + + +void +ServerApp::run_collocated_clients(ACE_ENV_SINGLE_ARG_DECL) +{ + if (this->num_collocated_clients_ > 0) + { + if (this->collocated_client_task_.open() == -1) + { + ACE_THROW (TestAppException ()); + } + } +} + + +void +ServerApp::run_orb_event_loop(ACE_ENV_SINGLE_ARG_DECL) +{ + OrbRunner orb_runner(this->orb_.in(), this->num_orb_threads_); + orb_runner.run(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + TheAppShutdown->wait (); +} + + +void +ServerApp::cleanup() +{ +} + + +int +ServerApp::parse_args(int argc, char* argv[]) +{ + this->exe_name_ = argv[0]; + + ACE_Get_Opt get_opts(argc, argv, "p:s:n:t:r:c:k:"); + + int c; + + while ((c = get_opts()) != -1) + { + int result = 0; + switch (c) + { + case 'p': + this->ior_filename_prefix_ = get_opts.opt_arg(); + break; + + case 's': + result = set_arg(this->num_servants_, + get_opts.opt_arg(), + c, + "num_servants", + 1); + break; + + case 'n': + result = set_arg(this->num_csd_threads_, + get_opts.opt_arg(), + c, + "num_servants", + 1); + break; + + case 't': + result = set_arg(this->num_orb_threads_, + get_opts.opt_arg(), + c, + "num_orb_threads", + 1); + break; + + case 'r': + result = set_arg(this->num_remote_clients_, + get_opts.opt_arg(), + c, + "num_remote_clients"); + break; + + case 'c': + result = set_arg(this->num_collocated_clients_, + get_opts.opt_arg(), + c, + "num_collocated_clients"); + break; + + case 'k': + result = set_arg(this->collocated_client_kind_, + get_opts.opt_arg(), + c, + "collocated_client_kind"); + break; + + case '?': + this->usage_statement(); + return 1; + + default: + this->usage_statement(); + return -1; + } + + if (result != 0) + { + return result; + } + } + + return this->arg_dependency_checks(); +} + +void +ServerApp::usage_statement() +{ + ACE_ERROR((LM_ERROR, + "Usage: %s [options]\n\n" + "OPTIONS:\n\n" + "\t[-p <ior_filename_prefix>]\n" + "\t[-s <num_servants>]\n" + "\t[-n <num_csd_threads>]\n" + "\t[-t <num_orb_threads>]\n" + "\t[-r <num_remote_clients>]\n" + "\t[-c <num_collocated_clients>]\n" + "\t[-k <collocated_client_kind>]\n" + "\t[-?]\n\n", + this->exe_name_.c_str())); +} + + +int +ServerApp::arg_dependency_checks() +{ + return (this->num_remote_clients_ + + this->num_collocated_clients_) > 0 ? 0 : -1; +} + + +int +ServerApp::set_arg(unsigned& value, + const char* arg, + char opt, + const char* name, + int min) +{ + int tmp = ACE_OS::atoi(arg); + + if (tmp < min) + { + ACE_ERROR((LM_ERROR, + "Error: -%c <%s> must be integer type with a value of, " + "at least, %d.\n", opt, name, min)); + this->usage_statement(); + return -1; + } + + value = tmp; + return 0; +} + + +PortableServer::POA_ptr +ServerApp::create_poa(CORBA::ORB_ptr orb, + const char* poa_name + ACE_ENV_ARG_DECL) +{ + // Get the Root POA. + PortableServer::POA_var root_poa + = RefHelper<PortableServer::POA>::resolve_initial_ref(orb, + "RootPOA" + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + // Get the POAManager from the Root POA. + PortableServer::POAManager_var poa_manager + = root_poa->the_POAManager(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + // Create the child POA Policies. + CORBA::PolicyList policies(0); + policies.length(0); + + // Create the child POA + PortableServer::POA_var poa = AppHelper::create_poa(poa_name, + root_poa.in(), + poa_manager.in(), + policies + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + // Give away the child POA_ptr from the POA_var variable. + return poa._retn(); +} + + +bool +ServerApp::check_validity () +{ + return true; +#if 0 + // Check whether the clients return any errors. + if (this->num_collocated_clients_ > 0 + && this->collocated_client_task_.failure_count () > 0) + { + return false; + } + + Foo_B_Statistics stats (this->num_remote_clients_, + this->num_collocated_clients_); + + Foo_B_SimpleClientEngine::expected_results (stats); + + for (unsigned i = 0; i < this->num_servants_; i++) + { + this->foo_servants_.servant(i)->gather_stats (stats); + } + + if (this->num_collocated_clients_ > 0) + { + this->cb_servants_.servant (0)->gather_stats (stats); + } + + return stats.actual_vs_expected (); +#endif +} + diff --git a/TAO/tests/CSD_Strategy_Tests/Broken/ServerApp.h b/TAO/tests/CSD_Strategy_Tests/Broken/ServerApp.h new file mode 100644 index 00000000000..c90b7671534 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/Broken/ServerApp.h @@ -0,0 +1,85 @@ +// $Id$ +#ifndef SERVERAPP_H +#define SERVERAPP_H + +#include "TestAppBase.h" +#include "ServantList_T.h" +#include "ClientTask.h" +#include "Foo_B_i.h" +#include "Callback_i.h" +#include "tao/CSD_ThreadPool/CSD_TP_Strategy.h" +#include "ace/SString.h" + + +class ServerApp : public TestAppBase +{ + public: + + ServerApp(); + virtual ~ServerApp(); + + + protected: + + virtual int run_i(int argc, char* argv[] ACE_ENV_ARG_DECL); + + + private: + + // These are all called, in order, by the run_i() method. + int init(int argc, char* argv[] ACE_ENV_ARG_DECL); + void poa_setup(ACE_ENV_SINGLE_ARG_DECL); + void csd_setup(ACE_ENV_SINGLE_ARG_DECL); + void servant_setup(ACE_ENV_SINGLE_ARG_DECL); + void collocated_setup(ACE_ENV_SINGLE_ARG_DECL); + void poa_activate(ACE_ENV_SINGLE_ARG_DECL); + void run_collocated_clients(ACE_ENV_SINGLE_ARG_DECL); + void run_orb_event_loop(ACE_ENV_SINGLE_ARG_DECL); + bool check_validity (); + void cleanup(); + + + // Helper methods used by the methods above. + int parse_args(int argc, char* argv[]); + + int set_arg(unsigned& value, + const char* arg, + char opt, + const char* name, + int min = 0); + + void usage_statement(); + int arg_dependency_checks(); + + + PortableServer::POA_ptr create_poa(CORBA::ORB_ptr orb, + const char* poa_name + ACE_ENV_ARG_DECL); + + typedef ServantList<Foo_B_i> FooServantListType; + typedef ServantList<Callback_i> CallbackServantListType; + + CORBA::ORB_var orb_; + PortableServer::POA_var poa_; + TAO::CSD::TP_Strategy_Handle tp_strategy_; + + PortableServer::POA_var cb_poa_; + TAO::CSD::TP_Strategy_Handle cb_tp_strategy_; + + FooServantListType foo_servants_; + CallbackServantListType cb_servants_; + + ClientTask collocated_client_task_; + + ACE_CString exe_name_; + + ACE_CString ior_filename_prefix_; + unsigned num_servants_; + unsigned num_csd_threads_; + unsigned num_orb_threads_; + unsigned num_remote_clients_; + unsigned num_collocated_clients_; + unsigned collocated_client_kind_; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/Broken/client_main.cpp b/TAO/tests/CSD_Strategy_Tests/Broken/client_main.cpp new file mode 100644 index 00000000000..3814bef5ff9 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/Broken/client_main.cpp @@ -0,0 +1,7 @@ +// $Id$ +#include "ClientApp.h" +#include "TestAppMain.h" + +TEST_APP_MAIN(ClientApp) + + diff --git a/TAO/tests/CSD_Strategy_Tests/Broken/run_test.pl b/TAO/tests/CSD_Strategy_Tests/Broken/run_test.pl new file mode 100755 index 00000000000..3000ac7a43c --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/Broken/run_test.pl @@ -0,0 +1,172 @@ +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; + +my $status = 0; + +my $iorfname_prefix = "servant"; +my $num_servants = 1; +my $num_orb_threads = 1; +my $num_remote_clients = 1; +my $num_csd_threads = 1; +my $num_collocated_clients = 0; +my $collocated_client_kind = 0; +my $client_kind = 0; + +my $i; +my $j; +my @iorfile; + +my $ARGC = @ARGV; + +if ($ARGC > 0) +{ + if ($ARGC > 1) + { + print STDERR "ERROR: Too many command-line arguments for $0.\n"; + exit 1; + } + + my $subtest = $ARGV[0]; + + if ($subtest eq 'remote') + { + $num_remote_clients = 40; + } + elsif ($subtest eq 'collocated') + { + $num_remote_clients = 0; + $num_collocated_clients = 1; + $num_csd_threads=1; + } + elsif ($subtest eq 'remote_orbthreads') + { + $num_orb_threads = 5; + $num_remote_clients = 40; + } + elsif ($subtest eq 'remote_servants') + { + $num_servants = 5; + $num_remote_clients = 40; + } + elsif ($subtest eq 'remote_csdthreads') + { + $num_csd_threads = 5; + $num_remote_clients = 40; + } + elsif ($subtest eq 'remote_big') + { + $num_csd_threads = 5; + $num_servants = 10; + $num_orb_threads = 4; + $num_remote_clients = 40; + } + elsif ($subtest eq 'big') + { + $num_csd_threads = 5; + $num_servants = 10; + $num_orb_threads = 4; + $num_remote_clients = 40; + $num_collocated_clients = 40; + } + elsif ($subtest eq 'usage') + { + print STDOUT "Usage: $0 [<subtest>]\n" . + "\n" . + "Supported <subtest> values:\n" . + "\n" . + "\tremote\n" . + "\tcollocated\n" . + "\tremote_orbthreads\n" . + "\tremote_servants\n" . + "\tremote_csdthreads\n" . + "\tremote_big\n" . + "\tusage\n" . + "\n"; + exit 0; + } + else + { + print STDERR "ERROR: invalid subtest argument for $0: $subtest\n"; + exit 1; + } +} + +#Delete old ior files. +for ($i = 0; $i < $num_servants; $i++) { + my $servant_id = sprintf("%02d", ($i + 1)); + $iorfile[$i] = PerlACE::LocalFile($iorfname_prefix . "_$servant_id.ior"); + unlink $iorfile[$i]; +} + +$SV = new PerlACE::Process("server_main", +# "-ORBNegotiateCodesets 0 " . + "-p $iorfname_prefix " . + "-s $num_servants " . + "-n $num_csd_threads " . + "-t $num_orb_threads " . + "-r $num_remote_clients " . + "-c $num_collocated_clients " . + "-k $collocated_client_kind"); + + +$SV->Spawn(); + +# Wait for the servant ior files created by server. +for ($i = 0; $i < $num_servants; $i++) { + if (PerlACE::waitforfile_timed + ($iorfile[$i], + $PerlACE::wait_interval_for_process_creation) == -1) { + print STDERR "ERROR: cannot find file <$iorfile[$i]>\n"; + $SV->Kill(); + $SV->TimedWait(1); + exit 1; + } +} + +my $count = 0; + +for ($i = 0; $i < $num_remote_clients; $i++) +{ + $client_id = $i + 1; + + $j = $i % $num_servants; + + $CLS[$i] = new PerlACE::Process("client_main", + "-i file://$iorfile[$j] ". + "-k $client_kind ". + "-n $client_id"); + $CLS[$i]->Spawn(); +} + +for ($i = 0; $i < $num_remote_clients; $i++) +{ + $client = $CLS[$i]->WaitKill(60); + + if ($client != 0) + { + print STDERR "ERROR: client $i returned $client\n"; + $status = 1; + } +} + + +$server = $SV->WaitKill(60); + +if ($server != 0) { + print STDERR "ERROR: server returned $server\n"; + $status = 1; +} + +#Delete ior files generated by this run. +for ($i = 0; $i < $num_servants; $i++) { + unlink $iorfile[$i]; +} + +exit $status; diff --git a/TAO/tests/CSD_Strategy_Tests/Broken/server_main.cpp b/TAO/tests/CSD_Strategy_Tests/Broken/server_main.cpp new file mode 100644 index 00000000000..82e987f6d41 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/Broken/server_main.cpp @@ -0,0 +1,5 @@ +// $Id$ +#include "ServerApp.h" +#include "TestAppMain.h" + +TEST_APP_MAIN(ServerApp) diff --git a/TAO/tests/CSD_Strategy_Tests/README b/TAO/tests/CSD_Strategy_Tests/README new file mode 100644 index 00000000000..4ab0940d42b --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/README @@ -0,0 +1,117 @@ +This directory contains tests for the Custom Servant Dispatching (CSD) +feature implemented within TAO. Specifically, these tests use the reference +implementation CSD Strategy, called the Thread Pool (TP) CSD Strategy. + +Each sub-directory should contain its own README file which describes the +contents of the particular sub-directory in more detail. The following +is a list of sub-directories located here under the +$TAO_ROOT/tests/CSD_Strategy_Tests directory: + +TP_Test_Lib +----------- + + This sub-directory contains source code used to build the + "CSD_TP_Test" library (ie, libCSD_TP_Test.so). This library contains + infrastructure code used by all of the CSD test applications. The + purpose of this library is code re-use and ease of maintenance (ie, + change/fix something in this library, and all applications using it + will gain the benefit.) + + +TP_Foo_A +-------- + + This sub-directory contains source code used to build the + "CSD_TP_Foo_A" library (ie, libCSD_TP_Foo_A.so). This library contains + one IDL file which declares the "Foo_A" interface. All of the other + source code in this library is used to support client and/or server + applications that will use the Foo_A interface. + + +TP_Foo_B +-------- + + This sub-directory contains source code used to build the + "CSD_TP_Foo_B" library (ie, libCSD_TP_Foo_B.so). This library contains + one IDL file which declares the "Foo_B" interface. All of the other + source code in this library is used to support client and/or server + applications that will use the Foo_B interface. + + +TP_Foo_C +-------- + + This sub-directory contains source code used to build the + "CSD_TP_Foo_C" library (ie, libCSD_TP_Foo_C.so). This library contains + one IDL file which declares the "Foo_C" interface. All of the other + source code in this library is used to support client and/or server + applications that will use the Foo_C interface. + + +TP_Test_1 +--------- + + This sub-directory contains source code that is used to build a + client application and a server application. These applications + make use of the Foo_A interface (see the TP_Foo_A directory). + This particular pair of applications do not use all of the infrastructure + types made available to them by the TP_Test_Lib. + + The TP_Test_1 application code is really more of an example than a test. + Other test applications (ie, TP_Test_2) do the same thing as TP_Test_1, + except that the other test applications take advantage of the + infrastructure types provided by the TP_Test_Lib. Another big difference + is that the TP_Test_1 does not perform any "actual" vs. "expected" + results checking - and the other TP tests do perform these checks. + + +TP_Test_2 +--------- + + This sub-directory contains source code that is used to build a + client application and a server application. These applications + make use of the Foo_A interface (see the TP_Foo_A directory). + + The Foo_A interface is a simple interface with just a few simple + operations (both one-way and two-way). + + Each launched client application (ie, client process) represents a + "remote" client of a Foo_A servant object that lives in a server + process. The server application can be instructed, upon start up, + to use any number of "collocated clients". Each collocated client is + essentially a new thread in the server process that will perform the + same logic that is performed by the remote client application. + + +TP_Test_3 +--------- + + This sub-directory contains source code that is used to build a + client application and a server application. These applications + make use of the Foo_B interface (see the TP_Foo_B directory). + + The Foo_B interface has a rich set of operations, using a wide variety + of argument types. + + The TP_Test_3 applications are nearly identical to their TP_Test_2 + counterparts, except for the fact that Foo_B is the interface type + used in TP_Test_3, and Foo_A is the interface type used in TP_Test_2. + + +TP_Test_4 +--------- + + This sub-directory contains source code that is used to build a + client application and a server application. These applications + make use of the Foo_C interface (see the TP_Foo_C directory). + + The Foo_C interface is a simple interface with just a few simple + operations (both one-way and two-way). It is nearly (if not exactly) + identical to the Foo_A interface. + + The TP_Test_4 applications are nearly identical to the TP_Test_2 + applications with one significant difference: the TP_Test_4 server + application makes use of the "custom requests" feature provided by + the CSD Thread Pool Strategy. These custom requests are performed + by the collocated client code within the server application. + diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Common/AppHelper.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Common/AppHelper.cpp new file mode 100644 index 00000000000..db2d1ec202e --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Common/AppHelper.cpp @@ -0,0 +1,102 @@ +// $Id$ +#include "AppHelper.h" + +void +AppHelper::ref_to_file(CORBA::ORB_ptr orb, + CORBA::Object_ptr obj, + const char* filename + ACE_ENV_ARG_DECL) +{ + CORBA::String_var ior = orb->object_to_string(obj); + + FILE* ior_file = ACE_OS::fopen(filename, (const ACE_TCHAR *)("w")); + + if (ior_file == 0) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Cannot open output file [%s] to write IOR.", + filename)); + ACE_THROW (TestAppException()); + } + + ACE_OS::fprintf(ior_file, "%s", ior.in()); + ACE_OS::fclose(ior_file); +} + + +PortableServer::POA_ptr +AppHelper::create_poa(const char* name, + PortableServer::POA_ptr root_poa, + PortableServer::POAManager_ptr mgr, + CORBA::PolicyList& policies + ACE_ENV_ARG_DECL) +{ + PortableServer::POA_var child_poa = root_poa->create_POA(name, + mgr, + policies + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + if (CORBA::is_nil(child_poa.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to create child POA: %s.\n", name)); + ACE_THROW_RETURN (TestAppException(), PortableServer::POA::_nil ()); + } + + return child_poa._retn(); +} + + +CORBA::Object_ptr +AppHelper::activate_servant(PortableServer::POA_ptr poa, + PortableServer::Servant servant + ACE_ENV_ARG_DECL) +{ + // Activate the servant using the Child POA. + PortableServer::ObjectId_var oid + = poa->activate_object(servant ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (CORBA::Object::_nil ()); + + CORBA::Object_var obj + = poa->servant_to_reference(servant ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (CORBA::Object::_nil ()); + + if (CORBA::is_nil(obj.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to convert servant_to_ref.\n")); + ACE_THROW_RETURN (TestAppException(), CORBA::Object::_nil ()); + } + + return obj._retn(); +} + + +bool +AppHelper::validate_connection (CORBA::Object_ptr obj) +{ + for (CORBA::ULong j = 0; j != 100; ++j) + { + ACE_TRY_NEW_ENV + { +#if (TAO_HAS_CORBA_MESSAGING == 1) + CORBA::PolicyList_var unused; + obj->_validate_connection (unused + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; +#else + obj->_is_a ("Not_An_IDL_Type" + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; +#endif /* TAO_HAS_MESSAGING == 1 */ + return true; + } + ACE_CATCHANY + { + } + ACE_ENDTRY; + } + + return false; +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Common/AppHelper.h b/TAO/tests/CSD_Strategy_Tests/TP_Common/AppHelper.h new file mode 100644 index 00000000000..06a6ac721a2 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Common/AppHelper.h @@ -0,0 +1,114 @@ +// $Id$ +#ifndef APPHELPER_H +#define APPHELPER_H + +#include "CSD_TP_Test_Export.h" +#include "TestAppExceptionC.h" +#include "tao/PortableServer/PortableServer.h" +#include "tao/ORB.h" +#include "ace/OS.h" +#include "ace/Log_Msg.h" + + +template <typename T> +struct RefHelper +{ + typedef typename T::_ptr_type T_ptr; + typedef typename T::_var_type T_var; + + static T_ptr string_to_ref(CORBA::ORB_ptr orb, + const char* ior + ACE_ENV_ARG_DECL) + { + CORBA::Object_var obj = orb->string_to_object(ior ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN(T::_nil ()); + + if (CORBA::is_nil(obj.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to convert IOR string to obj ref.\n")); + ACE_THROW_RETURN (TestAppException(), T::_nil ()); + } + + T_var t_obj = T::_narrow(obj.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN(T::_nil ()); + + if (CORBA::is_nil(t_obj.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to narrow obj ref to T interface.\n")); + ACE_THROW_RETURN (TestAppException(), T::_nil ()); + } + + return t_obj._retn(); + } + + static T_ptr resolve_initial_ref(CORBA::ORB_ptr orb, + const char* name + ACE_ENV_ARG_DECL) + { + CORBA::Object_var obj + = orb->resolve_initial_references(name ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (T::_nil ()); + + if (CORBA::is_nil(obj.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to resolve initial ref for '%s'.\n", + name)); + ACE_THROW_RETURN (TestAppException(), T::_nil ()); + } + + T_var t_obj = T::_narrow(obj.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (T::_nil ()); + + + if (CORBA::is_nil(t_obj.in())) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to narrow resolved initial ref '%s'.\n", + name)); + ACE_THROW_RETURN (TestAppException(), T::_nil ()); + } + + return t_obj._retn(); + } + +}; + +struct CSD_TP_Test_Export AppHelper +{ + + static void ref_to_file(CORBA::ORB_ptr orb, + CORBA::Object_ptr obj, + const char* filename + ACE_ENV_ARG_DECL); + + static PortableServer::POA_ptr create_poa + (const char* name, + PortableServer::POA_ptr root_poa, + PortableServer::POAManager_ptr mgr, + CORBA::PolicyList& policies + ACE_ENV_ARG_DECL); + + static CORBA::Object_ptr activate_servant(PortableServer::POA_ptr poa, + PortableServer::Servant servant + ACE_ENV_ARG_DECL); + + // This helper method is used because there is a chance that the + // initial CORBA request made to the target ORB will fail during + // connection establishment with a TRANSIENT CORBA SystemException. + // This occurs for some platforms (ie, windows) when several clients + // make their initial CORBA request to the same ORB at the same time, + // causing the ORB to attempt to handle several connection establishments + // at one time. Apparently, under certain conditions, it will throw the + // TRANSIENT exception to tell the client application to "try again later". + // The analogy is making a phone call. Sometimes you get a busy tone. + // This means "try again later". + // This helper function will retry until the connection establishment + // works - or until it decides that enough is enough. + static bool validate_connection (CORBA::Object_ptr obj); +}; + +#endif + diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Common/AppShutdown.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Common/AppShutdown.cpp new file mode 100644 index 00000000000..53dec90290a --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Common/AppShutdown.cpp @@ -0,0 +1,85 @@ +// $Id$ +#include "AppShutdown.h" +#include "TestAppExceptionC.h" +#include "ace/Log_Msg.h" +#include "ace/OS_NS_unistd.h" + + +AppShutdown::AppShutdown() + : num_clients_(0), + num_clients_shutdown_(0) +{ +} + + +AppShutdown::~AppShutdown() +{ +} + + +void +AppShutdown::init(CORBA::ORB_ptr orb, + unsigned num_clients + ACE_ENV_ARG_DECL) +{ + if ((!CORBA::is_nil(this->orb_.in())) || + (CORBA::is_nil(orb)) || + (num_clients == 0)) + { + // Already init()'ed, or bad argument values. + ACE_THROW(TestAppException()); + } + else + { + this->orb_ = CORBA::ORB::_duplicate(orb); + this->num_clients_ = num_clients; + this->num_clients_shutdown_ = 0; + } +} + + +void +AppShutdown::wait () +{ + this->orb_shutdown_task_.wait(); +} + + +void +AppShutdown::client_done() +{ + if ((this->num_clients_ == 0) || (CORBA::is_nil(this->orb_.in()))) + { + ACE_ERROR((LM_ERROR, "(%P|%t) AppShutdown was never initialized.\n")); + return; + } + + unsigned cur_shutdown; + + { + GuardType guard(this->lock_); + cur_shutdown = ++this->num_clients_shutdown_; + } + + if (cur_shutdown == this->num_clients_) + { + // Sleep for one second before shutting down the ORB. This + // is a poor-man version of "wait until the CSD request queue drains". + ACE_OS::sleep(1); + this->orb_shutdown_task_.orb(this->orb_.in()); + if (this->orb_shutdown_task_.open(0) != 0) + { + ACE_ERROR((LM_ERROR, "(%P|%t) AppShutdown failed to create orb "\ + "shutdown thread.\n")); + return; + } + } +} + + +AppShutdown* +AppShutdown::instance () +{ + static AppShutdown app_shutdown; + return &app_shutdown; +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Common/AppShutdown.h b/TAO/tests/CSD_Strategy_Tests/TP_Common/AppShutdown.h new file mode 100644 index 00000000000..d79c2aababf --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Common/AppShutdown.h @@ -0,0 +1,42 @@ +// $Id$ +#ifndef APP_SHUTDOWN_H +#define APP_SHUTDOWN_H + +#include "CSD_TP_Test_Export.h" +#include "OrbShutdownTask.h" +#include "tao/ORB.h" + +class CSD_TP_Test_Export AppShutdown +{ + public: + + AppShutdown(); + virtual ~AppShutdown(); + + void init(CORBA::ORB_ptr orb, + unsigned num_clients + ACE_ENV_ARG_DECL); + + void wait (); + + void client_done(); + + static AppShutdown* instance (); + + private: + + typedef ACE_SYNCH_MUTEX LockType; + typedef ACE_Guard<LockType> GuardType; + + LockType lock_; + CORBA::ORB_var orb_; + unsigned num_clients_; + unsigned num_clients_shutdown_; + + OrbShutdownTask orb_shutdown_task_; +}; + + +#define TheAppShutdown AppShutdown::instance() + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Common/CSD_TP_Test_Export.h b/TAO/tests/CSD_Strategy_Tests/TP_Common/CSD_TP_Test_Export.h new file mode 100644 index 00000000000..9ebd7dc8f34 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Common/CSD_TP_Test_Export.h @@ -0,0 +1,58 @@ + +// -*- C++ -*- +// $Id$ +// Definition for Win32 Export directives. +// This file is generated automatically by generate_export_file.pl -s CSD_TP_Test +// ------------------------------ +#ifndef CSD_TP_TEST_EXPORT_H +#define CSD_TP_TEST_EXPORT_H + +#include "ace/config-all.h" + +#if defined (ACE_AS_STATIC_LIBS) && !defined (CSD_TP_TEST_HAS_DLL) +# define CSD_TP_TEST_HAS_DLL 0 +#endif /* ACE_AS_STATIC_LIBS && CSD_TP_TEST_HAS_DLL */ + +#if !defined (CSD_TP_TEST_HAS_DLL) +# define CSD_TP_TEST_HAS_DLL 1 +#endif /* ! CSD_TP_TEST_HAS_DLL */ + +#if defined (CSD_TP_TEST_HAS_DLL) && (CSD_TP_TEST_HAS_DLL == 1) +# if defined (CSD_TP_TEST_BUILD_DLL) +# define CSD_TP_Test_Export ACE_Proper_Export_Flag +# define CSD_TP_TEST_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T) +# define CSD_TP_TEST_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# else /* CSD_TP_TEST_BUILD_DLL */ +# define CSD_TP_Test_Export ACE_Proper_Import_Flag +# define CSD_TP_TEST_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T) +# define CSD_TP_TEST_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# endif /* CSD_TP_TEST_BUILD_DLL */ +#else /* CSD_TP_TEST_HAS_DLL == 1 */ +# define CSD_TP_Test_Export +# define CSD_TP_TEST_SINGLETON_DECLARATION(T) +# define CSD_TP_TEST_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +#endif /* CSD_TP_TEST_HAS_DLL == 1 */ + +// Set CSD_TP_TEST_NTRACE = 0 to turn on library specific tracing even if +// tracing is turned off for ACE. +#if !defined (CSD_TP_TEST_NTRACE) +# if (ACE_NTRACE == 1) +# define CSD_TP_TEST_NTRACE 1 +# else /* (ACE_NTRACE == 1) */ +# define CSD_TP_TEST_NTRACE 0 +# endif /* (ACE_NTRACE == 1) */ +#endif /* !CSD_TP_TEST_NTRACE */ + +#if (CSD_TP_TEST_NTRACE == 1) +# define CSD_TP_TEST_TRACE(X) +#else /* (CSD_TP_TEST_NTRACE == 1) */ +# if !defined (ACE_HAS_TRACE) +# define ACE_HAS_TRACE +# endif /* ACE_HAS_TRACE */ +# define CSD_TP_TEST_TRACE(X) ACE_TRACE_IMPL(X) +# include "ace/Trace.h" +#endif /* (CSD_TP_TEST_NTRACE == 1) */ + +#endif /* CSD_TP_TEST_EXPORT_H */ + +// End of auto generated file. diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Common/CSD_TP_Test_Lib.mpc b/TAO/tests/CSD_Strategy_Tests/TP_Common/CSD_TP_Test_Lib.mpc new file mode 100644 index 00000000000..c7f6e20a3f5 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Common/CSD_TP_Test_Lib.mpc @@ -0,0 +1,39 @@ +//$Id$ +project : taolib_with_idl, csd_threadpool { + sharedname = CSD_TP_Test + dynamicflags = CSD_TP_TEST_BUILD_DLL + idlflags += -Wb,export_macro=CSD_TP_Test_Export -Wb,export_include=CSD_TP_Test_Export.h + includes += $(TAO_ROOT)/tao + + IDL_Files { + FooException.idl + TestAppException.idl + CancelledException.idl + CustomException.idl + } + + Source_Files { + AppHelper.cpp + AppShutdown.cpp + ClientEngine.cpp + ClientTask.cpp + OrbRunner.cpp + OrbTask.cpp + TestAppBase.cpp + StatisticsHelper.cpp + OrbShutdownTask.cpp + FooExceptionC.cpp + FooExceptionS.cpp + TestAppExceptionC.cpp + TestAppExceptionS.cpp + CancelledExceptionC.cpp + CancelledExceptionS.cpp + CustomExceptionC.cpp + CustomExceptionS.cpp + } + + Template_Files { + ServantList_T.cpp + } + +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Common/CancelledException.idl b/TAO/tests/CSD_Strategy_Tests/TP_Common/CancelledException.idl new file mode 100644 index 00000000000..8f9afcf68de --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Common/CancelledException.idl @@ -0,0 +1,7 @@ +// $Id$ +#ifndef CANCELAPPXCEPTION_IDL +#define CANCELAPPXCEPTION_IDL + +exception CancelledException {}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Common/ClientEngine.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Common/ClientEngine.cpp new file mode 100644 index 00000000000..361bb3cd465 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Common/ClientEngine.cpp @@ -0,0 +1,12 @@ +// $Id$ +#include "ClientEngine.h" + + +ClientEngine::ClientEngine() +{ +} + + +ClientEngine::~ClientEngine() +{ +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Common/ClientEngine.h b/TAO/tests/CSD_Strategy_Tests/TP_Common/ClientEngine.h new file mode 100644 index 00000000000..3fdd3efd233 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Common/ClientEngine.h @@ -0,0 +1,38 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file ClientEngine.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef CLIENT_ENGINE_H +#define CLIENT_ENGINE_H + +#include "CSD_TP_Test_Export.h" +#include "tao/Intrusive_Ref_Count_Base_T.h" +#include "tao/Intrusive_Ref_Count_Handle_T.h" +#include "tao/Environment.h" +#include "ace/Synch.h" +#include "ace/CORBA_macros.h" + + +class ClientEngine; +typedef TAO_Intrusive_Ref_Count_Handle<ClientEngine> ClientEngine_Handle; + + +class CSD_TP_Test_Export ClientEngine : public TAO_Intrusive_Ref_Count_Base<ACE_SYNCH_MUTEX> +{ + public: + + ClientEngine(); + virtual ~ClientEngine(); + + virtual bool execute(ACE_ENV_SINGLE_ARG_DECL) = 0; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Common/ClientTask.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Common/ClientTask.cpp new file mode 100644 index 00000000000..5ac8d25f408 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Common/ClientTask.cpp @@ -0,0 +1,116 @@ +// $Id$ +#include "ClientTask.h" +#include "ClientEngine.h" +#include "AppShutdown.h" +#include "ace/SString.h" + + +ClientTask::ClientTask(bool shutdown_after_done) +: shutdown_after_done_(shutdown_after_done), + failure_count_(0) +{ +} + + +ClientTask::~ClientTask() +{ +} + + +void +ClientTask::add_engine(ClientEngine* engine) +{ + // Pass in false so that _add_ref() is called. + ClientEngine_Handle engine_handle(engine,false); + this->engines_.push_back(engine_handle); +} + + +int +ClientTask::open(void*) +{ + unsigned num_threads = this->engines_.size(); + + if (num_threads == 0) + { + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) ClientTask cannot activate 0 threads.\n"), + -1); + } + + if (this->activate(THR_NEW_LWP | THR_JOINABLE, num_threads) != 0) + { + // Assumes that when activate returns non-zero return code that + // no threads were activated. + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) ClientTask failed to activate " + "the %d client threads.\n", num_threads), + -1); + } + + return 0; +} + + +int +ClientTask::svc() +{ + ClientEngine_Handle engine; + + { + GuardType guard(this->lock_); + this->engines_.get(engine, this->engines_.size() - 1); + this->engines_.pop_back(); + } + + ACE_TRY_NEW_ENV + { + bool exec_ret = engine->execute(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + if (exec_ret == false) + { + GuardType guard(this->lock_); + this->failure_count_ ++; + } + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "ClientTask::svc Caught exception from execute():"); + + GuardType guard(this->lock_); + this->failure_count_ ++; + } + ACE_CATCHALL + { + ACE_ERROR((LM_ERROR, + "(%P|%t) ClientTask::svc caught unknown (...) exception "\ + "in execute() " )); + GuardType guard(this->lock_); + this->failure_count_ ++; + } + ACE_ENDTRY; + + if(this->shutdown_after_done_) + { + // This is used to shutdown orb for a client application + // with an orb running. + TheAppShutdown->client_done (); + } + + return 0; +} + + +int +ClientTask::close(u_long) +{ + return 0; +} + + +unsigned +ClientTask::failure_count () const +{ + return this->failure_count_; +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Common/ClientTask.h b/TAO/tests/CSD_Strategy_Tests/TP_Common/ClientTask.h new file mode 100644 index 00000000000..cc3de7ec8a2 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Common/ClientTask.h @@ -0,0 +1,51 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file ClientTask.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef CLIENT_TASK_H +#define CLIENT_TASK_H + +#include "CSD_TP_Test_Export.h" +#include "ClientEngine.h" +#include "ace/Task.h" +#include "ace/Vector_T.h" +#include "ace/Synch.h" + + +class CSD_TP_Test_Export ClientTask : public ACE_Task_Base +{ + public: + + ClientTask(bool shutdown_after_done = false); + virtual ~ClientTask(); + + void add_engine(ClientEngine* engine); + + virtual int open(void* arg = 0); + virtual int svc(); + virtual int close(u_long); + + unsigned failure_count () const; + + private: + + typedef ACE_SYNCH_MUTEX LockType; + typedef ACE_Guard<LockType> GuardType; + + typedef ACE_Vector<ClientEngine_Handle> EngineVector; + + LockType lock_; + EngineVector engines_; + bool shutdown_after_done_; + unsigned failure_count_; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Common/CustomException.idl b/TAO/tests/CSD_Strategy_Tests/TP_Common/CustomException.idl new file mode 100644 index 00000000000..794900c41ce --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Common/CustomException.idl @@ -0,0 +1,7 @@ +// $Id$ +#ifndef CUSTOMEXCEPTION_IDL +#define CUSTOMEXCEPTION_IDL + +exception CustomException {}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Common/FooException.idl b/TAO/tests/CSD_Strategy_Tests/TP_Common/FooException.idl new file mode 100644 index 00000000000..4f76953e24c --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Common/FooException.idl @@ -0,0 +1,7 @@ +// $Id$ +#ifndef FOOEXCEPTION_IDL +#define FOOEXCEPTION_IDL + +exception FooException {}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Common/OrbRunner.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Common/OrbRunner.cpp new file mode 100644 index 00000000000..0cc9c9bd5ad --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Common/OrbRunner.cpp @@ -0,0 +1,58 @@ +// $Id$ +#include "OrbRunner.h" +#include "OrbTask.h" +#include "TestAppExceptionC.h" + + +OrbRunner::OrbRunner(CORBA::ORB_ptr orb, unsigned num_orb_threads) + : orb_(CORBA::ORB::_duplicate(orb)), + num_orb_threads_(num_orb_threads) +{ +} + + +OrbRunner::~OrbRunner() +{ +} + + +void +OrbRunner::run(ACE_ENV_SINGLE_ARG_DECL) +{ + ACE_ASSERT(this->num_orb_threads_ > 0); + + // If the num_orb_threads_ is exactly one, then just use the current + // (mainline) thread to run the ORB event loop. + if (this->num_orb_threads_ == 1) + { + // Since the num_orb_threads_ is exactly one, we just use the current + // (mainline) thread to run the ORB event loop. + this->orb_->run(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + } + else + { + // The num_orb_threads_ is greater than 1, so we will use an OrbTask + // (active object) to run the ORB event loop in (num_orb_threads_ - 1) + // threads. We use the current (mainline) thread as the other thread + // running the ORB event loop. + OrbTask orb_task(this->orb_.in(), this->num_orb_threads_ - 1); + + // Activate the OrbTask worker threads + if (orb_task.open(0) != 0) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Failed to open the OrbTask.\n")); + ACE_THROW(TestAppException()); + } + + // This will use the current (mainline) thread to run the ORB event loop. + this->orb_->run(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + + // Now that the current thread has unblocked from running the orb, + // make sure to wait for all of the worker threads to complete. + orb_task.wait(); + } +} + diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Common/OrbRunner.h b/TAO/tests/CSD_Strategy_Tests/TP_Common/OrbRunner.h new file mode 100644 index 00000000000..71c7c4e358c --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Common/OrbRunner.h @@ -0,0 +1,24 @@ +// $Id$ +#ifndef ORB_RUNNER_H +#define ORB_RUNNER_H + +#include "CSD_TP_Test_Export.h" +#include "tao/ORB.h" + +class CSD_TP_Test_Export OrbRunner +{ + public: + + OrbRunner(CORBA::ORB_ptr orb, unsigned num_orb_threads = 1); + virtual ~OrbRunner(); + + void run(ACE_ENV_SINGLE_ARG_DECL); + + + private: + + CORBA::ORB_var orb_; + unsigned num_orb_threads_; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Common/OrbShutdownTask.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Common/OrbShutdownTask.cpp new file mode 100644 index 00000000000..79ba1ba3f5e --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Common/OrbShutdownTask.cpp @@ -0,0 +1,75 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file OrbShutdownTask.cpp + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#include "OrbShutdownTask.h" +#include "ace/CORBA_macros.h" +#include "ace/OS_NS_unistd.h" + + +OrbShutdownTask::OrbShutdownTask() +{ +} + + +OrbShutdownTask::~OrbShutdownTask() +{ +} + + +void +OrbShutdownTask::orb(CORBA::ORB_ptr orb) +{ + this->orb_ = CORBA::ORB::_duplicate(orb); +} + + +int +OrbShutdownTask::open(void*) +{ + if (this->activate(THR_NEW_LWP | THR_JOINABLE, 1) != 0) + { + // Assumes that when activate returns non-zero return code that + // no threads were activated. + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) OrbShutdownTask failed to open().\n"), + -1); + } + + return 0; +} + + +int +OrbShutdownTask::svc() +{ + ACE_TRY_NEW_ENV + { + this->orb_->shutdown(0 ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHALL + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Exception raised by ORB::shutdown() call " + "in OrbShutdownTask::svc().\n")); + } + ACE_ENDTRY; + + return 0; +} + + +int +OrbShutdownTask::close(u_long) +{ + return 0; +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Common/OrbShutdownTask.h b/TAO/tests/CSD_Strategy_Tests/TP_Common/OrbShutdownTask.h new file mode 100644 index 00000000000..221251a7d3f --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Common/OrbShutdownTask.h @@ -0,0 +1,40 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file OrbShutdownTask.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef ORB_SHUTDOWN_TASK_H +#define ORB_SHUTDOWN_TASK_H + +#include "CSD_TP_Test_Export.h" +#include "ace/Task.h" +#include "tao/ORB.h" + + +class CSD_TP_Test_Export OrbShutdownTask : public ACE_Task_Base +{ + public: + + OrbShutdownTask(); + virtual ~OrbShutdownTask(); + + void orb(CORBA::ORB_ptr orb); + + virtual int open(void*); + virtual int svc(); + virtual int close(u_long); + + + private: + + CORBA::ORB_var orb_; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Common/OrbTask.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Common/OrbTask.cpp new file mode 100644 index 00000000000..ff6ad717898 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Common/OrbTask.cpp @@ -0,0 +1,99 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file OrbTask.cpp + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#include "OrbTask.h" +#include "ace/CORBA_macros.h" + +namespace { enum { MAX_ORB_TASK_WORKER_THREADS = 20 }; } + + +OrbTask::OrbTask(CORBA::ORB_ptr orb, unsigned num_threads) + : orb_(CORBA::ORB::_duplicate(orb)), + num_threads_(num_threads) +{ +} + + +OrbTask::~OrbTask() +{ +} + + +int +OrbTask::open(void*) +{ + if (this->num_threads_ < 1) + { + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) OrbTask failed to open. " + "num_threads_ (%d) is less-than 1.\n", + this->num_threads_), + -1); + } + + if (this->num_threads_ > MAX_ORB_TASK_WORKER_THREADS) + { + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) OrbTask failed to open. " + "num_threads_ (%d) is too large. Max is %d.\n", + this->num_threads_, MAX_ORB_TASK_WORKER_THREADS), + -1); + } + + if (CORBA::is_nil(this->orb_.in())) + { + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) OrbTask failed to open. " + "ORB object reference is nil.\n"), + -1); + } + + if (this->activate(THR_NEW_LWP | THR_JOINABLE, this->num_threads_) != 0) + { + // Assumes that when activate returns non-zero return code that + // no threads were activated. + ACE_ERROR_RETURN((LM_ERROR, + "(%P|%t) OrbTask failed to activate " + "(%d) worker threads.\n", + this->num_threads_), + -1); + } + + return 0; +} + + +int +OrbTask::svc() +{ + ACE_TRY_NEW_ENV + { + this->orb_->run(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHALL + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Exception raised by ORB::run() method. " + "OrbTask is stopping.\n")); + } + ACE_ENDTRY; + + return 0; +} + + +int +OrbTask::close(u_long) +{ + return 0; +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Common/OrbTask.h b/TAO/tests/CSD_Strategy_Tests/TP_Common/OrbTask.h new file mode 100644 index 00000000000..dc01e3ca191 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Common/OrbTask.h @@ -0,0 +1,38 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file OrbTask.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef ORB_TASK_H +#define ORB_TASK_H + +#include "CSD_TP_Test_Export.h" +#include "ace/Task.h" +#include "tao/ORB.h" + +class CSD_TP_Test_Export OrbTask : public ACE_Task_Base +{ + public: + + OrbTask(CORBA::ORB_ptr orb, unsigned num_threads = 1); + virtual ~OrbTask(); + + virtual int open(void* x = 0); + virtual int svc(); + virtual int close(u_long); + + + private: + + CORBA::ORB_var orb_; + unsigned num_threads_; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Common/ServantList_T.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Common/ServantList_T.cpp new file mode 100644 index 00000000000..2727c975253 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Common/ServantList_T.cpp @@ -0,0 +1,135 @@ +// $Id$ +#include "ServantList_T.h" +#include "AppHelper.h" +#include "TestAppExceptionC.h" + + +template <typename T> +ServantList<T>::ServantList() +{ +} + + +template <typename T> +ServantList<T>::~ServantList() +{ +} + + +template <typename T> +void +ServantList<T>::create_and_activate(unsigned num_servants, + CORBA::ORB_ptr orb, + PortableServer::POA_ptr poa, + const char* ior_fname_prefix + ACE_ENV_ARG_DECL) +{ + for (unsigned i = 0; i < num_servants; i++) + { + char buf[32]; + ACE_OS::sprintf(buf, "%02d", i + 1); + ACE_CString filename = ACE_CString(ior_fname_prefix) + "_" + buf + ".ior"; + ServantRecord record; + record.servant_ = new T(); + record.safe_servant_ = record.servant_; + + CORBA::Object_var obj + = AppHelper::activate_servant(poa, + record.safe_servant_.in() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + AppHelper::ref_to_file(orb, obj.in(), filename.c_str() ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + record.obj_ = T_stub::_narrow(obj.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + if (CORBA::is_nil(record.obj_.in())) + { + ACE_THROW (TestAppException()); + } + + this->servant_records_.push_back(record); + } +} + + +template <typename T> +void +ServantList<T>::create_and_activate(unsigned num_servants, + PortableServer::POA_ptr poa + ACE_ENV_ARG_DECL) +{ + for (unsigned i = 0; i < num_servants; i++) + { + ServantRecord record; + record.servant_ = new T(); + record.safe_servant_ = record.servant_; + + CORBA::Object_var obj + = AppHelper::activate_servant(poa, + record.safe_servant_.in() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + record.obj_ = T_stub::_narrow(obj.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + if (CORBA::is_nil(record.obj_.in())) + { + ACE_THROW (TestAppException()); + } + + this->servant_records_.push_back(record); + } +} + + +// Code for reference - doesn't work right now +#if 0 +template <typename T> +void +ServantList<T>::deactivate(PortableServer::POA_ptr poa) +{ + ServantRecord record; + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + PortableServer::ObjectId_var id = + poa->servant_to_id(record.safe_servant_.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + poa->deactivate_object(id.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "ServantList_T::deactivate_servant ()"); + } + ACE_CATCHALL + { + ACE_ERROR((LM_ERROR, "(%P|%t)ServantList_T::deactivate_servant " + "Caught unknown exception \n")); + } + ACE_ENDTRY; + ACE_CHECK; +} +#endif + + +template <typename T> +typename ServantList<T>::T_stub_ptr +ServantList<T>::objref(unsigned index) +{ + return T_stub::_duplicate(this->servant_records_[index].obj_.in()); +} + + +template <typename T> +T* +ServantList<T>::servant(unsigned index) +{ + return this->servant_records_[index].servant_; +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Common/ServantList_T.h b/TAO/tests/CSD_Strategy_Tests/TP_Common/ServantList_T.h new file mode 100644 index 00000000000..3cc61e42905 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Common/ServantList_T.h @@ -0,0 +1,68 @@ +// $Id$ +#ifndef SERVANTLIST_T_H +#define SERVANTLIST_T_H + +#include "tao/PortableServer/PortableServer.h" +#include "tao/PortableServer/Servant_Base.h" +#include "ace/Vector_T.h" + + +// The T type is a concrete servant type. +template <class T> +class ServantList +{ + public: + + typedef typename T::_stub_type T_stub; + typedef typename T::_stub_ptr_type T_stub_ptr; + typedef typename T::_stub_var_type T_stub_var; + + ServantList(); + ~ServantList(); + + /// Activate servant and output ior to a file. + void create_and_activate(unsigned num_servants, + CORBA::ORB_ptr orb, + PortableServer::POA_ptr poa, + const char* ior_fname_prefix + ACE_ENV_ARG_DECL); + + /// Activate servant and not output ior to a file. + void create_and_activate(unsigned num_servants, + PortableServer::POA_ptr poa + ACE_ENV_ARG_DECL); + + // Code not used and not working right now - possible future addition. + //void deactivate(PortableServer::POA_ptr poa); + + /// Get a (copy) of one of the object references (for a specific servant). + T_stub_ptr objref(unsigned index); + /// This doesn't return a copy. + T* servant(unsigned index); + + + private: + + struct ServantRecord + { + T* servant_; + PortableServer::ServantBase_var safe_servant_; + T_stub_var obj_; + }; + + typedef ACE_Vector<ServantRecord> ServantRecordVector; + + ServantRecordVector servant_records_; +}; + + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ServantList_T.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("ServantList_T.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#endif /* SERVANTLIST_T_H */ + diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Common/StatisticsHelper.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Common/StatisticsHelper.cpp new file mode 100644 index 00000000000..456d7025478 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Common/StatisticsHelper.cpp @@ -0,0 +1,35 @@ +// $Id$ +#include "StatisticsHelper.h" + +// swap function for integers +void swap ( CORBA::Long& x, CORBA::Long& y ) +{ + CORBA::Long temp; + temp = x; + x = y; + y = temp; +} + + +void sort ( LongVector & vector ) +{ + unsigned size = vector.size (); + + if (size > 0) + { + unsigned indexOfMin; + unsigned pass; + unsigned j; + + for ( pass = 0; pass < size - 1; pass++ ) + { + indexOfMin = pass; + + for ( j = pass + 1; j < size; j++ ) + if ( vector[j] < vector[indexOfMin] ) + indexOfMin = j; + + swap ( vector[pass], vector[indexOfMin] ); + } + } +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Common/StatisticsHelper.h b/TAO/tests/CSD_Strategy_Tests/TP_Common/StatisticsHelper.h new file mode 100644 index 00000000000..7f26a4ae165 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Common/StatisticsHelper.h @@ -0,0 +1,24 @@ +// $Id$ +#ifndef STATISTICS_HELPER_H +#define STATISTICS_HELPER_H + +#include "CSD_TP_Test_Export.h" +#include "tao/Basic_Types.h" +#include "ace/Array.h" +#include "ace/Vector_T.h" +#include "ace/SString.h" + + +typedef ACE_Vector< CORBA::Long, 1000 > LongVector; +typedef ACE_Vector< ACE_CString, 1000 > StringVector; +typedef ACE_Array< CORBA::Long > LongArray; + + +extern CSD_TP_Test_Export +void swap ( CORBA::Long& x, CORBA::Long& y ); + +extern CSD_TP_Test_Export +void sort ( LongVector & vector ); + + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Common/TestAppBase.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Common/TestAppBase.cpp new file mode 100644 index 00000000000..f2a2e97b7a2 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Common/TestAppBase.cpp @@ -0,0 +1,30 @@ +// $Id$ +#include "TestAppBase.h" + +TestAppBase::TestAppBase(const char* name) + : name_(name) +{ +} + + +TestAppBase::~TestAppBase() +{ +} + + +const char* +TestAppBase::name() const +{ + return this->name_.c_str(); +} + + +int +TestAppBase::run(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + int rc = this->run_i(argc, argv ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Convert 1 to 0. Leave 0 and -1 as they are. + return (rc == 1) ? 0 : rc; +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Common/TestAppBase.h b/TAO/tests/CSD_Strategy_Tests/TP_Common/TestAppBase.h new file mode 100644 index 00000000000..5138ffbf84c --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Common/TestAppBase.h @@ -0,0 +1,36 @@ +// $Id$ +#ifndef TESTAPPBASE_H +#define TESTAPPBASE_H + +#include "CSD_TP_Test_Export.h" +#include "ace/SString.h" +#include "tao/Environment.h" +#include "ace/CORBA_macros.h" + + +class CSD_TP_Test_Export TestAppBase +{ + public: + + virtual ~TestAppBase(); + + // Returns 0 for success, and -1 for failure. + int run(int argc, char* argv[] ACE_ENV_ARG_DECL); + + const char* name() const; + + + protected: + + TestAppBase(const char* name); + + // Returns -1 for failure, 0 for success + virtual int run_i(int argc, char* argv[] ACE_ENV_ARG_DECL) = 0; + + + private: + + ACE_CString name_; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Common/TestAppException.idl b/TAO/tests/CSD_Strategy_Tests/TP_Common/TestAppException.idl new file mode 100644 index 00000000000..2ac53939b77 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Common/TestAppException.idl @@ -0,0 +1,7 @@ +// $Id$ +#ifndef TESTAPPXCEPTION_IDL +#define TESTAPPXCEPTION_IDL + +exception TestAppException {}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Common/TestAppMain.h b/TAO/tests/CSD_Strategy_Tests/TP_Common/TestAppMain.h new file mode 100644 index 00000000000..062b6fc0c8e --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Common/TestAppMain.h @@ -0,0 +1,49 @@ +// $Id$ +#ifndef TESTAPPMAIN_H +#define TESTAPPMAIN_H + +#include "ace/Log_Msg.h" +#include "ace/SString.h" +#include "tao/Exception.h" +#include "tao/Environment.h" + +#define TEST_APP_MAIN(APP_TYPE) \ +int \ +main(int argc, char* argv[]) \ +{ \ + ACE_LOG_MSG->priority_mask(LM_TRACE | \ + LM_DEBUG | \ + LM_INFO | \ + LM_NOTICE | \ + LM_WARNING | \ + LM_ERROR | \ + LM_CRITICAL | \ + LM_ALERT | \ + LM_EMERGENCY, \ + ACE_Log_Msg::PROCESS); \ +\ + APP_TYPE app; \ +\ + ACE_TRY_NEW_ENV \ + { \ + int ret = app.run(argc,argv ACE_ENV_ARG_PARAMETER); \ + ACE_TRY_CHECK; \ + return ret; \ + } \ + ACE_CATCHANY \ + { \ + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, \ + "Caught exception:"); \ + } \ + ACE_CATCHALL \ + { \ + ACE_ERROR((LM_ERROR, \ + "(%P|%t) Unknown (...) exception caught in main() " \ + "for App [%d].\n", app.name())); \ + } \ + ACE_ENDTRY; \ + \ + return 1; \ +} + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_A/CSD_TP_Foo_A_Export.h b/TAO/tests/CSD_Strategy_Tests/TP_Foo_A/CSD_TP_Foo_A_Export.h new file mode 100644 index 00000000000..9b855c486d8 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_A/CSD_TP_Foo_A_Export.h @@ -0,0 +1,58 @@ + +// -*- C++ -*- +// $Id$ +// Definition for Win32 Export directives. +// This file is generated automatically by generate_export_file.pl -s CSD_TP_Foo_A +// ------------------------------ +#ifndef CSD_TP_FOO_A_EXPORT_H +#define CSD_TP_FOO_A_EXPORT_H + +#include "ace/config-all.h" + +#if defined (ACE_AS_STATIC_LIBS) && !defined (CSD_TP_FOO_A_HAS_DLL) +# define CSD_TP_FOO_A_HAS_DLL 0 +#endif /* ACE_AS_STATIC_LIBS && CSD_TP_FOO_A_HAS_DLL */ + +#if !defined (CSD_TP_FOO_A_HAS_DLL) +# define CSD_TP_FOO_A_HAS_DLL 1 +#endif /* ! CSD_TP_FOO_A_HAS_DLL */ + +#if defined (CSD_TP_FOO_A_HAS_DLL) && (CSD_TP_FOO_A_HAS_DLL == 1) +# if defined (CSD_TP_FOO_A_BUILD_DLL) +# define CSD_TP_Foo_A_Export ACE_Proper_Export_Flag +# define CSD_TP_FOO_A_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T) +# define CSD_TP_FOO_A_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# else /* CSD_TP_FOO_A_BUILD_DLL */ +# define CSD_TP_Foo_A_Export ACE_Proper_Import_Flag +# define CSD_TP_FOO_A_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T) +# define CSD_TP_FOO_A_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# endif /* CSD_TP_FOO_A_BUILD_DLL */ +#else /* CSD_TP_FOO_A_HAS_DLL == 1 */ +# define CSD_TP_Foo_A_Export +# define CSD_TP_FOO_A_SINGLETON_DECLARATION(T) +# define CSD_TP_FOO_A_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +#endif /* CSD_TP_FOO_A_HAS_DLL == 1 */ + +// Set CSD_TP_FOO_A_NTRACE = 0 to turn on library specific tracing even if +// tracing is turned off for ACE. +#if !defined (CSD_TP_FOO_A_NTRACE) +# if (ACE_NTRACE == 1) +# define CSD_TP_FOO_A_NTRACE 1 +# else /* (ACE_NTRACE == 1) */ +# define CSD_TP_FOO_A_NTRACE 0 +# endif /* (ACE_NTRACE == 1) */ +#endif /* !CSD_TP_FOO_A_NTRACE */ + +#if (CSD_TP_FOO_A_NTRACE == 1) +# define CSD_TP_FOO_A_TRACE(X) +#else /* (CSD_TP_FOO_A_NTRACE == 1) */ +# if !defined (ACE_HAS_TRACE) +# define ACE_HAS_TRACE +# endif /* ACE_HAS_TRACE */ +# define CSD_TP_FOO_A_TRACE(X) ACE_TRACE_IMPL(X) +# include "ace/Trace.h" +#endif /* (CSD_TP_FOO_A_NTRACE == 1) */ + +#endif /* CSD_TP_FOO_A_EXPORT_H */ + +// End of auto generated file. diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_A/Foo_A.idl b/TAO/tests/CSD_Strategy_Tests/TP_Foo_A/Foo_A.idl new file mode 100644 index 00000000000..e9f3b0345f8 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_A/Foo_A.idl @@ -0,0 +1,29 @@ +// $Id$ +#ifndef FOO_A_IDL +#define FOO_A_IDL + +#include "FooException.idl" + +interface Foo_A +{ + /// void return-type, no arguments + void op1(); + + /// void return-type, 1 "in" argument + void op2(in long value); + + /// long return-type, 1 "in" argument + long op3(in long value); + + /// one-way version of op2 + oneway void op4(in long value); + + /// Operation that always raises an exception. + void op5() raises (FooException); + + /// Client calls this last. The last client to claim that it is + /// done will cause the server to shutdown. + void done(); +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_A/Foo_A_ClientEngine.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Foo_A/Foo_A_ClientEngine.cpp new file mode 100644 index 00000000000..bb0d1cf1bf7 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_A/Foo_A_ClientEngine.cpp @@ -0,0 +1,94 @@ +// $Id$ +#include "Foo_A_ClientEngine.h" +#include "Foo_A_Statistics.h" +#include "TestAppExceptionC.h" +#include "AppHelper.h" +#include "ace/Log_Msg.h" + +Foo_A_ClientEngine::Foo_A_ClientEngine(Foo_A_ptr obj, + unsigned client_id, + bool collocated) + : obj_(Foo_A::_duplicate(obj)), + client_id_ (client_id), + collocated_ (collocated) +{ +} + + +Foo_A_ClientEngine::~Foo_A_ClientEngine() +{ +} + + +bool +Foo_A_ClientEngine::execute(ACE_ENV_SINGLE_ARG_DECL) +{ + // Make sure the connection is established before making + // remote invocations. + if (AppHelper::validate_connection (this->obj_.in ()) == false) + { + ACE_ERROR((LM_ERROR, "(%P|%t)Foo_A_ClientEngine::execute " \ + "client %d connect failed.\n", this->client_id_)); + return false; + } + + // Verify the return values and return the results. + bool check_validity = true; + + CORBA::Long i = this->client_id_; + + this->obj_->op1(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + + this->obj_->op2(i ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + + CORBA::Long value = this->obj_->op3(i ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + + if (value != i) + { + check_validity = false; + } + + for (CORBA::Long j = 1; j <= 5; j++) + { + this->obj_->op4(495 + (i * 5) + j ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + } + + bool caught_exception = false; + + ACE_TRY + { + this->obj_->op5(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCH (FooException, ex) + { + // Expected + caught_exception = true; + } + ACE_ENDTRY; + + if (! caught_exception) + { + check_validity = false; + } + + this->obj_->done(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + + return check_validity; +} + + +void +Foo_A_ClientEngine::expected_results(Foo_A_Statistics& stats) +{ + stats.expected(1, 1); + stats.expected(2, 1); + stats.expected(3, 1); + stats.expected(4, 5); + stats.expected(5, 1); +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_A/Foo_A_ClientEngine.h b/TAO/tests/CSD_Strategy_Tests/TP_Foo_A/Foo_A_ClientEngine.h new file mode 100644 index 00000000000..4f49888f34f --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_A/Foo_A_ClientEngine.h @@ -0,0 +1,40 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file Foo_A_ClientEngine.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef FOO_A_CLIENT_ENGINE_H +#define FOO_A_CLIENT_ENGINE_H + +#include "CSD_TP_Foo_A_Export.h" +#include "ClientEngine.h" +#include "Foo_AC.h" + +class Foo_A_Statistics; + +class CSD_TP_Foo_A_Export Foo_A_ClientEngine : public ClientEngine +{ + public: + + Foo_A_ClientEngine(Foo_A_ptr obj, unsigned client_id = 0, bool collocated = false); + virtual ~Foo_A_ClientEngine(); + + virtual bool execute(ACE_ENV_SINGLE_ARG_DECL); + + static void expected_results(Foo_A_Statistics& stats); + + private: + + Foo_A_var obj_; + unsigned client_id_; + bool collocated_; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_A/Foo_A_Statistics.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Foo_A/Foo_A_Statistics.cpp new file mode 100644 index 00000000000..1ef8ce83cd7 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_A/Foo_A_Statistics.cpp @@ -0,0 +1,88 @@ +// $Id$ +#include "Foo_A_Statistics.h" +#include "Foo_A_ClientEngine.h" + +Foo_A_Statistics::Foo_A_Statistics(unsigned num_clients) +: num_clients_ (num_clients) +{ + for (unsigned i = 0; i < 5; i++) + { + this->expected_[i] = 0; + this->actual_[i] = 0; + } +} + + +Foo_A_Statistics::~Foo_A_Statistics() +{ +} + + +void +Foo_A_Statistics::expected(unsigned op_num, unsigned count) +{ + this->expected_[op_num-1] = count * this->num_clients_; +} + + +void +Foo_A_Statistics::actual(unsigned op_num, unsigned count) +{ + this->actual_[op_num-1] += count; +} + + +void +Foo_A_Statistics::actual_in_values(unsigned op_num, LongVector lv) +{ + size_t sz = lv.size(); + for (size_t i = 0; i < sz; i++) + { + this->actual_in_values_[op_num-1].push_back (lv[i]); + } +} + + +bool +Foo_A_Statistics::actual_vs_expected() +{ + Foo_A_Statistics stats (1); + Foo_A_ClientEngine::expected_results (stats); + + for (unsigned i = 0; i < 5; i++) + { + if (this->expected_[i] != this->actual_[i]) + { + return false; + } + + // Verify the "in" values. + // Skip op1/op5 since they do not have any "in" values. + if (i % 5 == 0 || i % 5 == 4) + { + continue; + } + + unsigned actual_size + = this->actual_in_values_[i].size (); + unsigned expected_size + = this->num_clients_ * stats.expected_[i]; + if (actual_size != expected_size) + { + return false; + } + sort (this->actual_in_values_[i]); + + for (unsigned j = 0; j < actual_size - 1; j++) + { + if (this->actual_in_values_[i][j] != this->actual_in_values_[i][j + 1] - 1) + { + return false; + } + } + } + return true; +} + + + diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_A/Foo_A_Statistics.h b/TAO/tests/CSD_Strategy_Tests/TP_Foo_A/Foo_A_Statistics.h new file mode 100644 index 00000000000..d5bf9ea2c71 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_A/Foo_A_Statistics.h @@ -0,0 +1,34 @@ +// $Id$ +#ifndef STATISTICS_A_H +#define STATISTICS_A_H + +#include "CSD_TP_Foo_A_Export.h" +#include "StatisticsHelper.h" + + +class CSD_TP_Foo_A_Export Foo_A_Statistics +{ + public: + + Foo_A_Statistics(unsigned num_clients); + + virtual ~Foo_A_Statistics(); + + void expected(unsigned op_num, unsigned count); + void actual(unsigned op_num, unsigned count); + void actual_in_values(unsigned op_num, LongVector lv); + + bool actual_vs_expected(); + + + private: + + unsigned num_clients_; + + unsigned expected_[5]; + unsigned actual_[5]; + + LongVector actual_in_values_ [5]; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_A/Foo_A_i.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Foo_A/Foo_A_i.cpp new file mode 100644 index 00000000000..a3bab7748aa --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_A/Foo_A_i.cpp @@ -0,0 +1,82 @@ +// $Id$ +#include "Foo_A_i.h" +#include "AppShutdown.h" + + +Foo_A_i::Foo_A_i() +{ + for (unsigned i = 0; i < 5; i++) + { + this->op_count_[i] = 0; + } +} + + +Foo_A_i::~Foo_A_i() +{ +} + + +void +Foo_A_i::op1(ACE_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + this->op_count_[0] ++; +} + + +void +Foo_A_i::op2(CORBA::Long value ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + this->in_values_[1].push_back (value); + this->op_count_[1] ++; +} + + +CORBA::Long +Foo_A_i::op3(CORBA::Long value ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + this->in_values_[2].push_back (value); + this->op_count_[2] ++; + return value; +} + + +void +Foo_A_i::op4(CORBA::Long value ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + this->in_values_[3].push_back (value); + this->op_count_[3] ++; +} + + +void +Foo_A_i::op5(ACE_ENV_SINGLE_ARG_DECL) + ACE_THROW_SPEC((CORBA::SystemException, FooException)) +{ + this->op_count_[4] ++; + ACE_THROW (FooException()); +} + + +void +Foo_A_i::done(ACE_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + TheAppShutdown->client_done(); +} + + +void +Foo_A_i::gather_stats(Foo_A_Statistics& stats) +{ + for (unsigned i = 0; i < 5; i++) + { + stats.actual (i + 1, this->op_count_[i]); + stats.actual_in_values (i + 1, this->in_values_[i]); + } +} + diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_A/Foo_A_i.h b/TAO/tests/CSD_Strategy_Tests/TP_Foo_A/Foo_A_i.h new file mode 100644 index 00000000000..094def1fb06 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_A/Foo_A_i.h @@ -0,0 +1,44 @@ +// $Id$ +#ifndef FOO_A_I_H +#define FOO_A_I_H + +#include "CSD_TP_Foo_A_Export.h" +#include "Foo_AS.h" +#include "Foo_A_Statistics.h" + + +class CSD_TP_Foo_A_Export Foo_A_i : public virtual POA_Foo_A, + public virtual PortableServer::RefCountServantBase +{ + public: + + Foo_A_i(); + virtual ~Foo_A_i(); + + virtual void op1(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void op2(CORBA::Long value ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual CORBA::Long op3(CORBA::Long value ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void op4(CORBA::Long value ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void op5(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException, FooException)); + + virtual void done(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + void gather_stats (Foo_A_Statistics& stats) ; + + private: + + LongVector in_values_ [5]; + unsigned op_count_ [5]; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_A/csd_tp_foo_a_lib.mpc b/TAO/tests/CSD_Strategy_Tests/TP_Foo_A/csd_tp_foo_a_lib.mpc new file mode 100644 index 00000000000..7f2027a9f5d --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_A/csd_tp_foo_a_lib.mpc @@ -0,0 +1,20 @@ +//$Id$ +project : csd_tp_test_lib { + sharedname = CSD_TP_Foo_A + dynamicflags = CSD_TP_FOO_A_BUILD_DLL + idlflags += -Wb,export_macro=CSD_TP_Foo_A_Export -Wb,export_include=CSD_TP_Foo_A_Export.h + includes += $(TAO_ROOT)/tao + + IDL_Files { + Foo_A.idl + } + + Source_Files { + Foo_AC.cpp + Foo_AS.cpp + Foo_A_ClientEngine.cpp + Foo_A_i.cpp + Foo_A_Statistics.cpp + } + +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/CSD_TP_Foo_B_Export.h b/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/CSD_TP_Foo_B_Export.h new file mode 100644 index 00000000000..c6e2f4cd967 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/CSD_TP_Foo_B_Export.h @@ -0,0 +1,58 @@ + +// -*- C++ -*- +// $Id$ +// Definition for Win32 Export directives. +// This file is generated automatically by generate_export_file.pl -s CSD_TP_Foo_B +// ------------------------------ +#ifndef CSD_TP_FOO_B_EXPORT_H +#define CSD_TP_FOO_B_EXPORT_H + +#include "ace/config-all.h" + +#if defined (ACE_AS_STATIC_LIBS) && !defined (CSD_TP_FOO_B_HAS_DLL) +# define CSD_TP_FOO_B_HAS_DLL 0 +#endif /* ACE_AS_STATIC_LIBS && CSD_TP_FOO_B_HAS_DLL */ + +#if !defined (CSD_TP_FOO_B_HAS_DLL) +# define CSD_TP_FOO_B_HAS_DLL 1 +#endif /* ! CSD_TP_FOO_B_HAS_DLL */ + +#if defined (CSD_TP_FOO_B_HAS_DLL) && (CSD_TP_FOO_B_HAS_DLL == 1) +# if defined (CSD_TP_FOO_B_BUILD_DLL) +# define CSD_TP_Foo_B_Export ACE_Proper_Export_Flag +# define CSD_TP_FOO_B_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T) +# define CSD_TP_FOO_B_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# else /* CSD_TP_FOO_B_BUILD_DLL */ +# define CSD_TP_Foo_B_Export ACE_Proper_Import_Flag +# define CSD_TP_FOO_B_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T) +# define CSD_TP_FOO_B_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# endif /* CSD_TP_FOO_B_BUILD_DLL */ +#else /* CSD_TP_FOO_B_HAS_DLL == 1 */ +# define CSD_TP_Foo_B_Export +# define CSD_TP_FOO_B_SINGLETON_DECLARATION(T) +# define CSD_TP_FOO_B_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +#endif /* CSD_TP_FOO_B_HAS_DLL == 1 */ + +// Set CSD_TP_FOO_B_NTRACE = 0 to turn on library specific tracing even if +// tracing is turned off for ACE. +#if !defined (CSD_TP_FOO_B_NTRACE) +# if (ACE_NTRACE == 1) +# define CSD_TP_FOO_B_NTRACE 1 +# else /* (ACE_NTRACE == 1) */ +# define CSD_TP_FOO_B_NTRACE 0 +# endif /* (ACE_NTRACE == 1) */ +#endif /* !CSD_TP_FOO_B_NTRACE */ + +#if (CSD_TP_FOO_B_NTRACE == 1) +# define CSD_TP_FOO_B_TRACE(X) +#else /* (CSD_TP_FOO_B_NTRACE == 1) */ +# if !defined (ACE_HAS_TRACE) +# define ACE_HAS_TRACE +# endif /* ACE_HAS_TRACE */ +# define CSD_TP_FOO_B_TRACE(X) ACE_TRACE_IMPL(X) +# include "ace/Trace.h" +#endif /* (CSD_TP_FOO_B_NTRACE == 1) */ + +#endif /* CSD_TP_FOO_B_EXPORT_H */ + +// End of auto generated file. diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Callback.idl b/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Callback.idl new file mode 100644 index 00000000000..49be42260cb --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Callback.idl @@ -0,0 +1,11 @@ +// $Id$ +#ifndef CALLBACK_IDL +#define CALLBACK_IDL + +interface Callback +{ + void test_method(); +}; + + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Callback_i.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Callback_i.cpp new file mode 100644 index 00000000000..d4158bf5324 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Callback_i.cpp @@ -0,0 +1,28 @@ +// $Id$ +#include "Callback_i.h" + +Callback_i::Callback_i() + : num_callbacks_(0) +{ +} + + +Callback_i::~Callback_i () +{ +} + + +void +Callback_i::test_method(ACE_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + this->num_callbacks_ ++; +} + + +void +Callback_i::gather_stats(Foo_B_Statistics& stats) +{ + stats.actual_callbacks(this->num_callbacks_.value ()); +} + diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Callback_i.h b/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Callback_i.h new file mode 100644 index 00000000000..8404d72e382 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Callback_i.h @@ -0,0 +1,32 @@ +// $Id$ +#ifndef CALLBACK_I_H +#define CALLBACK_I_H + +#include "CSD_TP_Foo_B_Export.h" +#include "CallbackS.h" +#include "Foo_B_Statistics.h" + + +class CSD_TP_Foo_B_Export Callback_i + : public virtual POA_Callback, + public virtual PortableServer::RefCountServantBase +{ + public: + + Callback_i(); + + virtual ~Callback_i(); + + virtual void test_method(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + void gather_stats(Foo_B_Statistics& stats); + + + private: + + ACE_Atomic_Op <ACE_SYNCH_MUTEX, unsigned> num_callbacks_; +}; + + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B.idl b/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B.idl new file mode 100644 index 00000000000..2b6b7382fab --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B.idl @@ -0,0 +1,70 @@ +// $Id$ +#ifndef FOO_B_IDL +#define FOO_B_IDL + +#include "FooException.idl" +#include "Callback.idl" + + +typedef sequence<char, 32> Bounded_Var_Size; +typedef sequence<char> Unbounded_Var_Size; +typedef long Fixed_Array[20]; +typedef string Var_Array [3]; + +struct TimeOfDay { + short hour; // 0 - 23 + short minute; // 0 - 59 + short second; // 0 - 59 +}; +interface Foo_B +{ + /// void return-type, no arguments + void op1(); + + /// void return-type, 1 "in" argument + void op2(in long value); + + /// long return-type, 1 "in" argument + long op3(in long value); + + /// one-way version of op2 + oneway void op4(in long value); + + /// Operation that always raises an exception. + void op5() raises (FooException); + + /// Test fixed size "in" argument and the "inout" parameter. + boolean op6(in TimeOfDay t, + inout string message); + + /// Callback test. + + /// Pass the callback object and the server invoke operation on + /// the callback object reference. + void op7 (in Callback cb) raises (FooException); + + oneway void test_unbounded_string_arg(in string message); + + oneway void test_bounded_string_arg(in string<20> message); + + oneway void test_fixed_array_arg(in Fixed_Array message); + + oneway void test_var_array_arg(in Var_Array messages); + + oneway void test_bounded_var_size_arg(in Bounded_Var_Size message); + + oneway void test_unbounded_var_size_arg(in Unbounded_Var_Size message); + + oneway void test_fixed_size_arg (in TimeOfDay t); + + oneway void test_special_basic_arg(in boolean value, in long client_id); + + oneway void test_objref_arg (in Callback cb); + + /// Client calls this last. The last client to claim that it is + /// done will cause the server to shutdown. + void done(); +}; + + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B_ClientEngine.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B_ClientEngine.cpp new file mode 100644 index 00000000000..2769f5ad9cf --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B_ClientEngine.cpp @@ -0,0 +1,206 @@ +// $Id$ +#include "Foo_B_ClientEngine.h" +#include "Callback_i.h" +#include "Foo_B_Statistics.h" +#include "TestAppExceptionC.h" +#include "AppHelper.h" +#include "ace/Log_Msg.h" +#include "ace/OS.h" + +const char* ONEWAY_ARG_TEST_STR = "TEST"; + +Foo_B_ClientEngine::Foo_B_ClientEngine(Foo_B_ptr obj, + Callback_ptr callback, + unsigned client_id, + bool collocated) + : obj_(Foo_B::_duplicate(obj)), + callback_(Callback::_duplicate(callback)), + client_id_(client_id), + collocated_(collocated) +{ +} + + +Foo_B_ClientEngine::~Foo_B_ClientEngine() +{ +} + + +bool +Foo_B_ClientEngine::execute(ACE_ENV_SINGLE_ARG_DECL) +{ + // Make sure the connection is established before making + // remote invocations. + if (AppHelper::validate_connection (this->obj_.in ()) == false) + { + ACE_ERROR((LM_ERROR, "(%P|%t)Foo_A_ClientEngine::execute " \ + "client %d connect failed.\n", this->client_id_)); + return false; + } + + // Verify the return values and return the results. + bool check_validity = true; + + this->obj_->op1(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + + this->obj_->op2(this->client_id_ ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + + CORBA::Long value = this->obj_->op3(this->client_id_ ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + + if (value != static_cast<CORBA::Long>(this->client_id_)) + { + check_validity = false; + } + + for (CORBA::ULong j = 1; j <= 5; j++) + { + this->obj_->op4(495 + (this->client_id_ * 5) + j ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + } + + bool caught_exception = false; + + ACE_TRY + { + this->obj_->op5(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCH (FooException, ex) + { + // Expected + caught_exception = true; + } + ACE_ENDTRY; + + if (! caught_exception) + { + check_validity = false; + } + + TimeOfDay t; + t.hour = 12; + t.minute = 30; + t.second = 10; + + char test_str [20]; + ACE_OS::sprintf (test_str, "%d %s", this->client_id_, ONEWAY_ARG_TEST_STR); + + char buffer [20]; + + // Two-Way calls with "inout" and fixed size "in" arguments. + CORBA::String_var message = CORBA::string_dup(test_str); + + CORBA::Boolean result = this->obj_->op6( t, message.inout() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + + ACE_UNUSED_ARG(result); + + ACE_OS::sprintf (buffer, "%d %s %d:%d:%d", this->client_id_, ONEWAY_ARG_TEST_STR, + t.hour, t.minute, t.second); + + if (ACE_OS::strncmp (message.in (), buffer, ACE_OS::strlen (buffer)) != 0) + { + check_validity = false; + } + + // Callback test. + this->obj_->op7 (this->callback_.in () ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + + // One-Way calls with various arguments. + CORBA::String_var ub_string = CORBA::string_dup( test_str ); + this->obj_->test_unbounded_string_arg (ub_string.in () ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + + CORBA::String_var bd_string = CORBA::string_dup( test_str ); + this->obj_->test_bounded_string_arg (bd_string.in () ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + + Fixed_Array fixed_array; + + for (CORBA::ULong m = 0 ; m < 20; m ++) + { + fixed_array[m] = this->client_id_ + m; + } + + this->obj_->test_fixed_array_arg (fixed_array ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + + Var_Array var_array; + + for (CORBA::ULong k = 0; k < 3; k++) + { + ACE_OS::sprintf (buffer, "%d %s %d", + this->client_id_, ONEWAY_ARG_TEST_STR, k); + var_array[k] = CORBA::string_dup(buffer); + } + + this->obj_->test_var_array_arg (var_array ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + + Bounded_Var_Size_var bd_var_size_string = new Bounded_Var_Size(); + + bd_var_size_string->replace (bd_var_size_string->maximum (), + ACE_OS::strlen (test_str) + 1, + test_str); + this->obj_->test_bounded_var_size_arg (bd_var_size_string.in () + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + + Unbounded_Var_Size_var ub_var_size_string = new Unbounded_Var_Size(100); + ub_var_size_string->replace (ub_var_size_string->maximum (), + ACE_OS::strlen (test_str) + 1, + test_str); + this->obj_->test_unbounded_var_size_arg (ub_var_size_string.in () + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + + this->obj_->test_fixed_size_arg (t ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + + this->obj_->test_special_basic_arg (this->client_id_ % 2, + this->client_id_ + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + + this->obj_->test_objref_arg (this->callback_.in () ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + + this->obj_->done(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + + return check_validity; +} + + +void +Foo_B_ClientEngine::expected_results(Foo_B_Statistics& stats) +{ + stats.expected(1, 1, Foo_B_Statistics::FOO_B_STAT_NONE); + stats.expected(2, 1, Foo_B_Statistics::FOO_B_STAT_LONG); + stats.expected(3, 1, Foo_B_Statistics::FOO_B_STAT_LONG); + stats.expected(4, 5, Foo_B_Statistics::FOO_B_STAT_LONG); + stats.expected(5, 1, Foo_B_Statistics::FOO_B_STAT_NONE); + stats.expected(6, 1, Foo_B_Statistics::FOO_B_STAT_NONE); + stats.expected(7, 1, Foo_B_Statistics::FOO_B_STAT_NONE); + stats.expected(8, 1, Foo_B_Statistics::FOO_B_STAT_STRING); + stats.expected(9, 1, Foo_B_Statistics::FOO_B_STAT_STRING); + stats.expected(10, 1, Foo_B_Statistics::FOO_B_STAT_LONG); + stats.expected(11, 1, Foo_B_Statistics::FOO_B_STAT_STRING); + stats.expected(12, 1, Foo_B_Statistics::FOO_B_STAT_STRING); + stats.expected(13, 1, Foo_B_Statistics::FOO_B_STAT_NONE); + stats.expected(14, 1, Foo_B_Statistics::FOO_B_STAT_STRING); + stats.expected(15, 1, Foo_B_Statistics::FOO_B_STAT_NONE); + stats.expected(16, 1, Foo_B_Statistics::FOO_B_STAT_NONE); + stats.expected_callbacks (1); +} + + +unsigned +Foo_B_ClientEngine::expected_callbacks () +{ + return 1; +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B_ClientEngine.h b/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B_ClientEngine.h new file mode 100644 index 00000000000..a6e8e51667b --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B_ClientEngine.h @@ -0,0 +1,47 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file Foo_B_ClientEngine.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef FOO_B_CLIENT_ENGINE_H +#define FOO_B_CLIENT_ENGINE_H + +#include "CSD_TP_Foo_B_Export.h" +#include "ClientEngine.h" +#include "Foo_BC.h" + +class Foo_B_Statistics; +class Callback_i; + +class CSD_TP_Foo_B_Export Foo_B_ClientEngine : public ClientEngine +{ + public: + + Foo_B_ClientEngine(Foo_B_ptr obj, + Callback_ptr callback, + unsigned client_id = 0, + bool collocated = false); + + virtual ~Foo_B_ClientEngine(); + + virtual bool execute(ACE_ENV_SINGLE_ARG_DECL); + + static void expected_results(Foo_B_Statistics& stats); + static unsigned expected_callbacks (); + + private: + + Foo_B_var obj_; + Callback_var callback_; + unsigned client_id_; + bool collocated_; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B_SimpleClientEngine.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B_SimpleClientEngine.cpp new file mode 100644 index 00000000000..ec2d97c6bdf --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B_SimpleClientEngine.cpp @@ -0,0 +1,83 @@ +// $Id$ +#include "Foo_B_SimpleClientEngine.h" +#include "Callback_i.h" +#include "Foo_B_Statistics.h" +#include "TestAppExceptionC.h" +#include "AppHelper.h" +#include "ace/Log_Msg.h" +#include "ace/OS.h" + +extern const char* ONEWAY_ARG_TEST_STR; + +Foo_B_SimpleClientEngine::Foo_B_SimpleClientEngine(Foo_B_ptr obj, + Callback_ptr callback, + unsigned client_id, + bool collocated) + : obj_(Foo_B::_duplicate(obj)), + callback_(Callback::_duplicate(callback)), + client_id_(client_id), + collocated_(collocated) +{ +} + + +Foo_B_SimpleClientEngine::~Foo_B_SimpleClientEngine() +{ +} + + +bool +Foo_B_SimpleClientEngine::execute(ACE_ENV_SINGLE_ARG_DECL) +{ + // Make sure the connection is established before making + // remote invocations. + if (AppHelper::validate_connection (this->obj_.in ()) == false) + { + ACE_ERROR((LM_ERROR, "(%P|%t)Foo_A_SimpleClientEngine::execute " \ + "client %d connect failed.\n", this->client_id_)); + return false; + } + + // Verify the return values and return the results. + bool check_validity = true; + + // Callback test. + ACE_TRY + { + if (CORBA::is_nil(this->callback_.in())) + { + ACE_ERROR((LM_ERROR, "(%P|%t)Foo_A_SimpleClientEngine::execute " \ + "The callback_ objref is nil before op7() call!\n")); + } + + this->obj_->op7 (this->callback_.in () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCH (FooException, ex) + { + ACE_ERROR((LM_ERROR, "(%P|%t)Foo_A_SimpleClientEngine::execute " \ + "FooException raised by op7() call.\n")); + check_validity = false; + } + ACE_ENDTRY; + + // Tell the servant that this client is done. + this->obj_->done(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + + return check_validity; +} + + +void +Foo_B_SimpleClientEngine::expected_results(Foo_B_Statistics& stats) +{ + stats.expected(7, 1, Foo_B_Statistics::FOO_B_STAT_NONE); +} + + +unsigned +Foo_B_SimpleClientEngine::expected_callbacks () +{ + return 1; +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B_SimpleClientEngine.h b/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B_SimpleClientEngine.h new file mode 100644 index 00000000000..38ef6a09bcf --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B_SimpleClientEngine.h @@ -0,0 +1,47 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file Foo_B_SimpleClientEngine.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef FOO_B_SIMPLE_CLIENT_ENGINE_H +#define FOO_B_SIMPLE_CLIENT_ENGINE_H + +#include "CSD_TP_Foo_B_Export.h" +#include "ClientEngine.h" +#include "Foo_BC.h" + +class Foo_B_Statistics; +class Callback_i; + +class CSD_TP_Foo_B_Export Foo_B_SimpleClientEngine : public ClientEngine +{ + public: + + Foo_B_SimpleClientEngine(Foo_B_ptr obj, + Callback_ptr callback, + unsigned client_id = 0, + bool collocated = false); + + virtual ~Foo_B_SimpleClientEngine(); + + virtual bool execute(ACE_ENV_SINGLE_ARG_DECL); + + static void expected_results(Foo_B_Statistics& stats); + static unsigned expected_callbacks (); + + private: + + Foo_B_var obj_; + Callback_var callback_; + unsigned client_id_; + bool collocated_; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B_Statistics.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B_Statistics.cpp new file mode 100644 index 00000000000..d282c058b8e --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B_Statistics.cpp @@ -0,0 +1,187 @@ +// $Id$ +#include "Foo_B_Statistics.h" +#include "Foo_B_ClientEngine.h" + +extern const char* ONEWAY_ARG_TEST_STR; +extern CORBA::Boolean special_value; + +Foo_B_Statistics::Foo_B_Statistics(unsigned num_remote_clients, + unsigned num_collcated_clients) +: num_clients_ (num_remote_clients + num_collcated_clients), + num_collcated_clients_ (num_collcated_clients), + expected_callbacks_ (0), + actual_callbacks_ (0), + servant_error_count_ (0) +{ + for (unsigned i = 0; i < 16; i++) + { + this->expected_op_count_[i] = 0; + this->actual_op_count_[i] = 0; + } +} + + +Foo_B_Statistics::~Foo_B_Statistics() +{ +} + + +void +Foo_B_Statistics::expected(unsigned op_num, unsigned count, In_Value_Type type) +{ + this->expected_op_count_[op_num-1] = count * this->num_clients_; + this->expected_in_value_type_[op_num-1] = type; +} + + +void +Foo_B_Statistics::actual(unsigned op_num, unsigned count) +{ + this->actual_op_count_[op_num-1] += count; +} + + +void +Foo_B_Statistics::actual(unsigned op_num, LongVector lv) +{ + unsigned sz = lv.size(); + for (unsigned i = 0; i < sz; i++) + { + this->actual_in_long_[op_num-1].push_back (lv[i]); + } +} + + +void +Foo_B_Statistics::actual(unsigned op_num, StringVector sv) +{ + unsigned sz = sv.size(); + for (unsigned i = 0; i < sz; i++) + { + this->actual_in_string_[op_num-1].push_back (sv[i]); + } +} + + +void +Foo_B_Statistics::expected_callbacks (unsigned num_cbs) +{ + expected_callbacks_ = num_cbs * this->num_collcated_clients_; +} + + +void +Foo_B_Statistics::actual_callbacks (unsigned num_cbs) +{ + actual_callbacks_ += num_cbs; +} + + +void +Foo_B_Statistics::servant_error_count (unsigned error_count) +{ + this->servant_error_count_ += error_count; +} + + +bool +Foo_B_Statistics::actual_vs_expected() +{ + // Verify the checking results in servant operation code. + if (this->servant_error_count_ > 0) + { + return false; + } + + // Verify the number of callbacks received for the collocated + // client. + if (actual_callbacks_ != expected_callbacks_) + { + return false; + } + + // Verify the number of operations server received. + for (unsigned int z = 0; z < 16; z++) + { + if (this->expected_op_count_[z] != this->actual_op_count_[z]) + { + return false; + } + } + + Foo_B_Statistics stats (1, 0); + Foo_B_ClientEngine::expected_results (stats); + + for (unsigned i = 0; i < 16; i++) + { + switch (expected_in_value_type_[i]) + { + case FOO_B_STAT_LONG: + { + unsigned actual_size + = this->actual_in_long_[i].size (); + unsigned expected_size + = this->num_clients_ * stats.expected_op_count_[i]; + if (actual_size != expected_size) + { + return false; + } + sort (this->actual_in_long_[i]); + + for (unsigned j = 0; j < actual_size - 1; j++) + { + if (this->actual_in_long_[i][j] != this->actual_in_long_[i][j + 1] - 1) + { + return false; + } + } + } + break; + + case FOO_B_STAT_STRING: + { + unsigned actual_size + = this->actual_in_string_[i].size (); + unsigned expected_size + = this->num_clients_ * stats.expected_op_count_[i]; + if (actual_size != expected_size) + { + return false; + } + + LongVector lvec; + char buffer[50]; + + for (unsigned k = 0; k < actual_size; k++) + { + unsigned client_id; + sscanf (this->actual_in_string_[i][k].c_str(), "%d %s", &client_id, buffer); + if (ACE_OS::strcmp (buffer, ONEWAY_ARG_TEST_STR) != 0) + { + return false; + } + lvec.push_back (client_id); + } + + sort (lvec); + + for (unsigned j = 0; j < actual_size - 1; j++) + { + if (lvec[j] != lvec[j + 1] - 1) + { + return false; + } + } + } + break; + + case FOO_B_STAT_NONE: + default: + break; + } + + } + + return true; +} + diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B_Statistics.h b/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B_Statistics.h new file mode 100644 index 00000000000..cf21382c549 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B_Statistics.h @@ -0,0 +1,54 @@ +// $Id$ +#ifndef STATISTICS_B_H +#define STATISTICS_B_H + +#include "CSD_TP_Foo_B_Export.h" +#include "StatisticsHelper.h" + + +class CSD_TP_Foo_B_Export Foo_B_Statistics +{ + public: + + enum In_Value_Type + { + FOO_B_STAT_NONE, + FOO_B_STAT_STRING, + FOO_B_STAT_LONG + }; + + Foo_B_Statistics(unsigned num_remote_clients, + unsigned num_collcated_clients); + + virtual ~Foo_B_Statistics(); + + void expected(unsigned op_num, unsigned count, In_Value_Type type); + void actual(unsigned op_num, unsigned count); + void actual(unsigned op_num, LongVector lv); + void actual(unsigned op_num, StringVector sv); + void servant_error_count(unsigned error_count); + + void expected_callbacks (unsigned num_cbs); + void actual_callbacks (unsigned num_cbs); + + bool actual_vs_expected(); + +private: + + unsigned num_clients_; + unsigned num_collcated_clients_; + + LongVector actual_in_long_ [16]; + StringVector actual_in_string_ [16]; + + unsigned expected_op_count_[16]; + unsigned actual_op_count_[16]; + unsigned expected_in_value_type_[16]; + + unsigned expected_callbacks_; + unsigned actual_callbacks_; + + unsigned servant_error_count_; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B_i.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B_i.cpp new file mode 100644 index 00000000000..73105ff1713 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B_i.cpp @@ -0,0 +1,283 @@ +// $Id$ +#include "Foo_B_i.h" +#include "AppShutdown.h" +#include "TestAppExceptionC.h" +#include "ace/OS.h" +#include "ace/SString.h" + + +Foo_B_i::Foo_B_i() +: error_count_ (0) +{ + for (unsigned i = 0; i < 16; i++) + { + op_count_[i] = 0; + } +} + + +Foo_B_i::~Foo_B_i() +{ +} + + +void +Foo_B_i::op1(ACE_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + this->op_count_[0] ++; +} + + +void +Foo_B_i::op2(CORBA::Long value ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + this->op_count_[1] ++; + this->in_long_[1].push_back (value); +} + + +CORBA::Long +Foo_B_i::op3(CORBA::Long value ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + this->op_count_[2] ++; + this->in_long_[2].push_back (value); + return value; +} + + +void +Foo_B_i::op4(CORBA::Long value ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + this->op_count_[3] ++; + this->in_long_[3].push_back (value); +} + + +void +Foo_B_i::op5(ACE_ENV_SINGLE_ARG_DECL) + ACE_THROW_SPEC((CORBA::SystemException, FooException)) +{ + this->op_count_[4] ++; + ACE_THROW (FooException()); +} + + +CORBA::Boolean +Foo_B_i::op6(const TimeOfDay& t, + char*& message + ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + this->op_count_[5] ++; + char buf [20]; + ACE_OS::sprintf (buf, "%s %d:%d:%d", message, t.hour, t.minute, t.second); + message = CORBA::string_dup (buf); + + return 1; +} + + +void +Foo_B_i::op7(Callback_ptr cb + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC((CORBA::SystemException, + FooException)) +{ + this->op_count_[6] ++; + + if (CORBA::is_nil (cb)) + { + error_count_ ++; + ACE_THROW (FooException ()); + } + else + { + cb->test_method (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + } +} + + +void +Foo_B_i::test_unbounded_string_arg(const char* message + ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + this->op_count_[7] ++; + //ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_B_i::test_unbounded_string_arg ") + // ACE_TEXT("got unbounded string %s\n"), + // message)); + this->in_string_[7].push_back (message); +} + + +void +Foo_B_i::test_bounded_string_arg(const char* message + ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + this->op_count_[8] ++; + //ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_B_i::test_bounded_string_arg ") + // ACE_TEXT("got bounded string %s\n"), + // message)); + this->in_string_[8].push_back (message); +} + + +void +Foo_B_i::test_fixed_array_arg(const Fixed_Array message + ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + this->op_count_[9] ++; + + for (unsigned i = 0; i < 19; i++) + { + //ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_B_i::test_fixed_array_arg ") + // ACE_TEXT("got fixed array[i] = %d\n"), + // i, message[i])); + + if (message[i] != message[i + 1] -1) + { + error_count_ ++; + break; + } + } + + + this->in_long_[9].push_back (message[0]); +} + + +void +Foo_B_i::test_bounded_var_size_arg(const Bounded_Var_Size& message + ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + this->op_count_[10] ++; + //ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_B_i::test_bounded_var_size_arg ") + // ACE_TEXT("got var array chars %s\n"), + // message.get_buffer ())); + this->in_string_[10].push_back (message.get_buffer ()); +} + + +void +Foo_B_i::test_unbounded_var_size_arg(const Unbounded_Var_Size& message + ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + this->op_count_[11] ++; + //ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_B_i::test_unbounded_var_size_arg ") + // ACE_TEXT("got var array chars %s\n"), + // message.get_buffer ())); + this->in_string_[11].push_back (message.get_buffer ()); +} + + +void +Foo_B_i::test_fixed_size_arg(const TimeOfDay& t + ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + ACE_UNUSED_ARG(t); + + this->op_count_[12] ++; + //ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_B_i::test_fixed_size_arg ") + // ACE_TEXT("got timeofday %d:%d:%d\n"), + // t.hour, t.minute, t.second)); +} + + +void +Foo_B_i::test_var_array_arg(const Var_Array messages + ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + this->op_count_[13] ++; + //ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_B_i::test_var_array_arg ") + // ACE_TEXT(" %s \n"), messages[0].in ())); + //ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_B_i::test_var_array_arg ") + // ACE_TEXT(" %s \n"), messages[1].in ())); + //ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_B_i::test_var_array_arg ") + // ACE_TEXT(" %s \n"), messages[2].in ())); + unsigned cur_client_id = 0; + + for (unsigned i = 0 ; i < 3; i ++) + { + unsigned client_id = 0; + unsigned str_id = 0; + char test_str[20]; + sscanf (messages[i].in (), "%d %s %d", &client_id, test_str, &str_id); + + if (str_id != i) + { + error_count_ ++; + } + + if (i == 0) + { + cur_client_id = client_id; + } + else if (client_id != cur_client_id) + { + error_count_ ++; + } + } + this->in_string_[13].push_back (messages[0].in ()); +} + + +void +Foo_B_i::test_special_basic_arg(CORBA::Boolean value, + CORBA::Long client_id + ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + this->op_count_[14] ++; + //ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_B_i::test_special_basic_arg ") + // ACE_TEXT(" got special basic arg: %d \n"), value)); + + CORBA::Boolean expected_special_value = client_id % 2; + if (expected_special_value != value) + { + error_count_ ++; + } +} + + +void +Foo_B_i::test_objref_arg(Callback_ptr cb + ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + ACE_UNUSED_ARG(cb); + this->op_count_[15] ++; + //ACE_DEBUG((LM_DEBUG, ACE_TEXT("(%P|%t)Foo_B_i::test_objref_arg ") + // ACE_TEXT(" got callback object. \n"))); +} + + +void +Foo_B_i::done(ACE_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + TheAppShutdown->client_done(); +} + + +void +Foo_B_i::gather_stats (Foo_B_Statistics& stats) +{ + for (unsigned i = 0; i < 16; i++) + { + stats.actual (i+1, this->op_count_[i]); + stats.actual (i+1, this->in_string_[i]); + stats.actual (i+1, this->in_long_[i]); + stats.servant_error_count (this->error_count_); + } +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B_i.h b/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B_i.h new file mode 100644 index 00000000000..c6838db5776 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/Foo_B_i.h @@ -0,0 +1,93 @@ +// $Id$ +#ifndef FOO_B_I_H +#define FOO_B_I_H + +#include "CSD_TP_Foo_B_Export.h" +#include "Foo_BS.h" +#include "Foo_B_Statistics.h" + + +class CSD_TP_Foo_B_Export Foo_B_i : public virtual POA_Foo_B, + public virtual PortableServer::RefCountServantBase +{ + public: + + Foo_B_i(); + virtual ~Foo_B_i(); + + virtual void op1(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void op2(CORBA::Long value ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual CORBA::Long op3(CORBA::Long value ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void op4(CORBA::Long value ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void op5(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException, FooException)); + + virtual CORBA::Boolean op6(const TimeOfDay& t, + char*& message + ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void op7(Callback_ptr cb + ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException, + FooException)); + + virtual void test_unbounded_string_arg(const char* message + ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void test_bounded_string_arg(const char* message + ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void test_fixed_array_arg(const Fixed_Array message + ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void test_var_array_arg(const Var_Array messages + ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void test_bounded_var_size_arg(const Bounded_Var_Size& message + ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void test_unbounded_var_size_arg(const Unbounded_Var_Size& message + ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void test_fixed_size_arg(const TimeOfDay& t + ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void test_special_basic_arg(CORBA::Boolean value, + CORBA::Long client_id + ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void test_objref_arg(Callback_ptr cb + ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void done(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + void gather_stats (Foo_B_Statistics& stats); + + private: + + LongVector in_long_ [16]; + StringVector in_string_ [16]; + unsigned op_count_ [16]; + unsigned error_count_; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/csd_tp_foo_b_lib.mpc b/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/csd_tp_foo_b_lib.mpc new file mode 100644 index 00000000000..a9503d73c5a --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_B/csd_tp_foo_b_lib.mpc @@ -0,0 +1,25 @@ +//$Id$ +project : csd_tp_test_lib { + sharedname = CSD_TP_Foo_B + dynamicflags = CSD_TP_FOO_B_BUILD_DLL + idlflags += -Wb,export_macro=CSD_TP_Foo_B_Export -Wb,export_include=CSD_TP_Foo_B_Export.h + includes += $(TAO_ROOT)/tao + + IDL_Files { + Foo_B.idl + Callback.idl + } + + Source_Files { + Foo_BC.cpp + Foo_BS.cpp + Foo_B_ClientEngine.cpp + Foo_B_SimpleClientEngine.cpp + Foo_B_i.cpp + Foo_B_Statistics.cpp + Callback_i.cpp + CallbackC.cpp + CallbackS.cpp + } + +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/CSD_TP_Foo_C_Export.h b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/CSD_TP_Foo_C_Export.h new file mode 100644 index 00000000000..ef1996b0a26 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/CSD_TP_Foo_C_Export.h @@ -0,0 +1,58 @@ + +// -*- C++ -*- +// $Id$ +// Definition for Win32 Export directives. +// This file is generated automatically by generate_export_file.pl -s CSD_TP_Foo_C +// ------------------------------ +#ifndef CSD_TP_FOO_C_EXPORT_H +#define CSD_TP_FOO_C_EXPORT_H + +#include "ace/config-all.h" + +#if defined (ACE_AS_STATIC_LIBS) && !defined (CSD_TP_FOO_C_HAS_DLL) +# define CSD_TP_FOO_C_HAS_DLL 0 +#endif /* ACE_AS_STATIC_LIBS && CSD_TP_FOO_C_HAS_DLL */ + +#if !defined (CSD_TP_FOO_C_HAS_DLL) +# define CSD_TP_FOO_C_HAS_DLL 1 +#endif /* ! CSD_TP_FOO_C_HAS_DLL */ + +#if defined (CSD_TP_FOO_C_HAS_DLL) && (CSD_TP_FOO_C_HAS_DLL == 1) +# if defined (CSD_TP_FOO_C_BUILD_DLL) +# define CSD_TP_Foo_C_Export ACE_Proper_Export_Flag +# define CSD_TP_FOO_C_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T) +# define CSD_TP_FOO_C_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# else /* CSD_TP_FOO_C_BUILD_DLL */ +# define CSD_TP_Foo_C_Export ACE_Proper_Import_Flag +# define CSD_TP_FOO_C_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T) +# define CSD_TP_FOO_C_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# endif /* CSD_TP_FOO_C_BUILD_DLL */ +#else /* CSD_TP_FOO_C_HAS_DLL == 1 */ +# define CSD_TP_Foo_C_Export +# define CSD_TP_FOO_C_SINGLETON_DECLARATION(T) +# define CSD_TP_FOO_C_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +#endif /* CSD_TP_FOO_C_HAS_DLL == 1 */ + +// Set CSD_TP_FOO_C_NTRACE = 0 to turn on library specific tracing even if +// tracing is turned off for ACE. +#if !defined (CSD_TP_FOO_C_NTRACE) +# if (ACE_NTRACE == 1) +# define CSD_TP_FOO_C_NTRACE 1 +# else /* (ACE_NTRACE == 1) */ +# define CSD_TP_FOO_C_NTRACE 0 +# endif /* (ACE_NTRACE == 1) */ +#endif /* !CSD_TP_FOO_C_NTRACE */ + +#if (CSD_TP_FOO_C_NTRACE == 1) +# define CSD_TP_FOO_C_TRACE(X) +#else /* (CSD_TP_FOO_C_NTRACE == 1) */ +# if !defined (ACE_HAS_TRACE) +# define ACE_HAS_TRACE +# endif /* ACE_HAS_TRACE */ +# define CSD_TP_FOO_C_TRACE(X) ACE_TRACE_IMPL(X) +# include "ace/Trace.h" +#endif /* (CSD_TP_FOO_C_NTRACE == 1) */ + +#endif /* CSD_TP_FOO_C_EXPORT_H */ + +// End of auto generated file. diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C.idl b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C.idl new file mode 100644 index 00000000000..b7eeea96f33 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C.idl @@ -0,0 +1,29 @@ +// $Id$ +#ifndef FOO_C_IDL +#define FOO_C_IDL + +#include "FooException.idl" + +interface Foo_C +{ + /// void return-type, no arguments + void op1(); + + /// void return-type, 1 "in" argument + void op2(in long value); + + /// long return-type, 1 "in" argument + long op3(in long value); + + /// one-way version of op2 + oneway void op4(in long value); + + /// Operation that always raises an exception. + void op5() raises (FooException); + + /// Client calls this last. The last client to claim that it is + /// done will cause the server to shutdown. + void done(); +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_ClientEngine.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_ClientEngine.cpp new file mode 100644 index 00000000000..fdd8b4e2671 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_ClientEngine.cpp @@ -0,0 +1,92 @@ +// $Id$ +#include "Foo_C_ClientEngine.h" +#include "AppHelper.h" +#include "ace/Log_Msg.h" + + +Foo_C_ClientEngine::Foo_C_ClientEngine(Foo_C_ptr obj, + unsigned client_id) + : obj_(Foo_C::_duplicate(obj)), + client_id_ (client_id) +{ +} + + +Foo_C_ClientEngine::~Foo_C_ClientEngine() +{ +} + + +bool +Foo_C_ClientEngine::execute(ACE_ENV_SINGLE_ARG_DECL) +{ + // Verify the return values and return the results. + bool check_validity = true; + + // Make sure the connection is established before making + // remote invocations. + if (AppHelper::validate_connection (this->obj_.in ()) == false) + { + ACE_ERROR((LM_ERROR, "(%P|%t)Foo_A_ClientEngine::execute " \ + "client %d connect failed.\n", this->client_id_)); + return false; + } + + CORBA::Long i = this->client_id_; + + this->obj_->op1(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + + this->obj_->op2(i ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + + CORBA::Long value = this->obj_->op3(i ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + + if (value != i) + { + check_validity = false; + } + + for (CORBA::Long j = 1; j <= 5; j++) + { + this->obj_->op4(495 + (i * 5) + j ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + } + + bool caught_exception = false; + + ACE_TRY + { + this->obj_->op5(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCH (FooException, ex) + { + // Expected + caught_exception = true; + } + ACE_ENDTRY; + + if (! caught_exception) + { + check_validity = false; + } + + this->obj_->done(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + + return check_validity; +} + + +void +Foo_C_ClientEngine::expected_results(Foo_C_Statistics& stats) +{ + // This ClientEngine is used by remote clients. + stats.expected(1, 1, true); + stats.expected(2, 1, true); + stats.expected(3, 1, true); + stats.expected(4, 5, true); + stats.expected(5, 1, true); +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_ClientEngine.h b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_ClientEngine.h new file mode 100644 index 00000000000..54247223f04 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_ClientEngine.h @@ -0,0 +1,40 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file Foo_C_ClientEngine.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef FOO_C_CLIENT_ENGINE_H +#define FOO_C_CLIENT_ENGINE_H + +#include "CSD_TP_Foo_C_Export.h" +#include "ClientEngine.h" +#include "Foo_CC.h" +#include "Foo_C_Statistics.h" + + +class CSD_TP_Foo_C_Export Foo_C_ClientEngine : public ClientEngine +{ + public: + + Foo_C_ClientEngine(Foo_C_ptr obj, + unsigned client_id); + virtual ~Foo_C_ClientEngine(); + + virtual bool execute(ACE_ENV_SINGLE_ARG_DECL); + + static void expected_results(Foo_C_Statistics& stats); + + private: + + Foo_C_var obj_; + unsigned client_id_; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_Custom_ClientEngine.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_Custom_ClientEngine.cpp new file mode 100644 index 00000000000..da6b44f7c71 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_Custom_ClientEngine.cpp @@ -0,0 +1,136 @@ +// $Id$ +#include "Foo_C_Custom_ClientEngine.h" +#include "CustomExceptionC.h" +#include "ace/Log_Msg.h" + + +Foo_C_Custom_ClientEngine::Foo_C_Custom_ClientEngine + (Foo_C_i* servant, + Foo_C_ptr objref, + TAO::CSD::TP_Strategy* strategy, + unsigned client_id) + : proxy_(servant,objref,strategy), + client_id_(client_id) +{ +} + + +Foo_C_Custom_ClientEngine::~Foo_C_Custom_ClientEngine() +{ +} + + +bool +Foo_C_Custom_ClientEngine::execute(ACE_ENV_SINGLE_ARG_DECL) +{ + // Make sure the connection is established before making + // remote invocations. + if (this->proxy_.validate_connection () == false) + { + ACE_ERROR((LM_ERROR, "(%P|%t)Foo_A_ClientEngine::execute " \ + "client %d connect failed.\n", this->client_id_)); + return false; + } + + bool check_validity = true; + CORBA::Long i = this->client_id_; + + this->proxy_.op1(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + this->proxy_.op2(i ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + CORBA::Long value = this->proxy_.op3(i ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + + if (value != i) + { + check_validity = false; + } + + + for (CORBA::Long j = 1; j <= 5; j++) + { + this->proxy_.op4(495 + (i * 5) + j ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + } + + bool caught_exception = false; + ACE_TRY_EX (op5) + { + this->proxy_.op5(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK_EX (op5); + } + ACE_CATCH (FooException, ex) + { + // Expected + caught_exception = true; + } + ACE_ENDTRY; + + if (! caught_exception) + { + check_validity = false; + } + + long cust_i = this->client_id_; + + this->proxy_.cust_op1(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + this->proxy_.cust_op2(cust_i ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + long cust_value = this->proxy_.cust_op3(cust_i ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + + if (cust_value != i) + { + check_validity = false; + } + + for (long cust_j = 1; cust_j <= 5; cust_j++) + { + this->proxy_.cust_op4(495 + (cust_i * 5) + cust_j ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + } + + caught_exception = false; + + ACE_TRY_EX (cust_op5) + { + this->proxy_.cust_op5(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK_EX (cust_op5) + } + ACE_CATCHANY //(CustomException, ex) + { + // Expected + caught_exception = true; + } + ACE_ENDTRY; + + if (! caught_exception) + { + check_validity = false; + } + + this->proxy_.done(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (false); + + return check_validity; +} + + +void +Foo_C_Custom_ClientEngine::expected_results(Foo_C_Statistics& stats) +{ + // This ClientEngine is used by collocated clients. + stats.expected(1, 1, false); + stats.expected(2, 1, false); + stats.expected(3, 1, false); + stats.expected(4, 5, false); + stats.expected(5, 1, false); + stats.expected(6, 1, false); + stats.expected(7, 1, false); + stats.expected(8, 1, false); + stats.expected(9, 5, false); + stats.expected(10, 1, false); +} + diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_Custom_ClientEngine.h b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_Custom_ClientEngine.h new file mode 100644 index 00000000000..d797927c042 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_Custom_ClientEngine.h @@ -0,0 +1,42 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file Foo_C_ClientEngine.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef FOO_C_CUSTOM_CLIENT_ENGINE_H +#define FOO_C_CUSTOM_CLIENT_ENGINE_H + +#include "CSD_TP_Foo_C_Export.h" +#include "ClientEngine.h" +#include "Foo_C_Custom_Proxy.h" + + +class CSD_TP_Foo_C_Export Foo_C_Custom_ClientEngine : public ClientEngine +{ + public: + + Foo_C_Custom_ClientEngine(Foo_C_i* servant, + Foo_C_ptr objref, + TAO::CSD::TP_Strategy* strategy, + unsigned client_id); + virtual ~Foo_C_Custom_ClientEngine(); + + virtual bool execute(ACE_ENV_SINGLE_ARG_DECL); + + static void expected_results(Foo_C_Statistics& stats); + + + private: + + Foo_C_Custom_Proxy proxy_; + unsigned client_id_; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_Custom_Proxy.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_Custom_Proxy.cpp new file mode 100644 index 00000000000..0fc2e22471a --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_Custom_Proxy.cpp @@ -0,0 +1,153 @@ +// $Id$ +#include "Foo_C_Custom_Proxy.h" +#include "Foo_C_cust_op1.h" +#include "Foo_C_cust_op2.h" +#include "Foo_C_cust_op3.h" +#include "Foo_C_cust_op4.h" +#include "Foo_C_cust_op5.h" +#include "AppHelper.h" + + +Foo_C_Custom_Proxy::Foo_C_Custom_Proxy(Foo_C_i* servant, + Foo_C_ptr objref, + TAO::CSD::TP_Strategy* strategy) + : servant_(servant), + objref_(Foo_C::_duplicate(objref)), + strategy_(strategy, false) +{ + // This try-catch block is not really necessary, but we have to add it to + // satisfy the non-exception builds. Since there is actually no exception + // raised from _add_ref, we just ignore the exception here. + ACE_TRY_NEW_ENV + { + servant_->_add_ref (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHALL + { + } + ACE_ENDTRY; +} + + +Foo_C_Custom_Proxy::~Foo_C_Custom_Proxy() +{ + // This try-catch block is not really necessary, but we have to add it to + // satisfy the non-exception builds. Since there is actually no exception + // raised from _add_ref, we just ignore the exception here. + ACE_TRY_NEW_ENV + { + servant_->_remove_ref (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHALL + { + } + ACE_ENDTRY; +} + + +bool +Foo_C_Custom_Proxy::validate_connection () +{ + return AppHelper::validate_connection (this->objref_.in ()); +} + + +void +Foo_C_Custom_Proxy::op1(ACE_ENV_SINGLE_ARG_DECL) +{ + this->objref_->op1(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; +} + + +void +Foo_C_Custom_Proxy::op2(CORBA::Long x ACE_ENV_ARG_DECL) +{ + this->objref_->op2(x ACE_ENV_ARG_PARAMETER); + ACE_CHECK; +} + + +CORBA::Long +Foo_C_Custom_Proxy::op3(CORBA::Long x ACE_ENV_ARG_DECL) +{ + CORBA::Long result = this->objref_->op3(x ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (0); + return result; +} + + +void +Foo_C_Custom_Proxy::op4(CORBA::Long x ACE_ENV_ARG_DECL) +{ + this->objref_->op4(x ACE_ENV_ARG_PARAMETER); + ACE_CHECK; +} + + +void +Foo_C_Custom_Proxy::op5(ACE_ENV_SINGLE_ARG_DECL) +{ + this->objref_->op5(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; +} + + +void +Foo_C_Custom_Proxy::done(ACE_ENV_SINGLE_ARG_DECL) +{ + this->objref_->done(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; +} + + +void +Foo_C_Custom_Proxy::cust_op1(ACE_ENV_SINGLE_ARG_DECL) +{ + Foo_C_cust_op1_Handle op = new Foo_C_cust_op1(this->servant_); + this->strategy_->custom_synch_request(op.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK; +} + + +void +Foo_C_Custom_Proxy::cust_op2(long x ACE_ENV_ARG_DECL) +{ + Foo_C_cust_op2_Handle op = new Foo_C_cust_op2(this->servant_, x); + this->strategy_->custom_synch_request(op.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK; +} + + +long +Foo_C_Custom_Proxy::cust_op3(long x ACE_ENV_ARG_DECL) +{ + Foo_C_cust_op3_Handle op = new Foo_C_cust_op3(this->servant_, x); + this->strategy_->custom_synch_request(op.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (0); + int ret = op->result(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (0); + return ret; +} + + +void +Foo_C_Custom_Proxy::cust_op4(long x ACE_ENV_ARG_DECL) +{ + Foo_C_cust_op4_Handle op = new Foo_C_cust_op4(this->servant_,x); + this->strategy_->custom_asynch_request(op.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK; +} + + +void +Foo_C_Custom_Proxy::cust_op5(ACE_ENV_SINGLE_ARG_DECL) +{ + Foo_C_cust_op5_Handle op = new Foo_C_cust_op5(this->servant_); + this->strategy_->custom_synch_request(op.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + op->result(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_Custom_Proxy.h b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_Custom_Proxy.h new file mode 100644 index 00000000000..5cd7eeae55a --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_Custom_Proxy.h @@ -0,0 +1,52 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file Foo_C_Custom_Proxy.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef FOO_C_CUSTOM_PROXY_H +#define FOO_C_CUSTOM_PROXY_H + +#include "CSD_TP_Foo_C_Export.h" +#include "ClientEngine.h" +#include "Foo_C_i.h" +#include "tao/CSD_ThreadPool/CSD_TP_Strategy.h" + + +class CSD_TP_Foo_C_Export Foo_C_Custom_Proxy +{ +public: + + Foo_C_Custom_Proxy(Foo_C_i* servant, + Foo_C_ptr objref, + TAO::CSD::TP_Strategy* strategy); + ~Foo_C_Custom_Proxy(); + + bool validate_connection (); + + void op1(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS); + void op2(CORBA::Long x ACE_ENV_ARG_DECL_WITH_DEFAULTS); + CORBA::Long op3(CORBA::Long x ACE_ENV_ARG_DECL_WITH_DEFAULTS); + void op4(CORBA::Long x ACE_ENV_ARG_DECL_WITH_DEFAULTS); + void op5(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS); + void done(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS); + + void cust_op1(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS); + void cust_op2(long x ACE_ENV_ARG_DECL_WITH_DEFAULTS); + long cust_op3(long x ACE_ENV_ARG_DECL_WITH_DEFAULTS); + void cust_op4(long x ACE_ENV_ARG_DECL_WITH_DEFAULTS); + void cust_op5(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS); + +private: + Foo_C_i* servant_; + Foo_C_var objref_; + TAO::CSD::TP_Strategy_Handle strategy_; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_Statistics.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_Statistics.cpp new file mode 100644 index 00000000000..b832e29d9a1 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_Statistics.cpp @@ -0,0 +1,111 @@ +// $Id$ +#include "Foo_C_Statistics.h" +#include "Foo_C_ClientEngine.h" +#include "Foo_C_Custom_ClientEngine.h" + +Foo_C_Statistics::Foo_C_Statistics(unsigned num_remote_clients, + unsigned num_collocated_clients) +: num_remote_clients_ (num_remote_clients), + num_collocated_clients_ (num_collocated_clients) +{ + for (unsigned i = 0; i < 10; i++) + { + this->expected_[i] = 0; + this->actual_[i] = 0; + } +} + + +Foo_C_Statistics::~Foo_C_Statistics() +{ +} + + +void +Foo_C_Statistics::expected(unsigned op_num, unsigned count, bool remote_client) +{ + if (remote_client) + { + this->expected_[op_num-1] += count * this->num_remote_clients_; + } + else + { + this->expected_[op_num-1] += count * this->num_collocated_clients_; + } +} + + +void +Foo_C_Statistics::actual(unsigned op_num, unsigned count) +{ + this->actual_[op_num-1] += count; +} + + +void +Foo_C_Statistics::actual_in_values(unsigned op_num, LongVector lv) +{ + size_t sz = lv.size(); + for (size_t i = 0; i < sz; i++) + { + this->actual_in_values_[op_num-1].push_back (lv[i]); + } +} + + +bool +Foo_C_Statistics::actual_vs_expected() +{ + // Get the expected statistics for a single remote client. + Foo_C_Statistics remote_client_stats (1, 0); + Foo_C_ClientEngine::expected_results (remote_client_stats); + // Get the expected statistics for a single collocated client. + Foo_C_Statistics collocated_client_stats (0, 1); + Foo_C_Custom_ClientEngine::expected_results (collocated_client_stats); + + for (unsigned i = 0; i < 10; i++) + { + if (this->expected_[i] != this->actual_[i]) + { + return false; + } + + // Verify the "in" values. + // Skip op1/op5 and cust_op1/cust_op5 since they do not have + // any "in" values. + if (i % 5 == 0 || i % 5 == 4) + { + continue; + } + + unsigned actual_size + = this->actual_in_values_[i].size (); + unsigned expected_size + = this->num_remote_clients_ * remote_client_stats.expected_[i] + + this->num_collocated_clients_ * collocated_client_stats.expected_[i]; + + if (actual_size == 0 && expected_size == 0) + { + continue; + } + + if (actual_size != expected_size) + { + return false; + } + + sort (this->actual_in_values_[i]); + + for (unsigned j = 0; j < actual_size - 1; j++) + { + if (this->actual_in_values_[i][j] != this->actual_in_values_[i][j + 1] - 1) + { + return false; + } + } + } + return true; +} + + + diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_Statistics.h b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_Statistics.h new file mode 100644 index 00000000000..4d7dcff1df9 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_Statistics.h @@ -0,0 +1,35 @@ +// $Id$ +#ifndef STATISTICS_C_H +#define STATISTICS_C_H + +#include "CSD_TP_Foo_C_Export.h" +#include "StatisticsHelper.h" + + +class CSD_TP_Foo_C_Export Foo_C_Statistics +{ + public: + + Foo_C_Statistics(unsigned num_remote_clients, + unsigned num_collocated_clients); + + virtual ~Foo_C_Statistics(); + + void expected(unsigned op_num, unsigned count, bool remote_client); + void actual(unsigned op_num, unsigned count); + void actual_in_values(unsigned op_num, LongVector lv); + + bool actual_vs_expected(); + + + private: + + unsigned num_remote_clients_; + unsigned num_collocated_clients_; + unsigned expected_[10]; + unsigned actual_[10]; + + LongVector actual_in_values_ [10]; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op1.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op1.cpp new file mode 100644 index 00000000000..3ca92e4af2e --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op1.cpp @@ -0,0 +1,65 @@ +// $Id$ +#include "Foo_C_cust_op1.h" +#include "Foo_C_i.h" +#include "CancelledExceptionC.h" + + +Foo_C_cust_op1::Foo_C_cust_op1(Foo_C_i* servant) + : TAO::CSD::TP_Custom_Request_Operation(servant), + cancelled_(false), + servant_(servant) +{ + // This try-catch block is not really necessary, but we have to add it to + // satisfy the non-exception builds. Since there is actually no exception + // raised from _add_ref, we just ignore the exception here. + ACE_TRY_NEW_ENV + { + servant_->_add_ref (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHALL + { + } + ACE_ENDTRY; +} + + +Foo_C_cust_op1::~Foo_C_cust_op1() +{ + // This try-catch block is not really necessary, but we have to add it to + // satisfy the non-exception builds. Since there is actually no exception + // raised from _add_ref, we just ignore the exception here. + ACE_TRY_NEW_ENV + { + servant_->_remove_ref (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHALL + { + } + ACE_ENDTRY; +} + + +void +Foo_C_cust_op1::result(ACE_ENV_SINGLE_ARG_DECL) +{ + if (this->cancelled_) + { + ACE_THROW (CancelledException()); + } +} + + +void +Foo_C_cust_op1::execute_i() +{ + this->servant_->cust_op1(); +} + + +void +Foo_C_cust_op1::cancel_i() +{ + this->cancelled_ = true; +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op1.h b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op1.h new file mode 100644 index 00000000000..553cb27a6d8 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op1.h @@ -0,0 +1,45 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file Foo_C_cust_op1.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef FOO_C_CUST_OP1_H +#define FOO_C_CUST_OP1_H + +#include "CSD_TP_Foo_C_Export.h" +#include "tao/CSD_ThreadPool/CSD_TP_Custom_Request_Operation.h" +#include "tao/Intrusive_Ref_Count_Handle_T.h" + +class Foo_C_i; + +class Foo_C_cust_op1; +typedef TAO_Intrusive_Ref_Count_Handle<Foo_C_cust_op1> Foo_C_cust_op1_Handle; + + +class CSD_TP_Foo_C_Export Foo_C_cust_op1 : public TAO::CSD::TP_Custom_Request_Operation +{ + public: + + Foo_C_cust_op1(Foo_C_i* servant); + virtual ~Foo_C_cust_op1(); + + void result(ACE_ENV_SINGLE_ARG_DECL); + + + protected: + virtual void execute_i(); + virtual void cancel_i(); + + private: + bool cancelled_; + Foo_C_i* servant_; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op2.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op2.cpp new file mode 100644 index 00000000000..c0bc62fb2f0 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op2.cpp @@ -0,0 +1,66 @@ +// $Id$ +#include "Foo_C_cust_op2.h" +#include "Foo_C_i.h" +#include "CancelledExceptionC.h" + + +Foo_C_cust_op2::Foo_C_cust_op2(Foo_C_i* servant, long arg) + : TAO::CSD::TP_Custom_Request_Operation(servant), + arg_(arg), + cancelled_(false), + servant_(servant) +{ + // This try-catch block is not really necessary, but we have to add it to + // satisfy the non-exception builds. Since there is actually no exception + // raised from _add_ref, we just ignore the exception here. + ACE_TRY_NEW_ENV + { + servant_->_add_ref (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHALL + { + } + ACE_ENDTRY; +} + + +Foo_C_cust_op2::~Foo_C_cust_op2() +{ + // This try-catch block is not really necessary, but we have to add it to + // satisfy the non-exception builds. Since there is actually no exception + // raised from _add_ref, we just ignore the exception here. + ACE_TRY_NEW_ENV + { + servant_->_remove_ref (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHALL + { + } + ACE_ENDTRY; +} + + +void +Foo_C_cust_op2::result(ACE_ENV_SINGLE_ARG_DECL) +{ + if (this->cancelled_) + { + ACE_THROW (CancelledException()); + } +} + + +void +Foo_C_cust_op2::execute_i() +{ + this->servant_->cust_op2(this->arg_); +} + + +void +Foo_C_cust_op2::cancel_i() +{ + this->cancelled_ = true; +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op2.h b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op2.h new file mode 100644 index 00000000000..8a319e3b50a --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op2.h @@ -0,0 +1,50 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file Foo_C_cust_op2.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef FOO_C_CUST_OP2_H +#define FOO_C_CUST_OP2_H + +#include "CSD_TP_Foo_C_Export.h" +#include "tao/CSD_ThreadPool/CSD_TP_Custom_Request_Operation.h" +#include "tao/Intrusive_Ref_Count_Handle_T.h" + +class Foo_C_i; + +class Foo_C_cust_op2; +typedef TAO_Intrusive_Ref_Count_Handle<Foo_C_cust_op2> Foo_C_cust_op2_Handle; + + +class CSD_TP_Foo_C_Export Foo_C_cust_op2 : public TAO::CSD::TP_Custom_Request_Operation +{ + public: + + Foo_C_cust_op2(Foo_C_i* servant, long arg); + virtual ~Foo_C_cust_op2(); + + void result(ACE_ENV_SINGLE_ARG_DECL); + + + protected: + + virtual void execute_i(); + virtual void cancel_i(); + + + private: + + long arg_; + bool cancelled_; + + Foo_C_i* servant_; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op3.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op3.cpp new file mode 100644 index 00000000000..b6bfad9dc67 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op3.cpp @@ -0,0 +1,69 @@ +// $Id$ +#include "Foo_C_cust_op3.h" +#include "Foo_C_i.h" +#include "CancelledExceptionC.h" + + +Foo_C_cust_op3::Foo_C_cust_op3(Foo_C_i* servant, long arg) + : TAO::CSD::TP_Custom_Request_Operation(servant), + arg_(arg), + result_(0), + cancelled_(false), + servant_(servant) +{ + // This try-catch block is not really necessary, but we have to add it to + // satisfy the non-exception builds. Since there is actually no exception + // raised from _add_ref, we just ignore the exception here. + ACE_TRY_NEW_ENV + { + servant_->_add_ref (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHALL + { + } + ACE_ENDTRY; +} + + +Foo_C_cust_op3::~Foo_C_cust_op3() +{ + // This try-catch block is not really necessary, but we have to add it to + // satisfy the non-exception builds. Since there is actually no exception + // raised from _add_ref, we just ignore the exception here. + ACE_TRY_NEW_ENV + { + servant_->_remove_ref (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHALL + { + } + ACE_ENDTRY; +} + + +long +Foo_C_cust_op3::result(ACE_ENV_SINGLE_ARG_DECL) +{ + if (this->cancelled_) + { + ACE_THROW_RETURN (CancelledException(), -1); + } + + return this->result_; +} + + +void +Foo_C_cust_op3::execute_i() +{ + this->result_ = this->servant_->cust_op3(this->arg_); +} + + +void +Foo_C_cust_op3::cancel_i() +{ + this->cancelled_ = true; +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op3.h b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op3.h new file mode 100644 index 00000000000..7e86e3c8a53 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op3.h @@ -0,0 +1,51 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file Foo_C_cust_op3.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef FOO_C_CUST_OP3_H +#define FOO_C_CUST_OP3_H + +#include "CSD_TP_Foo_C_Export.h" +#include "tao/CSD_ThreadPool/CSD_TP_Custom_Request_Operation.h" +#include "tao/Intrusive_Ref_Count_Handle_T.h" + +class Foo_C_i; + +class Foo_C_cust_op3; +typedef TAO_Intrusive_Ref_Count_Handle<Foo_C_cust_op3> Foo_C_cust_op3_Handle; + + +class CSD_TP_Foo_C_Export Foo_C_cust_op3 : public TAO::CSD::TP_Custom_Request_Operation +{ + public: + + Foo_C_cust_op3(Foo_C_i* servant, long arg); + virtual ~Foo_C_cust_op3(); + + long result(ACE_ENV_SINGLE_ARG_DECL); + + + protected: + + virtual void execute_i(); + virtual void cancel_i(); + + + private: + + long arg_; + long result_; + bool cancelled_; + + Foo_C_i* servant_; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op4.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op4.cpp new file mode 100644 index 00000000000..828e841990f --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op4.cpp @@ -0,0 +1,52 @@ +// $Id$ +#include "Foo_C_cust_op4.h" +#include "Foo_C_i.h" + + +Foo_C_cust_op4::Foo_C_cust_op4(Foo_C_i* servant, long arg) + : TAO::CSD::TP_Custom_Request_Operation(servant), + arg_(arg), + servant_(servant) +{ + // This try-catch block is not really necessary, but we have to add it to + // satisfy the non-exception builds. Since there is actually no exception + // raised from _add_ref, we just ignore the exception here. + ACE_TRY_NEW_ENV + { + servant_->_add_ref (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHALL + { + } + ACE_ENDTRY; +} + +Foo_C_cust_op4::~Foo_C_cust_op4() +{ + // This try-catch block is not really necessary, but we have to add it to + // satisfy the non-exception builds. Since there is actually no exception + // raised from _add_ref, we just ignore the exception here. + ACE_TRY_NEW_ENV + { + servant_->_remove_ref (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHALL + { + } + ACE_ENDTRY; +} + + +void +Foo_C_cust_op4::execute_i() +{ + this->servant_->cust_op4(this->arg_); +} + + +void +Foo_C_cust_op4::cancel_i() +{ +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op4.h b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op4.h new file mode 100644 index 00000000000..1f8e5eeb5db --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op4.h @@ -0,0 +1,47 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file Foo_C_cust_op4.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef FOO_C_CUST_OP4_H +#define FOO_C_CUST_OP4_H + +#include "CSD_TP_Foo_C_Export.h" +#include "tao/CSD_ThreadPool/CSD_TP_Custom_Request_Operation.h" +#include "tao/Intrusive_Ref_Count_Handle_T.h" + +class Foo_C_i; + +class Foo_C_cust_op4; +typedef TAO_Intrusive_Ref_Count_Handle<Foo_C_cust_op4> Foo_C_cust_op4_Handle; + + +class CSD_TP_Foo_C_Export Foo_C_cust_op4 : public TAO::CSD::TP_Custom_Request_Operation +{ + public: + + Foo_C_cust_op4(Foo_C_i* servant, long arg); + virtual ~Foo_C_cust_op4(); + + + protected: + + virtual void execute_i(); + virtual void cancel_i(); + + + private: + + long arg_; + + Foo_C_i* servant_; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op5.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op5.cpp new file mode 100644 index 00000000000..6f5b6756dda --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op5.cpp @@ -0,0 +1,81 @@ +// $Id$ +#include "Foo_C_cust_op5.h" +#include "Foo_C_i.h" +#include "CancelledExceptionC.h" +#include "CustomExceptionC.h" + + +Foo_C_cust_op5::Foo_C_cust_op5(Foo_C_i* servant) + : TAO::CSD::TP_Custom_Request_Operation(servant), + exception_(false), + cancelled_(false), + servant_(servant) +{ + // This try-catch block is not really necessary, but we have to add it to + // satisfy the non-exception builds. Since there is actually no exception + // raised from _add_ref, we just ignore the exception here. + ACE_TRY_NEW_ENV + { + servant_->_add_ref (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHALL + { + } + ACE_ENDTRY; +} + + +Foo_C_cust_op5::~Foo_C_cust_op5() +{ + // This try-catch block is not really necessary, but we have to add it to + // satisfy the non-exception builds. Since there is actually no exception + // raised from _add_ref, we just ignore the exception here. + ACE_TRY_NEW_ENV + { + servant_->_remove_ref (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHALL + { + } + ACE_ENDTRY; +} + + +void +Foo_C_cust_op5::result(ACE_ENV_SINGLE_ARG_DECL) +{ + if (this->cancelled_) + { + ACE_THROW (CancelledException()); + } + + if (this->exception_) + { + ACE_THROW (CustomException()); + } +} + + +void +Foo_C_cust_op5::execute_i() +{ + ACE_TRY_NEW_ENV + { + this->servant_->cust_op5(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCH (CustomException, ex) + { + this->exception_ = true; + } + ACE_ENDTRY; +} + + +void +Foo_C_cust_op5::cancel_i() +{ + this->cancelled_ = true; +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op5.h b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op5.h new file mode 100644 index 00000000000..d6963d31bbe --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_cust_op5.h @@ -0,0 +1,50 @@ +// This may look like C, but it's really -*- C++ -*- + +//============================================================================= +/** + * @file Foo_C_cust_op5.h + * + * $Id$ + * + * @author Tim Bradley <bradley_t@ociweb.com> + */ +//============================================================================= + +#ifndef FOO_C_CUST_OP5_H +#define FOO_C_CUST_OP5_H + +#include "CSD_TP_Foo_C_Export.h" +#include "tao/CSD_ThreadPool/CSD_TP_Custom_Request_Operation.h" +#include "tao/Intrusive_Ref_Count_Handle_T.h" + +class Foo_C_i; + +class Foo_C_cust_op5; +typedef TAO_Intrusive_Ref_Count_Handle<Foo_C_cust_op5> Foo_C_cust_op5_Handle; + + +class CSD_TP_Foo_C_Export Foo_C_cust_op5 : public TAO::CSD::TP_Custom_Request_Operation +{ + public: + + Foo_C_cust_op5(Foo_C_i* servant); + virtual ~Foo_C_cust_op5(); + + void result(ACE_ENV_SINGLE_ARG_DECL); + + + protected: + + virtual void execute_i(); + virtual void cancel_i(); + + + private: + + bool exception_; + bool cancelled_; + + Foo_C_i* servant_; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_i.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_i.cpp new file mode 100644 index 00000000000..25fadd9deef --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_i.cpp @@ -0,0 +1,148 @@ +// $Id$ +#include "Foo_C_i.h" +#include "AppShutdown.h" +#include "CustomExceptionC.h" + + +Foo_C_i::Foo_C_i() +{ + for (unsigned i = 0; i < 10; i++) + { + this->count_[i] = 0; + } +} + + +Foo_C_i::~Foo_C_i() +{ +} + + +void +Foo_C_i::op1(ACE_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + ++this->count_[0]; +} + + +void +Foo_C_i::op2(CORBA::Long value ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + this->in_values_[1].push_back (value); + ++this->count_[1]; +} + + +CORBA::Long +Foo_C_i::op3(CORBA::Long value ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + this->in_values_[2].push_back (value); + ++this->count_[2]; + return value; +} + + +void +Foo_C_i::op4(CORBA::Long value ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + this->in_values_[3].push_back (value); + ++this->count_[3]; +} + + +void +Foo_C_i::op5(ACE_ENV_SINGLE_ARG_DECL) + ACE_THROW_SPEC((CORBA::SystemException, FooException)) +{ + ++this->count_[4]; + ACE_THROW (FooException()); +} + + +void +Foo_C_i::done(ACE_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC((CORBA::SystemException)) +{ + TheAppShutdown->client_done(); +} + + +void +Foo_C_i::cust_op1(ACE_ENV_SINGLE_ARG_DECL_NOT_USED) +{ + ++this->count_[5]; +} + + +void +Foo_C_i::cust_op2(long value ACE_ENV_ARG_DECL_NOT_USED) +{ + this->in_values_[6].push_back (value); + ++this->count_[6]; +} + + +long +Foo_C_i::cust_op3(long value ACE_ENV_ARG_DECL_NOT_USED) +{ + this->in_values_[7].push_back (value); + ++this->count_[7]; + return value; +} + + +void +Foo_C_i::cust_op4(long value ACE_ENV_ARG_DECL_NOT_USED) +{ + this->in_values_[8].push_back (value); + ++this->count_[8]; +} + + +void +Foo_C_i::cust_op5(ACE_ENV_SINGLE_ARG_DECL) +{ + ++this->count_[9]; + ACE_THROW (CustomException()); +} + + +void +Foo_C_i::gather_stats(Foo_C_Statistics& stats) +{ + for (unsigned i = 0; i < 10; i++) + { + stats.actual (i + 1, this->count_[i]); + stats.actual_in_values (i + 1, this->in_values_[i]); + } +} + + +void +Foo_C_i::dump() +{ + static unsigned id = 0; + + ++id; + + ACE_DEBUG((LM_DEBUG, "Servant %d Stats:\n", id)); + ACE_DEBUG((LM_DEBUG, "------------------\n")); + + unsigned i; + + for (i = 0; i < 5; i++) + { + ACE_DEBUG((LM_DEBUG, "op%d : %d\n", i+1, this->count_[i])); + } + + for (i = 5; i < 10; i++) + { + ACE_DEBUG((LM_DEBUG, "cust_op%d: %d\n", i+1, this->count_[i])); + } + + ACE_DEBUG((LM_DEBUG, "------------------\n")); +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_i.h b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_i.h new file mode 100644 index 00000000000..f5de38ef1ce --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/Foo_C_i.h @@ -0,0 +1,54 @@ +// $Id$ +#ifndef FOO_C_I_H +#define FOO_C_I_H + +#include "CSD_TP_Foo_C_Export.h" +#include "Foo_CS.h" +#include "Foo_C_Statistics.h" + + +class CSD_TP_Foo_C_Export Foo_C_i : public virtual POA_Foo_C, + public virtual PortableServer::RefCountServantBase +{ + public: + + Foo_C_i(); + virtual ~Foo_C_i(); + + virtual void op1(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void op2(CORBA::Long value ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual CORBA::Long op3(CORBA::Long value ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void op4(CORBA::Long value ACE_ENV_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + virtual void op5(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException, + FooException)); + + virtual void done(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC((CORBA::SystemException)); + + void cust_op1(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS); + void cust_op2(long value ACE_ENV_ARG_DECL_WITH_DEFAULTS); + long cust_op3(long value ACE_ENV_ARG_DECL_WITH_DEFAULTS); + void cust_op4(long value ACE_ENV_ARG_DECL_WITH_DEFAULTS); + void cust_op5(ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS); + + void gather_stats(Foo_C_Statistics& stats); + + void dump(); + + + private: + + LongVector in_values_ [10]; + unsigned count_[10]; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/csd_tp_foo_c_lib.mpc b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/csd_tp_foo_c_lib.mpc new file mode 100644 index 00000000000..bc014925ccf --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Foo_C/csd_tp_foo_c_lib.mpc @@ -0,0 +1,27 @@ +//$Id$ +project : csd_tp_test_lib { + sharedname = CSD_TP_Foo_C + dynamicflags = CSD_TP_FOO_C_BUILD_DLL + idlflags += -Wb,export_macro=CSD_TP_Foo_C_Export -Wb,export_include=CSD_TP_Foo_C_Export.h + includes += $(TAO_ROOT)/tao + + IDL_Files { + Foo_C.idl + } + + Source_Files { + Foo_CC.cpp + Foo_CS.cpp + Foo_C_ClientEngine.cpp + Foo_C_Custom_ClientEngine.cpp + Foo_C_Custom_Proxy.cpp + Foo_C_cust_op1.cpp + Foo_C_cust_op2.cpp + Foo_C_cust_op3.cpp + Foo_C_cust_op4.cpp + Foo_C_cust_op5.cpp + Foo_C_i.cpp + Foo_C_Statistics.cpp + } + +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_1/CSD_TP_Test_1.mpc b/TAO/tests/CSD_Strategy_Tests/TP_Test_1/CSD_TP_Test_1.mpc new file mode 100644 index 00000000000..02cac4dc7da --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_1/CSD_TP_Test_1.mpc @@ -0,0 +1,21 @@ +// -*- MPC -*- +// $Id$ + +project(*Server): csd_tp_test_exe_a { + exename=server_main + + Source_Files { + ServerApp.cpp + server_main.cpp + } +} + +project(*Client): csd_tp_test_exe_a { + exename=client_main + + Source_Files { + ClientApp.cpp + client_main.cpp + } +} + diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_1/ClientApp.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Test_1/ClientApp.cpp new file mode 100644 index 00000000000..d51dfbda1b1 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_1/ClientApp.cpp @@ -0,0 +1,84 @@ +// $Id$ +#include "ClientApp.h" +#include "Foo_A_ClientEngine.h" +#include "AppHelper.h" +#include "TestAppExceptionC.h" +#include "ace/Get_Opt.h" +#include "ace/Log_Msg.h" + + +ClientApp::ClientApp() + : TestAppBase("TP_Test_1_Client") +{ +} + + +ClientApp::~ClientApp() +{ +} + + +int +ClientApp::run_i(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + // Initialize the ORB before parsing our own args. + CORBA::ORB_var orb = CORBA::ORB_init(argc, argv, "" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Parse the command-line args for this application. + // * Returns -1 if problems are encountered. + // * Returns 1 if the usage statement was explicitly requested. + // * Returns 0 otherwise. + int result = this->parse_args(argc, argv); + if (result != 0) + { + return result; + } + // Convert the IOR string to a Foo_A object reference. + Foo_A_var foo = RefHelper<Foo_A>::string_to_ref(orb.in(), + this->ior_.c_str() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Create the appropriate client "engine" object. + Foo_A_ClientEngine engine(foo.in()); + + // Execute the client algorithm + result = engine.execute(ACE_ENV_SINGLE_ARG_PARAMETER) ? 0 : -1; + ACE_CHECK_RETURN (-1); + + return result; +} + + +int +ClientApp::parse_args(int argc, char* argv[]) +{ + ACE_Get_Opt get_opts(argc, argv, "i:"); + + int c; + + while ((c = get_opts()) != -1) + { + switch (c) + { + case 'i': + this->ior_ = get_opts.opt_arg(); + break; + + case '?': + ACE_DEBUG((LM_DEBUG, + "(%P|%t) usage: %s -i <ior_string>\n", + argv[0])); + return 1; + + default: + ACE_ERROR((LM_ERROR, + "(%P|%t) usage: %s -i <ior_string>\n", + argv[0])); + return -1; + } + } + + return 0; +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_1/ClientApp.h b/TAO/tests/CSD_Strategy_Tests/TP_Test_1/ClientApp.h new file mode 100644 index 00000000000..1af2e9ff6a6 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_1/ClientApp.h @@ -0,0 +1,28 @@ +// $Id$ +#ifndef CLIENTAPP_H +#define CLIENTAPP_H + +#include "TestAppBase.h" +#include "ace/SString.h" + + +class ClientApp : public TestAppBase +{ + public: + + ClientApp(); + virtual ~ClientApp(); + + protected: + + virtual int run_i(int argc, char* argv[] ACE_ENV_ARG_DECL); + + + private: + + int parse_args(int argc, char* argv[]); + + ACE_CString ior_; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_1/ServerApp.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Test_1/ServerApp.cpp new file mode 100644 index 00000000000..a386c21d049 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_1/ServerApp.cpp @@ -0,0 +1,188 @@ +// $Id$ +#include "ServerApp.h" +#include "Foo_A_i.h" +#include "AppHelper.h" +#include "TestAppExceptionC.h" +#include "AppShutdown.h" +#include "ace/Get_Opt.h" +#include "tao/CSD_ThreadPool/CSD_TP_Strategy.h" +#include "tao/Intrusive_Ref_Count_Handle_T.h" +// To force static load the service. +#include "tao/CSD_ThreadPool/CSD_ThreadPool.h" + +ServerApp::ServerApp() + : TestAppBase("TP_Test_1_Server"), + num_clients_ (1) +{ +} + + +ServerApp::~ServerApp() +{ +} + + +int +ServerApp::run_i(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + // Initialize the ORB before parsing our own args. + CORBA::ORB_var orb = CORBA::ORB_init(argc, argv, "" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Parse the command-line args for this application. + // * Returns -1 if problems are encountered. + // * Returns 1 if the usage statement was explicitly requested. + // * Returns 0 otherwise. + int result = this->parse_args(argc, argv); + if (result != 0) + { + return result; + } + + TheAppShutdown->init(orb.in(), num_clients_ ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Get the Root POA + PortableServer::POA_var root_poa = + RefHelper<PortableServer::POA>::resolve_initial_ref(orb.in(), + "RootPOA" + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Get the POAManager from the Root POA. + PortableServer::POAManager_var poa_manager + = root_poa->the_POAManager(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Create the child POA Policies. + CORBA::PolicyList policies(0); + policies.length(0); + + // Create the child POA + PortableServer::POA_var child_poa = + AppHelper::create_poa("ChildPoa", + root_poa.in(), + poa_manager.in(), + policies + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + + // Create the thread pool servant dispatching strategy object, and + // hold it in a (local) smart pointer variable. + TAO_Intrusive_Ref_Count_Handle<TAO::CSD::TP_Strategy> csd_strategy = + new TAO::CSD::TP_Strategy(); + + // Tell the strategy to apply itself to the child poa. + if (csd_strategy->apply_to(child_poa.in() ACE_ENV_ARG_PARAMETER) == false) + { + ACE_ERROR((LM_ERROR, + "Failed to apply CSD strategy to child poa.\n")); + return -1; + } + ACE_CHECK_RETURN (-1); + + // Create the servant object. + Foo_A_i* servant = new Foo_A_i(); + + // Local smart pointer variable to deal with releasing the reference + // to the servant object when the variable falls out of scope. + PortableServer::ServantBase_var servant_owner(servant); + + // Obtain the object reference using the servant + CORBA::Object_var obj = AppHelper::activate_servant(child_poa.in(), + servant + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Stringify and save the object reference to a file + AppHelper::ref_to_file(orb.in(), + obj.in(), + this->ior_filename_.c_str() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Activate the POA Manager + poa_manager->activate(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp is ready. Running the ORB event loop.\n")); + + // Run the ORB event loop. + orb->run (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp ORB event loop has completed.\n")); + + TheAppShutdown->wait (); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp is destroying the Root POA.\n")); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp is destroying the Root POA.\n")); + + root_poa->destroy(1, 1 ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp is destroying the ORB.\n")); + + orb->destroy(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp has completed running successfully.\n")); + + return 0; +} + + +int +ServerApp::parse_args(int argc, char* argv[]) +{ + ACE_Get_Opt get_opts(argc, argv, "o:n:"); + + int c; + + while ((c = get_opts()) != -1) + { + switch (c) + { + case 'o': + this->ior_filename_ = get_opts.opt_arg(); + break; + + case 'n': + { + int tmp = ACE_OS::atoi(get_opts.opt_arg()); + if (tmp < 1) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Error. -n must be followed by an integer " + "value greater than 0.\n")); + return -1; + } + + this->num_clients_ = tmp; + } + break; + + case '?': + ACE_ERROR((LM_ERROR, + "(%P|%t) usage: %s -o <ior_filename> -n <num_clients>\n", + argv[0])); + return 1; + + default: + ACE_ERROR((LM_ERROR, + "(%P|%t) usage: %s -o <ior_filename> -n <num_clients>\n", + argv[0])); + return -1; + } + } + + return 0; +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_1/ServerApp.h b/TAO/tests/CSD_Strategy_Tests/TP_Test_1/ServerApp.h new file mode 100644 index 00000000000..3bfe10e6f0a --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_1/ServerApp.h @@ -0,0 +1,30 @@ +// $Id$ +#ifndef SERVERAPP_H +#define SERVERAPP_H + +#include "TestAppBase.h" +#include "ace/SString.h" + + +class ServerApp : public TestAppBase +{ + public: + + ServerApp(); + virtual ~ServerApp(); + + + protected: + + virtual int run_i(int argc, char* argv[] ACE_ENV_ARG_DECL); + + + private: + + int parse_args(int argc, char* argv[]); + + ACE_CString ior_filename_; + unsigned num_clients_; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_1/client_main.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Test_1/client_main.cpp new file mode 100644 index 00000000000..ae98ca0f6ac --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_1/client_main.cpp @@ -0,0 +1,5 @@ +// $Id$ +#include "ClientApp.h" +#include "TestAppMain.h" + +TEST_APP_MAIN(ClientApp) diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_1/run_test.pl b/TAO/tests/CSD_Strategy_Tests/TP_Test_1/run_test.pl new file mode 100755 index 00000000000..e15decb6a63 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_1/run_test.pl @@ -0,0 +1,55 @@ +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; + +$iorfile = PerlACE::LocalFile ("server.ior"); +unlink $iorfile; +$status = 0; + +$num_clients=40; + +$SV = new PerlACE::Process ("server_main", "-o $iorfile -n $num_clients"); + +$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; +} + +for ($i = 0; $i < $num_clients; $i++) { + + @CLS[$i] = new PerlACE::Process ("client_main", " -i file://$iorfile"); + + @CLS[$i]->Spawn (); +} + +for ($i = 0; $i < $num_clients; $i++) { + + $client = @CLS[$i]->WaitKill (60); + + if ($client != 0) { + print STDERR "ERROR: client $i returned $client\n"; + $status = 1; + } +} + + +$server = $SV->WaitKill (60); + +if ($server != 0) { + print STDERR "ERROR: server returned $server\n"; + $status = 1; +} + +unlink $iorfile; + +exit $status; diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_1/server_main.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Test_1/server_main.cpp new file mode 100644 index 00000000000..82e987f6d41 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_1/server_main.cpp @@ -0,0 +1,5 @@ +// $Id$ +#include "ServerApp.h" +#include "TestAppMain.h" + +TEST_APP_MAIN(ServerApp) diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_2/CSD_TP_Test_2.mpc b/TAO/tests/CSD_Strategy_Tests/TP_Test_2/CSD_TP_Test_2.mpc new file mode 100644 index 00000000000..02cac4dc7da --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_2/CSD_TP_Test_2.mpc @@ -0,0 +1,21 @@ +// -*- MPC -*- +// $Id$ + +project(*Server): csd_tp_test_exe_a { + exename=server_main + + Source_Files { + ServerApp.cpp + server_main.cpp + } +} + +project(*Client): csd_tp_test_exe_a { + exename=client_main + + Source_Files { + ClientApp.cpp + client_main.cpp + } +} + diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_2/ClientApp.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Test_2/ClientApp.cpp new file mode 100644 index 00000000000..531dba15f17 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_2/ClientApp.cpp @@ -0,0 +1,196 @@ +// $Id$ +#include "ClientApp.h" +#include "AppHelper.h" +#include "TestAppExceptionC.h" +#include "Foo_A_ClientEngine.h" +#include "ace/Get_Opt.h" + + +ClientApp::ClientApp() + : TestAppBase("TP_Test_2_Client"), + ior_("Not Set"), + client_kind_(0), + client_id_(0) +{ +} + + +ClientApp::~ClientApp() +{ +} + + +int +ClientApp::run_i(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + int result = this->init(argc, argv ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + if (result != 0) + { + return result; + } + + this->client_setup(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + result = this->run_engine(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->cleanup(); + return result; +} + + +int +ClientApp::init(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + this->orb_ = CORBA::ORB_init(argc, argv, "" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Parse the command-line args for this application. + // * Raises -1 if problems are encountered. + // * Returns 1 if the usage statement was explicitly requested. + // * Returns 0 otherwise. + return this->parse_args(argc, argv); +} + + +void +ClientApp::client_setup(ACE_ENV_SINGLE_ARG_DECL) +{ + // Turn the ior_ into a Foo_A obj ref. + Foo_A_var foo = RefHelper<Foo_A>::string_to_ref(this->orb_.in(), + this->ior_.c_str() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + // Create the ClientEngine object, and give it the Foo_A obj ref. + this->engine_ = new Foo_A_ClientEngine(foo.in(), this->client_id_); +} + + +int +ClientApp::run_engine(ACE_ENV_SINGLE_ARG_DECL) +{ + bool result = this->engine_->execute(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + return result ? 0 : -1; +} + + +void +ClientApp::cleanup() +{ +} + + +int +ClientApp::parse_args(int argc, char* argv[]) +{ + this->exe_name_ = argv[0]; + + ACE_Get_Opt get_opts(argc, argv, "i:k:n:"); + + int c; + + while ((c = get_opts()) != -1) + { + int result = 0; + switch (c) + { + case 'i': + this->ior_ = get_opts.opt_arg(); + break; + + case 'k': + result = set_arg(this->client_kind_, + get_opts.opt_arg(), + c, + "client_kind"); + break; + + case 'n': + result = set_arg(this->client_id_, + get_opts.opt_arg(), + c, + "client_id"); + break; + + case '?': + this->usage_statement(); + return 1; + + default: + this->usage_statement(); + return -1; + } + + if (result != 0) + { + return result; + } + } + + return this->arg_dependency_checks(); +} + +void +ClientApp::usage_statement() +{ + ACE_ERROR((LM_ERROR, + "Usage: %s [options]\n\n" + "OPTIONS:\n\n" + "\t[-i <ior>]\n" + "\t[-k <client_kind>]\n" + "\t[-n <client_id>]\n" + "\t[-?]\n\n", + this->exe_name_.c_str())); +} + + +int +ClientApp::arg_dependency_checks() +{ + if (this->ior_ == "Not Set") + { + ACE_ERROR((LM_ERROR, + "Error: Missing required command-line option (-i <ior>).\n")); + this->usage_statement(); + return -1; + } + + if (this->client_id_ <= 0) + { + ACE_ERROR((LM_ERROR, + "Error: Invalid command-line option (-n <client id>). \n" + " The client id should be positive integer. \n")); + this->usage_statement(); + return -1; + } + + return 0; +} + + +int +ClientApp::set_arg(unsigned& value, + const char* arg, + char opt, + const char* name, + int min) +{ + int tmp = ACE_OS::atoi(arg); + + if (tmp < min) + { + ACE_ERROR((LM_ERROR, + "Error: -%c <%s> must be integer type with a value of, " + "at least, %d.\n", opt, name, min)); + this->usage_statement(); + return -1; + } + + value = tmp; + return 0; +} + + diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_2/ClientApp.h b/TAO/tests/CSD_Strategy_Tests/TP_Test_2/ClientApp.h new file mode 100644 index 00000000000..d5bb80cf800 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_2/ClientApp.h @@ -0,0 +1,51 @@ +// $Id$ +#ifndef CLIENTAPP_H +#define CLIENTAPP_H + +#include "TestAppBase.h" +#include "ClientEngine.h" +#include "tao/ORB.h" +#include "ace/SString.h" + + +class ClientApp : public TestAppBase +{ + public: + + ClientApp(); + virtual ~ClientApp(); + + protected: + + virtual int run_i(int argc, char* argv[] ACE_ENV_ARG_DECL); + + private: + + // These are all called, in order, by the run_i() method. + int init(int argc, char* argv[] ACE_ENV_ARG_DECL); + void client_setup(ACE_ENV_SINGLE_ARG_DECL); + int run_engine(ACE_ENV_SINGLE_ARG_DECL); + void cleanup(); + + // Helper methods used by the methods above. + int parse_args(int argc, char* argv[]); + + int set_arg(unsigned& value, + const char* arg, + char opt, + const char* name, + int min = 0); + + void usage_statement(); + int arg_dependency_checks(); + + + CORBA::ORB_var orb_; + ACE_CString exe_name_; + ACE_CString ior_; + unsigned client_kind_; + ClientEngine_Handle engine_; + unsigned client_id_; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_2/ServerApp.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Test_2/ServerApp.cpp new file mode 100644 index 00000000000..8219f7bf2f1 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_2/ServerApp.cpp @@ -0,0 +1,368 @@ +// $Id$ +#include "ServerApp.h" +#include "AppHelper.h" +#include "OrbRunner.h" +#include "AppShutdown.h" +#include "TestAppExceptionC.h" +#include "Foo_A_ClientEngine.h" +#include "ace/OS.h" +#include "ace/Get_Opt.h" +// To force static load the service. +#include "tao/CSD_ThreadPool/CSD_ThreadPool.h" + +ServerApp::ServerApp() + : TestAppBase("TP_Test_2_Server"), + ior_filename_prefix_("foo"), + num_servants_(1), + num_csd_threads_(1), + num_orb_threads_(1), + num_remote_clients_(1), + num_collocated_clients_(0), + collocated_client_kind_(0) +{ +} + + +ServerApp::~ServerApp() +{ +} + + +int +ServerApp::run_i(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + int result = this->init(argc, argv ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + if (result != 0) + { + return result; + } + + this->poa_setup(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->csd_setup(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->servant_setup(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->collocated_setup(); + this->poa_activate(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->run_collocated_clients(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->run_orb_event_loop(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + this->cleanup(); + return this->check_validity () ? 0 : -1; +} + + +int +ServerApp::init(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + this->orb_ = CORBA::ORB_init(argc, argv, "" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Parse the command-line args for this application. + // * Raises -1 if problems are encountered. + // * Returns 1 if the usage statement was explicitly requested. + // * Returns 0 otherwise. + int result = this->parse_args(argc, argv); + + if (result != 0) + { + return result; + } + + unsigned num_clients = this->num_remote_clients_ + + this->num_collocated_clients_; + + TheAppShutdown->init (this->orb_.in (), num_clients ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + return 0; +} + + +void +ServerApp::poa_setup(ACE_ENV_SINGLE_ARG_DECL) +{ + this->poa_ = this->create_poa(this->orb_.in(), + "ChildPoa" + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; +} + + +void +ServerApp::csd_setup(ACE_ENV_SINGLE_ARG_DECL) +{ + this->tp_strategy_ = new TAO::CSD::TP_Strategy(this->num_csd_threads_); + + if (!this->tp_strategy_->apply_to(this->poa_.in() ACE_ENV_ARG_PARAMETER)) + { + ACE_ERROR((LM_ERROR, + "Failed to apply CSD strategy to poa.\n")); + ACE_THROW(TestAppException()); + } + ACE_CHECK; +} + + +void +ServerApp::servant_setup(ACE_ENV_SINGLE_ARG_DECL) +{ + this->servants_.create_and_activate(this->num_servants_, + this->orb_.in (), + this->poa_.in (), + this->ior_filename_prefix_.c_str() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; +} + + +void +ServerApp::collocated_setup() +{ + int client_id_start = this->num_remote_clients_; + for (unsigned i = 0; i < this->num_collocated_clients_; i++) + { + // Dole out the servant object references in a round-robin fashion. + unsigned servant_index = i % this->num_servants_; + + ServantListType::T_stub_var obj = this->servants_.objref(servant_index); + ClientEngine_Handle engine = new Foo_A_ClientEngine(obj.in(), ++client_id_start, true); + this->collocated_client_task_.add_engine(engine.in()); + } +} + + +void +ServerApp::poa_activate(ACE_ENV_SINGLE_ARG_DECL) +{ + PortableServer::POAManager_var poa_manager + = this->poa_->the_POAManager(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + + poa_manager->activate(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; +} + + +void +ServerApp::run_collocated_clients(ACE_ENV_SINGLE_ARG_DECL) +{ + if (this->num_collocated_clients_ > 0) + { + if (this->collocated_client_task_.open() == -1) + { + ACE_THROW (TestAppException ()); + } + } +} + + +void +ServerApp::run_orb_event_loop(ACE_ENV_SINGLE_ARG_DECL) +{ + OrbRunner orb_runner(this->orb_.in(), this->num_orb_threads_); + orb_runner.run(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + TheAppShutdown->wait (); +} + + +void +ServerApp::cleanup() +{ +} + + +int +ServerApp::parse_args(int argc, char* argv[]) +{ + this->exe_name_ = argv[0]; + + ACE_Get_Opt get_opts(argc, argv, "p:s:n:t:r:c:k:"); + + int c; + + while ((c = get_opts()) != -1) + { + int result = 0; + switch (c) + { + case 'p': + this->ior_filename_prefix_ = get_opts.opt_arg(); + break; + + case 's': + result = this->set_arg(this->num_servants_, + get_opts.opt_arg(), + c, + "num_servants", + 1); + break; + + case 'n': + result = this->set_arg(this->num_csd_threads_, + get_opts.opt_arg(), + c, + "num_servants", + 1); + break; + + case 't': + result = this->set_arg(this->num_orb_threads_, + get_opts.opt_arg(), + c, + "num_orb_threads", + 1); + break; + + case 'r': + result = this->set_arg(this->num_remote_clients_, + get_opts.opt_arg(), + c, + "num_remote_clients"); + break; + + case 'c': + result = this->set_arg(this->num_collocated_clients_, + get_opts.opt_arg(), + c, + "num_collocated_clients"); + break; + + case 'k': + result = this->set_arg(this->collocated_client_kind_, + get_opts.opt_arg(), + c, + "collocated_client_kind"); + break; + + case '?': + this->usage_statement(); + return 1; + + default: + this->usage_statement(); + return -1; + } + + if (result != 0) + { + return result; + } + } + + return this->arg_dependency_checks(); +} + +void +ServerApp::usage_statement() +{ + ACE_ERROR((LM_ERROR, + "Usage: %s [options]\n\n" + "OPTIONS:\n\n" + "\t[-p <ior_filename_prefix>]\n" + "\t[-s <num_servants>]\n" + "\t[-n <num_csd_threads>]\n" + "\t[-t <num_orb_threads>]\n" + "\t[-r <num_remote_clients>]\n" + "\t[-c <num_collocated_clients>]\n" + "\t[-k <collocated_client_kind>]\n" + "\t[-?]\n\n", + this->exe_name_.c_str())); +} + + +int +ServerApp::arg_dependency_checks() +{ + return (this->num_remote_clients_ + + this->num_collocated_clients_) > 0 ? 0 : -1; +} + + +int +ServerApp::set_arg(unsigned& value, + const char* arg, + char opt, + const char* name, + int min) +{ + int tmp = ACE_OS::atoi(arg); + + if (tmp < min) + { + ACE_ERROR((LM_ERROR, + "Error: -%c <%s> must be integer type with a value of, " + "at least, %d.\n", opt, name, min)); + this->usage_statement(); + return -1; + } + + value = tmp; + return 0; +} + + +PortableServer::POA_ptr +ServerApp::create_poa(CORBA::ORB_ptr orb, + const char* poa_name + ACE_ENV_ARG_DECL) +{ + // Get the Root POA. + PortableServer::POA_var root_poa + = RefHelper<PortableServer::POA>::resolve_initial_ref(orb, + "RootPOA" + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + // Get the POAManager from the Root POA. + PortableServer::POAManager_var poa_manager + = root_poa->the_POAManager(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + // Create the child POA Policies. + CORBA::PolicyList policies(0); + policies.length(0); + + // Create the child POA + PortableServer::POA_var poa = AppHelper::create_poa(poa_name, + root_poa.in(), + poa_manager.in(), + policies + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + // Give away the child POA_ptr from the POA_var variable. + return poa._retn(); +} + + +bool +ServerApp::check_validity () +{ + // Check whether the clients return any errors. + if (this->num_collocated_clients_ > 0 + && this->collocated_client_task_.failure_count () > 0) + { + return false; + } + + unsigned num_clients = this->num_remote_clients_ + + this->num_collocated_clients_; + + Foo_A_Statistics stats (num_clients); + + Foo_A_ClientEngine::expected_results (stats); + + for (unsigned i = 0; i < this->num_servants_; i++) + { + this->servants_.servant(i)->gather_stats(stats); + } + + return stats.actual_vs_expected (); +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_2/ServerApp.h b/TAO/tests/CSD_Strategy_Tests/TP_Test_2/ServerApp.h new file mode 100644 index 00000000000..73b5ccbbd94 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_2/ServerApp.h @@ -0,0 +1,79 @@ +// $Id$ +#ifndef SERVERAPP_H +#define SERVERAPP_H + +#include "TestAppBase.h" +#include "Foo_A_i.h" +#include "ServantList_T.h" +#include "ClientTask.h" +#include "tao/CSD_ThreadPool/CSD_TP_Strategy.h" +#include "ace/SString.h" + + +class ServerApp : public TestAppBase +{ + public: + + ServerApp(); + virtual ~ServerApp(); + + + protected: + + virtual int run_i(int argc, char* argv[] ACE_ENV_ARG_DECL); + + + private: + + // These are all called, in order, by the run_i() method. + int init(int argc, char* argv[] ACE_ENV_ARG_DECL); + void poa_setup(ACE_ENV_SINGLE_ARG_DECL); + void csd_setup(ACE_ENV_SINGLE_ARG_DECL); + void servant_setup(ACE_ENV_SINGLE_ARG_DECL); + void collocated_setup(); + void poa_activate(ACE_ENV_SINGLE_ARG_DECL); + void run_collocated_clients(ACE_ENV_SINGLE_ARG_DECL); + void run_orb_event_loop(ACE_ENV_SINGLE_ARG_DECL); + bool check_validity (); + void cleanup(); + + + // Helper methods used by the methods above. + int parse_args(int argc, char* argv[]); + + int set_arg(unsigned& value, + const char* arg, + char opt, + const char* name, + int min = 0); + + void usage_statement(); + int arg_dependency_checks(); + + + PortableServer::POA_ptr create_poa(CORBA::ORB_ptr orb, + const char* poa_name + ACE_ENV_ARG_DECL); + + typedef ServantList<Foo_A_i> ServantListType; + + CORBA::ORB_var orb_; + PortableServer::POA_var poa_; + TAO::CSD::TP_Strategy_Handle tp_strategy_; + + ServantListType servants_; + + ClientTask collocated_client_task_; + + ACE_CString exe_name_; + + ACE_CString ior_filename_prefix_; + unsigned num_servants_; + unsigned num_csd_threads_; + unsigned num_orb_threads_; + unsigned num_remote_clients_; + unsigned num_collocated_clients_; + unsigned collocated_client_kind_; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_2/client_main.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Test_2/client_main.cpp new file mode 100644 index 00000000000..3814bef5ff9 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_2/client_main.cpp @@ -0,0 +1,7 @@ +// $Id$ +#include "ClientApp.h" +#include "TestAppMain.h" + +TEST_APP_MAIN(ClientApp) + + diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_2/run_test.pl b/TAO/tests/CSD_Strategy_Tests/TP_Test_2/run_test.pl new file mode 100755 index 00000000000..a0daa50592b --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_2/run_test.pl @@ -0,0 +1,173 @@ +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; + +my $status = 0; + +my $iorfname_prefix = "servant"; +my $num_servants = 1; +my $num_orb_threads = 1; +my $num_remote_clients = 1; +my $num_csd_threads = 1; +my $num_collocated_clients = 0; +my $collocated_client_kind = 0; +my $client_kind = 0; + +my $i; +my $j; +my @iorfile; + +my $ARGC = @ARGV; + +if ($ARGC > 0) +{ + if ($ARGC > 1) + { + print STDERR "ERROR: Too many command-line arguments for $0.\n"; + exit 1; + } + + my $subtest = $ARGV[0]; + + if ($subtest eq 'remote') + { + $num_remote_clients = 40; + } + elsif ($subtest eq 'collocated') + { + $num_remote_clients = 0; + $num_collocated_clients = 1; + } + elsif ($subtest eq 'remote_orbthreads') + { + $num_orb_threads = 5; + $num_remote_clients = 40; + } + elsif ($subtest eq 'remote_servants') + { + $num_servants = 5; + $num_remote_clients = 40; + } + elsif ($subtest eq 'remote_csdthreads') + { + $num_csd_threads = 5; + $num_remote_clients = 40; + } + elsif ($subtest eq 'remote_big') + { + $num_csd_threads = 5; + $num_servants = 10; + $num_orb_threads = 4; + $num_remote_clients = 40; + } + elsif ($subtest eq 'big') + { + $num_csd_threads = 5; + $num_servants = 10; + $num_orb_threads = 4; + $num_remote_clients = 40; + $num_collocated_clients = 40; + } + elsif ($subtest eq 'usage') + { + print STDOUT "Usage: $0 [<subtest>]\n" . + "\n" . + "Supported <subtest> values:\n" . + "\n" . + "\tremote\n" . + "\tcollocated\n" . + "\tremote_orbthreads\n" . + "\tremote_servants\n" . + "\tremote_csdthreads\n" . + "\tremote_big\n" . + "\tusage\n" . + "\n"; + exit 0; + } + else + { + print STDERR "ERROR: invalid subtest argument for $0: $subtest\n"; + exit 1; + } +} + +#Delete old ior files. +for ($i = 0; $i < $num_servants; $i++) { + my $servant_id = sprintf("%02d", ($i + 1)); + $iorfile[$i] = PerlACE::LocalFile($iorfname_prefix . "_$servant_id.ior"); + unlink $iorfile[$i]; +} + +$SV = new PerlACE::Process("server_main", + "-p $iorfname_prefix " . + "-s $num_servants " . + "-n $num_csd_threads " . + "-t $num_orb_threads " . + "-r $num_remote_clients " . + "-c $num_collocated_clients " . + "-k $collocated_client_kind"); + +$SV->Spawn(); + + +# Wait for the servant ior files created by server. +for ($i = 0; $i < $num_servants; $i++) { + if (PerlACE::waitforfile_timed + ($iorfile[$i], + $PerlACE::wait_interval_for_process_creation) == -1) { + print STDERR "ERROR: cannot find file <$iorfile[$i]>\n"; + $SV->Kill(); + $SV->TimedWait(1); + exit 1; + } +} + + +my $count = 0; + +for ($i = 0; $i < $num_remote_clients; $i++) +{ + + $client_id = $i+1; + + $j = $i % $num_servants; + + $CLS[$i] = new PerlACE::Process("client_main", + "-i file://$iorfile[$j] ". + "-k $client_kind ". + "-n $client_id"); + + $CLS[$i]->Spawn(); +} + +for ($i = 0; $i < $num_remote_clients; $i++) +{ + $client = $CLS[$i]->WaitKill(60); + + if ($client != 0) + { + print STDERR "ERROR: client $i returned $client\n"; + $status = 1; + } +} + + +$server = $SV->WaitKill(60); + +if ($server != 0) { + print STDERR "ERROR: server returned $server\n"; + $status = 1; +} + +#Delete ior files generated by this run. +for ($i = 0; $i < $num_servants; $i++) { + unlink $iorfile[$i]; +} + +exit $status; diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_2/server_main.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Test_2/server_main.cpp new file mode 100644 index 00000000000..0be257accae --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_2/server_main.cpp @@ -0,0 +1,7 @@ +// $Id$ +#include "ServerApp.h" +#include "TestAppMain.h" + +TEST_APP_MAIN(ServerApp) + + diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_3/CSD_TP_Test_3.mpc b/TAO/tests/CSD_Strategy_Tests/TP_Test_3/CSD_TP_Test_3.mpc new file mode 100644 index 00000000000..016caef75ef --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_3/CSD_TP_Test_3.mpc @@ -0,0 +1,21 @@ +// -*- MPC -*- +// $Id$ + +project(*Server): csd_tp_test_exe_b { + exename=server_main + + Source_Files { + ServerApp.cpp + server_main.cpp + } +} + +project(*Client): csd_tp_test_exe_b { + exename=client_main + + Source_Files { + ClientApp.cpp + client_main.cpp + } +} + diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_3/ClientApp.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Test_3/ClientApp.cpp new file mode 100644 index 00000000000..85ddc34bb47 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_3/ClientApp.cpp @@ -0,0 +1,318 @@ +// $Id$ +#include "ClientApp.h" +#include "AppHelper.h" +#include "OrbRunner.h" +#include "AppShutdown.h" +#include "TestAppExceptionC.h" +#include "Foo_B_ClientEngine.h" +#include "ace/Get_Opt.h" +// To force static load the service. +#include "tao/CSD_ThreadPool/CSD_ThreadPool.h" + +ClientApp::ClientApp() +: TestAppBase("TP_Test_3_Client"), + client_task_ (true), // shutdown orb after client is done. + num_servants_ (1), + num_csd_threads_ (1), + num_orb_threads_ (1), + ior_("Not Set"), + client_kind_(0), + client_id_(0) +{ +} + + +ClientApp::~ClientApp() +{ +} + + +int +ClientApp::run_i(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + int result = this->init(argc, argv ACE_ENV_ARG_PARAMETER); + if (result != 0) + { + return result; + } + ACE_CHECK_RETURN (-1); + + this->poa_setup(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->csd_setup(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->client_setup(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->poa_activate(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->run_clients(); + this->run_orb_event_loop(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + result = this->check_validity () ? 0 : -1; + this->cleanup(); + + return result; +} + + +int +ClientApp::init(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + this->orb_ = CORBA::ORB_init(argc, argv, "" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Parse the command-line args for this application. + // * Raises -1 if problems are encountered. + // * Returns 1 if the usage statement was explicitly requested. + // * Returns 0 otherwise. + int result = this->parse_args(argc, argv); + if (result != 0) + { + return result; + } + + TheAppShutdown->init(this->orb_.in(), num_servants_ ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + return 0; +} + + +void +ClientApp::poa_setup(ACE_ENV_SINGLE_ARG_DECL) +{ + this->poa_ = this->create_poa(this->orb_.in(), + "ChildPoa" + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; +} + + +void +ClientApp::csd_setup(ACE_ENV_SINGLE_ARG_DECL) +{ + this->tp_strategy_ = new TAO::CSD::TP_Strategy(this->num_csd_threads_); + + if (!this->tp_strategy_->apply_to(this->poa_.in() ACE_ENV_ARG_PARAMETER)) + { + ACE_ERROR((LM_ERROR, + "Failed to apply CSD strategy to poa.\n")); + ACE_THROW(TestAppException()); + } + ACE_CHECK; +} + + +void +ClientApp::client_setup(ACE_ENV_SINGLE_ARG_DECL) +{ + // Turn the ior_ into a Foo_B obj ref. + Foo_B_var foo = RefHelper<Foo_B>::string_to_ref(this->orb_.in(), + this->ior_.c_str() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + this->servants_.create_and_activate(1, // number of callback servants + this->poa_.in() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + ServantListType::T_stub_var cb = this->servants_.objref(0); + + // Create the ClientEngine object, and give it the Foo_B and Callback object + // references. + ClientEngine_Handle engine + = new Foo_B_ClientEngine(foo.in(), cb.in (), this->client_id_); + this->client_task_.add_engine(engine.in()); +} + + +void +ClientApp::poa_activate(ACE_ENV_SINGLE_ARG_DECL) +{ + PortableServer::POAManager_var poa_manager + = this->poa_->the_POAManager(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + poa_manager->activate(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; +} + + +void +ClientApp::run_clients() +{ + this->client_task_.open(); +} + + +void +ClientApp::run_orb_event_loop(ACE_ENV_SINGLE_ARG_DECL) +{ + OrbRunner orb_runner(this->orb_.in(), this->num_orb_threads_); + orb_runner.run(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + TheAppShutdown->wait (); +} + + +PortableServer::POA_ptr +ClientApp::create_poa(CORBA::ORB_ptr orb, + const char* poa_name + ACE_ENV_ARG_DECL) +{ + // Get the Root POA. + PortableServer::POA_var root_poa + = RefHelper<PortableServer::POA>::resolve_initial_ref(orb, + "RootPOA" + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + // Get the POAManager from the Root POA. + PortableServer::POAManager_var poa_manager + = root_poa->the_POAManager(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + // Create the child POA Policies. + CORBA::PolicyList policies(0); + policies.length(0); + + // Create the child POA + PortableServer::POA_var poa = AppHelper::create_poa(poa_name, + root_poa.in(), + poa_manager.in(), + policies + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + // Give away the child POA_ptr from the POA_var variable. + return poa._retn(); +} + + +void +ClientApp::cleanup() +{ +} + + +int +ClientApp::parse_args(int argc, char* argv[]) +{ + this->exe_name_ = argv[0]; + + ACE_Get_Opt get_opts(argc, argv, "i:k:n:"); + + int c; + + while ((c = get_opts()) != -1) + { + int result = 0; + switch (c) + { + case 'i': + this->ior_ = get_opts.opt_arg(); + break; + + case 'k': + result = set_arg(this->client_kind_, + get_opts.opt_arg(), + c, + "client_kind"); + break; + + case 'n': + result = set_arg(this->client_id_, + get_opts.opt_arg(), + c, + "client_id"); + break; + + case '?': + this->usage_statement(); + return 1; + + default: + this->usage_statement(); + return -1; + } + + if (result != 0) + { + return result; + } + } + + return this->arg_dependency_checks(); +} + +void +ClientApp::usage_statement() +{ + ACE_ERROR((LM_ERROR, + "Usage: %s [options]\n\n" + "OPTIONS:\n\n" + "\t[-i <ior>]\n" + "\t[-k <client_kind>]\n" + "\t[-n <client_id>]\n" + "\t[-?]\n\n", + this->exe_name_.c_str())); +} + + +int +ClientApp::arg_dependency_checks() +{ + if (this->ior_ == "Not Set") + { + ACE_ERROR((LM_ERROR, + "Error: Missing required command-line option (-i <ior>).\n")); + this->usage_statement(); + return -1; + } + if (this->client_id_ <= 0) + { + ACE_ERROR((LM_ERROR, + "Error: Invalid command-line option (-n <client id>). \n" + " The client id should be positive integer. \n")); + this->usage_statement(); + return -1; + } + + return 0; +} + + +int +ClientApp::set_arg(unsigned& value, + const char* arg, + char opt, + const char* name, + int min) +{ + int tmp = ACE_OS::atoi(arg); + + if (tmp < min) + { + ACE_ERROR((LM_ERROR, + "Error: -%c <%s> must be integer type with a value of, " + "at least, %d.\n", opt, name, min)); + this->usage_statement(); + return -1; + } + + value = tmp; + return 0; +} + + +bool +ClientApp::check_validity () +{ + // Check whether the clients return any errors. + if (this->client_task_.failure_count () > 0) + { + return false; + } + + return true; +} + diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_3/ClientApp.h b/TAO/tests/CSD_Strategy_Tests/TP_Test_3/ClientApp.h new file mode 100644 index 00000000000..2eb6f23bd39 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_3/ClientApp.h @@ -0,0 +1,78 @@ +// $Id$ +#ifndef CLIENTAPP_H +#define CLIENTAPP_H + +#include "TestAppBase.h" +#include "ClientEngine.h" +#include "ServantList_T.h" +#include "Callback_i.h" +#include "ClientTask.h" +#include "tao/CSD_ThreadPool/CSD_TP_Strategy.h" +#include "tao/ORB.h" +#include "ace/SString.h" + + +class ClientApp : public TestAppBase +{ + public: + + ClientApp(); + virtual ~ClientApp(); + + protected: + + virtual int run_i(int argc, char* argv[] ACE_ENV_ARG_DECL); + + + private: + + // These are all called, in order, by the run_i() method. + int init(int argc, char* argv[] ACE_ENV_ARG_DECL); + void poa_setup(ACE_ENV_SINGLE_ARG_DECL); + void csd_setup(ACE_ENV_SINGLE_ARG_DECL); + void client_setup(ACE_ENV_SINGLE_ARG_DECL); + void poa_activate(ACE_ENV_SINGLE_ARG_DECL); + void run_clients(); + void run_orb_event_loop(ACE_ENV_SINGLE_ARG_DECL); + bool check_validity (); + void cleanup(); + + // Helper methods used by the methods above. + int parse_args(int argc, char* argv[]); + + int set_arg(unsigned& value, + const char* arg, + char opt, + const char* name, + int min = 0); + + void usage_statement(); + int arg_dependency_checks(); + + PortableServer::POA_ptr create_poa(CORBA::ORB_ptr orb, + const char* poa_name + ACE_ENV_ARG_DECL); + + + typedef ServantList<Callback_i> ServantListType; + + CORBA::ORB_var orb_; + PortableServer::POA_var poa_; + TAO::CSD::TP_Strategy_Handle tp_strategy_; + + ServantListType servants_; + + ClientTask client_task_; + + ACE_CString exe_name_; + + unsigned num_servants_; + unsigned num_csd_threads_; + unsigned num_orb_threads_; + + ACE_CString ior_; + unsigned client_kind_; + unsigned client_id_; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_3/ServerApp.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Test_3/ServerApp.cpp new file mode 100644 index 00000000000..3366a6abd73 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_3/ServerApp.cpp @@ -0,0 +1,408 @@ +// $Id$ +#include "ServerApp.h" +#include "AppHelper.h" +#include "OrbRunner.h" +#include "AppShutdown.h" +#include "TestAppExceptionC.h" +#include "Foo_B_ClientEngine.h" +#include "Foo_B_ClientEngine.h" +#include "Callback_i.h" +#include "ace/OS.h" +#include "ace/Get_Opt.h" +// To force static load the service. +#include "tao/CSD_ThreadPool/CSD_ThreadPool.h" + +ServerApp::ServerApp() + : TestAppBase("TP_Test_3_Server"), + ior_filename_prefix_("foo"), + num_servants_(1), + num_csd_threads_(1), + num_orb_threads_(1), + num_remote_clients_(1), + num_collocated_clients_(0), + collocated_client_kind_(0) +{ +} + + +ServerApp::~ServerApp() +{ +} + + +int +ServerApp::run_i(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + int result = this->init(argc, argv ACE_ENV_ARG_PARAMETER); + if (result != 0) + { + return result; + } + ACE_CHECK_RETURN (-1); + + this->poa_setup(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->csd_setup(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->servant_setup(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->collocated_setup(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->poa_activate(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->run_collocated_clients(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->run_orb_event_loop(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->cleanup(); + return this->check_validity () ? 0 : -1; +} + + +int +ServerApp::init(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + this->orb_ = CORBA::ORB_init(argc, argv, "" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Parse the command-line args for this application. + // * Raises -1 if problems are encountered. + // * Returns 1 if the usage statement was explicitly requested. + // * Returns 0 otherwise. + int result = this->parse_args(argc, argv); + if (result != 0) + { + return result; + } + + unsigned num_clients = this->num_remote_clients_ + + this->num_collocated_clients_; + + TheAppShutdown->init(this->orb_.in(), num_clients ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + return 0; +} + + +void +ServerApp::poa_setup(ACE_ENV_SINGLE_ARG_DECL) +{ + this->poa_ = this->create_poa(this->orb_.in(), + "ChildPoa" + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + if (this->num_collocated_clients_ > 0) + { + this->cb_poa_ = this->create_poa(this->orb_.in(), + "CallbackPoa" + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + } +} + +void +ServerApp::csd_setup(ACE_ENV_SINGLE_ARG_DECL) +{ + this->tp_strategy_ = new TAO::CSD::TP_Strategy(this->num_csd_threads_); + + if (!this->tp_strategy_->apply_to(this->poa_.in() ACE_ENV_ARG_PARAMETER)) + { + ACE_ERROR((LM_ERROR, + "Failed to apply CSD strategy to poa.\n")); + ACE_THROW(TestAppException()); + } + ACE_CHECK; + + // Use another poa and strategy for callbacks. This would resolve + // the deadlock situation that happens when having number of csd + // threads less than number of collocated clients. + if (this->num_collocated_clients_ > 0) + { + this->cb_tp_strategy_ = new TAO::CSD::TP_Strategy(); + if (!this->cb_tp_strategy_->apply_to(this->cb_poa_.in() ACE_ENV_ARG_PARAMETER)) + { + ACE_ERROR((LM_ERROR, + "Failed to apply CSD strategy to callback poa.\n")); + ACE_THROW(TestAppException()); + } + ACE_CHECK; + } +} + + +void +ServerApp::servant_setup(ACE_ENV_SINGLE_ARG_DECL) +{ + this->foo_servants_.create_and_activate(this->num_servants_, + this->orb_.in (), + this->poa_.in (), + this->ior_filename_prefix_.c_str() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; +} + + +void +ServerApp::collocated_setup(ACE_ENV_SINGLE_ARG_DECL) +{ + if (this->num_collocated_clients_ == 0) + return; + + this->cb_servants_.create_and_activate(1, // number of callback servants + this->cb_poa_.in() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + CallbackServantListType::T_stub_var cb = this->cb_servants_.objref(0); + + unsigned client_id = this->num_remote_clients_; + + for (unsigned i = 0; i < this->num_collocated_clients_; i++) + { + client_id ++; + // Dole out the servant object references in a round-robin fashion. + unsigned servant_index = i % this->num_servants_; + + FooServantListType::T_stub_var foo + = this->foo_servants_.objref(servant_index); + ClientEngine_Handle engine + = new Foo_B_ClientEngine(foo.in(), cb.in (), client_id, true); + this->collocated_client_task_.add_engine(engine.in()); + } +} + + +void +ServerApp::poa_activate(ACE_ENV_SINGLE_ARG_DECL) +{ + PortableServer::POAManager_var poa_manager + = this->poa_->the_POAManager(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + poa_manager->activate(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; +} + + +void +ServerApp::run_collocated_clients(ACE_ENV_SINGLE_ARG_DECL) +{ + if (this->num_collocated_clients_ > 0) + { + if (this->collocated_client_task_.open() == -1) + { + ACE_THROW (TestAppException ()); + } + } +} + + +void +ServerApp::run_orb_event_loop(ACE_ENV_SINGLE_ARG_DECL) +{ + OrbRunner orb_runner(this->orb_.in(), this->num_orb_threads_); + orb_runner.run(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + TheAppShutdown->wait (); +} + + +void +ServerApp::cleanup() +{ +} + + +int +ServerApp::parse_args(int argc, char* argv[]) +{ + this->exe_name_ = argv[0]; + + ACE_Get_Opt get_opts(argc, argv, "p:s:n:t:r:c:k:"); + + int c; + + while ((c = get_opts()) != -1) + { + int result = 0; + switch (c) + { + case 'p': + this->ior_filename_prefix_ = get_opts.opt_arg(); + break; + + case 's': + result = set_arg(this->num_servants_, + get_opts.opt_arg(), + c, + "num_servants", + 1); + break; + + case 'n': + result = set_arg(this->num_csd_threads_, + get_opts.opt_arg(), + c, + "num_servants", + 1); + break; + + case 't': + result = set_arg(this->num_orb_threads_, + get_opts.opt_arg(), + c, + "num_orb_threads", + 1); + break; + + case 'r': + result = set_arg(this->num_remote_clients_, + get_opts.opt_arg(), + c, + "num_remote_clients"); + break; + + case 'c': + result = set_arg(this->num_collocated_clients_, + get_opts.opt_arg(), + c, + "num_collocated_clients"); + break; + + case 'k': + result = set_arg(this->collocated_client_kind_, + get_opts.opt_arg(), + c, + "collocated_client_kind"); + break; + + case '?': + this->usage_statement(); + return 1; + + default: + this->usage_statement(); + return -1; + } + + if (result != 0) + { + return result; + } + } + + return this->arg_dependency_checks(); +} + +void +ServerApp::usage_statement() +{ + ACE_ERROR((LM_ERROR, + "Usage: %s [options]\n\n" + "OPTIONS:\n\n" + "\t[-p <ior_filename_prefix>]\n" + "\t[-s <num_servants>]\n" + "\t[-n <num_csd_threads>]\n" + "\t[-t <num_orb_threads>]\n" + "\t[-r <num_remote_clients>]\n" + "\t[-c <num_collocated_clients>]\n" + "\t[-k <collocated_client_kind>]\n" + "\t[-?]\n\n", + this->exe_name_.c_str())); +} + + +int +ServerApp::arg_dependency_checks() +{ + return (this->num_remote_clients_ + + this->num_collocated_clients_) > 0 ? 0 : -1; +} + + +int +ServerApp::set_arg(unsigned& value, + const char* arg, + char opt, + const char* name, + int min) +{ + int tmp = ACE_OS::atoi(arg); + + if (tmp < min) + { + ACE_ERROR((LM_ERROR, + "Error: -%c <%s> must be integer type with a value of, " + "at least, %d.\n", opt, name, min)); + this->usage_statement(); + return -1; + } + + value = tmp; + return 0; +} + + +PortableServer::POA_ptr +ServerApp::create_poa(CORBA::ORB_ptr orb, + const char* poa_name + ACE_ENV_ARG_DECL) +{ + // Get the Root POA. + PortableServer::POA_var root_poa + = RefHelper<PortableServer::POA>::resolve_initial_ref(orb, + "RootPOA" + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + // Get the POAManager from the Root POA. + PortableServer::POAManager_var poa_manager + = root_poa->the_POAManager(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + // Create the child POA Policies. + CORBA::PolicyList policies(0); + policies.length(0); + + // Create the child POA + PortableServer::POA_var poa = AppHelper::create_poa(poa_name, + root_poa.in(), + poa_manager.in(), + policies + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + // Give away the child POA_ptr from the POA_var variable. + return poa._retn(); +} + + +bool +ServerApp::check_validity () +{ + // Check whether the clients return any errors. + if (this->num_collocated_clients_ > 0 + && this->collocated_client_task_.failure_count () > 0) + { + return false; + } + + Foo_B_Statistics stats (this->num_remote_clients_, + this->num_collocated_clients_); + + Foo_B_ClientEngine::expected_results (stats); + + for (unsigned i = 0; i < this->num_servants_; i++) + { + this->foo_servants_.servant(i)->gather_stats (stats); + } + + if (this->num_collocated_clients_ > 0) + { + this->cb_servants_.servant (0)->gather_stats (stats); + } + + return stats.actual_vs_expected (); +} + diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_3/ServerApp.h b/TAO/tests/CSD_Strategy_Tests/TP_Test_3/ServerApp.h new file mode 100644 index 00000000000..12af1ec455b --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_3/ServerApp.h @@ -0,0 +1,85 @@ +// $Id$ +#ifndef SERVERAPP_H +#define SERVERAPP_H + +#include "TestAppBase.h" +#include "ServantList_T.h" +#include "ClientTask.h" +#include "Foo_B_i.h" +#include "Callback_i.h" +#include "tao/CSD_ThreadPool/CSD_TP_Strategy.h" +#include "ace/SString.h" + + +class ServerApp : public TestAppBase +{ + public: + + ServerApp(); + virtual ~ServerApp(); + + + protected: + + virtual int run_i(int argc, char* argv[] ACE_ENV_ARG_DECL); + + + private: + + // These are all called, in order, by the run_i() method. + int init(int argc, char* argv[] ACE_ENV_ARG_DECL); + void poa_setup(ACE_ENV_SINGLE_ARG_DECL); + void csd_setup(ACE_ENV_SINGLE_ARG_DECL); + void servant_setup(ACE_ENV_SINGLE_ARG_DECL); + void collocated_setup(ACE_ENV_SINGLE_ARG_DECL); + void poa_activate(ACE_ENV_SINGLE_ARG_DECL); + void run_collocated_clients(ACE_ENV_SINGLE_ARG_DECL); + void run_orb_event_loop(ACE_ENV_SINGLE_ARG_DECL); + bool check_validity (); + void cleanup(); + + + // Helper methods used by the methods above. + int parse_args(int argc, char* argv[]); + + int set_arg(unsigned& value, + const char* arg, + char opt, + const char* name, + int min = 0); + + void usage_statement(); + int arg_dependency_checks(); + + + PortableServer::POA_ptr create_poa(CORBA::ORB_ptr orb, + const char* poa_name + ACE_ENV_ARG_DECL); + + typedef ServantList<Foo_B_i> FooServantListType; + typedef ServantList<Callback_i> CallbackServantListType; + + CORBA::ORB_var orb_; + PortableServer::POA_var poa_; + TAO::CSD::TP_Strategy_Handle tp_strategy_; + + PortableServer::POA_var cb_poa_; + TAO::CSD::TP_Strategy_Handle cb_tp_strategy_; + + FooServantListType foo_servants_; + CallbackServantListType cb_servants_; + + ClientTask collocated_client_task_; + + ACE_CString exe_name_; + + ACE_CString ior_filename_prefix_; + unsigned num_servants_; + unsigned num_csd_threads_; + unsigned num_orb_threads_; + unsigned num_remote_clients_; + unsigned num_collocated_clients_; + unsigned collocated_client_kind_; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_3/client_main.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Test_3/client_main.cpp new file mode 100644 index 00000000000..3814bef5ff9 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_3/client_main.cpp @@ -0,0 +1,7 @@ +// $Id$ +#include "ClientApp.h" +#include "TestAppMain.h" + +TEST_APP_MAIN(ClientApp) + + diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_3/run_test.pl b/TAO/tests/CSD_Strategy_Tests/TP_Test_3/run_test.pl new file mode 100755 index 00000000000..1fdb29e8cc5 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_3/run_test.pl @@ -0,0 +1,170 @@ +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; + +my $status = 0; + +my $iorfname_prefix = "servant"; +my $num_servants = 1; +my $num_orb_threads = 1; +my $num_remote_clients = 1; +my $num_csd_threads = 1; +my $num_collocated_clients = 0; +my $collocated_client_kind = 0; +my $client_kind = 0; + +my $i; +my $j; +my @iorfile; + +my $ARGC = @ARGV; + +if ($ARGC > 0) +{ + if ($ARGC > 1) + { + print STDERR "ERROR: Too many command-line arguments for $0.\n"; + exit 1; + } + + my $subtest = $ARGV[0]; + + if ($subtest eq 'remote') + { + $num_remote_clients = 40; + } + elsif ($subtest eq 'collocated') + { + $num_remote_clients = 0; + $num_collocated_clients = 1; + $num_csd_threads=1; + } + elsif ($subtest eq 'remote_orbthreads') + { + $num_orb_threads = 5; + $num_remote_clients = 40; + } + elsif ($subtest eq 'remote_servants') + { + $num_servants = 5; + $num_remote_clients = 40; + } + elsif ($subtest eq 'remote_csdthreads') + { + $num_csd_threads = 5; + $num_remote_clients = 40; + } + elsif ($subtest eq 'remote_big') + { + $num_csd_threads = 5; + $num_servants = 10; + $num_orb_threads = 4; + $num_remote_clients = 40; + } + elsif ($subtest eq 'big') + { + $num_csd_threads = 5; + $num_servants = 10; + $num_orb_threads = 4; + $num_remote_clients = 40; + $num_collocated_clients = 40; + } + elsif ($subtest eq 'usage') + { + print STDOUT "Usage: $0 [<subtest>]\n" . + "\n" . + "Supported <subtest> values:\n" . + "\n" . + "\tremote\n" . + "\tcollocated\n" . + "\tremote_orbthreads\n" . + "\tremote_servants\n" . + "\tremote_csdthreads\n" . + "\tremote_big\n" . + "\tusage\n" . + "\n"; + exit 0; + } + else + { + print STDERR "ERROR: invalid subtest argument for $0: $subtest\n"; + exit 1; + } +} + +#Delete old ior files. +for ($i = 0; $i < $num_servants; $i++) { + my $servant_id = sprintf("%02d", ($i + 1)); + $iorfile[$i] = PerlACE::LocalFile($iorfname_prefix . "_$servant_id.ior"); + unlink $iorfile[$i]; +} + +$SV = new PerlACE::Process("server_main", + "-p $iorfname_prefix " . + "-s $num_servants " . + "-n $num_csd_threads " . + "-t $num_orb_threads " . + "-r $num_remote_clients " . + "-c $num_collocated_clients " . + "-k $collocated_client_kind"); + +$SV->Spawn(); + +# Wait for the servant ior files created by server. +for ($i = 0; $i < $num_servants; $i++) { + if (PerlACE::waitforfile_timed + ($iorfile[$i], + $PerlACE::wait_interval_for_process_creation) == -1) { + print STDERR "ERROR: cannot find file <$iorfile[$i]>\n"; + $SV->Kill(); + $SV->TimedWait(1); + exit 1; + } +} + +my $count = 0; + +for ($i = 0; $i < $num_remote_clients; $i++) +{ + $client_id = $i + 1; + + $j = $i % $num_servants; + + $CLS[$i] = new PerlACE::Process("client_main", + "-i file://$iorfile[$j] ". + "-k $client_kind ". + "-n $client_id"); + $CLS[$i]->Spawn(); +} + +for ($i = 0; $i < $num_remote_clients; $i++) +{ + $client = $CLS[$i]->WaitKill(60); + + if ($client != 0) + { + print STDERR "ERROR: client $i returned $client\n"; + $status = 1; + } +} + + +$server = $SV->WaitKill(60); + +if ($server != 0) { + print STDERR "ERROR: server returned $server\n"; + $status = 1; +} + +#Delete ior files generated by this run. +for ($i = 0; $i < $num_servants; $i++) { + unlink $iorfile[$i]; +} + +exit $status; diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_3/server_main.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Test_3/server_main.cpp new file mode 100644 index 00000000000..82e987f6d41 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_3/server_main.cpp @@ -0,0 +1,5 @@ +// $Id$ +#include "ServerApp.h" +#include "TestAppMain.h" + +TEST_APP_MAIN(ServerApp) diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_4/CSD_TP_Test_4.mpc b/TAO/tests/CSD_Strategy_Tests/TP_Test_4/CSD_TP_Test_4.mpc new file mode 100644 index 00000000000..ca9f92ac607 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_4/CSD_TP_Test_4.mpc @@ -0,0 +1,21 @@ +// -*- MPC -*- +// $Id$ + +project(*Server): csd_tp_test_exe_c { + exename=server_main + + Source_Files { + ServerApp.cpp + server_main.cpp + } +} + +project(*Client): csd_tp_test_exe_c { + exename=client_main + + Source_Files { + ClientApp.cpp + client_main.cpp + } +} + diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_4/ClientApp.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Test_4/ClientApp.cpp new file mode 100644 index 00000000000..57520df303c --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_4/ClientApp.cpp @@ -0,0 +1,199 @@ +// $Id$ +#include "ClientApp.h" +#include "AppHelper.h" +#include "TestAppExceptionC.h" +#include "Foo_C_ClientEngine.h" +#include "ace/Get_Opt.h" + + +ClientApp::ClientApp() + : TestAppBase("TP_Test_4_Client"), + ior_("Not Set"), + client_kind_(0), + client_id_(0) +{ +} + + +ClientApp::~ClientApp() +{ +} + + +int +ClientApp::run_i(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + int result = this->init(argc, argv ACE_ENV_ARG_PARAMETER); + if (result != 0) + { + return result; + } + ACE_CHECK_RETURN (-1); + + this->client_setup(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + result = this->run_engine(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + this->cleanup(); + + return result; +} + + +int +ClientApp::init(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + this->orb_ = CORBA::ORB_init(argc, argv, "" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Parse the command-line args for this application. + // * Raises -1 if problems are encountered. + // * Returns 1 if the usage statement was explicitly requested. + // * Returns 0 otherwise. + return this->parse_args(argc, argv); +} + + +void +ClientApp::client_setup(ACE_ENV_SINGLE_ARG_DECL) +{ + // Turn the ior_ into a Foo_C obj ref. + Foo_C_var foo = RefHelper<Foo_C>::string_to_ref(this->orb_.in(), + this->ior_.c_str() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + // Create the ClientEngine object, and give it the Foo_C obj ref. + this->engine_ = new Foo_C_ClientEngine(foo.in(), this->client_id_); +} + + +int +ClientApp::run_engine(ACE_ENV_SINGLE_ARG_DECL) +{ + bool result = this->engine_->execute(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + return result ? 0 : -1; +} + + +void +ClientApp::cleanup() +{ +} + + +int +ClientApp::parse_args(int argc, char* argv[]) +{ + this->exe_name_ = argv[0]; + + ACE_Get_Opt get_opts(argc, argv, "i:k:n:"); + + int c; + + while ((c = get_opts()) != -1) + { + int result = 0; + switch (c) + { + case 'i': + this->ior_ = get_opts.opt_arg(); + break; + + case 'k': + result = set_arg(this->client_kind_, + get_opts.opt_arg(), + c, + "client_kind"); + break; + + case 'n': + result = set_arg(this->client_id_, + get_opts.opt_arg(), + c, + "client_id"); + break; + + case '?': + this->usage_statement(); + return 1; + + default: + this->usage_statement(); + return -1; + } + + if (result != 0) + { + return result; + } + } + + return this->arg_dependency_checks(); +} + +void +ClientApp::usage_statement() +{ + ACE_ERROR((LM_ERROR, + "Usage: %s [options]\n\n" + "OPTIONS:\n\n" + "\t[-i <ior>]\n" + "\t[-k <client_kind>]\n" + "\t[-n <client_id>]\n" + "\t[-?]\n\n", + this->exe_name_.c_str())); +} + + +int +ClientApp::arg_dependency_checks() +{ + if (this->ior_ == "Not Set") + { + ACE_ERROR((LM_ERROR, + "Error: Missing required command-line option (-i <ior>).\n")); + this->usage_statement(); + return -1; + } + + if (this->client_id_ <= 0) + { + ACE_ERROR((LM_ERROR, + "Error: Invalid command-line option (-n <client id>). \n" + " The client id should be positive integer. \n")); + this->usage_statement(); + return -1; + } + + return 0; +} + + +int +ClientApp::set_arg(unsigned& value, + const char* arg, + char opt, + const char* name, + int min) +{ + int tmp = ACE_OS::atoi(arg); + + if (tmp < min) + { + ACE_ERROR((LM_ERROR, + "Error: -%c <%s> must be integer type with a value of, " + "at least, %d.\n", opt, name, min)); + this->usage_statement(); + return -1; + } + + value = tmp; + + return 0; +} + diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_4/ClientApp.h b/TAO/tests/CSD_Strategy_Tests/TP_Test_4/ClientApp.h new file mode 100644 index 00000000000..e2f7bf6fc06 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_4/ClientApp.h @@ -0,0 +1,52 @@ +// $Id$ +#ifndef CLIENTAPP_H +#define CLIENTAPP_H + +#include "TestAppBase.h" +#include "ClientEngine.h" +#include "tao/ORB.h" +#include "ace/SString.h" + + +class ClientApp : public TestAppBase +{ + public: + + ClientApp(); + virtual ~ClientApp(); + + protected: + + virtual int run_i(int argc, char* argv[] ACE_ENV_ARG_DECL); + + + private: + + // These are all called, in order, by the run_i() method. + int init(int argc, char* argv[] ACE_ENV_ARG_DECL); + void client_setup(ACE_ENV_SINGLE_ARG_DECL); + int run_engine(ACE_ENV_SINGLE_ARG_DECL); + void cleanup(); + + // Helper methods used by the methods above. + int parse_args(int argc, char* argv[]); + + int set_arg(unsigned& value, + const char* arg, + char opt, + const char* name, + int min = 0); + + void usage_statement(); + int arg_dependency_checks(); + + + CORBA::ORB_var orb_; + ACE_CString exe_name_; + ACE_CString ior_; + unsigned client_kind_; + ClientEngine_Handle engine_; + unsigned client_id_; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_4/README b/TAO/tests/CSD_Strategy_Tests/TP_Test_4/README new file mode 100644 index 00000000000..100428e0103 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_4/README @@ -0,0 +1,337 @@ +// $Id$ +=========================================================================== +Directory: $TAO_ROOT/tests/CSD_Strategy_Tests/TP_Test_4 + +Uses Libs: $TAO_ROOT/tests/CSD_Strategy_Tests/TP_Test_Lib + $TAO_ROOT/tests/CSD_Strategy_Tests/TP_Foo_C + +=========================================================================== +Executable: server_main + +Description: The test server application. + +Command-Line: + + % server_main [options] + + where, [options] includes the following: + + -p <ior_filename_prefix> + -s <num_servants> + -n <num_csd_threads> + -t <num_orb_threads> + -r <num_remote_clients> + -c <num_collocated_clients> + -k <collocated_client_kind> + -? + +Command-Line Arguments: + + -p <ior_filename_prefix> + + If not specified, the <ior_filename_prefix> defaults to "foo". + This value is used as the prefix for the filename(s) to which + the server application will write stringified object reference(s). + Each "IOR file" contains the (stringified) object reference + associated with a distinct servant object within the server + application. These files are the way that the client application(s) + are able to "locate" the object reference(s) upon which they will + invoke (CORBA) operations. In essence, the filesystem is used + as a "poor-man" Naming Service. + + The filenames are of the form, "prefix_%02d.ior", using a unique + integer "id" for each file - starting with an "id" of 1. Thus, + if the server application was told to create 3 servants (via the + -s <num_servants> option), and the <ior_filename_prefix> is "foo", + then three files will be written by the server application: + + foo_01.ior + foo_02.ior + foo_03.ior + + + -s <num_servants> + + The <num_servants> must be an integer value greater than 0. + + If not specified, the <num_servants> defaults to 1. This is used + to inform the server application of the number of distinct servant + objects that it should create. + + + -n <num_csd_threads> + + The <num_csd_threads> must be an integer value greater than 0. + + If not specified, the <num_csd_threads> defaults to 1. This is + used to inform the server application of the number of worker + threads that should be activated by the Thread Pool CSD Strategy. + The worker threads are responsible for servicing the strategy's + request queue. This can also be called the "size of the thread + pool". + + + -t <num_orb_threads> + + The <num_orb_threads> must be an integer value greater than 0. + + If not specified, the <num_orb_threads> defaults to 1. This option + is used to tell the server application how many distinct threads + should be used to run the ORB event loop. The "mainline thread" + will always run the ORB event loop itself, so that accounts for + one of the num_orb_threads. If num_orb_threads is greater than 1, + then (num_orb_threads - 1) threads will be activated by the server + application, and each of these threads will run the ORB event loop. + The end result is that there will be <num_orb_threads> distinct + threads (including the mainline thread) running the ORB event loop. + + + -r <num_remote_clients> + + The <num_remote_clients> must be an integer value greater than, + or equal to, 0. In addition, the sum of the <num_remote_clients> + and the <num_collocated_clients> (see the -c option) must be + greater than 0. Both cannot be 0, since the server application + would interpret this to mean that no clients will ever use it, + and that's kind of pointless. + + If not specified, the <num_remote_clients> defaults to 1. This + option informs the server application how many remote clients it + can expect to "hear" from over the course of its lifetime. Each + distinct test client, remote or collocated, is required to invoke + the done() operation on one of the servant objects. The server + application decides to shut itself down gracefully when it has + received one done() invocation for each remote client and for + each collocated client. Once all of the expected done() calls + have been made, the server application assumes that no more clients + will need its services, and thus it shuts itself down. This is + used to support the automated test scenarios implemented within + the run_test.pl script. It provides a way for a test scenario to + automate the graceful shutdown of the server by telling the server + how many clients to expect (remote + collocated). + + + -c <num_collocated_clients> + + The <num_collocated_clients> must be an integer value greater than, + or equal to, 0. In addition, the sum of the <num_collocated_clients> + and the <num_remote_clients> (see the -r option) must be + greater than 0. Both cannot be 0, since the server application + would interpret this to mean that no clients will ever use it, + and that's kind of pointless. + + If not specified, the <num_collocated_clients> defaults to 0. This + option informs the server application how many collocated clients + should "live", collocated, within the server application. Each + collocated client will execute its logic in a distinct thread + within the server application. As an example, if the server + application was told to use a <num_collocated_clients> value of 40, + then the server application will activate 40 threads - each + carrying out the logic of one "client". This client "logic" is + identical to the logic carried out by a single remote client + application (client_main) process. As with remote clients, + each collocated client will invoke the done() operation on + one of the servants (via an object ref) when the client logic + has been completed. See the "-r <num_remote_clients>" option + for more information about the done() operation, and its purpose. + + For this particular server application (TP_Test_4), each + collocated client will perform the normal client logic as well + as carry out a set of "custom" requests on the collocated servant. + Custom operations not defined in IDL. + + + -k <collocated_client_kind> + + This is reserved for future use. It currently doesn't get used + for anything. + + + -? + + This is used to request the "Usage Statement" for the Server + Application (ie, "server_main -?" prints the usage statement). + + +=========================================================================== +Executable: client_main + +Description: The test client application. + +Command-Line: + + % client_main [options] + + where, [options] includes the following: + + -i <ior> + -n <client_id> + -k <collocated_client_kind> + -? + + +Command-Line Arguments: + + -i <ior> + + The <ior> is required, and must be a valid IOR. In our case, where + the server application saves stringified object references to files, + we supply the client application with an <ior> in the following + form: "file://foo_01.ior". See the server application's description + of its "-p <ior_filename_prefix>" option for more information. + + The client application will use the <ior> to obtain an object + reference using the CORBA::ORB::string_to_object() method. This + is the object reference upon which the client logic will invoke + operations. The object reference will be associated with a + distinct servant object within the server application. + + + -n <client_id> + + The <client_id> is required, and must be an integer value greater + than 0. + + As part of the logic used to check actual vs. expected results, + each client is assigned a unique id. As a side-note, each + collocated client within the server application (if there are + any) will also be assigned a unique client_id. For any given + test scenario run by the run_test.pl script, each client (remote + and/or collocated) will be assigned a unique client_id. + + The server application assigns client_ids to its collocated clients + based upon its knowledge of how many remote clients will be used + in the test scenario (see the "-r <num_remote_clients>" option + for the server application). The server application assumes that + the run_test.pl will assign client_ids to remote clients starting + with 1, and up to the <num_remote_clients>. Thus, the server + application assigns client_ids to collocated clients starting + with (<num_remote_clients> + 1), and incrementing by 1 for each + additional collocated client_id. + + + -k <collocated_client_kind> + + This is reserved for future use. It currently doesn't get used + for anything. + + + -? + + This is used to request the "Usage Statement" for the Client + Application (ie, "client_main -?" prints the usage statement). + + +=========================================================================== +Executable: run_test.pl (PERL script). + +Description: Script used to run a specific test scenario. This includes + the launching of a server application process and client + applications processes as called for by the specific scenario. + +Command-Line: + + % run_test.pl <scenario> + + where, <scenario> can be one of the following values: + + "big" + "a" + "b" + + If a <scenario> is not specified on the run_test.pl command-line, + then a default scenario is used. + + +Scenarios: + + ----------------------------------------------------------------------- + Default: (when no <scenario> is specified on the command-line) + + $iorfname_prefix = "servant"; + $num_servants = 1; + $num_orb_threads = 1; + $num_remote_clients = 1; + $num_csd_threads = 1; + $num_collocated_clients = 0; + + ----------------------------------------------------------------------- + "remote": + + Uses the Default values, with the following overrides: + + $num_remote_clients = 40; + + ----------------------------------------------------------------------- + "collocated": + + Uses the Default values, with the following overrides: + + $num_remote_clients = 0; + $num_collocated_clients = 1; + + ----------------------------------------------------------------------- + "collocated_big": + + Uses the Default values, with the following overrides: + + $num_remote_clients = 0; + $num_csd_threads = 5; + $num_collocated_clients = 40; + + ----------------------------------------------------------------------- + "remote_orbthreads": + + Uses the Default values, with the following overrides: + + $num_orb_threads = 5; + $num_remote_clients = 40; + + ----------------------------------------------------------------------- + "remote_servants": + + Uses the Default values, with the following overrides: + + $num_servants = 5; + $num_remote_clients = 40; + + ----------------------------------------------------------------------- + "remote_csdthreads": + + Uses the Default values, with the following overrides: + + $num_csd_threads = 5; + $num_remote_clients = 40; + + ----------------------------------------------------------------------- + "remote_big": + + Uses the Default values, with the following overrides: + + $num_csd_threads = 5; + $num_servants = 10; + $num_orb_threads = 4; + $num_remote_clients = 40; + + ----------------------------------------------------------------------- + "big": + + Uses the Default values, with the following overrides: + + $num_csd_threads = 5; + $num_servants = 10; + $num_orb_threads = 4; + $num_remote_clients = 40; + $num_collocated_clients = 40; + + ----------------------------------------------------------------------- + "usage": + + This is not really a test scenario, but it will cause the + run_test.pl script to print a "Usage Statement", which includes + a list of the supported <scenario> values. + + ----------------------------------------------------------------------- + + +=========================================================================== diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_4/ServerApp.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Test_4/ServerApp.cpp new file mode 100644 index 00000000000..93c4ba59b53 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_4/ServerApp.cpp @@ -0,0 +1,383 @@ +// $Id$ +#include "ServerApp.h" +#include "AppHelper.h" +#include "OrbRunner.h" +#include "AppShutdown.h" +#include "TestAppExceptionC.h" +#include "Foo_C_Custom_ClientEngine.h" +#include "Foo_C_ClientEngine.h" +#include "Foo_C_Statistics.h" +#include "ace/OS.h" +#include "ace/Get_Opt.h" +// To force static load the service. +#include "tao/CSD_ThreadPool/CSD_ThreadPool.h" + +ServerApp::ServerApp() + : TestAppBase("TP_Test_4_Server"), + ior_filename_prefix_("foo"), + num_servants_(1), + num_csd_threads_(1), + num_orb_threads_(1), + num_remote_clients_(1), + num_collocated_clients_(0), + collocated_client_kind_(0) +{ +} + + +ServerApp::~ServerApp() +{ +} + + +int +ServerApp::run_i(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + int result = this->init(argc, argv ACE_ENV_ARG_PARAMETER); + if (result != 0) + { + return result; + } + ACE_CHECK_RETURN (-1); + + this->poa_setup(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->csd_setup(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->servant_setup(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->collocated_setup(); + this->poa_activate(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->run_collocated_clients(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->run_orb_event_loop(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->cleanup(); + return this->check_validity () ? 0 : -1; +} + + +int +ServerApp::init(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + this->orb_ = CORBA::ORB_init(argc, argv, "" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Parse the command-line args for this application. + // * Raises -1 if problems are encountered. + // * Returns 1 if the usage statement was explicitly requested. + // * Returns 0 otherwise. + int result = this->parse_args(argc, argv); + if (result != 0) + { + return result; + } + + unsigned num_clients = this->num_remote_clients_ + + this->num_collocated_clients_; + + TheAppShutdown->init(this->orb_.in(), num_clients ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + return 0; +} + + +void +ServerApp::poa_setup(ACE_ENV_SINGLE_ARG_DECL) +{ + this->poa_ = this->create_poa(this->orb_.in(), + "ChildPoa" + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; +} + + +void +ServerApp::csd_setup(ACE_ENV_SINGLE_ARG_DECL) +{ + this->tp_strategy_ = new TAO::CSD::TP_Strategy(this->num_csd_threads_); + + if (!this->tp_strategy_->apply_to(this->poa_.in() ACE_ENV_ARG_PARAMETER)) + { + ACE_ERROR((LM_ERROR, + "Failed to apply CSD strategy to poa.\n")); + ACE_THROW(TestAppException()); + } + ACE_CHECK; +} + + +void +ServerApp::servant_setup(ACE_ENV_SINGLE_ARG_DECL) +{ + this->servants_.create_and_activate(this->num_servants_, + this->orb_.in (), + this->poa_.in (), + this->ior_filename_prefix_.c_str() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; +} + + +void +ServerApp::collocated_setup() +{ + int custom_client_id_start = this->num_remote_clients_; + + unsigned servant_index = 0; + + for (unsigned i = 0; i < this->num_collocated_clients_; i++) + { + if (i > 0) + { + // Dole out the servant object references in a round-robin fashion. + servant_index = (servant_index + 1) % this->num_servants_; + } + + ServantListType::T_stub_var obj = this->servants_.objref(servant_index); + + ClientEngine_Handle engine = + new Foo_C_Custom_ClientEngine(this->servants_.servant(servant_index), + obj.in(), + this->tp_strategy_.in(), + ++ custom_client_id_start); + this->collocated_client_task_.add_engine(engine.in()); + } +} + + +void +ServerApp::poa_activate(ACE_ENV_SINGLE_ARG_DECL) +{ + PortableServer::POAManager_var poa_manager + = this->poa_->the_POAManager(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + + poa_manager->activate(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; +} + + +void +ServerApp::run_collocated_clients(ACE_ENV_SINGLE_ARG_DECL) +{ + if (this->num_collocated_clients_ > 0) + { + if (this->collocated_client_task_.open() == -1) + { + ACE_THROW (TestAppException ()); + } + } +} + + +void +ServerApp::run_orb_event_loop(ACE_ENV_SINGLE_ARG_DECL) +{ + OrbRunner orb_runner(this->orb_.in(), this->num_orb_threads_); + orb_runner.run(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + TheAppShutdown->wait (); +} + + +void +ServerApp::cleanup() +{ + for (unsigned i = 0; i < this->num_servants_; i++) + { + this->servants_.servant(i)->dump(); + } + + // Wait for all of the collocated client task threads to finish. + if (this->num_collocated_clients_ > 0) + { + this->collocated_client_task_.wait(); + } +} + + +int +ServerApp::parse_args(int argc, char* argv[]) +{ + this->exe_name_ = argv[0]; + + ACE_Get_Opt get_opts(argc, argv, "p:s:n:t:r:c:k:"); + + int c; + + while ((c = get_opts()) != -1) + { + int result = 0; + switch (c) + { + case 'p': + this->ior_filename_prefix_ = get_opts.opt_arg(); + break; + + case 's': + result = this->set_arg(this->num_servants_, + get_opts.opt_arg(), + c, + "num_servants", + 1); + break; + + case 'n': + result = this->set_arg(this->num_csd_threads_, + get_opts.opt_arg(), + c, + "num_servants", + 1); + break; + + case 't': + result = this->set_arg(this->num_orb_threads_, + get_opts.opt_arg(), + c, + "num_orb_threads", + 1); + break; + + case 'r': + result = this->set_arg(this->num_remote_clients_, + get_opts.opt_arg(), + c, + "num_remote_clients"); + break; + + case 'c': + result = this->set_arg(this->num_collocated_clients_, + get_opts.opt_arg(), + c, + "num_collocated_clients"); + break; + + case 'k': + result = this->set_arg(this->collocated_client_kind_, + get_opts.opt_arg(), + c, + "collocated_client_kind"); + break; + + case '?': + this->usage_statement(); + return 1; + + default: + this->usage_statement(); + return -1; + } + + if (result != 0) + { + return result; + } + } + + return this->arg_dependency_checks(); +} + +void +ServerApp::usage_statement() +{ + ACE_ERROR((LM_ERROR, + "Usage: %s [options]\n\n" + "OPTIONS:\n\n" + "\t[-p <ior_filename_prefix>]\n" + "\t[-s <num_servants>]\n" + "\t[-n <num_csd_threads>]\n" + "\t[-t <num_orb_threads>]\n" + "\t[-r <num_remote_clients>]\n" + "\t[-c <num_collocated_clients>]\n" + "\t[-k <collocated_client_kind>]\n" + "\t[-?]\n\n", + this->exe_name_.c_str())); +} + + +int +ServerApp::arg_dependency_checks() +{ + return (this->num_remote_clients_ + + this->num_collocated_clients_) > 0 ? 0 : -1; +} + + +int +ServerApp::set_arg(unsigned& value, + const char* arg, + char opt, + const char* name, + int min) +{ + int tmp = ACE_OS::atoi(arg); + + if (tmp < min) + { + ACE_ERROR((LM_ERROR, + "Error: -%c <%s> must be integer type with a value of, " + "at least, %d.\n", opt, name, min)); + this->usage_statement(); + return -1; + } + + value = tmp; + + return 0; +} + + +PortableServer::POA_ptr +ServerApp::create_poa(CORBA::ORB_ptr orb, + const char* poa_name + ACE_ENV_ARG_DECL) +{ + // Get the Root POA. + PortableServer::POA_var root_poa + = RefHelper<PortableServer::POA>::resolve_initial_ref(orb, + "RootPOA" + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + // Get the POAManager from the Root POA. + PortableServer::POAManager_var poa_manager + = root_poa->the_POAManager(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + // Create the child POA Policies. + CORBA::PolicyList policies(0); + policies.length(0); + + // Create the child POA + PortableServer::POA_var poa + = AppHelper::create_poa(poa_name, + root_poa.in(), + poa_manager.in(), + policies + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + // Give away the child POA_ptr from the POA_var variable. + return poa._retn(); +} + + +bool +ServerApp::check_validity () +{ + Foo_C_Statistics stats (this->num_remote_clients_, + this->num_collocated_clients_); + + Foo_C_ClientEngine::expected_results (stats); + Foo_C_Custom_ClientEngine::expected_results (stats); + + for (unsigned i = 0; i < this->num_servants_; i++) + { + this->servants_.servant(i)->gather_stats(stats); + } + + return stats.actual_vs_expected (); +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_4/ServerApp.h b/TAO/tests/CSD_Strategy_Tests/TP_Test_4/ServerApp.h new file mode 100644 index 00000000000..99f0af758b5 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_4/ServerApp.h @@ -0,0 +1,79 @@ +// $Id$ +#ifndef SERVERAPP_H +#define SERVERAPP_H + +#include "TestAppBase.h" +#include "Foo_C_i.h" +#include "ServantList_T.h" +#include "ClientTask.h" +#include "tao/CSD_ThreadPool/CSD_TP_Strategy.h" +#include "ace/SString.h" + + +class ServerApp : public TestAppBase +{ + public: + + ServerApp(); + virtual ~ServerApp(); + + + protected: + + virtual int run_i(int argc, char* argv[] ACE_ENV_ARG_DECL); + + + private: + + // These are all called, in order, by the run_i() method. + int init(int argc, char* argv[] ACE_ENV_ARG_DECL); + void poa_setup(ACE_ENV_SINGLE_ARG_DECL); + void csd_setup(ACE_ENV_SINGLE_ARG_DECL); + void servant_setup(ACE_ENV_SINGLE_ARG_DECL); + void collocated_setup(); + void poa_activate(ACE_ENV_SINGLE_ARG_DECL); + void run_collocated_clients(ACE_ENV_SINGLE_ARG_DECL); + void run_orb_event_loop(ACE_ENV_SINGLE_ARG_DECL); + bool check_validity (); + void cleanup(); + + + // Helper methods used by the methods above. + int parse_args(int argc, char* argv[]); + + int set_arg(unsigned& value, + const char* arg, + char opt, + const char* name, + int min = 0); + + void usage_statement(); + int arg_dependency_checks(); + + + PortableServer::POA_ptr create_poa(CORBA::ORB_ptr orb, + const char* poa_name + ACE_ENV_ARG_DECL); + + typedef ServantList<Foo_C_i> ServantListType; + + CORBA::ORB_var orb_; + PortableServer::POA_var poa_; + TAO::CSD::TP_Strategy_Handle tp_strategy_; + + ServantListType servants_; + + ClientTask collocated_client_task_; + + ACE_CString exe_name_; + + ACE_CString ior_filename_prefix_; + unsigned num_servants_; + unsigned num_csd_threads_; + unsigned num_orb_threads_; + unsigned num_remote_clients_; + unsigned num_collocated_clients_; + unsigned collocated_client_kind_; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_4/client_main.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Test_4/client_main.cpp new file mode 100644 index 00000000000..3814bef5ff9 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_4/client_main.cpp @@ -0,0 +1,7 @@ +// $Id$ +#include "ClientApp.h" +#include "TestAppMain.h" + +TEST_APP_MAIN(ClientApp) + + diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_4/run_test.pl b/TAO/tests/CSD_Strategy_Tests/TP_Test_4/run_test.pl new file mode 100755 index 00000000000..5b93da07b74 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_4/run_test.pl @@ -0,0 +1,177 @@ +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; + +my $status = 0; + +my $iorfname_prefix = "servant"; +my $num_servants = 1; +my $num_orb_threads = 1; +my $num_remote_clients = 1; +my $num_csd_threads = 1; +my $num_collocated_clients = 0; +my $collocated_client_kind = 0; +my $client_kind = 0; + +my $i; +my $j; +my @iorfile; + +my $ARGC = @ARGV; + +if ($ARGC > 0) +{ + if ($ARGC > 1) + { + print STDERR "ERROR: Too many command-line arguments for $0.\n"; + exit 1; + } + + my $subtest = $ARGV[0]; + + if ($subtest eq 'remote') + { + $num_remote_clients = 40; + } + elsif ($subtest eq 'collocated') + { + $num_remote_clients = 0; + $num_collocated_clients = 1; + } + elsif ($subtest eq 'collocated_big') + { + $num_remote_clients = 0; + $num_csd_threads = 5; + $num_collocated_clients = 40; + } + elsif ($subtest eq 'remote_orbthreads') + { + $num_orb_threads = 5; + $num_remote_clients = 40; + } + elsif ($subtest eq 'remote_servants') + { + $num_servants = 5; + $num_remote_clients = 40; + } + elsif ($subtest eq 'remote_csdthreads') + { + $num_csd_threads = 5; + $num_remote_clients = 40; + } + elsif ($subtest eq 'remote_big') + { + $num_csd_threads = 5; + $num_servants = 10; + $num_orb_threads = 4; + $num_remote_clients = 40; + } + elsif ($subtest eq 'big') + { + $num_csd_threads = 5; + $num_servants = 10; + $num_orb_threads = 4; + $num_remote_clients = 40; + $num_collocated_clients = 40; + } + elsif ($subtest eq 'usage') + { + print STDOUT "Usage: $0 [<subtest>]\n" . + "\n" . + "Supported <subtest> values:\n" . + "\n" . + "\tremote\n" . + "\tcollocated\n" . + "\tremote_orbthreads\n" . + "\tremote_servants\n" . + "\tremote_csdthreads\n" . + "\tremote_big\n" . + "\tusage\n" . + "\n"; + exit 0; + } + else + { + print STDERR "ERROR: invalid subtest argument for $0: $subtest\n"; + exit 1; + } +} + +#Delete old ior files. +for ($i = 0; $i < $num_servants; $i++) { + my $servant_id = sprintf("%02d", ($i + 1)); + $iorfile[$i] = PerlACE::LocalFile($iorfname_prefix . "_$servant_id.ior"); + unlink $iorfile[$i]; +} + +$SV = new PerlACE::Process("server_main", + "-p $iorfname_prefix " . + "-s $num_servants " . + "-n $num_csd_threads " . + "-t $num_orb_threads " . + "-r $num_remote_clients " . + "-c $num_collocated_clients " . + "-k $collocated_client_kind"); + +$SV->Spawn(); + +# Wait for the servant ior files created by server. +for ($i = 0; $i < $num_servants; $i++) { + if (PerlACE::waitforfile_timed + ($iorfile[$i], + $PerlACE::wait_interval_for_process_creation) == -1) { + print STDERR "ERROR: cannot find file <$iorfile[$i]>\n"; + $SV->Kill(); + $SV->TimedWait(1); + exit 1; + } +} + +my $count = 0; + +for ($i = 0; $i < $num_remote_clients; $i++) +{ + + $client_id = $i+1; + + $j = $i % $num_servants; + + $CLS[$i] = new PerlACE::Process("client_main", + "-i file://$iorfile[$j] ". + "-k $client_kind ". + "-n $client_id"); + + $CLS[$i]->Spawn(); +} + +for ($i = 0; $i < $num_remote_clients; $i++) +{ + $client = $CLS[$i]->WaitKill(60); + + if ($client != 0) + { + print STDERR "ERROR: client $i returned $client\n"; + $status = 1; + } +} + + +$server = $SV->WaitKill(60); + +if ($server != 0) { + print STDERR "ERROR: server returned $server\n"; + $status = 1; +} + +#Delete ior files generated by this run. +for ($i = 0; $i < $num_servants; $i++) { + unlink $iorfile[$i]; +} + +exit $status; diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_4/server_main.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Test_4/server_main.cpp new file mode 100644 index 00000000000..82e987f6d41 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_4/server_main.cpp @@ -0,0 +1,5 @@ +// $Id$ +#include "ServerApp.h" +#include "TestAppMain.h" + +TEST_APP_MAIN(ServerApp) diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_Dynamic/CSD_TP_Test_Dynamic.mpc b/TAO/tests/CSD_Strategy_Tests/TP_Test_Dynamic/CSD_TP_Test_Dynamic.mpc new file mode 100644 index 00000000000..5b90572b45d --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_Dynamic/CSD_TP_Test_Dynamic.mpc @@ -0,0 +1,20 @@ +// -*- MPC -*- +// $Id$ + +project(*Server): taoserver { + idlflags += -Sa -St + Source_Files { + Hello.cpp + server.cpp + } +} + +project(*Client): taoclient { + Source_Files { + TestC.cpp + client.cpp + } +} + + + diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_Dynamic/Hello.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Test_Dynamic/Hello.cpp new file mode 100644 index 00000000000..70af3ea8a11 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_Dynamic/Hello.cpp @@ -0,0 +1,25 @@ +// +// $Id$ +// +#include "Hello.h" + +ACE_RCSID(Hello, Hello, "$Id$") + +Hello::Hello (CORBA::ORB_ptr orb) + : orb_ (CORBA::ORB::_duplicate (orb)) +{ +} + +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); +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_Dynamic/Hello.h b/TAO/tests/CSD_Strategy_Tests/TP_Test_Dynamic/Hello.h new file mode 100644 index 00000000000..9097ddddbb4 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_Dynamic/Hello.h @@ -0,0 +1,45 @@ +// +// $Id$ +// + +#ifndef HELLO_H +#define HELLO_H +#include /**/ "ace/pre.h" + +#include "TestS.h" + +#if defined (_MSC_VER) +# if (_MSC_VER >= 1200) +# pragma warning(push) +# endif /* _MSC_VER >= 1200 */ +# 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); + + // = 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)); + +private: + /// Use an ORB reference to conver strings to objects and shutdown + /// the application. + CORBA::ORB_var orb_; +}; + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma warning(pop) +#endif /* _MSC_VER */ + +#include /**/ "ace/post.h" +#endif /* HELLO_H */ diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_Dynamic/README b/TAO/tests/CSD_Strategy_Tests/TP_Test_Dynamic/README new file mode 100644 index 00000000000..a4e3fbcdc2a --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_Dynamic/README @@ -0,0 +1,37 @@ +// $Id$ +=========================================================================== +Directory: $TAO_ROOT/tests/CSD_Strategy_Tests/TP_Test_5 + +=========================================================================== + +=========================================================================== +Directory: $TAO_ROOT/tests/CSD_Strategy_Tests/TP_Test_Static + +=========================================================================== +This test shows the ThreadPool strategy can automatically apply to the poa +via service configuration file dynamic directive. + +This simple test is a copy of $TAO_ROOT/tests/Hello test. The difference is +this test contains the svc.conf file to configure the CSD strategies and the +poas that apply the CSD strategy. + +A new TP_Strategy object is created during the initialization of the +TP_Strategy_Factory service object and it will be automatically applied to +a poa. + +The service configuration file specifies the number of threads that +the ThreadPool strategy have and also specify which poa the strategy should +apply to. We can specify multiple ThreadPool strategies and the poas via -CSDtp +option. + +e.g +dynamic TAO_CSD_TP_Strategy_Factory Service_Object * +TAO_CSD_ThreadPool:_make_TAO_CSD_TP_Strategy_Factory() "-CSDtp RootPOA:2 -CSDtp childpoa:4" + + +To run the test use the run_test.pl script: + +$ ./run_test.pl + + the script returns 0 if the test was successful. + diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_Dynamic/Test.idl b/TAO/tests/CSD_Strategy_Tests/TP_Test_Dynamic/Test.idl new file mode 100644 index 00000000000..3c0976e106d --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_Dynamic/Test.idl @@ -0,0 +1,20 @@ +// +// $Id$ +// + +/// Put the interfaces in a module, to avoid global namespace pollution +module Test +{ + /// A very simple interface + interface Hello + { + /// Return a simple string + string get_string (); + + /// A method to shutdown the ORB + /** + * This method is used to simplify the test shutdown process + */ + oneway void shutdown (); + }; +}; diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_Dynamic/client.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Test_Dynamic/client.cpp new file mode 100644 index 00000000000..f85722246b5 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_Dynamic/client.cpp @@ -0,0 +1,86 @@ +// $Id$ + +#include "TestC.h" +#include "ace/Get_Opt.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[]) +{ + 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, + "Nil Test::Hello reference <%s>\n", + ior), + 1); + } + + CORBA::String_var the_string = + hello->get_string (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + ACE_DEBUG ((LM_DEBUG, "(%P|%t) - string returned <%s>\n", + the_string.in ())); + + 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, + "Exception caught:"); + return 1; + } + ACE_ENDTRY; + + return 0; +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_Dynamic/run_test.pl b/TAO/tests/CSD_Strategy_Tests/TP_Test_Dynamic/run_test.pl new file mode 100755 index 00000000000..02041ea0c25 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_Dynamic/run_test.pl @@ -0,0 +1,43 @@ +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; + +$iorfile = PerlACE::LocalFile ("server.ior"); +unlink $iorfile; +$status = 0; + +$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/tests/CSD_Strategy_Tests/TP_Test_Dynamic/server.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Test_Dynamic/server.cpp new file mode 100644 index 00000000000..177aad4d1d8 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_Dynamic/server.cpp @@ -0,0 +1,115 @@ +// $Id$ + +#include "Hello.h" +#include "ace/Get_Opt.h" +#include "ace/OS_NS_stdio.h" + +ACE_RCSID (Hello, + server, + "$Id$") + +const char *ior_output_file = "test.ior"; + +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; +} + +int +main (int argc, char *argv[]) +{ + ACE_TRY_NEW_ENV + { + 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; + + if (parse_args (argc, argv) != 0) + return 1; + + Hello *hello_impl; + ACE_NEW_RETURN (hello_impl, + Hello (orb.in ()), + 1); + PortableServer::ServantBase_var owner_transfer(hello_impl); + + Test::Hello_var hello = + hello_impl->_this (ACE_ENV_SINGLE_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", + 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; + + 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/tests/CSD_Strategy_Tests/TP_Test_Dynamic/svc.conf b/TAO/tests/CSD_Strategy_Tests/TP_Test_Dynamic/svc.conf new file mode 100644 index 00000000000..e59fb4ac94c --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_Dynamic/svc.conf @@ -0,0 +1 @@ +dynamic TAO_CSD_TP_Strategy_Factory Service_Object * TAO_CSD_ThreadPool:_make_TAO_CSD_TP_Strategy_Factory() "-CSDtp RootPOA:2" diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_Static/CSD_TP_Test_Static.mpc b/TAO/tests/CSD_Strategy_Tests/TP_Test_Static/CSD_TP_Test_Static.mpc new file mode 100644 index 00000000000..02cac4dc7da --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_Static/CSD_TP_Test_Static.mpc @@ -0,0 +1,21 @@ +// -*- MPC -*- +// $Id$ + +project(*Server): csd_tp_test_exe_a { + exename=server_main + + Source_Files { + ServerApp.cpp + server_main.cpp + } +} + +project(*Client): csd_tp_test_exe_a { + exename=client_main + + Source_Files { + ClientApp.cpp + client_main.cpp + } +} + diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_Static/ClientApp.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Test_Static/ClientApp.cpp new file mode 100644 index 00000000000..4fc25f46c1c --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_Static/ClientApp.cpp @@ -0,0 +1,86 @@ +// $Id$ +#include "ClientApp.h" +#include "Foo_A_ClientEngine.h" +#include "AppHelper.h" +#include "TestAppExceptionC.h" +#include "ace/Get_Opt.h" +#include "ace/Log_Msg.h" +// To force static load the service. +#include "tao/CSD_ThreadPool/CSD_ThreadPool.h" + +ClientApp::ClientApp() + : TestAppBase("TP_Test_1_Client"), + ior_ ("file://test.ior") +{ +} + + +ClientApp::~ClientApp() +{ +} + + +int +ClientApp::run_i(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + // Initialize the ORB before parsing our own args. + CORBA::ORB_var orb = CORBA::ORB_init(argc, argv, "" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Parse the command-line args for this application. + // * Returns -1 if problems are encountered. + // * Returns 1 if the usage statement was explicitly requested. + // * Returns 0 otherwise. + int result = this->parse_args(argc, argv); + if (result != 0) + { + return result; + } + // Convert the IOR string to a Foo_A object reference. + Foo_A_var foo = RefHelper<Foo_A>::string_to_ref(orb.in(), + this->ior_.c_str() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Create the appropriate client "engine" object. + Foo_A_ClientEngine engine(foo.in()); + + // Execute the client algorithm + result = engine.execute(ACE_ENV_SINGLE_ARG_PARAMETER) ? 0 : -1; + ACE_CHECK_RETURN (-1); + + return result; +} + + +int +ClientApp::parse_args(int argc, char* argv[]) +{ + ACE_Get_Opt get_opts(argc, argv, "i:"); + + int c; + + while ((c = get_opts()) != -1) + { + switch (c) + { + case 'i': + this->ior_ = get_opts.opt_arg(); + break; + + case '?': + ACE_DEBUG((LM_DEBUG, + "(%P|%t) usage: %s -i <ior_string>\n", + argv[0])); + return 1; + + default: + ACE_ERROR((LM_ERROR, + "(%P|%t) usage: %s -i <ior_string>\n", + argv[0])); + return -1; + } + } + + return 0; +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_Static/ClientApp.h b/TAO/tests/CSD_Strategy_Tests/TP_Test_Static/ClientApp.h new file mode 100644 index 00000000000..1af2e9ff6a6 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_Static/ClientApp.h @@ -0,0 +1,28 @@ +// $Id$ +#ifndef CLIENTAPP_H +#define CLIENTAPP_H + +#include "TestAppBase.h" +#include "ace/SString.h" + + +class ClientApp : public TestAppBase +{ + public: + + ClientApp(); + virtual ~ClientApp(); + + protected: + + virtual int run_i(int argc, char* argv[] ACE_ENV_ARG_DECL); + + + private: + + int parse_args(int argc, char* argv[]); + + ACE_CString ior_; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_Static/README b/TAO/tests/CSD_Strategy_Tests/TP_Test_Static/README new file mode 100644 index 00000000000..8090bdb87ce --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_Static/README @@ -0,0 +1,38 @@ +// $Id$ +=========================================================================== +Directory: $TAO_ROOT/tests/CSD_Strategy_Tests/TP_Test_Static + +=========================================================================== +This test shows the ThreadPool strategy can automatically apply to the poa +via service configuration file static directive. + +This simple test is a copy of TP_Test_1. The difference is the test +application does not need to create the TP_Strategy object and apply to the +poa. A new TP_Strategy object is created during the initialization of the +TP_Strategy_Factory service object and it will be automatically applied to +a poa. + +The application needs to include the following two files to force the +TAO_CSD_ORB_Loader and TAO_CSD_TP_Strategy_Factory service objects register +with the service repository before initializing the services specified in +.conf file. + +#include "tao/CSD_Framework/CSD_ORB_Loader.h" +#include "tao/CSD_ThreadPool/CSD_TP_Strategy_Factory.h" + + +The service configuration file specifies the number of threads that +the ThreadPool strategy have and also specify which poa the strategy should +apply to. We can specify multiple ThreadPool strategies and the poas via -CSDtp +option. + +e.g +static TAO_CSD_TP_Strategy_Factory "-CSDtp RootPOA:2 -CSDtp ChildPoa:3" + + +To run the test use the run_test.pl script: + +$ ./run_test.pl + + the script returns 0 if the test was successful. + diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_Static/ServerApp.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Test_Static/ServerApp.cpp new file mode 100644 index 00000000000..348e7987ba8 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_Static/ServerApp.cpp @@ -0,0 +1,171 @@ +// $Id$ +#include "ServerApp.h" +#include "Foo_A_i.h" +#include "AppHelper.h" +#include "TestAppExceptionC.h" +#include "AppShutdown.h" +#include "ace/Get_Opt.h" +// To force static load the service. +#include "tao/CSD_ThreadPool/CSD_ThreadPool.h" + + +ServerApp::ServerApp() + : TestAppBase("TP_Test_1_Server"), + ior_filename_ ("test.ior"), + num_clients_ (1) +{ +} + +ServerApp::~ServerApp() +{ +} + +int +ServerApp::run_i(int argc, char* argv[] ACE_ENV_ARG_DECL) +{ + // Initialize the ORB before parsing our own args. + CORBA::ORB_var orb = CORBA::ORB_init(argc, argv, "" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Parse the command-line args for this application. + // * Returns -1 if problems are encountered. + // * Returns 1 if the usage statement was explicitly requested. + // * Returns 0 otherwise. + int result = this->parse_args(argc, argv); + if (result != 0) + { + return result; + } + + TheAppShutdown->init(orb.in(), num_clients_ ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Get the Root POA + PortableServer::POA_var root_poa = + RefHelper<PortableServer::POA>::resolve_initial_ref(orb.in(), + "RootPOA" + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Get the POAManager from the Root POA. + PortableServer::POAManager_var poa_manager + = root_poa->the_POAManager(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Create the child POA Policies. + CORBA::PolicyList policies(0); + policies.length(0); + + // Create the child POA + PortableServer::POA_var child_poa = + AppHelper::create_poa("ChildPoa", + root_poa.in(), + poa_manager.in(), + policies + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Create the servant object. + Foo_A_i* servant = new Foo_A_i(); + + // Local smart pointer variable to deal with releasing the reference + // to the servant object when the variable falls out of scope. + PortableServer::ServantBase_var servant_owner(servant); + + // Obtain the object reference using the servant + CORBA::Object_var obj = AppHelper::activate_servant(child_poa.in(), + servant + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Stringify and save the object reference to a file + AppHelper::ref_to_file(orb.in(), + obj.in(), + this->ior_filename_.c_str() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Activate the POA Manager + poa_manager->activate(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp is ready. Running the ORB event loop.\n")); + + // Run the ORB event loop. + orb->run (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp ORB event loop has completed.\n")); + + TheAppShutdown->wait (); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp is destroying the Root POA.\n")); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp is destroying the Root POA.\n")); + + root_poa->destroy(1, 1 ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp is destroying the ORB.\n")); + + orb->destroy(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + ACE_DEBUG((LM_DEBUG, + "(%P|%t) ServerApp has completed running successfully.\n")); + + return 0; +} + + +int +ServerApp::parse_args(int argc, char* argv[]) +{ + ACE_Get_Opt get_opts(argc, argv, "o:n:"); + + int c; + + while ((c = get_opts()) != -1) + { + switch (c) + { + case 'o': + this->ior_filename_ = get_opts.opt_arg(); + break; + + case 'n': + { + int tmp = ACE_OS::atoi(get_opts.opt_arg()); + if (tmp < 1) + { + ACE_ERROR((LM_ERROR, + "(%P|%t) Error. -n must be followed by an integer " + "value greater than 0.\n")); + return -1; + } + + this->num_clients_ = tmp; + } + break; + + case '?': + ACE_ERROR((LM_ERROR, + "(%P|%t) usage: %s -o <ior_filename> -n <num_clients>\n", + argv[0])); + return 1; + + default: + ACE_ERROR((LM_ERROR, + "(%P|%t) usage: %s -o <ior_filename> -n <num_clients>\n", + argv[0])); + return -1; + } + } + + return 0; +} diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_Static/ServerApp.h b/TAO/tests/CSD_Strategy_Tests/TP_Test_Static/ServerApp.h new file mode 100644 index 00000000000..3bfe10e6f0a --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_Static/ServerApp.h @@ -0,0 +1,30 @@ +// $Id$ +#ifndef SERVERAPP_H +#define SERVERAPP_H + +#include "TestAppBase.h" +#include "ace/SString.h" + + +class ServerApp : public TestAppBase +{ + public: + + ServerApp(); + virtual ~ServerApp(); + + + protected: + + virtual int run_i(int argc, char* argv[] ACE_ENV_ARG_DECL); + + + private: + + int parse_args(int argc, char* argv[]); + + ACE_CString ior_filename_; + unsigned num_clients_; +}; + +#endif diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_Static/client_main.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Test_Static/client_main.cpp new file mode 100644 index 00000000000..ae98ca0f6ac --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_Static/client_main.cpp @@ -0,0 +1,5 @@ +// $Id$ +#include "ClientApp.h" +#include "TestAppMain.h" + +TEST_APP_MAIN(ClientApp) diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_Static/run_test.pl b/TAO/tests/CSD_Strategy_Tests/TP_Test_Static/run_test.pl new file mode 100755 index 00000000000..e15decb6a63 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_Static/run_test.pl @@ -0,0 +1,55 @@ +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; + +$iorfile = PerlACE::LocalFile ("server.ior"); +unlink $iorfile; +$status = 0; + +$num_clients=40; + +$SV = new PerlACE::Process ("server_main", "-o $iorfile -n $num_clients"); + +$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; +} + +for ($i = 0; $i < $num_clients; $i++) { + + @CLS[$i] = new PerlACE::Process ("client_main", " -i file://$iorfile"); + + @CLS[$i]->Spawn (); +} + +for ($i = 0; $i < $num_clients; $i++) { + + $client = @CLS[$i]->WaitKill (60); + + if ($client != 0) { + print STDERR "ERROR: client $i returned $client\n"; + $status = 1; + } +} + + +$server = $SV->WaitKill (60); + +if ($server != 0) { + print STDERR "ERROR: server returned $server\n"; + $status = 1; +} + +unlink $iorfile; + +exit $status; diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_Static/server_main.cpp b/TAO/tests/CSD_Strategy_Tests/TP_Test_Static/server_main.cpp new file mode 100644 index 00000000000..82e987f6d41 --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_Static/server_main.cpp @@ -0,0 +1,5 @@ +// $Id$ +#include "ServerApp.h" +#include "TestAppMain.h" + +TEST_APP_MAIN(ServerApp) diff --git a/TAO/tests/CSD_Strategy_Tests/TP_Test_Static/svc.conf b/TAO/tests/CSD_Strategy_Tests/TP_Test_Static/svc.conf new file mode 100644 index 00000000000..a274350e4ac --- /dev/null +++ b/TAO/tests/CSD_Strategy_Tests/TP_Test_Static/svc.conf @@ -0,0 +1 @@ +static TAO_CSD_TP_Strategy_Factory "-CSDtp ChildPoa:2" |