diff options
author | nobody <nobody@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2006-04-27 20:45:26 +0000 |
---|---|---|
committer | nobody <nobody@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2006-04-27 20:45:26 +0000 |
commit | 317d8c1ce78436f0107f056418c0c5f5b4231069 (patch) | |
tree | d432edf6760c4d9b42f941ba9453db96cd3fa75e | |
parent | 664244e804da11536f2712a61116204e8042f312 (diff) | |
download | ATCD-317d8c1ce78436f0107f056418c0c5f5b4231069.tar.gz |
This commit was manufactured by cvs2svn to create branch
'oci_dave_wchar_refactor_branch'.
59 files changed, 5653 insertions, 0 deletions
diff --git a/TAO/tao/EndpointPolicy/EndpointPolicyC.cpp b/TAO/tao/EndpointPolicy/EndpointPolicyC.cpp new file mode 100644 index 00000000000..1cfa58e8522 --- /dev/null +++ b/TAO/tao/EndpointPolicy/EndpointPolicyC.cpp @@ -0,0 +1,351 @@ +// -*- 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:282 + + +#include "EndpointPolicyC.h" +#include "tao/CDR.h" +#include "ace/OS_NS_string.h" + +// TAO_IDL - Generated from +// be/be_visitor_arg_traits.cpp:71 +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + + + +// Arg traits specializations. +namespace TAO +{ +} + +TAO_END_VERSIONED_NAMESPACE_DECL + + + +// TAO_IDL - Generated from +// be/be_visitor_interface/interface_cs.cpp:60 + +// Traits specializations for EndpointPolicy::EndpointValueBase. + +EndpointPolicy::EndpointValueBase_ptr +TAO::Objref_Traits<EndpointPolicy::EndpointValueBase>::duplicate ( + EndpointPolicy::EndpointValueBase_ptr p + ) +{ + return EndpointPolicy::EndpointValueBase::_duplicate (p); +} + +void +TAO::Objref_Traits<EndpointPolicy::EndpointValueBase>::release ( + EndpointPolicy::EndpointValueBase_ptr p + ) +{ + ::CORBA::release (p); +} + +EndpointPolicy::EndpointValueBase_ptr +TAO::Objref_Traits<EndpointPolicy::EndpointValueBase>::nil (void) +{ + return EndpointPolicy::EndpointValueBase::_nil (); +} + +::CORBA::Boolean +TAO::Objref_Traits<EndpointPolicy::EndpointValueBase>::marshal ( + const EndpointPolicy::EndpointValueBase_ptr p, + TAO_OutputCDR & cdr + ) +{ + return ::CORBA::Object::marshal (p, cdr); +} + +EndpointPolicy::EndpointValueBase::EndpointValueBase (void) +{} + +EndpointPolicy::EndpointValueBase::~EndpointValueBase (void) +{} + +EndpointPolicy::EndpointValueBase_ptr +EndpointPolicy::EndpointValueBase::_narrow ( + ::CORBA::Object_ptr _tao_objref + ACE_ENV_ARG_DECL_NOT_USED + ) +{ + return EndpointValueBase::_duplicate ( + dynamic_cast<EndpointValueBase_ptr> (_tao_objref) + ); +} + +EndpointPolicy::EndpointValueBase_ptr +EndpointPolicy::EndpointValueBase::_unchecked_narrow ( + ::CORBA::Object_ptr _tao_objref + ACE_ENV_ARG_DECL_NOT_USED + ) +{ + return EndpointValueBase::_duplicate ( + dynamic_cast<EndpointValueBase_ptr> (_tao_objref) + ); +} + +EndpointPolicy::EndpointValueBase_ptr +EndpointPolicy::EndpointValueBase::_duplicate (EndpointValueBase_ptr obj) +{ + if (! ::CORBA::is_nil (obj)) + { + obj->_add_ref (); + } + + return obj; +} + +void +EndpointPolicy::EndpointValueBase::_tao_release (EndpointValueBase_ptr obj) +{ + ::CORBA::release (obj); +} + +::CORBA::Boolean +EndpointPolicy::EndpointValueBase::_is_a ( + const char *value + ACE_ENV_ARG_DECL_NOT_USED + ) +{ + if ( + !ACE_OS::strcmp ( + value, + "IDL:EndpointPolicy/EndpointValueBase: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* EndpointPolicy::EndpointValueBase::_interface_repository_id (void) const +{ + return "IDL:EndpointPolicy/EndpointValueBase:1.0"; +} + +::CORBA::Boolean +EndpointPolicy::EndpointValueBase::marshal (TAO_OutputCDR &) +{ + return false; +} + +// TAO_IDL - Generated from +// be/be_visitor_sequence/sequence_cs.cpp:65 + +#if !defined (_ENDPOINTPOLICY_ENDPOINTLIST_CS_) +#define _ENDPOINTPOLICY_ENDPOINTLIST_CS_ + +EndpointPolicy::EndpointList::EndpointList (void) +{} + +EndpointPolicy::EndpointList::EndpointList ( + ::CORBA::ULong max + ) + : TAO::unbounded_object_reference_sequence< + EndpointValueBase, + EndpointValueBase_var + > + (max) +{} + +EndpointPolicy::EndpointList::EndpointList ( + ::CORBA::ULong max, + ::CORBA::ULong length, + EndpointPolicy::EndpointValueBase_ptr * buffer, + ::CORBA::Boolean release + ) + : TAO::unbounded_object_reference_sequence< + EndpointValueBase, + EndpointValueBase_var + > + (max, length, buffer, release) +{} + +EndpointPolicy::EndpointList::EndpointList ( + const EndpointList &seq + ) + : TAO::unbounded_object_reference_sequence< + EndpointValueBase, + EndpointValueBase_var + > + (seq) +{} + +EndpointPolicy::EndpointList::~EndpointList (void) +{} + +void EndpointPolicy::EndpointList::_tao_any_destructor ( + void * _tao_void_pointer + ) +{ + EndpointList * _tao_tmp_pointer = + static_cast<EndpointList *> (_tao_void_pointer); + delete _tao_tmp_pointer; +} + +#endif /* end #if !defined */ + +// TAO_IDL - Generated from +// be/be_visitor_interface/interface_cs.cpp:60 + +// Traits specializations for EndpointPolicy::Policy. + +EndpointPolicy::Policy_ptr +TAO::Objref_Traits<EndpointPolicy::Policy>::duplicate ( + EndpointPolicy::Policy_ptr p + ) +{ + return EndpointPolicy::Policy::_duplicate (p); +} + +void +TAO::Objref_Traits<EndpointPolicy::Policy>::release ( + EndpointPolicy::Policy_ptr p + ) +{ + ::CORBA::release (p); +} + +EndpointPolicy::Policy_ptr +TAO::Objref_Traits<EndpointPolicy::Policy>::nil (void) +{ + return EndpointPolicy::Policy::_nil (); +} + +::CORBA::Boolean +TAO::Objref_Traits<EndpointPolicy::Policy>::marshal ( + const EndpointPolicy::Policy_ptr p, + TAO_OutputCDR & cdr + ) +{ + return ::CORBA::Object::marshal (p, cdr); +} + +EndpointPolicy::Policy::Policy (void) +{} + +EndpointPolicy::Policy::~Policy (void) +{} + +EndpointPolicy::Policy_ptr +EndpointPolicy::Policy::_narrow ( + ::CORBA::Object_ptr _tao_objref + ACE_ENV_ARG_DECL_NOT_USED + ) +{ + return Policy::_duplicate ( + dynamic_cast<Policy_ptr> (_tao_objref) + ); +} + +EndpointPolicy::Policy_ptr +EndpointPolicy::Policy::_unchecked_narrow ( + ::CORBA::Object_ptr _tao_objref + ACE_ENV_ARG_DECL_NOT_USED + ) +{ + return Policy::_duplicate ( + dynamic_cast<Policy_ptr> (_tao_objref) + ); +} + +EndpointPolicy::Policy_ptr +EndpointPolicy::Policy::_duplicate (Policy_ptr obj) +{ + if (! ::CORBA::is_nil (obj)) + { + obj->_add_ref (); + } + + return obj; +} + +void +EndpointPolicy::Policy::_tao_release (Policy_ptr obj) +{ + ::CORBA::release (obj); +} + +::CORBA::Boolean +EndpointPolicy::Policy::_is_a ( + const char *value + ACE_ENV_ARG_DECL_NOT_USED + ) +{ + if ( + !ACE_OS::strcmp ( + value, + "IDL:omg.org/CORBA/Policy:1.0" + ) || + !ACE_OS::strcmp ( + value, + "IDL:EndpointPolicy/Policy: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* EndpointPolicy::Policy::_interface_repository_id (void) const +{ + return "IDL:EndpointPolicy/Policy:1.0"; +} + +::CORBA::Boolean +EndpointPolicy::Policy::marshal (TAO_OutputCDR &) +{ + return false; +} diff --git a/TAO/tao/EndpointPolicy/EndpointPolicyC.h b/TAO/tao/EndpointPolicy/EndpointPolicyC.h new file mode 100644 index 00000000000..6993b9640bd --- /dev/null +++ b/TAO/tao/EndpointPolicy/EndpointPolicyC.h @@ -0,0 +1,383 @@ +// -*- 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_ENDPOINTPOLICYC_H_ +#define _TAO_IDL_ENDPOINTPOLICYC_H_ + +#include /**/ "ace/pre.h" + + +#include "ace/config-all.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "tao/EndpointPolicy/EndpointPolicy_Export.h" +#include "tao/ORB.h" +#include "tao/SystemException.h" +#include "tao/Environment.h" +#include "tao/Object.h" +#include "tao/Sequence_T.h" +#include "tao/Objref_VarOut_T.h" +#include "tao/Seq_Var_T.h" +#include "tao/Seq_Out_T.h" +#include "tao/Versioned_Namespace.h" + +#include "tao/PolicyC.h" +#include "tao/EndpointPolicy/EndpointPolicyTypeC.h" + +#if defined (TAO_EXPORT_MACRO) +#undef TAO_EXPORT_MACRO +#endif +#define TAO_EXPORT_MACRO TAO_EndpointPolicy_Export + +// TAO_IDL - Generated from +// be/be_visitor_module/module_ch.cpp:49 + +namespace EndpointPolicy +{ + + // TAO_IDL - Generated from + // be/be_interface.cpp:640 + +#if !defined (_ENDPOINTPOLICY_ENDPOINTVALUEBASE__VAR_OUT_CH_) +#define _ENDPOINTPOLICY_ENDPOINTVALUEBASE__VAR_OUT_CH_ + + class EndpointValueBase; + typedef EndpointValueBase *EndpointValueBase_ptr; + + typedef + TAO_Objref_Var_T< + EndpointValueBase + > + EndpointValueBase_var; + + typedef + TAO_Objref_Out_T< + EndpointValueBase + > + EndpointValueBase_out; + +#endif /* end #if !defined */ + + // TAO_IDL - Generated from + // be/be_visitor_interface/interface_ch.cpp:54 + +#if !defined (_ENDPOINTPOLICY_ENDPOINTVALUEBASE_CH_) +#define _ENDPOINTPOLICY_ENDPOINTVALUEBASE_CH_ + + class TAO_EndpointPolicy_Export EndpointValueBase + : public virtual ::CORBA::Object + { + public: + typedef EndpointValueBase_ptr _ptr_type; + typedef EndpointValueBase_var _var_type; + + // The static operations. + static EndpointValueBase_ptr _duplicate (EndpointValueBase_ptr obj); + + static void _tao_release (EndpointValueBase_ptr obj); + + static EndpointValueBase_ptr _narrow ( + ::CORBA::Object_ptr obj + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ); + + static EndpointValueBase_ptr _unchecked_narrow ( + ::CORBA::Object_ptr obj + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ); + + static EndpointValueBase_ptr _nil (void) + { + return static_cast<EndpointValueBase_ptr> (0); + } + + + + // TAO_IDL - Generated from + // be/be_visitor_operation/operation_ch.cpp:46 + + virtual ::CORBA::ULong protocol_tag ( + ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + ::CORBA::SystemException + )) = 0; + + // TAO_IDL - Generated from + // 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. + EndpointValueBase (void); + + virtual ~EndpointValueBase (void); + + private: + // Private and unimplemented for concrete interfaces. + EndpointValueBase (const EndpointValueBase &); + + void operator= (const EndpointValueBase &); + }; + +#endif /* end #if !defined */ + + // TAO_IDL - Generated from + // be/be_visitor_sequence/sequence_ch.cpp:101 + +#if !defined (_ENDPOINTPOLICY_ENDPOINTLIST_CH_) +#define _ENDPOINTPOLICY_ENDPOINTLIST_CH_ + + class EndpointList; + + typedef + TAO_VarSeq_Var_T< + EndpointList + > + EndpointList_var; + + typedef + TAO_Seq_Out_T< + EndpointList + > + EndpointList_out; + + class TAO_EndpointPolicy_Export EndpointList + : public + TAO::unbounded_object_reference_sequence< + EndpointValueBase, + EndpointValueBase_var + > + { + public: + EndpointList (void); + EndpointList ( ::CORBA::ULong max); + EndpointList ( + ::CORBA::ULong max, + ::CORBA::ULong length, + EndpointValueBase_ptr* buffer, + ::CORBA::Boolean release = false + ); + EndpointList (const EndpointList &); + ~EndpointList (void); + + static void _tao_any_destructor (void *); + + typedef EndpointList_var _var_type; + }; + +#endif /* end #if !defined */ + + // TAO_IDL - Generated from + // be/be_interface.cpp:640 + +#if !defined (_ENDPOINTPOLICY_POLICY__VAR_OUT_CH_) +#define _ENDPOINTPOLICY_POLICY__VAR_OUT_CH_ + + class Policy; + typedef Policy *Policy_ptr; + + typedef + TAO_Objref_Var_T< + Policy + > + Policy_var; + + typedef + TAO_Objref_Out_T< + Policy + > + Policy_out; + +#endif /* end #if !defined */ + + // TAO_IDL - Generated from + // be/be_visitor_interface/interface_ch.cpp:54 + +#if !defined (_ENDPOINTPOLICY_POLICY_CH_) +#define _ENDPOINTPOLICY_POLICY_CH_ + + class TAO_EndpointPolicy_Export Policy + : public virtual ::CORBA::Policy + { + public: + typedef Policy_ptr _ptr_type; + typedef Policy_var _var_type; + + // The static operations. + static Policy_ptr _duplicate (Policy_ptr obj); + + static void _tao_release (Policy_ptr obj); + + static Policy_ptr _narrow ( + ::CORBA::Object_ptr obj + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ); + + static Policy_ptr _unchecked_narrow ( + ::CORBA::Object_ptr obj + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ); + + static Policy_ptr _nil (void) + { + return static_cast<Policy_ptr> (0); + } + + + + // TAO_IDL - Generated from + // be/be_visitor_operation/operation_ch.cpp:46 + + virtual ::EndpointPolicy::EndpointList * value ( + ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + ::CORBA::SystemException + )) = 0; + + // TAO_IDL - Generated from + // be/be_visitor_operation/operation_ch.cpp:46 + + virtual ::CORBA::Policy_ptr copy ( + ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + ::CORBA::SystemException + )) = 0; + + // TAO_IDL - Generated from + // be/be_visitor_operation/operation_ch.cpp:46 + + virtual void destroy ( + ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC (( + ::CORBA::SystemException + )) = 0; + + // TAO_IDL - Generated from + // 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. + Policy (void); + + virtual ~Policy (void); + + private: + // Private and unimplemented for concrete interfaces. + Policy (const Policy &); + + void operator= (const Policy &); + }; + +#endif /* end #if !defined */ + +// TAO_IDL - Generated from +// be/be_visitor_module/module_ch.cpp:78 + +} // module EndpointPolicy + +// TAO_IDL - Generated from +// be/be_visitor_traits.cpp:63 +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + + + +// Traits specializations. +namespace TAO +{ + +#if !defined (_ENDPOINTPOLICY_ENDPOINTVALUEBASE__TRAITS_) +#define _ENDPOINTPOLICY_ENDPOINTVALUEBASE__TRAITS_ + + template<> + struct TAO_EndpointPolicy_Export Objref_Traits< ::EndpointPolicy::EndpointValueBase> + { + static ::EndpointPolicy::EndpointValueBase_ptr duplicate ( + ::EndpointPolicy::EndpointValueBase_ptr + ); + static void release ( + ::EndpointPolicy::EndpointValueBase_ptr + ); + static ::EndpointPolicy::EndpointValueBase_ptr nil (void); + static ::CORBA::Boolean marshal ( + const ::EndpointPolicy::EndpointValueBase_ptr p, + TAO_OutputCDR & cdr + ); + }; + +#endif /* end #if !defined */ + +#if !defined (_ENDPOINTPOLICY_POLICY__TRAITS_) +#define _ENDPOINTPOLICY_POLICY__TRAITS_ + + template<> + struct TAO_EndpointPolicy_Export Objref_Traits< ::EndpointPolicy::Policy> + { + static ::EndpointPolicy::Policy_ptr duplicate ( + ::EndpointPolicy::Policy_ptr + ); + static void release ( + ::EndpointPolicy::Policy_ptr + ); + static ::EndpointPolicy::Policy_ptr nil (void); + static ::CORBA::Boolean marshal ( + const ::EndpointPolicy::Policy_ptr p, + TAO_OutputCDR & cdr + ); + }; + +#endif /* end #if !defined */ +} +TAO_END_VERSIONED_NAMESPACE_DECL + +#include /**/ "ace/post.h" + +#endif /* ifndef */ diff --git a/TAO/tao/EndpointPolicy/Endpoint_Acceptor_Filter.cpp b/TAO/tao/EndpointPolicy/Endpoint_Acceptor_Filter.cpp new file mode 100644 index 00000000000..b44df235724 --- /dev/null +++ b/TAO/tao/EndpointPolicy/Endpoint_Acceptor_Filter.cpp @@ -0,0 +1,156 @@ +// @(#) $Id$ + +#include "tao/EndpointPolicy/Endpoint_Acceptor_Filter.h" +#include "tao/EndpointPolicy/EndpointPolicyC.h" +#include "tao/EndpointPolicy/Endpoint_Value_Impl.h" + +#include "tao/Transport_Acceptor.h" +#include "tao/MProfile.h" +#include "tao/IIOP_Profile.h" + +ACE_RCSID(EndpointPolicy, + Endpoint_Acceptor_Filter, + "$Id$") + + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +TAO_Endpoint_Acceptor_Filter::TAO_Endpoint_Acceptor_Filter (EndpointPolicy::Policy_ptr p) +: endpoints_(p->value()) +{ +} + +int +TAO_Endpoint_Acceptor_Filter::fill_profile (const TAO::ObjectKey &object_key, + TAO_MProfile &mprofile, + TAO_Acceptor **acceptors_begin, + TAO_Acceptor **acceptors_end, + CORBA::Short priority) +{ + CORBA::ULong num_endpoints = endpoints_->length (); + + for (TAO_Acceptor** acceptor = acceptors_begin; + acceptor != acceptors_end; + ++acceptor) + { + bool tagfound = false; + for (CORBA::ULong epx = 0; !tagfound && epx < num_endpoints; epx++) + { + tagfound = (*acceptor)->tag () == endpoints_[epx]->protocol_tag(); + } + if (!tagfound) + continue; + + if ((*acceptor)->create_profile (object_key, + mprofile, + priority) == -1) + return -1; + } + + if (TAO_debug_level > 2) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT("(%P|%t) EndpointPolicy filtering acceptors") + ACE_TEXT(" - mprofile has %d profiles,") + ACE_TEXT(" endpoint list has %d entries\n"), + mprofile.profile_count(), num_endpoints)); + + for (TAO_PHandle pfile_ndx = 0; + pfile_ndx < mprofile.profile_count (); + ++pfile_ndx) + { + TAO_Profile *pfile =mprofile.get_profile (pfile_ndx); + + TAO_Endpoint *ep_in_pfile = pfile->endpoint (); + + if (TAO_debug_level > 2) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT("(%P|%t) Testing profile %d - ") + ACE_TEXT("it contains %d endpoints\n"), + pfile_ndx, pfile->endpoint_count())); + + bool first_endpoint = true; + // Iterate the endpoints in the profile. + while (ep_in_pfile != 0 && pfile->endpoint_count() > 0) + { + // Iterate the endpoints in the endpoint policy to see if the endpoint + // in the profile matches. + CORBA::ULong ep_ndx = 0; + bool epmatch = false; + for (ep_ndx = 0; !epmatch && ep_ndx < num_endpoints; ++ep_ndx) + { + if (endpoints_[ep_ndx]->protocol_tag() != pfile->tag()) + continue; + + const EndpointPolicy::EndpointValueBase *evb = + endpoints_[ep_ndx]; + + const TAO_Endpoint_Value_Impl *evi = + dynamic_cast <const TAO_Endpoint_Value_Impl*>(evb); + + epmatch = evi->is_equivalent(ep_in_pfile); + } + + // The endpoint in profile does not match the endpoint specified in + // Endpoint policy, now remove the endpoint from the profile. + if (!epmatch) + { + //Get next endpoint before removing current one. + TAO_Endpoint * next = ep_in_pfile->next (); + if (TAO_debug_level > 2) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) EndpointPolicy filter ") + ACE_TEXT ("removing endpoint\n"))); + pfile->remove_generic_endpoint (ep_in_pfile); + ep_in_pfile = first_endpoint ? pfile->endpoint() : next; + } + else + { + if (TAO_debug_level > 2) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) EndpointPolicy filter ") + ACE_TEXT ("Endpoint matched policy value\n"))); + ep_in_pfile = ep_in_pfile->next(); + first_endpoint = false; + } + } + // Remove the profiles that have no endpoints match the endpoints in + // endpoint policy. + if (pfile->endpoint_count () == 0) + { + if (TAO_debug_level > 2) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT("(%P|%t) EndpointPolicy filter ") + ACE_TEXT("removing profile\n"))); + mprofile.remove_profile (pfile); + --pfile_ndx; // step back one, we've just shifted the profile list. + } + else + { + if (TAO_debug_level > 2) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT("(%P|%t) EndpointPolicy filter ") + ACE_TEXT("profile retained with %d endpoints\n"), + pfile->endpoint_count())); + } + } + + if (mprofile.profile_count () == 0) { + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT("(%P|%t) EndpointPolicy filter ") + ACE_TEXT("eliminated all profiles\n"))); + + return -1; + } + + if (TAO_debug_level > 2) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT("(%P|%t) EndpointPolicy filter returning mprofile ") + ACE_TEXT("with %d profiles\n"), + mprofile.profile_count())); + + return 0; +} + + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/tao/EndpointPolicy/Endpoint_Value_Impl.cpp b/TAO/tao/EndpointPolicy/Endpoint_Value_Impl.cpp new file mode 100644 index 00000000000..cf81937bfd6 --- /dev/null +++ b/TAO/tao/EndpointPolicy/Endpoint_Value_Impl.cpp @@ -0,0 +1,16 @@ +// -*- C++ -*- +//============================================================================= +/** + * @file Endpoint_Value_Impl.cpp + * + * $Id$ + * + * @author Phil Mesnier <mesnier_p@ociweb.com> + */ +//============================================================================= + +#include "tao/EndpointPolicy/Endpoint_Value_Impl.h" + +TAO_Endpoint_Value_Impl::~TAO_Endpoint_Value_Impl() +{ +} diff --git a/TAO/tao/EndpointPolicy/Endpoint_Value_Impl.h b/TAO/tao/EndpointPolicy/Endpoint_Value_Impl.h new file mode 100644 index 00000000000..4151f19f572 --- /dev/null +++ b/TAO/tao/EndpointPolicy/Endpoint_Value_Impl.h @@ -0,0 +1,61 @@ +// -*- C++ -*- +//============================================================================= +/** + * @file Endpoint_Value_Impl.h + * + * $Id$ + * + * Implementation of the IIOP-Specific endpoint policy value + * + * @author Phil Mesnier <mesnier_p@ociweb.com> + */ +//============================================================================= + +#ifndef _TAO_ENDPOINT_VALUE_IMPL_H_ +#define _TAO_ENDPOINT_VALUE_IMPL_H_ + +#include /**/ "ace/pre.h" + +#include "tao/Basic_Types.h" +#include "tao/EndpointPolicy/EndpointPolicy_Export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +class TAO_Endpoint; +class TAO_Acceptor; + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +/** + * @class Endpoint_Value_Impl + * + * @brief Abstract base class to be mixed in to servants of protocol + * specific EndpointValues. + * + * This inteface defines the methods necessary for the + * protocol-specific endpoint value to be used with the endpoint + * policy + */ + +class TAO_EndpointPolicy_Export TAO_Endpoint_Value_Impl +{ +public: + virtual ~TAO_Endpoint_Value_Impl(void); + + /// This method is used to compare a candidate IOR endpoint with the + /// endpoint defined by this policy value. + virtual CORBA::Boolean is_equivalent (const TAO_Endpoint * ) const = 0; + + /// This method is used by the framework to validate that an + /// acceptor is available to produce an endpoint required by at + /// least one of the endpoint policies values. + virtual CORBA::Boolean validate_acceptor (TAO_Acceptor *) const = 0; +}; + +TAO_END_VERSIONED_NAMESPACE_DECL + +#include /**/ "ace/post.h" + +#endif /* _TAO_Endpoint_Value_Impl_H_ */ diff --git a/TAO/tao/PortableServer/POAManagerFactory.cpp b/TAO/tao/PortableServer/POAManagerFactory.cpp new file mode 100644 index 00000000000..25d6b0bdc28 --- /dev/null +++ b/TAO/tao/PortableServer/POAManagerFactory.cpp @@ -0,0 +1,162 @@ +// $Id$ + +#include "tao/PortableServer/POAManagerFactory.h" +#include "tao/PortableServer/POAManager.h" +#include "tao/EndpointPolicy/EndpointPolicyTypeC.h" + +#include "ace/OS_NS_string.h" + +ACE_RCSID (PortableServer, + POAManagerFactory, + "$Id$") + + +TAO_POAManager_Factory::TAO_POAManager_Factory (TAO_Object_Adapter &object_adapter) : + object_adapter_ (object_adapter) +{ +} + +TAO_POAManager_Factory::~TAO_POAManager_Factory (void) +{ + if (TAO_debug_level > 0) + { + ACE_DEBUG ((LM_DEBUG, "(%P|%t)~TAO_POAManager_Factory \n")); + } + + for (POAMANAGERSET::iterator iterator = this->poamanager_set_.begin (); + iterator != this->poamanager_set_.end (); + ++iterator) + { + ::PortableServer::POAManager_ptr poamanager = (*iterator); + CORBA::release (poamanager); + } +} + +::PortableServer::POAManager_ptr +TAO_POAManager_Factory::create_POAManager ( + const char * id, + const ::CORBA::PolicyList & policies + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, + ::PortableServer::POAManagerFactory::ManagerAlreadyExists, + ::CORBA::PolicyError)) +{ + if (policies.length () > 1 + || (policies.length () == 1 && + policies[0]->policy_type () != EndpointPolicy::ENDPOINT_POLICY_TYPE)) + { + ACE_THROW_RETURN (CORBA::PolicyError (CORBA::BAD_POLICY), + ::PortableServer::POAManager::_nil ()); + } + + PortableServer::POAManager_var poamanager = + PortableServer::POAManager::_nil (); + if (id != 0) + { + poamanager = this->find (id ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (::PortableServer::POAManager::_nil ()); + + // If we already have a manager with the same name throw an exception + if (!CORBA::is_nil (poamanager.in())) + { + ACE_THROW_RETURN ( + ::PortableServer::POAManagerFactory::ManagerAlreadyExists (), + ::PortableServer::POAManager::_nil ()); + } + } + + // this indirection brought to you by borland's compiler and its refusal + // to directly assign the newly crated TAO_POA_Manager to a POAManager_var. + { + PortableServer::POAManager_ptr pm = 0; + ACE_NEW_THROW_EX (pm, + TAO_POA_Manager (object_adapter_, id, policies, this), + CORBA::NO_MEMORY + (CORBA::SystemException::_tao_minor_code (0, ENOMEM), + CORBA::COMPLETED_NO)); + ACE_CHECK_RETURN (::PortableServer::POAManager::_nil ()); + poamanager = pm; + } + + this->register_poamanager (poamanager.in ()); + + return PortableServer::POAManager::_duplicate (poamanager.in ()); +} + +::PortableServer::POAManagerFactory::POAManagerSeq * +TAO_POAManager_Factory::list ( + ACE_ENV_SINGLE_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + ::PortableServer::POAManagerFactory::POAManagerSeq_var poamanagers; + CORBA::ULong number_of_poamanagers = static_cast <CORBA::ULong> + (this->poamanager_set_.size ()); + ACE_NEW_THROW_EX (poamanagers, + PortableServer::POAManagerFactory::POAManagerSeq ( + number_of_poamanagers), + CORBA::NO_MEMORY ()); + ACE_CHECK_RETURN (0); + + poamanagers->length (number_of_poamanagers); + + CORBA::ULong index = 0; + for (POAMANAGERSET::iterator iterator = this->poamanager_set_.begin (); + iterator != this->poamanager_set_.end (); + ++iterator, ++index) + { + ::PortableServer::POAManager_ptr poamanager = (*iterator); + poamanagers[index] = + PortableServer::POAManager::_duplicate (poamanager); + } + + return poamanagers._retn (); +} + +::PortableServer::POAManager_ptr +TAO_POAManager_Factory::find ( + const char * id ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + ::PortableServer::POAManager_ptr poamanager = + ::PortableServer::POAManager::_nil(); + + for (POAMANAGERSET::iterator iterator = this->poamanager_set_.begin (); + iterator != this->poamanager_set_.end (); + ++iterator) + { + CORBA::String_var poamanagerid = + (*iterator)->get_id (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (::PortableServer::POAManager::_nil()); + + if (ACE_OS::strcmp (id, poamanagerid) == 0) + { + poamanager = PortableServer::POAManager::_duplicate (*iterator); + break; + } + } + + return poamanager; +} + +int +TAO_POAManager_Factory::remove_poamanager ( + ::PortableServer::POAManager_ptr poamanager) +{ + int retval = 0; + retval = this->poamanager_set_.remove (poamanager); + + if (retval == 0) + { + CORBA::release (poamanager); + } + + return retval; +} + +int +TAO_POAManager_Factory::register_poamanager ( + ::PortableServer::POAManager_ptr poamanager) +{ + return this->poamanager_set_.insert ( + PortableServer::POAManager::_duplicate (poamanager)); +} diff --git a/TAO/tests/ORB_Local_Config/Bunch/Bunch.mpc b/TAO/tests/ORB_Local_Config/Bunch/Bunch.mpc new file mode 100644 index 00000000000..c71a117c14b --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Bunch/Bunch.mpc @@ -0,0 +1,15 @@ +// -*- MPC -*- +// $Id$ + + +project(*) : ../../../tests/acetest, taoserver { + after += lib + exename = Test + includes += ../lib + libpaths += ../lib + libs += lib + Source_Files { + Test.cpp + } +} + diff --git a/TAO/tests/ORB_Local_Config/Bunch/Service_Config_Test.UTF-16.conf b/TAO/tests/ORB_Local_Config/Bunch/Service_Config_Test.UTF-16.conf Binary files differnew file mode 100644 index 00000000000..e5d36fd215f --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Bunch/Service_Config_Test.UTF-16.conf diff --git a/TAO/tests/ORB_Local_Config/Bunch/Service_Config_Test.UTF-16.conf.xml b/TAO/tests/ORB_Local_Config/Bunch/Service_Config_Test.UTF-16.conf.xml Binary files differnew file mode 100644 index 00000000000..1d75d2763c0 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Bunch/Service_Config_Test.UTF-16.conf.xml diff --git a/TAO/tests/ORB_Local_Config/Bunch/Service_Config_Test.WCHAR_T.conf b/TAO/tests/ORB_Local_Config/Bunch/Service_Config_Test.WCHAR_T.conf Binary files differnew file mode 100644 index 00000000000..a36db0600c9 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Bunch/Service_Config_Test.WCHAR_T.conf diff --git a/TAO/tests/ORB_Local_Config/Bunch/Service_Config_Test.WCHAR_T.conf.xml b/TAO/tests/ORB_Local_Config/Bunch/Service_Config_Test.WCHAR_T.conf.xml Binary files differnew file mode 100644 index 00000000000..88e7c26e8eb --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Bunch/Service_Config_Test.WCHAR_T.conf.xml diff --git a/TAO/tests/ORB_Local_Config/Bunch/Service_Config_Test.conf b/TAO/tests/ORB_Local_Config/Bunch/Service_Config_Test.conf new file mode 100644 index 00000000000..34d51068365 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Bunch/Service_Config_Test.conf @@ -0,0 +1,19 @@ +# Dynamically loading each of the Service Objects below causes a +# number of threads to be spawned, each one invoking the Service +# Configurator (e.g. ACE_Service_Config::process_directive(). If the +# Service Configurator is thread safe and reentrant, then parsing of +# this `Service_Config_Test.conf' file should run to completion +# without error. +# +# Test_Object_1 will cause Test_Object_2 and Test_Object_3 to be +# dynamically loaded. Dynamic loading of each of object will occur in +# a separate thread. +dynamic Test_Object_1 Service_Object * Service_Config_DLL:_make_Service_Config_DLL() "2 3" + +# Test_Object_4 will cause Test_Object_5 and Test_Object_6 to be +# dynamically loaded. Dynamic loading of each of object will occur in +# a separate thread. +dynamic Test_Object_4 Service_Object * Service_Config_DLL:_make_Service_Config_DLL() "5 6" + +# Final_Object does nothing but print a completion message. +dynamic Final_Object Service_Object * Service_Config_DLL:_make_Service_Config_DLL() "FINAL" diff --git a/TAO/tests/ORB_Local_Config/Bunch/Service_Config_Test.conf.xml b/TAO/tests/ORB_Local_Config/Bunch/Service_Config_Test.conf.xml new file mode 100644 index 00000000000..f3273f0cb93 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Bunch/Service_Config_Test.conf.xml @@ -0,0 +1,27 @@ +<?xml version='1.0'?> +<!-- Converted from Service_Config_Test.conf by svcconf-convert.pl --> +<ACE_Svc_Conf> + <!-- Dynamically loading each of the Service Objects below causes a --> + <!-- number of threads to be spawned, each one invoking the Service --> + <!-- Configurator (e.g. ACE_Service_Config::process_directive(). If the --> + <!-- Service Configurator is thread safe and reentrant, then parsing of --> + <!-- this `Service_Config_Test.conf' file should run to completion --> + <!-- without error. --> + <!-- --> + <!-- Test_Object_1 will cause Test_Object_2 and Test_Object_3 to be --> + <!-- dynamically loaded. Dynamic loading of each of object will occur in --> + <!-- a separate thread. --> + <dynamic id="Test_Object_1" type="Service_Object"> + <initializer init="_make_Service_Config_DLL" path="Service_Config_DLL" params="2 3"/> + </dynamic> + <!-- Test_Object_4 will cause Test_Object_5 and Test_Object_6 to be --> + <!-- dynamically loaded. Dynamic loading of each of object will occur in --> + <!-- a separate thread. --> + <dynamic id="Test_Object_4" type="Service_Object"> + <initializer init="_make_Service_Config_DLL" path="Service_Config_DLL" params="5 6"/> + </dynamic> + <!-- Final_Object does nothing but print a completion message. --> + <dynamic id="Final_Object" type="Service_Object"> + <initializer init="_make_Service_Config_DLL" path="Service_Config_DLL" params="FINAL"/> + </dynamic> +</ACE_Svc_Conf> diff --git a/TAO/tests/ORB_Local_Config/Bunch/Test.cpp b/TAO/tests/ORB_Local_Config/Bunch/Test.cpp new file mode 100644 index 00000000000..ddaae2341c3 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Bunch/Test.cpp @@ -0,0 +1,315 @@ +// $Id$ + +#include "tao/CORBANAME_Parser.h" +#include "tao/CORBALOC_Parser.h" +#include "tao/IIOP_Factory.h" +#include "tao/ORBInitializer_Registry_Adapter.h" + +#include "ace/Thread_Manager.h" +#include "ace/ARGV.h" +#include "ace/Dynamic_Service.h" + +ACE_RCSID (tests, server, "$Id$") + + +#include "Service_Configuration_Per_ORB.h" + +// @brief The "new" interfaces must be compatible with the "old" ones + +int +testCompatibility (int , ACE_TCHAR *[]) +{ + ACE_TRACE ("testCompatibility"); + + // This uses the same default ACE_Service_Repository + ACE_Service_Gestalt_Test glob; + + // Use the "old" interface + ACE_ASSERT (0 == ACE_Service_Config::process_directive + (ace_svc_desc_TAO_CORBANAME_Parser)); + ACE_ASSERT (0 == ACE_Service_Config::process_directive + (ace_svc_desc_TAO_CORBALOC_Parser)); + + { + // This uses the same default ACE_Service_Repository + ACE_Service_Gestalt_Test one; + + TAO_CORBANAME_Parser* p20 = + ACE_Dynamic_Service<TAO_CORBANAME_Parser>::instance (&one, "CORBANAME_Parser"); + ACE_ASSERT ((p20 != 0)); + + TAO_CORBALOC_Parser* p21 = + ACE_Dynamic_Service<TAO_CORBALOC_Parser>::instance (&one, "CORBALOC_Parser"); + ACE_ASSERT ((p21 != 0)); + + ACE_DEBUG ((LM_DEBUG, "\tglobal.services_count () -> %d\n", + one.services_count ())); + ACE_ASSERT (33 == one.services_count ()); + + // Exiting this scope should fini all services ... + } + + TAO_CORBANAME_Parser* p20 = + ACE_Dynamic_Service<TAO_CORBANAME_Parser>::instance ("CORBANAME_Parser"); + ACE_ASSERT ((p20 == 0)); + + TAO_CORBALOC_Parser* p21 = + ACE_Dynamic_Service<TAO_CORBALOC_Parser>::instance ("CORBALOC_Parser"); + ACE_ASSERT ((p21 == 0)); + + + + p20 = ACE_Dynamic_Service<TAO_CORBANAME_Parser>::instance (&glob, "CORBANAME_Parser"); + ACE_ASSERT ((p20 == 0)); + + p21 =ACE_Dynamic_Service<TAO_CORBALOC_Parser>::instance (&glob, "CORBALOC_Parser"); + ACE_ASSERT ((p21 == 0)); + + return 0; +} + +// @brief Test commandline processing + + +int +testCommandLineDirectives (int , ACE_TCHAR *[]) +{ + ACE_TRACE ("testCommandLineDirectives"); + + ACE_ARGV new_argv; + ACE_ASSERT (new_argv.add (ACE_TEXT ("-f")) != -1 + && new_argv.add (ACE_TEXT ("-S")) != -1 + && new_argv.add (ACE_TEXT ("d1")) != -1 + && new_argv.add (ACE_TEXT ("-S")) != -1 + && new_argv.add (ACE_TEXT ("d2")) != -1); + + ACE_Service_Gestalt_Test g(5); + ACE_ASSERT (g.parse_args (new_argv.argc (), + new_argv.argv ()) != -1 + || errno == ENOENT); + + ACE_DEBUG ((LM_DEBUG, "\tg.command_line_directives_count () -> %d\n", + g.command_line_directives_count ())); + + ACE_ASSERT (2 == g.command_line_directives_count ()); + return 0; +} + + + +// @brief Loading dynamic services in a local repository + +int +testOpenDynamicServices (int , ACE_TCHAR *[]) +{ + ACE_TRACE ("testOpenDynamicServices"); + + ACE_ARGV new_argv; + + // Process the Service Configurator directives in this test's + ACE_ASSERT (new_argv.add (ACE_TEXT ("bogus")) != -1 + && new_argv.add (ACE_TEXT ("-f")) != -1 + && new_argv.add (file_Service_Config_Test ()) != -1); + + // We need this scope to make sure that the destructor for the + // <ACE_Service_Config> gets called. + ACE_Service_Gestalt_Test daemon(10); + + ACE_ASSERT (daemon.open (new_argv.argc (), + new_argv.argv ()) != -1 || errno == ENOENT); + + ACE_DEBUG ((LM_DEBUG, + "\tdaemon.services_count () -> %d\n", + daemon.services_count ())); + + ACE_ASSERT (5 == daemon.services_count ()); + + // Since the loaded services start their own threads, wait until all of them + // are done to avoid pulling the rug under their feet. + ACE_Thread_Manager::instance ()->wait (); + return 0; +} + + + + + +// @brief Try loading the ORBInitializer_Registry locally + +int +testORBInitializer_Registry(int, ACE_TCHAR *[]) +{ + ACE_TRACE ("testORBInitializer_Registry"); + + ACE_Service_Gestalt_Test glob; // The global service registrations are here + ACE_Service_Gestalt_Test one (10); // Localized ones go here + + size_t glob_size = glob.services_count (); + size_t loca_size = one.services_count (); + + // It is expected to be empty at this point since it is not using the global repo + ACE_ASSERT (loca_size == 0); + + // Lookup it up. + TAO::ORBInitializer_Registry_Adapter* oir = + ACE_Dynamic_Service<TAO::ORBInitializer_Registry_Adapter>::instance + (&one, "ORBInitializer_Registry"); + +#if defined (TAO_AS_STATIC_LIBS) + ACE_ASSERT ((oir != 0)); +#else + ACE_ASSERT ((oir == 0)); +#endif + + +#if !defined (TAO_AS_STATIC_LIBS) + // In case we build shared, try to load the PI Client library, in a + // static build we just can't do this, so don't try it, lower layers + // output an error then. + if (oir == 0) + { + one.process_directive ( + ACE_DYNAMIC_SERVICE_DIRECTIVE("ORBInitializer_Registry", + "TAO_PI", + "_make_ORBInitializer_Registry", + "")); + oir = + ACE_Dynamic_Service<TAO::ORBInitializer_Registry_Adapter>::instance + (&one, "ORBInitializer_Registry"); + } + ACE_ASSERT ((oir != 0)); +#endif + + + ACE_DEBUG ((LM_DEBUG, + "Expected %d global static service registrations, found %d\n", + glob_size, + glob.services_count ())); + + ACE_ASSERT (glob_size == glob.services_count ()); + + ACE_DEBUG ((LM_DEBUG, + "Expected %d local static service registrations, found %d\n", + 5, + one.services_count ())); + + // The local repository must have asquired also the static services + // registered within the dynamic service we just loaded. As of this + // writing, loading ORBInitializer_Registry causes the registration of + // four other (static) services. The PolicyFactory_Loader, + // ClientRequestInterceptor_Adapter_Factory and PICurrent_Loader are + // registred explicitely, while CodecFactory_Loader - indirectly. + // Hence the number 5. + + ACE_ASSERT (loca_size != one.services_count ()); + ACE_ASSERT (5 == one.services_count ()); + + ACE_DEBUG ((LM_DEBUG, "(%P|%t) try global dynamic service on ORBInitializer_Registry ...\n")); + + // Try to instantiate the dynamic service from the global repository ... + TAO::ORBInitializer_Registry_Adapter* oir1 = + ACE_Dynamic_Service<TAO::ORBInitializer_Registry_Adapter>::instance + ("ORBInitializer_Registry"); + + ACE_ASSERT ((oir1 == 0)); // Right! It should not have been global. + + ACE_DEBUG ((LM_DEBUG, "(%P|%t) try local dynamic service on ORBInitializer_Registry ...\n")); + + // Try to instantiate the dynamic service from the local repository ... + TAO::ORBInitializer_Registry_Adapter* oir2 = + ACE_Dynamic_Service<TAO::ORBInitializer_Registry_Adapter>::instance + (&one, "ORBInitializer_Registry"); + + ACE_ASSERT ((oir2 != 0)); // Right! That's local. + + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) Explicitely initialize ORBInitializer_Registry" + " (although Dynamic_Service already did it) ...\n")); + + // ... initialize, but note that without the guard there is nothing to tell + // the service which gestalt must be used. If init() does static service + // registrations, those may end up in the wrong (global) gestalt and will + // be in memory, which may not be mapped by finalization time! + { + ACE_Service_Config_Guard guard (&one); + oir2->init (0,0); + } + + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) Try dynamic_service on a " + "dependent static service (CodecFactory_Loader) ...\n")); + + // ... and also one of the dependent static services + ACE_ASSERT (0 != ACE_Dynamic_Service <ACE_Service_Object>::instance + (&one, "CodecFactory_Loader")); + + + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) Explicitely dynamic_service PolicyFactory_Loader" + " (although ORBInitializer_Registry already did it) ...\n")); + + one.process_directive + (ACE_DYNAMIC_SERVICE_DIRECTIVE("PolicyFactory_Loader", + "TAO_PI", + "_make_TAO_PolicyFactory_Loader", + "")); + + ACE_ASSERT (0 != ACE_Dynamic_Service <ACE_Service_Object>::instance + (&one, "PolicyFactory_Loader")); + + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) We're done testing.\n")); + return 0; +} + + +// @brief Test the helper components used to implement the temporary +// substitution of the repository currently used as "global" for the +// sake of registering static services, which are dependent on a dynamic +// service + +int +testTSSGestalt (int , ACE_TCHAR *[]) +{ + ACE_TRACE ("testTSSGestalt"); + + ACE_Service_Gestalt_Test one (10); // Localized ones go here + + ACE_Service_Gestalt *global_instance = ACE_Service_Config::instance (); + + ACE_ASSERT (global_instance == ACE_Service_Config::instance ()); + ACE_ASSERT (global_instance != &one); + + { + ACE_Service_Config_Guard temporary (&one); + + ACE_Service_Gestalt *global_instance2 = ACE_Service_Config::instance (); + + ACE_ASSERT (global_instance != global_instance2); + ACE_ASSERT (global_instance2 == &one); + } + + ACE_ASSERT (global_instance == ACE_Service_Config::instance ()); + ACE_ASSERT (global_instance != &one); + + return 0; +} + + + +// @brief the main driver + +int +run_main(int argc, ACE_TCHAR *argv[]) +{ + testCompatibility (argc, argv); + testCommandLineDirectives (argc, argv); + testOpenDynamicServices (argc, argv); + testORBInitializer_Registry(argc, argv); + testTSSGestalt(argc, argv); + return 0; +} + + + + diff --git a/TAO/tests/ORB_Local_Config/Bunch/run_test.pl b/TAO/tests/ORB_Local_Config/Bunch/run_test.pl new file mode 100755 index 00000000000..2b7f1395785 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Bunch/run_test.pl @@ -0,0 +1,49 @@ +eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' + & eval 'exec perl -S $0 $argv:q' + if 0; + +# $Id$ +# -*- perl -*- + +use lib '../../../../bin'; +use PerlACE::Run_Test; + +sub add_path { + my($name) = shift; + my($value) = shift; + if (defined $ENV{$name}) { + $ENV{$name} .= ':' . $value + } + else { + $ENV{$name} = $value; + } +} + +# Set the library path for the client to be able to load +# the Time_Date library. +add_path('LD_LIBRARY_PATH', '../lib'); +add_path('LIBPATH', '../lib'); +add_path('SHLIB_PATH', '../lib'); + +sub test($) +{ + (my $executable, my $arguments) = @_; + my $t1 = new PerlACE::Process ($executable, ($arguments ? $arguments : "")); + my $status = $t1->SpawnWaitKill (10); + if ($status != 0) { + print STDERR "ERROR: test failed, status=$status\n"; + } + return $status; +} + +my $status = 0; +$status |= test("Test"); + +if ($status == 0) { + print STDERR "SUCCESS: All tests passed\n"; +} +else { + print STDERR "ERROR: Some test failed, status=$status\n"; +} +exit $status; + diff --git a/TAO/tests/ORB_Local_Config/Limits/Limits.mpc b/TAO/tests/ORB_Local_Config/Limits/Limits.mpc new file mode 100644 index 00000000000..c71a117c14b --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Limits/Limits.mpc @@ -0,0 +1,15 @@ +// -*- MPC -*- +// $Id$ + + +project(*) : ../../../tests/acetest, taoserver { + after += lib + exename = Test + includes += ../lib + libpaths += ../lib + libs += lib + Source_Files { + Test.cpp + } +} + diff --git a/TAO/tests/ORB_Local_Config/Limits/Test.cpp b/TAO/tests/ORB_Local_Config/Limits/Test.cpp new file mode 100644 index 00000000000..c0b3b4ecc75 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Limits/Test.cpp @@ -0,0 +1,19 @@ +// $Id$ + +#include "tao/CORBANAME_Parser.h" +#include "tao/CORBALOC_Parser.h" + +#include "Service_Configuration_Per_ORB.h" + +// @brief The size of a repository is pre-determined and can not be exceeded + +int +run_main (int , ACE_TCHAR *[]) +{ + ACE_Service_Gestalt one(1); // Room for just one ... + ACE_ASSERT (0 == one.process_directive (ace_svc_desc_TAO_CORBANAME_Parser)); + ACE_ASSERT (-1 == one.process_directive (ace_svc_desc_TAO_CORBALOC_Parser)); + ACE_ASSERT (ENOSPC == errno); + ACE_DEBUG ((LM_DEBUG, "%p\n", "\tReporting an expected error: ")); + return 0; +} diff --git a/TAO/tests/ORB_Local_Config/Limits/run_test.pl b/TAO/tests/ORB_Local_Config/Limits/run_test.pl new file mode 100755 index 00000000000..2b7f1395785 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Limits/run_test.pl @@ -0,0 +1,49 @@ +eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' + & eval 'exec perl -S $0 $argv:q' + if 0; + +# $Id$ +# -*- perl -*- + +use lib '../../../../bin'; +use PerlACE::Run_Test; + +sub add_path { + my($name) = shift; + my($value) = shift; + if (defined $ENV{$name}) { + $ENV{$name} .= ':' . $value + } + else { + $ENV{$name} = $value; + } +} + +# Set the library path for the client to be able to load +# the Time_Date library. +add_path('LD_LIBRARY_PATH', '../lib'); +add_path('LIBPATH', '../lib'); +add_path('SHLIB_PATH', '../lib'); + +sub test($) +{ + (my $executable, my $arguments) = @_; + my $t1 = new PerlACE::Process ($executable, ($arguments ? $arguments : "")); + my $status = $t1->SpawnWaitKill (10); + if ($status != 0) { + print STDERR "ERROR: test failed, status=$status\n"; + } + return $status; +} + +my $status = 0; +$status |= test("Test"); + +if ($status == 0) { + print STDERR "SUCCESS: All tests passed\n"; +} +else { + print STDERR "ERROR: Some test failed, status=$status\n"; +} +exit $status; + diff --git a/TAO/tests/ORB_Local_Config/ORB_Local_Config.mwc b/TAO/tests/ORB_Local_Config/ORB_Local_Config.mwc new file mode 100644 index 00000000000..9237c7d3541 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/ORB_Local_Config.mwc @@ -0,0 +1,14 @@ +// -*- MPC -*- +// $Id$ + +workspace { + lib + Bunch + Bug_1459 + Limits + Separation + Service_Dependency + Shared + Simple + Two_DLL_ORB +} diff --git a/TAO/tests/ORB_Local_Config/README b/TAO/tests/ORB_Local_Config/README new file mode 100644 index 00000000000..013590337f7 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/README @@ -0,0 +1,50 @@ +# $Id$ + +This is a collection of tests for the refactoring of the Service Configurator. +The following executables are self-sufficient test suites: + +These tests require ACE_wrappers/tests/Test_Output. + +test-bunch + + A collection of miscellaneous tests for + * (testCompatibility) Compatibility of the new interfaces with the old; + * (testCommandLineDirectives) Processing of the command-line directives; + * (testOpenDynamicServices) Loading dynamic services in a local repository; + * (testORBInitializer_Registry) Loading the ORBInitializer_Registry locally; + * (testTSSGestalt) Test the helper components used to implement the + temporary substitution of the repository currently used as "global" for the + sake of registering static services, which are dependent on a dynamic + service; + +test-dependency + + * Tests the working of the ACE_Dynamic_Service_Dependency class; + +test-new-cfg + + * + +test-orb-service + + * Loading a dynamic service, which initializes its own ORB; + +test-reusing-globals + + * If all default-constructor-created Service Config instances refer to the + The One Global Configuration; + +test-separation + + * Services registered with separate repositories must remain separate + and inaccessible through anyone but the one they were registered with + +test-simple + + * Dynamic services loading through the new interfaces; + +test-too-many + + * Testing the size limits of a gestalt + +The executables can be run independently, or together using the run_test.pl diff --git a/TAO/tests/ORB_Local_Config/Separation/Separation.mpc b/TAO/tests/ORB_Local_Config/Separation/Separation.mpc new file mode 100644 index 00000000000..02156762f83 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Separation/Separation.mpc @@ -0,0 +1,14 @@ +// -*- MPC -*- +// $Id$ + + +project(*) : ../../../tests/acetest, taoserver { + exename = Test + includes += ../lib + libpaths += ../lib + libs += lib + Source_Files { + Test.cpp + } +} + diff --git a/TAO/tests/ORB_Local_Config/Separation/Test.cpp b/TAO/tests/ORB_Local_Config/Separation/Test.cpp new file mode 100644 index 00000000000..876d43c55b8 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Separation/Test.cpp @@ -0,0 +1,55 @@ +// $Id$ + +#include "tao/CORBANAME_Parser.h" +#include "tao/CORBALOC_Parser.h" +#include "tao/IIOP_Factory.h" + +#include "ace/Dynamic_Service.h" + +#include "Service_Configuration_Per_ORB.h" + +// @brief Services registered with separate repositories must remain separate +// and inaccesible through anyone but the one they were gegistered with + +int +run_main(int , ACE_TCHAR *[]) +{ + ACE_TRACE ("testSeparation"); + + ACE_Service_Gestalt_Test one (10); + + one.process_directive (ace_svc_desc_TAO_CORBANAME_Parser); + + ACE_Service_Gestalt_Test two (10); + + two.process_directive (ace_svc_desc_TAO_CORBALOC_Parser); + + TAO_Protocol_Factory* p10 = + ACE_Dynamic_Service<TAO_Protocol_Factory>::instance (&one, "IIOP_Factory"); + ACE_ASSERT ((p10 == 0)); + + TAO_Protocol_Factory* p11 = + ACE_Dynamic_Service<TAO_Protocol_Factory>::instance (&two, "IIOP_Factory"); + ACE_ASSERT ((p11 == 0)); + + + TAO_CORBANAME_Parser* p20 = + ACE_Dynamic_Service<TAO_CORBANAME_Parser>::instance (&one, "CORBANAME_Parser"); + ACE_ASSERT ((p20 != 0)); + + TAO_CORBALOC_Parser* p21 = + ACE_Dynamic_Service<TAO_CORBALOC_Parser>::instance (&one, "CORBALOC_Parser"); + ACE_ASSERT ((p21 == 0)); + + + TAO_CORBALOC_Parser* p30 = + ACE_Dynamic_Service<TAO_CORBALOC_Parser>::instance (&two, "CORBALOC_Parser"); + ACE_ASSERT ((p30 != 0)); + + TAO_CORBANAME_Parser* p31 = + ACE_Dynamic_Service<TAO_CORBANAME_Parser>::instance (&two, "CORBANAME_Parser"); + ACE_ASSERT ((p31 == 0)); + + return 0; +} + diff --git a/TAO/tests/ORB_Local_Config/Separation/run_test.pl b/TAO/tests/ORB_Local_Config/Separation/run_test.pl new file mode 100755 index 00000000000..2b7f1395785 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Separation/run_test.pl @@ -0,0 +1,49 @@ +eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' + & eval 'exec perl -S $0 $argv:q' + if 0; + +# $Id$ +# -*- perl -*- + +use lib '../../../../bin'; +use PerlACE::Run_Test; + +sub add_path { + my($name) = shift; + my($value) = shift; + if (defined $ENV{$name}) { + $ENV{$name} .= ':' . $value + } + else { + $ENV{$name} = $value; + } +} + +# Set the library path for the client to be able to load +# the Time_Date library. +add_path('LD_LIBRARY_PATH', '../lib'); +add_path('LIBPATH', '../lib'); +add_path('SHLIB_PATH', '../lib'); + +sub test($) +{ + (my $executable, my $arguments) = @_; + my $t1 = new PerlACE::Process ($executable, ($arguments ? $arguments : "")); + my $status = $t1->SpawnWaitKill (10); + if ($status != 0) { + print STDERR "ERROR: test failed, status=$status\n"; + } + return $status; +} + +my $status = 0; +$status |= test("Test"); + +if ($status == 0) { + print STDERR "SUCCESS: All tests passed\n"; +} +else { + print STDERR "ERROR: Some test failed, status=$status\n"; +} +exit $status; + diff --git a/TAO/tests/ORB_Local_Config/Service_Dependency/Service_Config_DLL.cpp b/TAO/tests/ORB_Local_Config/Service_Dependency/Service_Config_DLL.cpp new file mode 100644 index 00000000000..2ffbdab6f80 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Service_Dependency/Service_Config_DLL.cpp @@ -0,0 +1,196 @@ +// -*- C++ -*- + +#include "Service_Config_DLL.h" +#include "ace/Service_Config.h" +#include "ace/OS_NS_stdio.h" +#include "ace/OS_NS_string.h" + +ACE_RCSID (tests, + Service_Config_DLL, + "$Id$") + +static ACE_THR_FUNC_RETURN +invoke_service_config (void *arg) +{ + const ACE_TCHAR *directive = reinterpret_cast<const ACE_TCHAR *> (arg); + + + // Process a Service Configurator directive in the current thread. + if (ACE_Service_Config::process_directive (directive) != 0) + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) Service_Config_DLL::svc() - ") + ACE_TEXT ("process_directive() failed for:\n") + ACE_TEXT ("\"%s\"\n"), + directive)); + + return 0; +} + +Service_Config_DLL::Service_Config_DLL (void) +{ + ACE_OS::memset (this->directive_[0], 0, BUFSIZ * sizeof (ACE_TCHAR)); + ACE_OS::memset (this->directive_[1], 0, BUFSIZ * sizeof (ACE_TCHAR)); +} + +int +Service_Config_DLL::init (int argc, ACE_TCHAR *argv[]) +{ + if (argc == 2) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("Loading Test_Object_%s and Test_Object_%s\n"), + argv[0], + argv[1])); + + ACE_OS::sprintf (this->directive_[0], +#if (ACE_USES_CLASSIC_SVC_CONF == 1) + ACE_TEXT ("dynamic Test_Object_%s Service_Object * Service_Config_Dependent_DLL:_make_Service_Config_DLL() \"Test_Object_%s\""), +#else + ACE_TEXT ("<?xml version='1.0'?> <dynamic id='Test_Object_%s' type='service_object'> <initializer init='_make_Service_Config_DLL' path='Service_Config_Dependent_DLL' params='Test_Object_%s'/> </dynamic>"), +#endif + argv[0], + argv[0]); + + ACE_OS::sprintf (this->directive_[1], +#if (ACE_USES_CLASSIC_SVC_CONF == 1) + ACE_TEXT ("dynamic Test_Object_%s Service_Object * Service_Config_Dependent_DLL:_make_Service_Config_DLL() \"Test_Object_%s\""), +#else + ACE_TEXT ("<?xml version='1.0'?> <dynamic id='Test_Object_%s' type='service_object'> <initializer init='_make_Service_Config_DLL' path='Service_Config_Dependent_DLL' params='Test_Object_%s'/> </dynamic>"), +#endif + + argv[1], + argv[1]); + + if (ACE_Service_Config::process_directive (this->directive_[0]) != 0) + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) Service_Config_DLL::init() - ") + ACE_TEXT ("process_directive() failed for:\n") + ACE_TEXT ("\"%s\"\n"), + this->directive_[0])); + +#if defined (ACE_HAS_THREADS) + + // Become an Active Object if more than one argument passed. + // Two arguments indicate two "test objects" to be dynamically + // loaded. + return this->activate (); + +#endif /* ACE_HAS_THREADS */ + + } + else if (argc == 1) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("Service_Config_DLL::init () - %s\n"), + argv[0])); + } + else + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("(%P|%t) Incorrect number of arguments ") + ACE_TEXT ("(%d) passed to Service_Config_DLL::init ()"), + argc), + -1); + } + + return 0; +} + +int +Service_Config_DLL::fini (void) +{ + return 0; +} + +int +Service_Config_DLL::svc (void) +{ + if (ACE_Thread_Manager::instance ()->spawn (invoke_service_config, + this->directive_[1]) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("(%P|%t) Unable to spawn thread to ") + ACE_TEXT ("invoke Service Configurator.\n")), + -1); + + return 0; +} + +// The same class (Service_Config_DLL) is used to implement each of the +// Service Objects whose service descriptors are defined below. + +// ----------------------------------------------------------------- + +ACE_STATIC_SVC_DEFINE (Test_Object_1, + ACE_TEXT ("Test_Object_1"), + ACE_SVC_OBJ_T, + &ACE_SVC_NAME (Service_Config_DLL), + ACE_Service_Type::DELETE_THIS + | ACE_Service_Type::DELETE_OBJ, + 0) + +// ----------------------------------------------------------------- + +ACE_STATIC_SVC_DEFINE (Test_Object_2, + ACE_TEXT ("Test_Object_2"), + ACE_SVC_OBJ_T, + &ACE_SVC_NAME (Service_Config_DLL), + ACE_Service_Type::DELETE_THIS + | ACE_Service_Type::DELETE_OBJ, + 0) + +// ----------------------------------------------------------------- + +ACE_STATIC_SVC_DEFINE (Test_Object_3, + ACE_TEXT ("Test_Object_3"), + ACE_SVC_OBJ_T, + &ACE_SVC_NAME (Service_Config_DLL), + ACE_Service_Type::DELETE_THIS + | ACE_Service_Type::DELETE_OBJ, + 0) + +// ----------------------------------------------------------------- + +ACE_STATIC_SVC_DEFINE (Test_Object_4, + ACE_TEXT ("Test_Object_4"), + ACE_SVC_OBJ_T, + &ACE_SVC_NAME (Service_Config_DLL), + ACE_Service_Type::DELETE_THIS + | ACE_Service_Type::DELETE_OBJ, + 0) + +// ----------------------------------------------------------------- + +ACE_STATIC_SVC_DEFINE (Test_Object_5, + ACE_TEXT ("Test_Object_5"), + ACE_SVC_OBJ_T, + &ACE_SVC_NAME (Service_Config_DLL), + ACE_Service_Type::DELETE_THIS + | ACE_Service_Type::DELETE_OBJ, + 0) + +// ----------------------------------------------------------------- + +ACE_STATIC_SVC_DEFINE (Test_Object_6, + ACE_TEXT ("Test_Object_6"), + ACE_SVC_OBJ_T, + &ACE_SVC_NAME (Service_Config_DLL), + ACE_Service_Type::DELETE_THIS + | ACE_Service_Type::DELETE_OBJ, + 0) + +// ----------------------------------------------------------------- + +ACE_STATIC_SVC_DEFINE (Final_Object, + ACE_TEXT ("Final_Object"), + ACE_SVC_OBJ_T, + &ACE_SVC_NAME (Service_Config_DLL), + ACE_Service_Type::DELETE_THIS + | ACE_Service_Type::DELETE_OBJ, + 0) + +// ----------------------------------------------------------------- + +// Same factory is used for all service descriptors defined above. +ACE_FACTORY_DEFINE (Service_Config_DLL, Service_Config_DLL) + + diff --git a/TAO/tests/ORB_Local_Config/Service_Dependency/Service_Config_DLL.h b/TAO/tests/ORB_Local_Config/Service_Dependency/Service_Config_DLL.h new file mode 100644 index 00000000000..3875b70aef8 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Service_Dependency/Service_Config_DLL.h @@ -0,0 +1,69 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file Service_Config_DLL.h + * + * $Id$ + * + * @author Ossama Othman <ossama@uci.edu> + */ +//============================================================================= + +#ifndef SERVICE_CONFIG_DLL_H +#define SERVICE_CONFIG_DLL_H + +#include /**/ "ace/pre.h" + +#include "Service_Config_DLL_Export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/Task.h" + +/** + * @class Service_Config_DLL + * + * @brief The Service_Config_DLL that is instantiated when the + * client-side test module/library is dynamically loaded. + * + * This class is the implementation used for all service instances + * (i.e. those declared using the ACE_FACTORY_* macros). + */ +class Service_Config_DLL_Export Service_Config_DLL : public ACE_Task_Base +{ +public: + + /// Constructor. + Service_Config_DLL (void); + + /// Initializes object when dynamic linking occurs. + virtual int init (int argc, ACE_TCHAR *argv[]); + + /// Terminates object when dynamic unlinking occurs. + virtual int fini (void); + + /// Run by a daemon thread. + /** + * Each thread will invoke the Service Configurator via this + * method unless the object is the "FINAL" object. + */ + virtual int svc (void); + +private: + + /// Directives to be passed to be processed by the Service + /// Configurator in seperate threads. + ACE_TCHAR directive_[2][BUFSIZ]; + +}; + + +ACE_FACTORY_DECLARE (Service_Config_DLL, Service_Config_DLL) + + +#include /**/ "ace/post.h" + +#endif /* SERVICE_CONFIG_DLL_H */ diff --git a/TAO/tests/ORB_Local_Config/Service_Dependency/Service_Config_DLL_Export.h b/TAO/tests/ORB_Local_Config/Service_Dependency/Service_Config_DLL_Export.h new file mode 100644 index 00000000000..1688a745350 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Service_Dependency/Service_Config_DLL_Export.h @@ -0,0 +1,38 @@ + +// -*- C++ -*- +// $Id$ +// Definition for Win32 Export directives. +// This file is generated automatically by generate_export_file.pl +// ------------------------------ +#ifndef SERVICE_CONFIG_DLL_EXPORT_H +#define SERVICE_CONFIG_DLL_EXPORT_H + +#include "ace/config-all.h" + +#if defined (ACE_AS_STATIC_LIBS) && !defined (SERVICE_CONFIG_DLL_HAS_DLL) +# define SERVICE_CONFIG_DLL_HAS_DLL 0 +#endif /* ACE_AS_STATIC_LIBS && ! SERVICE_CONFIG_DLL_HAS_DLL */ + +#if !defined (SERVICE_CONFIG_DLL_HAS_DLL) +# define SERVICE_CONFIG_DLL_HAS_DLL 1 +#endif /* ! TEST_HAS_DLL */ + +#if defined (SERVICE_CONFIG_DLL_HAS_DLL) && (SERVICE_CONFIG_DLL_HAS_DLL == 1) +# if defined (SERVICE_CONFIG_DLL_BUILD_DLL) +# define Service_Config_DLL_Export ACE_Proper_Export_Flag +# define TEST_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T) +# define TEST_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# else /* SERVICE_CONFIG_DLL_BUILD_DLL */ +# define Service_Config_DLL_Export ACE_Proper_Import_Flag +# define TEST_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T) +# define TEST_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# endif /* SERVICE_CONFIG_DLL_BUILD_DLL */ +#else /* SERVICE_CONFIG_DLL_HAS_DLL == 1 */ +# define Service_Config_DLL_Export +# define TEST_SINGLETON_DECLARATION(T) +# define TEST_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +#endif /* SERVICE_CONFIG_DLL_HAS_DLL == 1 */ + +#endif /* SERVICE_CONFIG_DLL_EXPORT_H */ + +// End of auto generated file. diff --git a/TAO/tests/ORB_Local_Config/Service_Dependency/Service_Dependency.mpc b/TAO/tests/ORB_Local_Config/Service_Dependency/Service_Dependency.mpc new file mode 100644 index 00000000000..2701ce4e293 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Service_Dependency/Service_Dependency.mpc @@ -0,0 +1,28 @@ +// -*- MPC -*- +// $Id$ + +project(*) : ../../../tests/acetest, taoserver { + after += lib Service_Config_Dependent_DLL TAO + exename = Test + includes += ../lib + libpaths += ../lib + libs += lib + Source_Files { + Test.cpp + } +} + +project(Service Config Dependent DLL) : acelib { + sharedname = Service_Config_Dependent_DLL + dynamicflags = SERVICE_CONFIG_DLL_BUILD_DLL + + Source_Files { + Service_Config_DLL.cpp + } + Header_Files { + Service_Config_DLL.h + Service_Config_DLL_Export.h + } +} + + diff --git a/TAO/tests/ORB_Local_Config/Service_Dependency/Test.cpp b/TAO/tests/ORB_Local_Config/Service_Dependency/Test.cpp new file mode 100644 index 00000000000..bb211a3b619 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Service_Dependency/Test.cpp @@ -0,0 +1,66 @@ +// $Id$ + +#include "tao/Codeset_Descriptor_Base.h" +#include "tao/Codeset_Manager_Factory_Base.h" +#include "tao/Codeset_Manager.h" + +#include "ace/Dynamic_Service.h" +#include "ace/Dynamic_Service_Dependency.h" + +#include "Service_Configuration_Per_ORB.h" + +// @brief ... + + +int +run_main(int , ACE_TCHAR *[]) +{ + ACE_TRACE ("testDependency"); + + ACE_DEBUG ((LM_DEBUG, "sizeof (ACE_DLL) == %d\n", sizeof (ACE_DLL))); + ACE_DEBUG ((LM_DEBUG, "sizeof (ACE_Dynamic_Service_Dependency) == %d\n", sizeof (ACE_Dynamic_Service_Dependency))); + + TAO_Codeset_Manager *codeset_manager = 0; + ACE_Dynamic_Service_Dependency *pdep = 0; + + { + /// Start a block to limit the lifespan of a gestalt + ACE_Service_Gestalt_Test one (10); + + int result = one.process_directive + (ACE_DYNAMIC_SERVICE_DIRECTIVE("TAO_Codeset", + "TAO_Codeset", + "_make_TAO_Codeset_Manager_Factory", + "")); + ACE_ASSERT (result == 0); + + TAO_Codeset_Manager_Factory_Base *factory = + ACE_Dynamic_Service<TAO_Codeset_Manager_Factory_Base>::instance (&one, "TAO_Codeset"); + ACE_ASSERT (factory != 0); + + codeset_manager = factory->create (); + ACE_ASSERT (codeset_manager != 0); + + ACE_DEBUG ((LM_DEBUG, "Creating dependency ...\n")); + + // [1] + // + // Stating that a thing depends on that dynamic service. Why? + // Read on ... + + pdep = new ACE_Dynamic_Service_Dependency (&one, "TAO_Codeset"); + + /// This would ordinarily cause the dynamic services to get unloaded and their DLL's + /// unmapped ... + } + + // ... therefore the following code would crash miserably because it needs the + // ~TAO_Codeset_Manager()'s code, which is in the (unlodaed) DLL's text segment ... + delete codeset_manager; + + // ... unless of course we used the magic dependency statement, above - [1] + delete pdep; + + return 0; +} + diff --git a/TAO/tests/ORB_Local_Config/Service_Dependency/run_test.pl b/TAO/tests/ORB_Local_Config/Service_Dependency/run_test.pl new file mode 100755 index 00000000000..2b7f1395785 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Service_Dependency/run_test.pl @@ -0,0 +1,49 @@ +eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' + & eval 'exec perl -S $0 $argv:q' + if 0; + +# $Id$ +# -*- perl -*- + +use lib '../../../../bin'; +use PerlACE::Run_Test; + +sub add_path { + my($name) = shift; + my($value) = shift; + if (defined $ENV{$name}) { + $ENV{$name} .= ':' . $value + } + else { + $ENV{$name} = $value; + } +} + +# Set the library path for the client to be able to load +# the Time_Date library. +add_path('LD_LIBRARY_PATH', '../lib'); +add_path('LIBPATH', '../lib'); +add_path('SHLIB_PATH', '../lib'); + +sub test($) +{ + (my $executable, my $arguments) = @_; + my $t1 = new PerlACE::Process ($executable, ($arguments ? $arguments : "")); + my $status = $t1->SpawnWaitKill (10); + if ($status != 0) { + print STDERR "ERROR: test failed, status=$status\n"; + } + return $status; +} + +my $status = 0; +$status |= test("Test"); + +if ($status == 0) { + print STDERR "SUCCESS: All tests passed\n"; +} +else { + print STDERR "ERROR: Some test failed, status=$status\n"; +} +exit $status; + diff --git a/TAO/tests/ORB_Local_Config/Shared/Shared.mpc b/TAO/tests/ORB_Local_Config/Shared/Shared.mpc new file mode 100644 index 00000000000..02156762f83 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Shared/Shared.mpc @@ -0,0 +1,14 @@ +// -*- MPC -*- +// $Id$ + + +project(*) : ../../../tests/acetest, taoserver { + exename = Test + includes += ../lib + libpaths += ../lib + libs += lib + Source_Files { + Test.cpp + } +} + diff --git a/TAO/tests/ORB_Local_Config/Shared/Test.cpp b/TAO/tests/ORB_Local_Config/Shared/Test.cpp new file mode 100644 index 00000000000..595c4aff3a5 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Shared/Test.cpp @@ -0,0 +1,50 @@ +// $Id$ + +#include "tao/CORBANAME_Parser.h" +#include "tao/CORBALOC_Parser.h" +#include "tao/Protocol_Factory.h" +#include "ace/Dynamic_Service.h" + +#include "Service_Configuration_Per_ORB.h" + +// @brief All default-constructor-created Service Config instabces referr to the +// The One Global Configuration + +int +run_main(int , ACE_TCHAR *[]) +{ + ACE_TRACE ("testReusingGlobals"); + + { + ACE_Service_Gestalt/*_Test*/ one; // The ACE_Service_Gestalt_Test will teardown all! + + one.process_directive (ace_svc_desc_TAO_CORBANAME_Parser); + one.process_directive (ace_svc_desc_TAO_CORBALOC_Parser); + + TAO_Protocol_Factory* p1 = + ACE_Dynamic_Service<TAO_Protocol_Factory>::instance (&one, "IIOP_Factory"); + + ACE_ASSERT ((p1 == 0)); + + TAO_CORBANAME_Parser* p2 = + ACE_Dynamic_Service<TAO_CORBANAME_Parser>::instance (&one, "CORBANAME_Parser"); + + ACE_ASSERT ((p2 != 0)); + + TAO_CORBALOC_Parser* p3 = + ACE_Dynamic_Service<TAO_CORBALOC_Parser>::instance (&one, "CORBALOC_Parser"); + + ACE_ASSERT ((p3 != 0)); + } + + + ACE_Service_Gestalt_Test two; // Use the ACE_Service_Repository::instance () + + TAO_CORBANAME_Parser* p2 = + ACE_Dynamic_Service<TAO_CORBANAME_Parser>::instance (&two, "CORBANAME_Parser"); + + ACE_ASSERT ((p2 != 0)); // You should be able to find the same stuff here, too + + return 0; +} + diff --git a/TAO/tests/ORB_Local_Config/Shared/run_test.pl b/TAO/tests/ORB_Local_Config/Shared/run_test.pl new file mode 100755 index 00000000000..2b7f1395785 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Shared/run_test.pl @@ -0,0 +1,49 @@ +eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' + & eval 'exec perl -S $0 $argv:q' + if 0; + +# $Id$ +# -*- perl -*- + +use lib '../../../../bin'; +use PerlACE::Run_Test; + +sub add_path { + my($name) = shift; + my($value) = shift; + if (defined $ENV{$name}) { + $ENV{$name} .= ':' . $value + } + else { + $ENV{$name} = $value; + } +} + +# Set the library path for the client to be able to load +# the Time_Date library. +add_path('LD_LIBRARY_PATH', '../lib'); +add_path('LIBPATH', '../lib'); +add_path('SHLIB_PATH', '../lib'); + +sub test($) +{ + (my $executable, my $arguments) = @_; + my $t1 = new PerlACE::Process ($executable, ($arguments ? $arguments : "")); + my $status = $t1->SpawnWaitKill (10); + if ($status != 0) { + print STDERR "ERROR: test failed, status=$status\n"; + } + return $status; +} + +my $status = 0; +$status |= test("Test"); + +if ($status == 0) { + print STDERR "SUCCESS: All tests passed\n"; +} +else { + print STDERR "ERROR: Some test failed, status=$status\n"; +} +exit $status; + diff --git a/TAO/tests/ORB_Local_Config/Simple/Simple.mpc b/TAO/tests/ORB_Local_Config/Simple/Simple.mpc new file mode 100644 index 00000000000..c71a117c14b --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Simple/Simple.mpc @@ -0,0 +1,15 @@ +// -*- MPC -*- +// $Id$ + + +project(*) : ../../../tests/acetest, taoserver { + after += lib + exename = Test + includes += ../lib + libpaths += ../lib + libs += lib + Source_Files { + Test.cpp + } +} + diff --git a/TAO/tests/ORB_Local_Config/Simple/Test.cpp b/TAO/tests/ORB_Local_Config/Simple/Test.cpp new file mode 100644 index 00000000000..e6ecf217d95 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Simple/Test.cpp @@ -0,0 +1,37 @@ +// $Id$ + +#include "tao/CORBANAME_Parser.h" +#include "tao/CORBALOC_Parser.h" +#include "tao/Protocol_Factory.h" +#include "ace/Dynamic_Service.h" + +#include "Service_Configuration_Per_ORB.h" + + +// @brief Dynamic services loading + +int +run_main (int , ACE_TCHAR *[]) +{ + ACE_Service_Gestalt_Test one; // Use the ACE_Service_Repository::instance () + + one.process_directive (ace_svc_desc_TAO_CORBANAME_Parser); + one.process_directive (ace_svc_desc_TAO_CORBALOC_Parser); + + TAO_Protocol_Factory* p1 = + ACE_Dynamic_Service<TAO_Protocol_Factory>::instance (&one, "IIOP_Factory"); + + ACE_ASSERT ((p1 == 0)); + + TAO_CORBANAME_Parser* p2 = + ACE_Dynamic_Service<TAO_CORBANAME_Parser>::instance (&one, "CORBANAME_Parser"); + + ACE_ASSERT ((p2 != 0)); + + TAO_CORBALOC_Parser* p3 = + ACE_Dynamic_Service<TAO_CORBALOC_Parser>::instance (&one, "CORBALOC_Parser"); + + ACE_ASSERT ((p3 != 0)); + + return 0; +} diff --git a/TAO/tests/ORB_Local_Config/Simple/run_test.pl b/TAO/tests/ORB_Local_Config/Simple/run_test.pl new file mode 100755 index 00000000000..2b7f1395785 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Simple/run_test.pl @@ -0,0 +1,49 @@ +eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' + & eval 'exec perl -S $0 $argv:q' + if 0; + +# $Id$ +# -*- perl -*- + +use lib '../../../../bin'; +use PerlACE::Run_Test; + +sub add_path { + my($name) = shift; + my($value) = shift; + if (defined $ENV{$name}) { + $ENV{$name} .= ':' . $value + } + else { + $ENV{$name} = $value; + } +} + +# Set the library path for the client to be able to load +# the Time_Date library. +add_path('LD_LIBRARY_PATH', '../lib'); +add_path('LIBPATH', '../lib'); +add_path('SHLIB_PATH', '../lib'); + +sub test($) +{ + (my $executable, my $arguments) = @_; + my $t1 = new PerlACE::Process ($executable, ($arguments ? $arguments : "")); + my $status = $t1->SpawnWaitKill (10); + if ($status != 0) { + print STDERR "ERROR: test failed, status=$status\n"; + } + return $status; +} + +my $status = 0; +$status |= test("Test"); + +if ($status == 0) { + print STDERR "SUCCESS: All tests passed\n"; +} +else { + print STDERR "ERROR: Some test failed, status=$status\n"; +} +exit $status; + diff --git a/TAO/tests/ORB_Local_Config/Two_DLL_ORB/ORB_DLL.cpp b/TAO/tests/ORB_Local_Config/Two_DLL_ORB/ORB_DLL.cpp new file mode 100644 index 00000000000..0ded5ce3258 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Two_DLL_ORB/ORB_DLL.cpp @@ -0,0 +1,134 @@ +// -*- C++ -*- + +#include "ORB_DLL.h" +#include "ace/Service_Config.h" +#include "ace/OS_NS_stdio.h" +#include "ace/OS_NS_strings.h" + +#include "ace/Get_Opt.h" +#include "ace/Log_Msg.h" + +ACE_RCSID (tests, + ORB_DLL, + "$Id$") + + +// +Abstract_Worker::Abstract_Worker (const char* s) + : ior_file_ (s) +{ +} + +// +Abstract_Worker::~Abstract_Worker (void) +{ +} + + +// +Service_Config_ORB_DLL::Service_Config_ORB_DLL (void) + : is_server_ (-1) + , worker_ (0) + , argv_ (0) +{ +} + +// +Service_Config_ORB_DLL::~Service_Config_ORB_DLL (void) +{ +} + +// +int +Service_Config_ORB_DLL::init (int argc, ACE_TCHAR *argv[]) +{ + ACE_ARGV* tmp = 0; + ACE_NEW_RETURN (tmp, ACE_ARGV (argv), -1); + this->argv_.reset (tmp); + + ACE_Get_Opt get_opts (argc, argv, "cs"); + for (int c=0;((c = get_opts ()) != -1); ) + switch (c) + { + case 'c': + this->is_server_ = 0; + break; + + case 's': + this->is_server_ = 1; + break; + } + + if (this->is_server_ < 0) + ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) You must specify -c(lient) or -s(erver) argument. Aborting."), -1); + + Abstract_Worker* worker = 0; + if (this->is_server_) + { + ACE_NEW_RETURN (worker, Server_Worker, -1); + } + else + { + ACE_NEW_RETURN (worker, Client_Worker, -1); + } + this->worker_.reset (worker); + +#if defined (ACE_HAS_THREADS) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) About to activate %s, argv[%d]=\'%s\' ...\n"), + this->worker_->kind (), + this->argv_->argc (), + this->argv_->buf ())); + + // Become an Active Object if more than one argument passed. + // Two arguments indicate two "test objects" to be dynamically + // loaded. + return this->activate (); +#else + ACE_ERROR_RETURN (("(%P|%t) Threading support is required for this test. Aborting."), -1); +#endif /* ACE_HAS_THREADS */ +} + +int +Service_Config_ORB_DLL::svc (void) +{ + ACE_ASSERT (this->worker_.get () != 0); + ACE_ASSERT (this->argv_.get () != 0); + + ACE_DECLARE_NEW_ENV; + ACE_TRY + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) %@ %s is active, argv[%d]=\'%s\'\n"), + this, + this->worker_->kind (), + this->argv_->argc (), + this->argv_->buf ())); + + int ret = this->worker_->main (this->argv_->argc (), this->argv_->argv () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) %@ %s bowes out - so long, cruel world! (%d)\n"), + this, + this->worker_->kind (), + ret)); + return ret; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION(ACE_ANY_EXCEPTION, ACE_TEXT("Failure:")); + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("(%P|%t) Aborting.\n")), + -1); + } + ACE_ENDTRY; + +} + + +// Define our service for using with the Service Configurator +ACE_FACTORY_DEFINE (Service_Config_ORB_DLL, Service_Config_ORB_DLL) + + + diff --git a/TAO/tests/ORB_Local_Config/Two_DLL_ORB/ORB_DLL.h b/TAO/tests/ORB_Local_Config/Two_DLL_ORB/ORB_DLL.h new file mode 100644 index 00000000000..061340149c1 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Two_DLL_ORB/ORB_DLL.h @@ -0,0 +1,112 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file ORB_DLL.h + * + * $Id$ + * + * @author Iliyan Jeliazkov <iliyan@ociweb.com> + */ +//============================================================================= + +#ifndef SERVICE_CONFIG_ORB_DLL_H +#define SERVICE_CONFIG_ORB_DLL_H + +#include /**/ "ace/pre.h" + +#include "ORB_DLL_Export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/Task.h" +#include "ace/ARGV.h" +#include "ace/String_Base.h" +#include "tao/ORB.h" + +/// +class Abstract_Worker +{ +public: + Abstract_Worker (const char* ior); + virtual ~Abstract_Worker (void); + virtual int main (int argc, + ACE_TCHAR *argv[] ACE_ENV_ARG_DECL_WITH_DEFAULTS) = 0; + virtual const ACE_TCHAR * kind (void) const = 0; +protected: + ACE_TString ior_file_; +}; + +/** + * A server kind of test + */ +class Server_Worker : public Abstract_Worker +{ +public: + Server_Worker (); + ~Server_Worker (void); + int main (int argc, ACE_TCHAR *argv[] ACE_ENV_ARG_DECL_WITH_DEFAULTS); + const ACE_TCHAR * kind (void) const; + +private: + int parse_args (int argc, ACE_TCHAR *argv[]); +}; + +/** + * A client kind of test + */ +class Client_Worker : public Abstract_Worker +{ +public: + Client_Worker (); + ~Client_Worker (void); + int main (int argc, ACE_TCHAR *argv[] ACE_ENV_ARG_DECL_WITH_DEFAULTS); + const ACE_TCHAR * kind (void) const; + +private: + int parse_args (int argc, ACE_TCHAR *argv[]); +}; + + +/** + * @class Service_Config_ORB_DLL + * + * @brief The Service_Config_ORB_DLL that is instantiated when the + * client-side test module/library is dynamically loaded. + * + */ +class Service_Config_ORB_DLL_Export Service_Config_ORB_DLL + : public ACE_Task_Base +{ +public: + + /// Constructor. + Service_Config_ORB_DLL (void); + ~Service_Config_ORB_DLL (void); + + /// Initializes object when dynamic linking occurs. + virtual int init (int argc, ACE_TCHAR *argv[]); + + /// Run by a daemon thread. + /** + * Each thread will invoke the Service Configurator via this + * method unless the object is the "FINAL" object. + */ + virtual int svc (void); + +private: + signed char is_server_; + auto_ptr<Abstract_Worker> worker_; + auto_ptr<ACE_ARGV> argv_; +}; + + +ACE_FACTORY_DECLARE (Service_Config_ORB_DLL, Service_Config_ORB_DLL) + + + +#include /**/ "ace/post.h" + +#endif /* SERVICE_CONFIG_ORB_DLL_H */ diff --git a/TAO/tests/ORB_Local_Config/Two_DLL_ORB/ORB_DLL_Export.h b/TAO/tests/ORB_Local_Config/Two_DLL_ORB/ORB_DLL_Export.h new file mode 100644 index 00000000000..3812349efcd --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Two_DLL_ORB/ORB_DLL_Export.h @@ -0,0 +1,54 @@ + +// -*- C++ -*- +// $Id$ +// Definition for Win32 Export directives. +// This file is generated automatically by generate_export_file.pl Service_Config_ORB_DLL +// ------------------------------ +#ifndef SERVICE_CONFIG_ORB_DLL_EXPORT_H +#define SERVICE_CONFIG_ORB_DLL_EXPORT_H + +#include "ace/config-all.h" + +#if !defined (SERVICE_CONFIG_ORB_DLL_HAS_DLL) +# define SERVICE_CONFIG_ORB_DLL_HAS_DLL 1 +#endif /* ! SERVICE_CONFIG_ORB_DLL_HAS_DLL */ + +#if defined (SERVICE_CONFIG_ORB_DLL_HAS_DLL) && (SERVICE_CONFIG_ORB_DLL_HAS_DLL == 1) +# if defined (SERVICE_CONFIG_ORB_DLL_BUILD_DLL) +# define Service_Config_ORB_DLL_Export ACE_Proper_Export_Flag +# define SERVICE_CONFIG_ORB_DLL_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T) +# define SERVICE_CONFIG_ORB_DLL_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# else /* SERVICE_CONFIG_ORB_DLL_BUILD_DLL */ +# define Service_Config_ORB_DLL_Export ACE_Proper_Import_Flag +# define SERVICE_CONFIG_ORB_DLL_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T) +# define SERVICE_CONFIG_ORB_DLL_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# endif /* SERVICE_CONFIG_ORB_DLL_BUILD_DLL */ +#else /* SERVICE_CONFIG_ORB_DLL_HAS_DLL == 1 */ +# define Service_Config_ORB_DLL_Export +# define SERVICE_CONFIG_ORB_DLL_SINGLETON_DECLARATION(T) +# define SERVICE_CONFIG_ORB_DLL_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +#endif /* SERVICE_CONFIG_ORB_DLL_HAS_DLL == 1 */ + +// Set SERVICE_CONFIG_ORB_DLL_NTRACE = 0 to turn on library specific tracing even if +// tracing is turned off for ACE. +#if !defined (SERVICE_CONFIG_ORB_DLL_NTRACE) +# if (ACE_NTRACE == 1) +# define SERVICE_CONFIG_ORB_DLL_NTRACE 1 +# else /* (ACE_NTRACE == 1) */ +# define SERVICE_CONFIG_ORB_DLL_NTRACE 0 +# endif /* (ACE_NTRACE == 1) */ +#endif /* !SERVICE_CONFIG_ORB_DLL_NTRACE */ + +#if (SERVICE_CONFIG_ORB_DLL_NTRACE == 1) +# define SERVICE_CONFIG_ORB_DLL_TRACE(X) +#else /* (SERVICE_CONFIG_ORB_DLL_NTRACE == 1) */ +# if !defined (ACE_HAS_TRACE) +# define ACE_HAS_TRACE +# endif /* ACE_HAS_TRACE */ +# define SERVICE_CONFIG_ORB_DLL_TRACE(X) ACE_TRACE_IMPL(X) +# include "ace/Trace.h" +#endif /* (SERVICE_CONFIG_ORB_DLL_NTRACE == 1) */ + +#endif /* SERVICE_CONFIG_ORB_DLL_EXPORT_H */ + +// End of auto generated file. diff --git a/TAO/tests/ORB_Local_Config/Two_DLL_ORB/Service_Config_ORB_Test.conf b/TAO/tests/ORB_Local_Config/Two_DLL_ORB/Service_Config_ORB_Test.conf new file mode 100644 index 00000000000..536102ed7cd --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Two_DLL_ORB/Service_Config_ORB_Test.conf @@ -0,0 +1,5 @@ +dynamic ORB_DLL_Server Service_Object * ORB_DLL_Server:_make_Service_Config_ORB_DLL() "dummy_server -s -ORBId SERVER" +dynamic ORB_DLL_Client Service_Object * ORB_DLL_Client:_make_Service_Config_ORB_DLL() "dummy_client -c -ORBId CLIENT" + +#dynamic ORB_DLL_Server Service_Object * ORB_DLL_Server:_make_Service_Config_ORB_DLL() "-s -ORBDebugLevel 10 -ORBId SERVER -ORBSvcConf Service_Config_ORB_Test2.conf" +#dynamic ORB_DLL_Client Service_Object * ORB_DLL_Client:_make_Service_Config_ORB_DLL() "-c -ORBDebugLevel 10 -ORBId CLIENT -ORBSvcConf Service_Config_ORB_Test2.conf" diff --git a/TAO/tests/ORB_Local_Config/Two_DLL_ORB/Service_Config_ORB_Test2.conf b/TAO/tests/ORB_Local_Config/Two_DLL_ORB/Service_Config_ORB_Test2.conf new file mode 100644 index 00000000000..477c4795007 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Two_DLL_ORB/Service_Config_ORB_Test2.conf @@ -0,0 +1 @@ +# Nothing so far diff --git a/TAO/tests/ORB_Local_Config/Two_DLL_ORB/Test.cpp b/TAO/tests/ORB_Local_Config/Two_DLL_ORB/Test.cpp new file mode 100644 index 00000000000..d61650d07e6 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Two_DLL_ORB/Test.cpp @@ -0,0 +1,32 @@ +// $Id$ + +#include "ace/ARGV.h" +#include "ace/Thread_Manager.h" + +#include "Service_Configuration_Per_ORB.h" + +// @brief Loading a dynamic services in a local repository, which +// initializes its own ORB + +int +run_main (int , ACE_TCHAR *argv[]) +{ + ACE_ARGV new_argv; + + ACE_DEBUG ((LM_DEBUG, "Looking for conf file %s\n", file_Service_Config_ORB_Test ())); + + // Process the Service Configurator directives in this test's + ACE_ASSERT (new_argv.add (argv) != -1 + && new_argv.add (ACE_TEXT ("-f")) != -1 + && new_argv.add (file_Service_Config_ORB_Test ()) != -1); + + ACE_ASSERT (ACE_Service_Config::instance() ->open (new_argv.argc (), + new_argv.argv ()) != -1 || errno == ENOENT); + + + // Since the loaded services start their own threads, wait until all of them + // are done to avoid pulling the rug under their feet. + ACE_Thread_Manager::instance ()->wait (); + return 0; +} + diff --git a/TAO/tests/ORB_Local_Config/Two_DLL_ORB/Test.idl b/TAO/tests/ORB_Local_Config/Two_DLL_ORB/Test.idl new file mode 100644 index 00000000000..3c0976e106d --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Two_DLL_ORB/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/ORB_Local_Config/Two_DLL_ORB/Test_i.cpp b/TAO/tests/ORB_Local_Config/Two_DLL_ORB/Test_i.cpp new file mode 100644 index 00000000000..97c8347258a --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Two_DLL_ORB/Test_i.cpp @@ -0,0 +1,25 @@ +// +// $Id$ +// +#include "Test_i.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/ORB_Local_Config/Two_DLL_ORB/Test_i.h b/TAO/tests/ORB_Local_Config/Two_DLL_ORB/Test_i.h new file mode 100644 index 00000000000..1a404058944 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Two_DLL_ORB/Test_i.h @@ -0,0 +1,33 @@ +// +// $Id$ +// + +#ifndef HELLO_H +#define HELLO_H +#include /**/ "ace/pre.h" + +#include "TestS.h" + +/// Implement the Test::Hello interface +class Hello + : public virtual POA_Test::Hello +{ +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_; +}; + +#include /**/ "ace/post.h" +#endif /* HELLO_H */ diff --git a/TAO/tests/ORB_Local_Config/Two_DLL_ORB/Two_DLL_ORB.mpc b/TAO/tests/ORB_Local_Config/Two_DLL_ORB/Two_DLL_ORB.mpc new file mode 100644 index 00000000000..636f83716aa --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Two_DLL_ORB/Two_DLL_ORB.mpc @@ -0,0 +1,63 @@ +// -*- MPC -*- +// $Id$ + +project(ORB DLL Server) : taolib_with_idl { + sharedname = ORB_DLL_Server + dynamicflags = ORB_DLL_BUILD_DLL + + IDL_Files { + Test.idl + } + + Source_Files { + ORB_DLL.cpp + Test_i.cpp + TestC.cpp + TestS.cpp + server.cpp + client.cpp + } + Header_Files { + ORB_DLL.h + ORB_DLL_Export.h + } + Resource_Files { + } +} + +project(ORB DLL Client) : taolib_with_idl { + sharedname = ORB_DLL_Client + dynamicflags = ORB_DLL_BUILD_DLL + + IDL_Files { + Test.idl + } + + Source_Files { + ORB_DLL.cpp + TestC.cpp + client.cpp + server.cpp + } + Header_Files { + ORB_DLL.h + ORB_DLL_Export.h + } + Resource_Files { + } +} + + +project(*) : ../../../tests/acetest, taoserver { + after += lib ORB_DLL_Client ORB_DLL_Server + exename = Test + includes += ../lib + libpaths += ../lib + libs += lib + Source_Files { + Test.cpp + } +} + + + diff --git a/TAO/tests/ORB_Local_Config/Two_DLL_ORB/client.cpp b/TAO/tests/ORB_Local_Config/Two_DLL_ORB/client.cpp new file mode 100644 index 00000000000..41e6f5c43fe --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Two_DLL_ORB/client.cpp @@ -0,0 +1,110 @@ +// $Id$ + +#include "Test_i.h" +#include "ORB_DLL.h" + +//#include "TestC.h" +#include "ace/Get_Opt.h" +#include "ace/Argv_Type_Converter.h" +#include "ace/OS_NS_unistd.h" + +ACE_RCSID(Hello, client, "$Id$") + +Client_Worker::Client_Worker () + : Abstract_Worker ("file://test.ior") +{ + // ACE_DEBUG ((LM_DEBUG, "(%P|%t) %@ Client::<ctor>\n", this)); +} + +const ACE_TCHAR * +Client_Worker::kind (void) const +{ + return ACE_TEXT ("Client"); +} + +Client_Worker::~Client_Worker (void) +{ + ACE_DEBUG ((LM_DEBUG, "(%P|%t) %@ Client::<dtor>\n", this)); +} + +int +Client_Worker::parse_args (int argc, ACE_TCHAR *argv[]) +{ + ACE_Get_Opt get_opts (argc, argv, "k:"); + + for( int c = 0; ((c = get_opts ()) != -1); ) + switch (c) + { + case 'k': + this->ior_file_ = get_opts.opt_arg (); + break; + } + + // Indicates sucessful parsing of the command line + return 0; +} + +int +Client_Worker::main (int argc, ACE_TCHAR *argv[] ACE_ENV_ARG_DECL) +{ + + ACE_Argv_Type_Converter cvt (argc, argv); + CORBA::ORB_var orb = CORBA::ORB_init (cvt.get_argc (), cvt.get_ASCII_argv () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (parse_args (cvt.get_argc (), cvt.get_ASCII_argv ()) != 0) + return 1; + + // Doing this dance to allow the server some time to come up. + CORBA::Object_ptr co = 0; + for (int attempts_left=5; co == 0 && attempts_left > 0; --attempts_left) + { + ACE_DEBUG ((LM_DEBUG, "(%P|%t) Delaying the client to give the server a chance to start ...\n")); + ACE_OS::sleep (5); + + ACE_TRY + { + co = orb->string_to_object(ior_file_.c_str () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCH (CORBA::TRANSIENT, ex) + { + if (!attempts_left) + ACE_RE_THROW; + } + ACE_ENDTRY; + } + + ACE_ASSERT (co != 0); + CORBA::Object_var tmp (co); + + 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, + "(%P|%t) Nil Test::Hello reference <%s>\n", + ior_file_.c_str ()), + 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 from the server <%s>\n", + the_string.in ())); + + hello->shutdown (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + orb->shutdown (0 ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + orb->destroy (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + return 0; +} diff --git a/TAO/tests/ORB_Local_Config/Two_DLL_ORB/run_test.pl b/TAO/tests/ORB_Local_Config/Two_DLL_ORB/run_test.pl new file mode 100755 index 00000000000..2b7f1395785 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Two_DLL_ORB/run_test.pl @@ -0,0 +1,49 @@ +eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' + & eval 'exec perl -S $0 $argv:q' + if 0; + +# $Id$ +# -*- perl -*- + +use lib '../../../../bin'; +use PerlACE::Run_Test; + +sub add_path { + my($name) = shift; + my($value) = shift; + if (defined $ENV{$name}) { + $ENV{$name} .= ':' . $value + } + else { + $ENV{$name} = $value; + } +} + +# Set the library path for the client to be able to load +# the Time_Date library. +add_path('LD_LIBRARY_PATH', '../lib'); +add_path('LIBPATH', '../lib'); +add_path('SHLIB_PATH', '../lib'); + +sub test($) +{ + (my $executable, my $arguments) = @_; + my $t1 = new PerlACE::Process ($executable, ($arguments ? $arguments : "")); + my $status = $t1->SpawnWaitKill (10); + if ($status != 0) { + print STDERR "ERROR: test failed, status=$status\n"; + } + return $status; +} + +my $status = 0; +$status |= test("Test"); + +if ($status == 0) { + print STDERR "SUCCESS: All tests passed\n"; +} +else { + print STDERR "ERROR: Some test failed, status=$status\n"; +} +exit $status; + diff --git a/TAO/tests/ORB_Local_Config/Two_DLL_ORB/server.cpp b/TAO/tests/ORB_Local_Config/Two_DLL_ORB/server.cpp new file mode 100644 index 00000000000..f9b53292977 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/Two_DLL_ORB/server.cpp @@ -0,0 +1,129 @@ +// $Id$ + + +#include "Test_i.h" +#include "ORB_DLL.h" + +#include "ace/Get_Opt.h" +#include "ace/OS_NS_stdio.h" +#include "ace/Argv_Type_Converter.h" + + +ACE_RCSID (Hello, + server, + "$Id$") + +// +Server_Worker::Server_Worker () + : Abstract_Worker ("test.ior") +{ + // ACE_DEBUG ((LM_DEBUG, "(%P|%t) %@ Server::<ctor>\n", this)); +} + +// +const ACE_TCHAR * +Server_Worker::kind (void) const +{ + return ACE_TEXT ("Server"); +} + +// +Server_Worker::~Server_Worker (void) +{ + ACE_DEBUG ((LM_DEBUG, "(%P|%t) %@ Server::<dtor>\n", this)); +} + +// +int +Server_Worker::parse_args (int argc, ACE_TCHAR *argv[]) +{ + ACE_Get_Opt get_opts (argc, argv, "o:"); + + for( int c = 0; ((c = get_opts ()) != -1); ) + switch (c) + { + case 'o': + this->ior_file_ = get_opts.opt_arg (); + break; + } + + // Indicates sucessful parsing of the command line + return 0; +} + +// +int +Server_Worker::main (int argc, ACE_TCHAR *argv[] ACE_ENV_ARG_DECL) +{ + ACE_Argv_Type_Converter cvt (argc, argv); + CORBA::ORB_var orb = CORBA::ORB_init (cvt.get_argc (), cvt.get_ASCII_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 (cvt.get_argc (), cvt.get_ASCII_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_file_.c_str (), "w"); + if (output_file == 0) + ACE_ERROR_RETURN ((LM_ERROR, + "(%P|%t) Cannot open output file for writing IOR: %s", + ior_file_.c_str ()), + 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; + + ACE_DEBUG ((LM_DEBUG, "(%P|%t) server - entering event loop\n")); + + 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; + + // During normal test execution the ORB would have been destroyed + // by a request from the client. + + // orb->shutdown (0 ACE_ENV_ARG_PARAMETER); + // ACE_CHECK; + + orb->destroy (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + return 0; +} diff --git a/TAO/tests/ORB_Local_Config/lib/Service_Configuration_Per_ORB.cpp b/TAO/tests/ORB_Local_Config/lib/Service_Configuration_Per_ORB.cpp new file mode 100644 index 00000000000..ef928a30df8 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/lib/Service_Configuration_Per_ORB.cpp @@ -0,0 +1,58 @@ +// $Id$ + +#include "Service_Configuration_Per_ORB.h" + + +// Return the name of the service configuration file, based on the current ACE +// support for wide characters and unicode +/// Borrowing this from the $ACE_ROOT/test/Service_Config_Test +/// The various config files have the same effect of loading 5 +/// new service objects. + +const ACE_TCHAR* +file_Service_Config_Test () +{ +#if defined (ACE_USES_WCHAR) + // When using full Unicode support, use the version of the Service + // Configurator file appropriate to the platform. + // For example, Windows Unicode uses UTF-16. + // + // iconv(1) found on Linux and Solaris, for example, can + // be used to convert between encodings. + // + // Byte ordering is also an issue, so we should be + // generating this file on-the-fly from the UTF-8 encoded + // file by using functions like iconv(1) or iconv(3). +# if defined (ACE_WIN32) + static const ACE_TCHAR svc_conf[] = + ACE_TEXT ("Service_Config_Test.UTF-16") + ACE_TEXT (ACE_DEFAULT_SVC_CONF_EXT); +# else + static const ACE_TCHAR svc_conf[] = + ACE_TEXT ("Service_Config_Test.WCHAR_T") + ACE_TEXT (ACE_DEFAULT_SVC_CONF_EXT); +# endif /* ACE_WIN32 */ +#else + // ASCII (UTF-8) encoded Service Configurator file. + static const ACE_TCHAR svc_conf[] = + ACE_TEXT ("Service_Config_Test") + ACE_TEXT (ACE_DEFAULT_SVC_CONF_EXT); +#endif /* ACE_USES_WCHAR */ + + return svc_conf; +} + +// Return the name of the service configuration file, for the ORB-based +// service object test + +const ACE_TCHAR* +file_Service_Config_ORB_Test () +{ + // ASCII (UTF-8) encoded Service Configurator file. + static const ACE_TCHAR svc_conf[] = + ACE_TEXT ("Service_Config_ORB_Test") + ACE_TEXT (ACE_DEFAULT_SVC_CONF_EXT); + + return svc_conf; +} + diff --git a/TAO/tests/ORB_Local_Config/lib/Service_Configuration_Per_ORB.h b/TAO/tests/ORB_Local_Config/lib/Service_Configuration_Per_ORB.h new file mode 100644 index 00000000000..a79b3e104a7 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/lib/Service_Configuration_Per_ORB.h @@ -0,0 +1,82 @@ +// $Id$ + +#ifndef SERVICE_CONFIGURATION_PER_ORB_H +# define SERVICE_CONFIGURATION_PER_ORB_H + + +#include "ace/Trace.h" +#include "ace/Service_Config.h" + +/// We need this wrapper to "break" the encapsulation and test +/// the internals of the class. The class also does a complete +/// teardown on the service repository used. So, do not expect +/// to find *any*, even static services in the global repo afer +/// this class desructor is done. + +class ACE_Service_Gestalt_Test : public ACE_Service_Gestalt +{ + public: + ACE_Service_Gestalt_Test (size_t n) + : ACE_Service_Gestalt (n) + , teardown_ (false) + { + }; + + ACE_Service_Gestalt_Test () + : ACE_Service_Gestalt () + , teardown_ (true) + { + }; + + ~ACE_Service_Gestalt_Test (void) + { + if (this->teardown_) + { + // Close and possibly delete all service instances in the Service + // Repository. + ACE_Service_Config::fini_svcs (); + + // Unlink all services in the Service Repository and close/delete + // all ACE library services and singletons. + ACE_Service_Config::close (); + } + }; + + size_t command_line_directives_count (void) const + { + return this->svc_queue_->size (); + }; + + size_t service_config_files_count (void) const + { + return this->svc_conf_file_queue_->size (); + }; + + size_t services_count (void) const + { + return this->repo_->current_size (); + }; + + bool has_same_service_repository ( ACE_Service_Gestalt_Test const * psg) + { + return (this->repo_ == psg->repo_); + } + +private: + bool teardown_; +}; + +// Return the name of the service configuration file, based on the current ACE +// support for wide characters and unicode +/// Borrowing this from the $ACE_ROOT/test/Service_Config_Test +/// The various config files have the same effect of loading 5 +/// new service objects. + +const ACE_TCHAR* file_Service_Config_Test (); + +// Return the name of the service configuration file, for the ORB-based +// service object test + +const ACE_TCHAR* file_Service_Config_ORB_Test (); + +#endif /* SERVICE_CONFIGURATION_PER_ORB_H */ diff --git a/TAO/tests/ORB_Local_Config/lib/lib.mpc b/TAO/tests/ORB_Local_Config/lib/lib.mpc new file mode 100644 index 00000000000..725f103fcc5 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/lib/lib.mpc @@ -0,0 +1,15 @@ +// -*- MPC -*- +// $Id$ + + +project(*) : acelib { + + Source_Files { + Service_Configuration_Per_ORB.cpp + } + + Header_Files { + Service_Configuration_Per_ORB.h + } +} + diff --git a/TAO/tests/ORB_Local_Config/run_tests_all.pl b/TAO/tests/ORB_Local_Config/run_tests_all.pl new file mode 100755 index 00000000000..3aae9463dd5 --- /dev/null +++ b/TAO/tests/ORB_Local_Config/run_tests_all.pl @@ -0,0 +1,62 @@ +eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' + & eval 'exec perl -S $0 $argv:q' + if 0; + +# $Id$ +# -*- perl -*- + +use lib "$ENV{ACE_ROOT}/bin"; +use PerlACE::Run_Test; + +sub add_path { + my($name) = shift; + my($value) = shift; + if (defined $ENV{$name}) { + $ENV{$name} .= ':' . $value + } + else { + $ENV{$name} = $value; + } +} + +# Set the library path for the client to be able to load +# the Time_Date library. +add_path('LD_LIBRARY_PATH', '../lib'); +add_path('LIBPATH', '../lib'); +add_path('SHLIB_PATH', '../lib'); + +sub test($) +{ + (my $executable, my $arguments) = @_; + chdir ($executable); + my $t1 = new PerlACE::Process ("Test", ($arguments ? $arguments : "")); + print STDERR "\nTest $executable is running ...\n"; + my $status = $t1->SpawnWaitKill (10); + chdir (".."); + if ($status != 0) { + print STDERR "\nERROR: Test $executable failed, status=$status\n"; + return -1; + } + + print STDERR "Test $executable reported success.\n"; + return 0; +} + +my $status = 0; +$status += test("Bug_1459"); +$status += test("Bunch"); +$status += test("Limits"); +$status += test("Separation"); +$status += test("Service_Dependency"); +$status += test("Shared"); +$status += test("Simple"); +$status += test("Two_DLL_ORB"); + +if ($status == 0) { + print STDERR "SUCCESS: All tests passed\n"; +} +else { + print STDERR "ERROR: Some test failed, status=$status\n"; +} +exit $status; + diff --git a/ace/Dynamic_Service_Dependency.cpp b/ace/Dynamic_Service_Dependency.cpp new file mode 100644 index 00000000000..cfb556f3e1c --- /dev/null +++ b/ace/Dynamic_Service_Dependency.cpp @@ -0,0 +1,48 @@ +#include "ace/DLL_Manager.h" +#include "ace/Dynamic_Service_Dependency.h" +#include "ace/Service_Config.h" + +ACE_RCSID (ace, + Dynamic_Service_Dependency, + "$Id$") + + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + + +ACE_Dynamic_Service_Dependency::ACE_Dynamic_Service_Dependency (const ACE_TCHAR *principal) +{ + this->init (ACE_Service_Config::current (), principal); +} + +ACE_Dynamic_Service_Dependency::ACE_Dynamic_Service_Dependency (const ACE_Service_Gestalt *cfg, + const ACE_TCHAR *principal) +{ + this->init (cfg, principal); +} + + +ACE_Dynamic_Service_Dependency::~ACE_Dynamic_Service_Dependency (void) +{ + if (ACE::debug () > 1) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) DSD, this=%@ - destroying dependency\n"), + this)); +} + +void +ACE_Dynamic_Service_Dependency::init (const ACE_Service_Gestalt *cfg, + const ACE_TCHAR *principal) +{ + const ACE_Service_Type* st = ACE_Dynamic_Service_Base::find_i (cfg, principal); + if (ACE::debug () > 1) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) DSD, this=%@ - creating dependency on "), this)); + st->dump (); + } + this->tracker_ = st->dll (); +} + + +ACE_END_VERSIONED_NAMESPACE_DECL diff --git a/ace/Dynamic_Service_Dependency.h b/ace/Dynamic_Service_Dependency.h new file mode 100644 index 00000000000..8f4b3b3cd18 --- /dev/null +++ b/ace/Dynamic_Service_Dependency.h @@ -0,0 +1,70 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file Dynamic_Service_Dependency.h + * + * $Id$ + * + * @author Iliyan Jeliazkov <iliyan@ociweb.com> + */ +//============================================================================= + +#ifndef ACE_DYNAMIC_SERVICE_DEPENDENCY_H +#define ACE_DYNAMIC_SERVICE_DEPENDENCY_H + +#include /**/ "ace/pre.h" + + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/Dynamic_Service_Base.h" +#include "ace/Service_Object.h" +#include "ace/DLL.h" + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +/** + * @class ACE_Dynamic_Service_Dependency + * + * @brief Provides a way to declare dependency on specific service, + * thus helping to avoid order of initialization issues with instances + * of an objects whose implementation code resides in dynamically loaded + * services. + * + * It is disastrous to have dynamically loadable services create and give away + * ownership of objects and then ending up being unloaded before all those + * instances have been deleted. Normally the code for such objects classes + * resides within the TEXT segment of the DLL, which implements the service. + * If a service gets removed, its DLL may be unmapped from memory and then + * any attempt to invoke a method on the said objects will cause SEGV. + * + * Such instances must contain a member of @code ACE_Dynamic_Service_Dependency + * initialized with the service they depend on. + * @code ACE_Dynamic_Service_Dependency's constructor and destructor are + * "magical" - they work by maintaining the underlying dynamic service's + * DLL reference count. + */ +class ACE_Export ACE_Dynamic_Service_Dependency +{ +public: + ACE_Dynamic_Service_Dependency (const ACE_Service_Gestalt *cfg, + const ACE_TCHAR *principal); + ACE_Dynamic_Service_Dependency (const ACE_TCHAR *principal); + ~ACE_Dynamic_Service_Dependency (void); + +private: + void init (const ACE_Service_Gestalt *cfg, const ACE_TCHAR *principal); + +private: + ACE_DLL tracker_; +}; + +ACE_END_VERSIONED_NAMESPACE_DECL + + +#include /**/ "ace/post.h" + +#endif /* ACE_DYNAMIC_SERVICE_DEPENDENCY_H */ diff --git a/ace/Service_Gestalt.cpp b/ace/Service_Gestalt.cpp new file mode 100644 index 00000000000..456958ac732 --- /dev/null +++ b/ace/Service_Gestalt.cpp @@ -0,0 +1,1114 @@ +// $Id$ + +#include "ace/Svc_Conf.h" +#include "ace/Get_Opt.h" +#include "ace/ARGV.h" +#include "ace/Malloc.h" +#include "ace/Service_Manager.h" +#include "ace/Service_Types.h" +#include "ace/Containers.h" +#include "ace/Auto_Ptr.h" +#include "ace/Reactor.h" +#include "ace/Thread_Manager.h" +#include "ace/DLL.h" +#include "ace/XML_Svc_Conf.h" +#include "ace/SString.h" + +#ifndef ACE_LACKS_UNIX_SIGNALS +# include "ace/Signal.h" +#endif /* !ACE_LACKS_UNIX_SIGNALS */ + +#include "ace/OS_NS_stdio.h" +#include "ace/OS_NS_time.h" +#include "ace/OS_NS_unistd.h" +#include "ace/OS_NS_sys_stat.h" + +#include "ace/TSS_T.h" +#include "ace/Service_Gestalt.h" + +#include "ace/Svc_Conf_Param.h" + +ACE_RCSID (ace, + Service_Gestalt, + "$Id$") + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +// This is here, in the implementation, because it depends on the ACE_DLL type, +// which would be unnecessary to introduuce all over the place, had we declared +// this in the header file. + +// A forward service declaration guard. Used to declare a Service Type with a +// specific name in a Service Repository, which may later be replaced by the +// "real" Service Type. The only application is in the implementation of +// ACE_Service_Gestalt::initialize (), hence the declaration scoping in +// this file. +class ACE_Service_Type_Forward_Declaration_Guard +{ +public: + ACE_Service_Type_Forward_Declaration_Guard (ACE_Service_Repository *r, + ACE_TCHAR const *name); + + ~ACE_Service_Type_Forward_Declaration_Guard (void); + +private: + const ACE_DLL dummy_dll_; + ACE_Service_Repository *repo_; + ACE_TCHAR const * const name_; + ACE_Service_Type const * dummy_; +}; + +ACE_Service_Type_Forward_Declaration_Guard::ACE_Service_Type_Forward_Declaration_Guard +(ACE_Service_Repository *r, const ACE_TCHAR *name) + : repo_ (r) + , name_ (name) +{ + ACE_ASSERT (this->repo_ != 0); // No repository specified? + ACE_ASSERT (this->name_ != 0); // No name? + + ACE_NEW_NORETURN (this->dummy_, // Allocate the forward declaration ... + ACE_Service_Type (this->name_, // ... use the same name + 0, // ... inactive + this->dummy_dll_, // ... bogus ACE_DLL + 0)); // ... no type_impl + + ACE_ASSERT (this->dummy_ != 0); // No memory? + + if(ACE::debug ()) + ACE_DEBUG ((LM_DEBUG, + ACE_LIB_TEXT ("(%P|%t) FWDCL::start, repo=%@, \'%s\' ") + ACE_LIB_TEXT ("- type=%@ (impl=(nil))\n"), + this->repo_, + this->name_, + this->dummy_)); + + // Note that the dummy_'s memory can disaper between invoking + // the ctor and dtor, if the expected "real" dynamic service is + // inserted in the repository. + this->repo_->insert (this->dummy_); +} + +ACE_Service_Type_Forward_Declaration_Guard::~ACE_Service_Type_Forward_Declaration_Guard (void) +{ + const ACE_Service_Type *tmp = 0; + + // Lookup without ignoring suspended services. Making sure + // not to ignore any inactive services, since those may be forward + // declarations + int ret = this->repo_->find (this->name_, &tmp, 0); + + // We inserted it (as inactive), so we expect to find it, right? + if (ret < 0 && ret != -2) + { + ACE_ERROR ((LM_WARNING, + ACE_LIB_TEXT ("(%P|%t) FWDCL::end - Failed (%d) to find %s\n"), + ret, this->name_)); + ACE_ASSERT (ret == -2 || ret >= 0); + } + + if (tmp != 0 && tmp->type () != 0) + { + // Something has registered a proper (non-forward-decl) service with + // the same name as our dummy. The ACE_Service_Gestalt::insert() modifies + // the memory for the previous ACE_Service_Type instance. It has in fact + // taken ownership and deleted the instance when it replaced it with the + // actual implementation, so nothing is left to do. We are hereby giving + // up any ownership claims. + this->dummy_ = 0; + + if(ACE::debug ()) + { + ACE_DEBUG ((LM_DEBUG, + ACE_LIB_TEXT ("(%P|%t) FWDCL::end, repo=%@ - ") + ACE_LIB_TEXT ("Found different decl - "), + this->repo_, + this->name_)); + tmp->dump (); + } + + } + else + { + if(ACE::debug ()) + { + ACE_DEBUG ((LM_DEBUG, + ACE_LIB_TEXT ("(%P|%t) FWDCL::end, repo=%@ - ") + ACE_LIB_TEXT ("Removing incomplete decl - "), + this->repo_, + this->name_)); + this->dummy_->dump (); + } + + // The (dummy) forward declaration is still there and is + // the same, which means that no actual declaration was + // provided inside the guarded scope. Therefore, the forward + // declaration is no longer necessary. + if (this->repo_->remove (this->name_, + const_cast< ACE_Service_Type**> (&this->dummy_)) == 0) + { + delete this->dummy_; + } + else + { + ACE_ERROR ((LM_ERROR, + ACE_LIB_TEXT ("(%P|%t) FWDCL::end, repo=%@ - ") + ACE_LIB_TEXT ("Failed to remove incomplete decl"), + this->repo_, + this->name_)); + this->dummy_->dump (); + } + } + + + // Clean up + this->dummy_ = 0; + this->repo_ = 0; +} + + + +// ---------------------------------------- + +ACE_Service_Gestalt::~ACE_Service_Gestalt (void) +{ + ACE_ASSERT (this->repo_ != 0); + + if (this->repo_is_owned_) + delete this->repo_; +} + +ACE_Service_Gestalt::ACE_Service_Gestalt (size_t size) + : repo_ (new ACE_Service_Repository (size)) + , repo_is_owned_ (true) + , is_opened_ (0) + , svc_conf_file_queue_ (0) + , static_svcs_ (new ACE_STATIC_SVCS) + , svc_queue_ (0) + , logger_key_ (ACE_DEFAULT_LOGGER_KEY) + , no_static_svcs_ (1) +{ + ACE_ASSERT (this->repo_ != 0); +} + +ACE_Service_Gestalt::ACE_Service_Gestalt (void) + : repo_ (ACE_Service_Repository::instance ()) + , repo_is_owned_ (false) + , is_opened_ (0) + , svc_conf_file_queue_ (0) + , static_svcs_ (new ACE_STATIC_SVCS) + , svc_queue_ (0) + , logger_key_ (ACE_DEFAULT_LOGGER_KEY) + , no_static_svcs_ (1) +{ + ACE_ASSERT (this->repo_ != 0); +} + + + +// Add the default statically-linked services to the Service +// Repository. + +int +ACE_Service_Gestalt::load_static_svcs (void) +{ + ACE_TRACE ("ACE_Service_Gestalt::load_static_svcs"); + + if (this->static_svcs_ == 0) + return 0; // Nothing to do + + ACE_Static_Svc_Descriptor **ssdp = 0; + for (ACE_STATIC_SVCS_ITERATOR iter (*this->static_svcs_); + iter.next (ssdp) != 0; + iter.advance ()) + { + ACE_Static_Svc_Descriptor *ssd = *ssdp; + + if (this->process_directive (*ssd, 1) == -1) + return -1; + } + return 0; + +} /* load_static_svcs () */ + + + +/// Find a static service descriptor by name + +int +ACE_Service_Gestalt::find_static_svc_descriptor (const ACE_TCHAR* name, + ACE_Static_Svc_Descriptor **ssd) const +{ + ACE_TRACE ("ACE_Service_Gestalt::find_static_svc_descriptor"); + + if (this->static_svcs_ == 0) + return -1; + + ACE_Static_Svc_Descriptor **ssdp = 0; + for (ACE_STATIC_SVCS_ITERATOR iter ( *this->static_svcs_); + iter.next (ssdp) != 0; + iter.advance ()) + { + if (ACE_OS::strcmp ((*ssdp)->name_, name) == 0) + { + if (ssd != 0) + *ssd = *ssdp; + + return 0; + } + } + return -1; + +} /* find_static_svc_descriptor () */ + + +int +ACE_Service_Gestalt::insert (ACE_Static_Svc_Descriptor *stsd) +{ + if (ACE::debug () > 1) + { + // If called during static initialization ACE_Log_Msg may not have + // been initialized yet, so use printf intead. + ACE_OS::fprintf (stderr, + "// (%d|0) SG::insert" + " repo=%p, name=%s - Static_Svc_Descriptor: active=%d, opened=%d.\n", + ACE_OS::getpid (), + this->repo_, + stsd->name_, + stsd->active_, + this->is_opened_); + } + + // Inserting a service after teh Gestalt has been opened makes it + // impossible to activate it later. Perhaps open came too soon? + //ACE_ASSERT (this->is_opened_ == 0); + + return this->static_svcs_->insert (stsd); +} + + +ACE_ALLOC_HOOK_DEFINE (ACE_Service_Gestalt) + + +void +ACE_Service_Gestalt::dump (void) const +{ +#if defined (ACE_HAS_DUMP) + ACE_TRACE ("ACE_Service_Gestalt::dump"); +#endif /* ACE_HAS_DUMP */ +} + + + +ACE_ALLOC_HOOK_DEFINE (ACE_Service_Type_Factory) + +ACE_Service_Type_Factory::ACE_Service_Type_Factory (ACE_TCHAR const *name, + int type, + ACE_Location_Node *location, + int active) + : name_ (name) + , type_ (type) + , location_ (location) + , is_active_ (active) +{ + ACE_TRACE ("ACE_Service_Type_Factory::ACE_Service_Type_Factory"); +}; + +ACE_Service_Type_Factory::~ACE_Service_Type_Factory (void) +{ + ACE_TRACE ("ACE_Service_Type_Factory::~ACE_Service_Type_Factory"); +} + + +ACE_Service_Type * +ACE_Service_Type_Factory::make_service_type (ACE_Service_Gestalt *cfg) const +{ + ACE_TRACE ("ACE_Service_Type_Factory::make_service_type"); + + u_int flags = ACE_Service_Type::DELETE_THIS + | (this->location_->dispose () == 0 ? 0 : ACE_Service_Type::DELETE_OBJ); + + ACE_Service_Object_Exterminator gobbler = 0; + + int yyerrno = 0; + void *sym = this->location_->symbol (cfg, yyerrno, &gobbler); + + if (sym != 0) + { + ACE_Service_Type_Impl *stp + = ACE_Service_Config::create_service_type_impl (this->name (), + this->type_, + sym, + flags, + gobbler); + if (stp == 0) + ++yyerrno; + + return new ACE_Service_Type (this->name (), + stp, + this->location_->dll (), + this->is_active_); + } + else + { + ACE_ERROR ((LM_ERROR, + ACE_LIB_TEXT ("Unable to find service: %s\n"), + this->name ())); + ++yyerrno; + return 0; + } +} + +ACE_TCHAR const* +ACE_Service_Type_Factory::name (void) const +{ + return name_.c_str (); +} + + +/// + +int +ACE_Service_Gestalt::initialize (const ACE_TCHAR *svc_name, + const ACE_TCHAR *parameters) +{ + ACE_TRACE ("ACE_Service_Gestalt_Base::initialize (repo)"); + ACE_ARGV args (parameters); + + if (ACE::debug () > 1) + { + ACE_DEBUG ((LM_DEBUG, + ACE_LIB_TEXT ("(%P|%t) SG::initialize - () repo=%@, looking up static ") + ACE_LIB_TEXT ("service \'%s\' to initialize\n"), + this->repo_, + svc_name)); + } + + const ACE_Service_Type *srp = 0; + if (this->repo_->find (svc_name, &srp) == -1) + { + // Since we're searching by name, the service may be in the + // process-wide repository, so check that before reporting + // failure. + if (this->repo_ == ACE_Service_Repository::instance () + || ACE_Service_Repository::instance ()->find (svc_name, &srp) == -1) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_LIB_TEXT ("(%P|%t) SG::initialize - service \'%s\'") + ACE_LIB_TEXT (" was not located.\n"), + svc_name), + -1); + } + } + + /// If initialization fails ... + if (srp->type ()->init (args.argc (), + args.argv ()) == -1) + { + // ... report and remove this entry. + ACE_ERROR ((LM_ERROR, + ACE_LIB_TEXT ("(%P|%t) SG::initialize - static init of \'%s\'") + ACE_LIB_TEXT (" failed (%p)\n"), + svc_name)); + this->repo_->remove (svc_name); + return -1; + } + + // If everything is ok, activate it + const_cast<ACE_Service_Type *>(srp)->active (1); + return 0; +} + + +int +ACE_Service_Gestalt::initialize (const ACE_Service_Type_Factory *stf, + const ACE_TCHAR *parameters) +{ + ACE_TRACE ("ACE_Service_Gestalt::initialize"); + + if (ACE::debug () > 1) + ACE_DEBUG ((LM_DEBUG, + ACE_LIB_TEXT ("(%P|%t) SG::initialize - repo=%@, looking up dynamic ") + ACE_LIB_TEXT ("service \'%s\' to initialize\n"), + this->repo_, + stf->name ())); + + ACE_Service_Type *srp = 0; + int retv = this->repo_->find (stf->name (), + (const ACE_Service_Type **) &srp); + + // If there is an active service already, it must first be removed, + // before it could be re-installed. + if (retv >= 0) + ACE_ERROR_RETURN ((LM_WARNING, + ACE_LIB_TEXT ("(%P|%t) \'%s\' already installed.") + ACE_LIB_TEXT (" Must be removes before re-installing\n"), + stf->name ()), + 0); + + // There is an inactive service by that name, so it may have been + // either inactivated, or just a forward declaration for a service, + // that is in the process of being loaded. If the latter, then we + // have detected an attempt to initialize the same dynamic service + // while still processing previous attempt. This can lock up the + // process, because the ACE_DLL_Manager::open () is not re-entrant - + // it uses a Singleton lock to serialize concurent invocations. This + // use case must be handled here, because if the DLL_Manager was + // re-entrant we would have entered an infinite recursion here. + if (retv == -2 && srp->type () == 0) + ACE_ERROR_RETURN ((LM_WARNING, + ACE_LIB_TEXT ("(%P|%t) \'%s\' has not been ") + ACE_LIB_TEXT ("completely defined. Recursive ") + ACE_LIB_TEXT ("initialization request while ") + ACE_LIB_TEXT ("already performing one.\n"), + stf->name ()), + -1); + + // Reserve a spot for the dynamic service by inserting an incomplete + // service declaration, i.e. one that can not produce a service + // object if asked. Having this incomplete declaration works + // similar to C++'s forward declaration to allow, in this case + // proper partial ordering of the loaded services in respect to + // their finalization. I.e. dependent static services must be + // registered *after* the dynamic service that loads them, so that + // their finalization is complete *before* finalizing the dynamic + // service. + ACE_Service_Type_Forward_Declaration_Guard dummy (this->repo_, + stf->name ()); + + // make_service_type() is doing the dynamic loading and also runs + // any static initializers + ACE_Auto_Ptr<ACE_Service_Type> tmp (stf->make_service_type (this)); + + if (tmp.get () != 0 && + this->initialize_i (tmp.get (), parameters) == 0) + { + // All good the ACE_Service_Type instance is now owned by the repository + // and we should make sure it is not destroyed upon exit from this method. + (void)tmp.release (); + return 0; + } + + // Something went wrong ... + ACE_ERROR_RETURN ((LM_ERROR, + ACE_LIB_TEXT ("(%P|%t) Error initializing \'%s\'\n"), + stf->name()), + -1); +} + + +// Dynamically link the shared object file and retrieve a pointer to +// the designated shared object in this file. +// @note This is obsolete (and error-prone) in the presense of dynamic +// services with their own static services. This method will allow those +// static services to register *before* the dynamic service that owns them. +// Upon finalization of the static services the process may crash, because +// the dynamic service's DLL may have been already released, together with +// the memory in which the static services reside. +// It may not crash, for instance, when the first static service to register +// is the same as the dynamic service being loaded. You should be so lucky! .. + +int +ACE_Service_Gestalt::initialize (const ACE_Service_Type *sr, + const ACE_TCHAR *parameters) +{ + ACE_TRACE ("ACE_Service_Gestalt::initialize"); + + if (ACE::debug ()) + ACE_DEBUG ((LM_DEBUG, + ACE_LIB_TEXT ("(%P|%t) SG::initialize - looking up dynamic ") + ACE_LIB_TEXT (" service \'%s\' to initialize\n"), + sr->name ())); + + ACE_Service_Type *srp = 0; + if (this->repo_->find (sr->name (), + (const ACE_Service_Type **) &srp) >= 0) + ACE_ERROR_RETURN ((LM_WARNING, + ACE_LIB_TEXT ("(%P|%t) SG::initialize - \'%s\' ") + ACE_LIB_TEXT ("has already been installed. ") + ACE_LIB_TEXT ("Remove before reinstalling\n"), + sr->name ()), + 0); + + return this->initialize_i (sr, parameters); + +} + +// Dynamically link the shared object file and retrieve a pointer to +// the designated shared object in this file. +int +ACE_Service_Gestalt::initialize_i (const ACE_Service_Type *sr, + const ACE_TCHAR *parameters) +{ + ACE_TRACE ("ACE_Service_Gestalt::initialize_i"); + ACE_ARGV args (parameters); + + if (sr->type ()->init (args.argc (), + args.argv ()) == -1) + { + ACE_ERROR ((LM_ERROR, + ACE_LIB_TEXT ("(%P|%t) SG - dynamic initialization ") + ACE_LIB_TEXT ("failed for \'%s\'\n"), + sr->name ())); + + ACE_Service_Type *ps = 0; + this->repo_->remove (sr->name (), &ps); + + // We just get ps to avoid having remove() delete it. + return -1; + } + + if (this->repo_->insert (sr) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_LIB_TEXT ("(%P|%t) SG - inserting service") + ACE_LIB_TEXT (" description failed, %p\n"), + sr->name ()), + -1); + return 0; +} + +// Totally remove <svc_name> from the daemon by removing it from the +// ACE_Reactor, and unlinking it if necessary. + +int +ACE_Service_Gestalt::remove (const ACE_TCHAR svc_name[]) +{ + ACE_TRACE ("ACE_Service_Gestalt::remove"); + return this->repo_->remove (svc_name); +} + +// Suspend <svc_name>. Note that this will not unlink the service +// from the daemon if it was dynamically linked, it will mark it as +// being suspended in the Service Repository and call the <suspend> +// member function on the appropriate <ACE_Service_Object>. A service +// can be resumed later on by calling the <resume> method... + +int +ACE_Service_Gestalt::suspend (const ACE_TCHAR svc_name[]) +{ + ACE_TRACE ("ACE_Service_Gestalt::suspend"); + return this->repo_->suspend (svc_name); +} + +// Resume a SVC_NAME that was previously suspended or has not yet +// been resumed (e.g., a static service). + +int +ACE_Service_Gestalt::resume (const ACE_TCHAR svc_name[]) +{ + ACE_TRACE ("ACE_Service_Gestalt::resume"); + return this->repo_->resume (svc_name); +} + + +int +ACE_Service_Gestalt::process_directive (const ACE_Static_Svc_Descriptor &ssd, + int force_replace) +{ + if (ACE::debug () > 2) + ACE_DEBUG ((LM_DEBUG, + ACE_LIB_TEXT ("(%P|%t) SG::process_directive, ") + ACE_LIB_TEXT ("repo=%@, replace=%d - %s\n"), + this->repo_, + force_replace, + ssd.name_)); + + if (!force_replace) + { + if (this->repo_->find (ssd.name_, 0, 0) >= 0) + { + // The service is already there, just return + return 0; + } + } + + ACE_Service_Object_Exterminator gobbler; + void *sym = (ssd.alloc_)(&gobbler); + + ACE_Service_Type_Impl *stp = + ACE_Service_Config::create_service_type_impl (ssd.name_, + ssd.type_, + sym, + ssd.flags_, + gobbler); + if (stp == 0) + return 0; + + + ACE_Service_Type *service_type; + + // This is just a temporary to force the compiler to use the right + // constructor in ACE_Service_Type + ACE_DLL tmp_dll; + + ACE_NEW_RETURN (service_type, + ACE_Service_Type (ssd.name_, + stp, + tmp_dll, + ssd.active_), + -1); + + return this->repo_->insert (service_type); +} + + +#if (ACE_USES_CLASSIC_SVC_CONF == 1) + +int +ACE_Service_Gestalt::process_directives_i (ACE_Svc_Conf_Param *param) +{ + // AC 970827 Skip the heap check because yacc allocates a buffer + // here which will be reported as a memory leak for some reason. + ACE_NO_HEAP_CHECK + + // Were we called in the context of the current instance? + ACE_ASSERT (this == param->config); + + // Temporarily (for the duration of this call) make sure that *any* static + // service registrations will happen with this instance. Such registrations + // are possible as a side-effect of dynamically loading a DLL, which has + // other static services registered. Thus this instance will own both the + // DLL and those static services, which implies that their finalization + // will be performed in the correct order, i.e. prior to finalizing the DLL + ACE_Service_Config_Guard guard (this); + + if (ACE::debug ()) + ACE_DEBUG ((LM_DEBUG, + ACE_LIB_TEXT ("(%P|%t) SG::process_directives_i, ") + ACE_LIB_TEXT ("repo=%@ - %s\n"), + this->repo_, + (param->type == ACE_Svc_Conf_Param::SVC_CONF_FILE) + ? ACE_TEXT ("<from file>") + : param->source.directive)); + + + ::ace_yyparse (param); + + if (param->yyerrno > 0) + { + // This is a hack, better errors should be provided... + errno = EINVAL; + return param->yyerrno; + } + else + return 0; +} + +#else + +ACE_XML_Svc_Conf * +ACE_Service_Gestalt::get_xml_svc_conf (ACE_DLL &xmldll) +{ + if (xmldll.open (ACE_LIB_TEXT ("ACEXML_XML_Svc_Conf_Parser")) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_LIB_TEXT ("Fail to open ACEXML_XML_Svc_Conf_Parser: %p\n"), + "ACE_Service_Config::get_xml_svc_conf"), + 0); + + void *foo; + foo = xmldll.symbol (ACE_LIB_TEXT ("_ACEXML_create_XML_Svc_Conf_Object")); + + // Cast the void* to long first. + long tmp = reinterpret_cast<long> (foo); + ACE_XML_Svc_Conf::Factory factory = + reinterpret_cast<ACE_XML_Svc_Conf::Factory> (tmp); + if (factory == 0) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_LIB_TEXT ("Unable to resolve factory: %p\n"), + xmldll.error ()), + 0); + + return factory (); +} +#endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */ + +int +ACE_Service_Gestalt::process_file (const ACE_TCHAR file[]) +{ + ACE_TRACE ("ACE_Service_Gestalt::process_file"); + + // To avoid recursive processing of the same file and the same repository + // we maintain an implicit stack of dummy "services" named after the file + // being processed. Anytime we have to open a new file, we then can check + // to see if it is not already being processed by searching for a dummy + // service with a matching name. + if (this->repo_->find (file, 0, 0) >=0) + { + ACE_DEBUG ((LM_WARNING, + ACE_TEXT ("(%P|%t) Configuration file %s has not finished") + ACE_TEXT (" processing yet. Ignoring.\n"), + file)); + return 0; + } + + // Register a dummy service as a forward decl, using the file name as name. + // The entry will be automaticaly removed once the thread exits this block. + ACE_Service_Type_Forward_Declaration_Guard recursion_guard (this->repo_, file); + + /* + * @TODO: Test with ACE_USES_CLASSIC_SVC_CONF turned off! + */ +#if (ACE_USES_CLASSIC_SVC_CONF == 1) + int result = 0; + + FILE *fp = ACE_OS::fopen (file, + ACE_LIB_TEXT ("r")); + + if (fp == 0) + { + // Invalid svc.conf file. We'll report it here and break out of + // the method. + if (ACE::debug ()) + ACE_DEBUG ((LM_ERROR, + ACE_LIB_TEXT ("%p\n"), + file)); + + // Use stat to find out if the file exists. I didn't use access() + // because stat is better supported on most non-unix platforms. + ACE_stat exists; + if (ACE_OS::stat (file, &exists) == 0) + // If it exists, but we couldn't open it for reading then we + // must not have permission to read it. + errno = EPERM; + else + errno = ENOENT; + result = -1; + } + else + { + ACE_Svc_Conf_Param f (this, fp); + + // Keep track of the number of errors. + result = this->process_directives_i (&f); + + (void) ACE_OS::fclose (fp); + } + return result; +#else + ACE_DLL dll; + + auto_ptr<ACE_XML_Svc_Conf> + xml_svc_conf (ACE_Service_Config::get_xml_svc_conf (dll)); + + if (xml_svc_conf.get () == 0) + return -1; + + return xml_svc_conf->parse_file (file); +#endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */ +} + +int +ACE_Service_Gestalt::process_directive (const ACE_TCHAR directive[]) +{ + ACE_TRACE ("ACE_Service_Gestalt::process_directive"); + + if (ACE::debug ()) + ACE_DEBUG ((LM_DEBUG, + ACE_LIB_TEXT ("(%P|%t) SG::process_directive, repo=%@ - %s\n"), + this->repo_, + directive)); + +#if (ACE_USES_CLASSIC_SVC_CONF == 1) + ACE_UNUSED_ARG (directive); + + ACE_Svc_Conf_Param d (this, directive); + + int result = this->process_directives_i (&d); + + return result; +#else + ACE_DLL dll; + + auto_ptr<ACE_XML_Svc_Conf> + xml_svc_conf (this->get_xml_svc_conf (dll)); + + if (xml_svc_conf.get () == 0) + return -1; + + return xml_svc_conf->parse_string (directive); +#endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */ + +} /* process_directive () */ + + +int +ACE_Service_Gestalt::init_svc_conf_file_queue (void) +{ + if (this->svc_conf_file_queue_ == 0) + { + ACE_SVC_QUEUE *tmp = 0; + ACE_NEW_RETURN (tmp, + ACE_SVC_QUEUE, + -1); + delete this->svc_conf_file_queue_; + this->svc_conf_file_queue_ = tmp; + } + + if (ACE::debug () > 1) + ACE_DEBUG ((LM_DEBUG, + ACE_LIB_TEXT ("(%P|%t) SG::init_svc_conf_file_queue ") + ACE_LIB_TEXT ("- this=%@, repo=%@\n"), + this, this->repo_)); + return 0; + +} /* init_svc_conf_file_queue () */ + + +int +ACE_Service_Gestalt::open_i (const ACE_TCHAR /*program_name*/[], + const ACE_TCHAR* /*logger_key*/, + bool /*ignore_static_svcs*/, + bool /*ignore_default_svc_conf_file*/, + bool ignore_debug_flag) +{ + ACE_TRACE ("ACE_Service_Gestalt::open_i"); + int result = 0; + ACE_Log_Msg *log_msg = ACE_LOG_MSG; + + // Record the current log setting upon entering this thread. + u_long old_process_mask = log_msg->priority_mask + (ACE_Log_Msg::PROCESS); + u_long old_thread_mask = log_msg->priority_mask + (ACE_Log_Msg::THREAD); + + if (ACE::debug ()) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) SG::open_i - this=%@, ") + ACE_TEXT ("opened=%d, loadstatics=%d\n"), + this, this->is_opened_, this->no_static_svcs_)); + + // Guard against reentrant processing. For example, + // if the singleton gestalt (ubergestalt) was already open, + // do not open it again... + if (this->is_opened_++ != 0) + return 0; + + if (ignore_debug_flag == 0) + { + // If -d was included as a startup parameter, the user wants debug + // information printed during service initialization. + if (ACE::debug ()) + ACE_Log_Msg::enable_debug_messages (); + else + // The user has requested no debugging info. + ACE_Log_Msg::disable_debug_messages (); + } + + // See if we need to load the static services. + if (this->no_static_svcs_ == 0 + && this->load_static_svcs () == -1) + result = -1; + else + { + if (this->process_commandline_directives () == -1) + result = -1; + else + result = this->process_directives (); + } + + + // Reset debugging back to the way it was when we came into + // into <open_i>. + { + // Make sure to save/restore errno properly. + ACE_Errno_Guard error (errno); + + if (ignore_debug_flag == 0) + { + log_msg->priority_mask (old_process_mask, ACE_Log_Msg::PROCESS); + log_msg->priority_mask (old_thread_mask, ACE_Log_Msg::THREAD); + } + } + + return result; +} /* open_i () */ + + +int +ACE_Service_Gestalt::is_opened (void) +{ + return this->is_opened_; +} + +int +ACE_Service_Gestalt::process_commandline_directives (void) +{ + int result = 0; + if (this->svc_queue_ != 0) + { + ACE_TString *sptr = 0; + for (ACE_SVC_QUEUE_ITERATOR iter (*this->svc_queue_); + iter.next (sptr) != 0; + iter.advance ()) + { + // Process just a single directive. + if (this->process_directive ((sptr->fast_rep ())) != 0) + { + ACE_ERROR ((LM_ERROR, + ACE_LIB_TEXT ("%p\n"), + ACE_LIB_TEXT ("process_directive"))); + result = -1; + } + } + + delete this->svc_queue_; + this->svc_queue_ = 0; + } + + return result; + +} /* process_commandline_directives () */ + + +int +ACE_Service_Gestalt::parse_args (int argc, ACE_TCHAR *argv[]) +{ + ACE_TRACE ("ACE_Service_Gestalt::parse_args"); + return parse_args_i (argc, argv); +} + +int +ACE_Service_Gestalt::parse_args_i (int argc, ACE_TCHAR *argv[]) +{ + ACE_TRACE ("ACE_Service_Gestalt::parse_args_i"); + ACE_Get_Opt getopt (argc, + argv, + ACE_LIB_TEXT ("df:k:nyp:s:S:"), + 1); // Start at argv[1]. + + if (this->init_svc_conf_file_queue () == -1) + return -1; + + for (int c; (c = getopt ()) != -1; ) + switch (c) + { + case 'd': + ACE::debug (1); + break; + case 'f': + if (this->svc_conf_file_queue_->enqueue_tail (ACE_TString (getopt.opt_arg ())) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_LIB_TEXT ("%p\n"), + ACE_LIB_TEXT ("enqueue_tail")), + -1); + break; + case 'k': + /* + * @TODO: Is this always a static storage? Shouldn't we copy + * & gain ownership of the value? + */ + this->logger_key_ = getopt.opt_arg (); + break; + case 'n': + this->no_static_svcs_ = 1; + break; + case 'y': + this->no_static_svcs_ = 0; + break; + case 'S': + if (this->svc_queue_ == 0) + { + ACE_NEW_RETURN (this->svc_queue_, + ACE_SVC_QUEUE, + -1); + } + + if (this->svc_queue_->enqueue_tail (ACE_TString (getopt.opt_arg ())) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_LIB_TEXT ("%p\n"), + ACE_LIB_TEXT ("enqueue_tail")), + -1); + break; + default: + if (ACE::debug () > 0) + ACE_DEBUG ((LM_DEBUG, + ACE_LIB_TEXT ("%c is not a ACE_Service_Config option\n"), + c)); + } + + return 0; +} /* parse_args_i () */ + + + +// Process service configuration requests as indicated in the queue of +// svc.conf files. +int +ACE_Service_Gestalt::process_directives (void) +{ + ACE_TRACE ("ACE_Service_Gestalt::process_directives"); + + int result = 0; + + if (this->svc_conf_file_queue_ != 0) + { + ACE_TString *sptr = 0; + + // Iterate through all the svc.conf files. + for (ACE_SVC_QUEUE_ITERATOR iter (*this->svc_conf_file_queue_); + iter.next (sptr) != 0; + iter.advance ()) + { + int r = this->process_file (sptr->fast_rep ()); + + if (r < 0) + { + result = r; + break; + } + + result += r; + } + } + + return result; + +} /* process_directives () */ + + + +// Tidy up and perform last rites on a terminating ACE_Service_Gestalt. +int +ACE_Service_Gestalt::close (void) +{ + ACE_TRACE ("ACE_Service_Gestalt::close"); + + if (ACE::debug () > 1) + ACE_DEBUG ((LM_DEBUG, + ACE_LIB_TEXT ("(%P|%t) SG::close - this=%@, repo=%@, is_opened=%d\n"), + this, this->repo_, this->is_opened_)); + + this->is_opened_--; + if (this->is_opened_ > 0) + return 0; + + // Delete the service repository. All the objects inside the + // service repository should already have been finalized. + // ACE_Service_Config::close_svcs (); + + // Delete the list fo svc.conf files + delete this->svc_conf_file_queue_; + this->svc_conf_file_queue_ = 0; + + // Delete the dynamically allocated static_svcs instance. + if (ACE::debug ()) + ACE_DEBUG ((LM_DEBUG, + ACE_LIB_TEXT ("(%P|%t) SG::close - this=%@, repo=%@\n"), + this, this->repo_)); + + delete this->static_svcs_; + this->static_svcs_ = 0; + + return 0; + +} /* close () */ + + +ACE_END_VERSIONED_NAMESPACE_DECL + +#if !defined (__ACE_INLINE__) +#include "ace/Service_Gestalt.inl" +#endif /* __ACE_INLINE__ */ + + +// Allocate a Service Manager. +ACE_FACTORY_DEFINE (ACE, ACE_Service_Manager) diff --git a/ace/Service_Gestalt.h b/ace/Service_Gestalt.h new file mode 100644 index 00000000000..39618b402d6 --- /dev/null +++ b/ace/Service_Gestalt.h @@ -0,0 +1,438 @@ +// -*- C++ -*- + +//==================================================================== +/** + * @file Service_Gestalt.h + * + * $Id$ + * + * @author Iliyan Jeliazkov <iliyan@ociweb.com> + */ +//==================================================================== + +#ifndef ACE_SERVICE_GESTALT_H +#define ACE_SERVICE_GESTALT_H + +#include /**/ "ace/pre.h" + +#include "ace/config-all.h" +#include "ace/Default_Constants.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/SString.h" +#include "ace/Unbounded_Queue.h" +#include "ace/Service_Repository.h" +#include "ace/Singleton.h" +#include "ace/OS_NS_signal.h" +#include "ace/Synch_Traits.h" + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +class ACE_Service_Type_Factory; +class ACE_Static_Svc_Descriptor; +class ACE_Svc_Conf_Param; + +class ACE_Service_Gestalt; + +/** + * @class ACE_Service_Gestalt + * + * @brief Supplies common server operations for dynamic and static + * configuration of services. + */ +class ACE_Export ACE_Service_Gestalt +{ +private: + /** + * Not implemented to enforce no copying + */ + ACE_UNIMPLEMENTED_FUNC (ACE_Service_Gestalt(const ACE_Service_Gestalt&)) + ACE_UNIMPLEMENTED_FUNC (ACE_Service_Gestalt& operator=(const ACE_Service_Gestalt&)) + +public: + enum + { + MAX_SERVICES = ACE_DEFAULT_SERVICE_REPOSITORY_SIZE + }; + + /// Default constructor - associates the instance with the process-wide + /// singleton instance of ACE_Service_Repository. + ACE_Service_Gestalt (void); + + /// Creates an instance with a specified repository size. Takes ownership + /// of the repository. + ACE_Service_Gestalt (size_t size); + + /// Perform user-specified close activities and remove dynamic + /// memory. + virtual ~ACE_Service_Gestalt (void); + + /// Dump the state of an object. + void dump (void) const; + + /** + * Performs an open without parsing command-line arguments. The + * @a logger_key indicates where to write the logging output, which + * is typically either a STREAM pipe or a socket address. If + * @a ignore_static_svcs is 1 then static services are not loaded, + * otherwise, they are loaded. If @a ignore_default_svc_conf_file is + * non-0 then the <svc.conf> configuration file will be ignored. + * Returns zero upon success, -1 if the file is not found or cannot + * be opened (errno is set accordingly), otherwise returns the + * number of errors encountered loading the services in the + * specified svc.conf configuration file. If @a ignore_debug_flag is + * non-0 then the application is responsible for setting the + * <ACE_Log_Msg::priority_mask> appropriately. + */ + int open (const ACE_TCHAR program_name[], + const ACE_TCHAR *logger_key = ACE_DEFAULT_LOGGER_KEY, + int ignore_static_svcs = 1, + int ignore_default_svc_conf_file = 0, + int ignore_debug_flag = 0); + + /** + * This is the primary entry point into the ACE_Service_Config (the + * constructor just handles simple initializations). It parses + * arguments passed in from @a argc and @a argv parameters. The + * arguments that are valid in a call to this method include: + * + * - '-b' Option to indicate that we should be a daemon. Note that when + * this option is used, the process will be daemonized before the + * service configuration file(s) are read. During daemonization, + * (on POSIX systems) the current directory will be changed to "/" + * so the caller should either fully specify the file names, or + * execute a @c chroot() to the appropriate directory. + * @sa ACE::daemonize(). + * - '-d' Turn on debugging mode + * - '-f' Specifies a configuration file name other than the default + * svc.conf. Can be specified multiple times to use multiple files. + * - '-k' Specifies the rendezvous point to use for the ACE distributed + * logger. + * - '-y' Explicitly enables the use of static services. This flag + * overrides the @a ignore_static_svcs parameter value. + * - '-n' Explicitly disables the use of static services. This flag + * overrides the @a ignore_static_svcs parameter value. + * - '-p' Specifies a pathname which is used to store the process id. + * - '-s' Specifies a signal number other than SIGHUP to trigger reprocessing + * of the configuration file(s). Ignored for platforms that do not + * have POSIX signals, such as Windows. + * - '-S' Specifies a service directive string. Enclose the string in quotes + * and escape any embedded quotes with a backslash. This option + * specifies service directives without the need for a configuration + * file. + * + * @param argc The number of commandline arguments. + * @param argv The array with commandline arguments + * @param logger_key Indicates where to write the logging output, + * which is typically either a STREAM pipe or a + * socket address. + * @param ignore_static_svcs If 1 then static services are not loaded, + * otherwise, they are loaded. + * @param ignore_default_svc_conf_file If non-0 then the @c svc.conf + * configuration file will be ignored. + * @param ignore_debug_flag If non-0 then the application is responsible + * for setting the @c ACE_Log_Msg::priority_mask + * appropriately. + * + * @retval -1 The configuration file is not found or cannot + * be opened (errno is set accordingly). + * @retval 0 Success. + * @retval >0 The number of errors encountered while processing + * the service configuration file(s). + */ + int open (int argc, + ACE_TCHAR *argv[], + const ACE_TCHAR *logger_key = ACE_DEFAULT_LOGGER_KEY, + int ignore_static_svcs = 1, + int ignore_default_svc_conf_file = 0, + int ignore_debug_flag = 0); + + /// Has it been opened? Returns the difference between the times + /// open and close have been called on this instance + int is_opened (void); + + /// Declare the dynamic allocation hooks. + ACE_ALLOC_HOOK_DECLARE; + + /// Process one service configuration @a directive, which is passed as + /// a string. Returns the number of errors that occurred. + int process_directive (const ACE_TCHAR directive[]); + + /// Process one static service definition. + /** + * Load a new static service. + * + * @param ssd Service descriptor, see the document of + * ACE_Static_Svc_Descriptor for more details. + * + * @param force_replace If set the new service descriptor replaces + * any previous instance in the repository. + * + * @return Returns -1 if the service cannot be 'loaded'. + */ + int process_directive (const ACE_Static_Svc_Descriptor &ssd, + int force_replace = 0); + + /// Process a file containing a list of service configuration + /// directives. + int process_file (const ACE_TCHAR file[]); + + /** + * Locate an entry with <name> in the table. If <ignore_suspended> + * is set then only consider services marked as resumed. If the + * caller wants the located entry, pass back a pointer to the + * located entry via <srp>. If <name> is not found, -1 is returned. + * If <name> is found, but it is suspended and the caller wants to + * ignore suspended services a -2 is returned. + */ + int find (const ACE_TCHAR name[], + const ACE_Service_Type **srp = 0, + int ignore_suspended = 1) const; + + /** + * Handle the command-line options intended for the + * <ACE_Service_Config>. Note that <argv[0]> is assumed to be the + * program name. + * The arguments that are valid in a call to this method are + * - '-b' Option to indicate that we should be a daemon + * - '-d' Turn on debugging mode + * - '-f' Option to read in the list of svc.conf file names + * - '-k' Option to read a wide string where in the logger output can + * be written + * - '-y' Turn on the flag for a repository of statically + * linked services + * - '-n' Need not have a repository of statically linked services + * - '-S' Option to read in the list of services on the command-line + * Please observe the difference between options '-f' that looks + * for a list of files and here a list of services. + */ + int parse_args (int, ACE_TCHAR *argv[]); + + /** + * Process (or re-process) service configuration requests that are + * provided in the svc.conf file(s). Returns the number of errors + * that occurred. + */ + int process_directives (void); + + /// Tidy up and perform last rites when ACE_Service_Config is shut + /// down. This method calls <close_svcs>. Returns 0. + int close (void); + + + // Registers a service descriptor for a static service object + int insert (ACE_Static_Svc_Descriptor *stsd); + + // = Utility methods. + /// Dynamically link the shared object file and retrieve a pointer to + /// the designated shared object in this file. Also account for the + /// possiblity to have static services registered when loading the DLL, by + /// ensuring that the dynamic sevice is registered before any of its + /// subordibnate static services. Thus avoiding any finalization order + /// problems. + int initialize (const ACE_Service_Type_Factory *, + const ACE_TCHAR *parameters); + + // Dynamically link the shared object file and retrieve a pointer to + // the designated shared object in this file. + // @obsolete + // @note This is error-prone in the presense of dynamic + // services with their own static services. This method will allow those + // static services to register *before* the dynamic service that owns them. + // Upon finalization of the static services the process may crash, because + // the dynamic service's DLL may have been already released, together with + // the memory in which the static services reside. + // It may not crash, for instance, when the first static service to register + // is the same as the dynamic service being loaded. You should be so lucky! + int initialize (const ACE_Service_Type *, + const ACE_TCHAR *parameters); + + /// Initialize and activate a statically @a svc_name service. + int initialize (const ACE_TCHAR *svc_name, + const ACE_TCHAR *parameters); + + /// Resume a @a svc_name that was previously suspended or has not yet + /// been resumed (e.g., a static service). + int resume (const ACE_TCHAR svc_name[]); + + /** + * Suspend @a svc_name. Note that this will not unlink the service + * from the daemon if it was dynamically linked, it will mark it as + * being suspended in the Service Repository and call the <suspend> + * member function on the appropriate <ACE_Service_Object>. A + * service can be resumed later on by calling the <RESUME> member + * function... + */ + int suspend (const ACE_TCHAR svc_name[]); + + /// Totally remove @a svc_name from the daemon by removing it + /// from the ACE_Reactor, and unlinking it if necessary. + int remove (const ACE_TCHAR svc_name[]); + + /** + * Using the supplied name, finds and (if needed) returns a pointer to a + * static service descriptor. Returns 0 for success and -1 for failure + */ + int find_static_svc_descriptor (const ACE_TCHAR* name, + ACE_Static_Svc_Descriptor **ssd = 0) const; + +protected: + + /** + * + */ + virtual int parse_args_i (int, ACE_TCHAR *argv[]); + + /** + * Performs an open without parsing command-line arguments. The + * @a logger_key indicates where to write the logging output, which + * is typically either a STREAM pipe or a socket address. If + * @a ignore_default_svc_conf_file is non-0 then the "svc.conf" file + * will be ignored. If @a ignore_debug_flag is non-0 then the + * application is responsible for setting the + * @c ACE_Log_Msg::priority_mask() appropriately. Returns number of + * errors that occurred on failure and 0 otherwise. + */ + virtual int open_i (const ACE_TCHAR program_name[], + const ACE_TCHAR *logger_key = ACE_DEFAULT_LOGGER_KEY, + bool ignore_static_svcs = true, + bool ignore_default_svc_conf_file = false, + bool ignore_debug_flag = false); + + /// Initialize the <svc_conf_file_queue_> if necessary. + int init_svc_conf_file_queue (void); + + /// Add the default statically-linked services to the + /// ACE_Service_Repository. + int load_static_svcs (void); + + /// Process service configuration requests that were provided on the + /// command-line. Returns the number of errors that occurred. + int process_commandline_directives (void); + +#if (ACE_USES_CLASSIC_SVC_CONF == 1) + /// This is the implementation function that process_directives() + /// and process_directive() both call. Returns the number of errors + /// that occurred. + int process_directives_i (ACE_Svc_Conf_Param *param); +#else + /// Helper function to dynamically link in the XML Service Configurator + /// parser. + ACE_XML_Svc_Conf *get_xml_svc_conf (ACE_DLL &d); +#endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */ + + // Dynamically link the shared object file and retrieve a pointer to + // the designated shared object in this file. + int initialize_i (const ACE_Service_Type *sr, const ACE_TCHAR *parameters); + + +protected: + + // Maintain a queue of services to be configured from the + // command-line. + typedef ACE_Unbounded_Queue<ACE_TString> ACE_SVC_QUEUE; + typedef ACE_Unbounded_Queue_Iterator<ACE_TString> ACE_SVC_QUEUE_ITERATOR; + + // Maintain a set of the statically linked service descriptors. + typedef ACE_Unbounded_Set<ACE_Static_Svc_Descriptor *> + ACE_STATIC_SVCS; + + typedef ACE_Unbounded_Set_Iterator<ACE_Static_Svc_Descriptor *> + ACE_STATIC_SVCS_ITERATOR; + + friend class ACE_Dynamic_Service_Base; + friend class ACE_Service_Object; + friend class ACE_Service_Config_Guard; + +protected: + + /// The service repository to hold the services. + ACE_Service_Repository* const repo_; + + /// Do we own the service repository instance or have only been given a ptr + /// to the singleton one? + bool repo_is_owned_; + + /// Keep track of the number of times the instance has been + /// initialized (opened). "If so, we can't allow <yyparse> to be called since + /// it's not reentrant" is the original motivation, but that does not seem + /// to be the case anymore. This variable is incremented by the + /// <ACE_Service_Gestalt::open> method and decremented by the + /// <ACE_Service_Gestalt::close> method. + int is_opened_; + + /** Queue of svc.conf files specified on the command-line. + * @@ This should probably be made to handle unicode filenames... + */ + ACE_SVC_QUEUE* svc_conf_file_queue_; + + /// Repository of statically linked services. + ACE_STATIC_SVCS* static_svcs_; + + /// Queue of services specified on the command-line. + ACE_SVC_QUEUE* svc_queue_; + + /// Indicates where to write the logging output. This is typically + /// either a STREAM pipe or a socket + const ACE_TCHAR *logger_key_; + + /// Should we avoid loading the static services? + int no_static_svcs_; + +}; /* class ACE_Service_Gestalt */ + + +class ACE_Location_Node; + +// A helper class used to safely register dynamic services, which may contains +// subordinate static services. It is used to capture the necessary data during +// the parsing, but perform the actuall instantiation later. +class ACE_Service_Type_Factory +{ +public: + ACE_Service_Type_Factory (ACE_TCHAR const *name, + int type, + ACE_Location_Node *location, + int active); + + ~ACE_Service_Type_Factory (void); + + ACE_Service_Type *make_service_type (ACE_Service_Gestalt *pcfg) const; + + ACE_TCHAR const* name (void) const; + + /// Declare the dynamic allocation hooks. + ACE_ALLOC_HOOK_DECLARE; + +private: + + /** + * Not implemented to enforce no copying + */ + ACE_UNIMPLEMENTED_FUNC + (ACE_Service_Type_Factory(const ACE_Service_Type_Factory&)); + + ACE_UNIMPLEMENTED_FUNC + (ACE_Service_Type_Factory& operator=(const ACE_Service_Type_Factory&)); + +private: + ACE_TString name_; + int type_; + ACE_Auto_Ptr<ACE_Location_Node> location_; + int is_active_; +}; + + +ACE_END_VERSIONED_NAMESPACE_DECL + +#if defined (__ACE_INLINE__) +#include "ace/Service_Gestalt.inl" +#endif /* __ACE_INLINE__ */ + + +#include /**/ "ace/post.h" + +#endif /* ACE_SERVICE_GESTALT_H */ diff --git a/ace/Service_Gestalt.inl b/ace/Service_Gestalt.inl new file mode 100644 index 00000000000..9897b83c681 --- /dev/null +++ b/ace/Service_Gestalt.inl @@ -0,0 +1,64 @@ +// -*- C++ -*- +// +// $Id$ + + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + + +// This is the primary entry point into the ACE_Service_Config (the +// constructor just handles simple initializations). + +ACE_INLINE int +ACE_Service_Gestalt::open (const ACE_TCHAR program_name[], + const ACE_TCHAR *logger_key, + int ignore_static_svcs, + int ignore_default_svc_conf, + int ignore_debug_flag) +{ + ACE_TRACE ("ACE_Service_Gestalt::open"); + this->no_static_svcs_ = ignore_static_svcs; + + return this->open_i (program_name, + logger_key, + ignore_static_svcs, + ignore_default_svc_conf, + ignore_debug_flag); +} + +ACE_INLINE int +ACE_Service_Gestalt::open (int argc, + ACE_TCHAR *argv[], + const ACE_TCHAR *logger_key, + int ignore_static_svcs, + int ignore_default_svc_conf, + int ignore_debug_flag) +{ + ACE_TRACE ("ACE_Service_Gestalt::open"); + this->no_static_svcs_ = ignore_static_svcs; + + if (this->parse_args_i (argc, + argv) == -1) + return -1; + else + return this->open_i (argv == 0 ? 0 : argv[0], + logger_key, + ignore_static_svcs, + ignore_default_svc_conf, + ignore_debug_flag); +} + +/// Searches for a service object declaration in the local repo, only + +ACE_INLINE int +ACE_Service_Gestalt::find (const ACE_TCHAR name[], + const ACE_Service_Type **srp, + int ignore_suspended) const +{ + ACE_ASSERT (this->repo_ != 0); + return this->repo_->find (name, srp, ignore_suspended); +} + + + +ACE_END_VERSIONED_NAMESPACE_DECL diff --git a/ace/Svc_Conf_Param.h b/ace/Svc_Conf_Param.h new file mode 100644 index 00000000000..898b3b5cd07 --- /dev/null +++ b/ace/Svc_Conf_Param.h @@ -0,0 +1,140 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file Svc_Conf_Param.h + * + * $Id$ + * + * @author Iliyan Jeliazkov <iliyan@ociweb.com> + */ +//============================================================================= + + +#ifndef ACE_SVC_CONF_PARAM_H +#define ACE_SVC_CONF_PARAM_H + +#include /**/ "ace/pre.h" + +// Globally visible macros, type decls, and extern var decls for +// Service Configurator utility. + +#include "ace/Obstack.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +// Forward declarations. +struct ace_yy_buffer_state; +class ACE_Service_Gestalt; + +extern void ace_yy_delete_buffer (ace_yy_buffer_state *buffer); + +/** + * @class ACE_Svc_Conf_Param + * + * @brief An instance of this object will be passed down to the + * yyparse() and yylex() functions. + * + * This is intended for internal use within ACE service configuration + * framework only. + * + * This class retains the state for a given parse/scan. It primarily + * makes it possible to hold the static object lock in the scanner + * for as short a period of time as possible. The resulting finer + * grained locking prevents deadlocks from occuring when scanning a + * `svc.conf' file and activating an ACE_Task, for example, as a + * result of processing the directives in that file. + */ +class ACE_Svc_Conf_Param +{ +public: + + enum SVC_CONF_PARAM_TYPE + { + /// The lexer will scan a file containing one or more directives. + SVC_CONF_FILE, + + /// The lexer will scan a string containing a directive. + SVC_CONF_DIRECTIVE + }; + + /// Constructor + ACE_Svc_Conf_Param (ACE_Service_Gestalt* config, FILE *file) + : type (SVC_CONF_FILE), + yyerrno (0), + yylineno (1), + buffer (0), + obstack (), + config (config) + { + source.file = file; + } + + /// Constructor + ACE_Svc_Conf_Param (ACE_Service_Gestalt* config, const ACE_TCHAR *directive) + : type (SVC_CONF_DIRECTIVE), + yyerrno (0), + yylineno (1), + buffer (0), + obstack (), + config (config) + { + source.directive = directive; + } + + ~ACE_Svc_Conf_Param (void) + { + ace_yy_delete_buffer (this->buffer); + } + +public: + + union + { + /// FILE stream from which directives will be scanned and parsed. + FILE *file; + + /// String containing directive that will be scanned and parsed. + const ACE_TCHAR *directive; + + } source; + + /// Discriminant use to determine which union member to use. + SVC_CONF_PARAM_TYPE type; + + /// Keeps track of the number of errors encountered so far. + int yyerrno; + + /// Keeps track of the current line number for error-handling routine. + int yylineno; + + /// Lexer buffer that corresponds to the current Service + /// Configurator file/direct scan. + ace_yy_buffer_state *buffer; + + /// Obstack used for efficient memory allocation when + /// parsing/scanning a service configurator directive. + ACE_Obstack_T<ACE_TCHAR> obstack; + + /// A reference to the configuration + ACE_Service_Gestalt *config; +}; + + +// Parameter that is passed down to the yyparse() function, and +// eventually to yylex(). +#define ACE_YYPARSE_PARAM ace_svc_conf_parameter + +#define ACE_YYLEX_PARAM ACE_YYPARSE_PARAM + +#define ACE_SVC_CONF_PARAM (static_cast<ACE_Svc_Conf_Param *> (ACE_YYLEX_PARAM)) + +ACE_END_VERSIONED_NAMESPACE_DECL + +#include /**/ "ace/post.h" + +#endif /* ACE_SVC_CONF_PARAM_H */ diff --git a/tests/Sendfile_Test.cpp b/tests/Sendfile_Test.cpp new file mode 100644 index 00000000000..df151194bc0 --- /dev/null +++ b/tests/Sendfile_Test.cpp @@ -0,0 +1,316 @@ +// $Id$ + +/** + * @file Sendfile_Test.cpp + * + * This is a test of the @c ACE_OS::sendfile() wrapper function. It + * is primarily meant to test the case when ACE_HAS_SENDFILE is not + * defined, i.e. when sendfile() support is emulated. + * + * @author + * Steve Huston <shuston@riverace.com> + * Ossama Othman <ossama@dre.vanderbilt.edu> + */ + +#include "test_config.h" +#include "ace/OS_NS_sys_wait.h" +#include "ace/OS_NS_unistd.h" +#include "ace/Thread.h" +#include "ace/Thread_Manager.h" +#include "ace/Time_Value.h" +#include "ace/SOCK_Connector.h" +#include "ace/SOCK_Acceptor.h" +#include "ace/SOCK_Stream.h" +#include "ace/OS_NS_sys_sendfile.h" + +// Change to non-zero if test fails +static int Test_Result = 0; + +#if !defined (ACE_LACKS_FORK) || defined (ACE_HAS_THREADS) + +// This test sends a large amount of data. The purpose is to overflow the +// TCP send window, causing the sender to block (it's a send_n). This value +// is the amount to send. The assumption is that no implementation has a +// receive window larger than 128K bytes. If one is found, this is the place +// to change it. +// For some odd reason, NT will try to send a single large buffer, but not +// multiple smaller ones that add up to the large size. +const size_t Test3_Send_Size = 4*1024; +const size_t Test3_Loops = 10; +const size_t Test3_Total_Size = Test3_Send_Size * Test3_Loops; + + +static void * +client (void *arg) +{ + ACE_INET_Addr *remote_addr = reinterpret_cast<ACE_INET_Addr *> (arg); + ACE_INET_Addr server_addr (remote_addr->get_port_number (), + ACE_LOCALHOST); + ACE_SOCK_Stream cli_stream; + ACE_SOCK_Connector con; + ACE_Time_Value timeout (ACE_DEFAULT_TIMEOUT); + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) Connecting to port %d\n"), + server_addr.get_port_number())); + + // Initiate connection with server; don't wait forever + if (con.connect (cli_stream, + server_addr, + &timeout) == -1) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) %p\n"), + ACE_TEXT ("connection failed"))); + Test_Result = 1; + return 0; + } + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) connected to %s\n"), + ACE_TEXT_CHAR_TO_TCHAR(server_addr.get_host_name ()))); + + //******************* TEST 1 ****************************** + // + // Send the 255 byte buffer in 5 chunks. The + // server will verify that the correct data is sent, and that there + // is no more and no less. + + u_char buffer[255]; + size_t i; + + // The server will verify that this data pattern gets there intact. + + for (i = 0; i < sizeof buffer; ++i) + buffer[i] = static_cast<u_char> (i); + + ACE_TCHAR const test_file[] = ACE_TEXT ("Sendfile_Test_File"); + ACE_HANDLE in_fd = + ACE_OS::open (test_file, + O_CREAT | O_RDWR | O_TRUNC, + ACE_DEFAULT_FILE_PERMS); + + ACE_ASSERT (in_fd != ACE_INVALID_HANDLE); + + ACE_OS::unlink (test_file); + + ssize_t const byte_count = + ACE_OS::write (in_fd, buffer, sizeof (buffer)); + + ACE_ASSERT (byte_count == static_cast<ssize_t> (sizeof (buffer))); + + off_t offset = 0; + + ssize_t len = + ACE_OS::sendfile (cli_stream.get_handle (), + in_fd, + &offset, + byte_count); + + if (len == -1) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) %p\n"), + ACE_TEXT ("Test 1, sendfile failed"))); + Test_Result = 1; + } + else + ACE_ASSERT (len == 255); + + //******************* TEST 2 ****************************** + // + // The same data is coming back - receive it using recv (size_t n, + // ...) and compare it to the original data. + + u_char buffer2[255]; + // Give it a chance to get here + ACE_OS::sleep (2); + len = cli_stream.recv (4, + buffer2, + 150, + &buffer2[150], + 105); + if (len != 255) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) %p; len is %d, but should be 255!\n"), + len)); + } + ACE_ASSERT (len == 255); + + for (i = 0; i < 255; i++) + if (buffer2[i] != buffer[i]) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) Test 2, rcvd byte %d is %d, not %d\n"), + i, buffer2[i], buffer[i])); + Test_Result = 1; + } + + + cli_stream.close (); + (void) ACE_OS::close (in_fd); + + return 0; +} + +static void * +server (void *arg) +{ + ACE_SOCK_Acceptor *peer_acceptor = (ACE_SOCK_Acceptor *) arg; + ACE_SOCK_Stream sock_str; + ACE_INET_Addr cli_addr; + ACE_Time_Value timeout (ACE_DEFAULT_TIMEOUT); + + // Accept the connection over which the stream tests will run. + // Don't lock up if client doesn't connect + if (peer_acceptor->accept (sock_str, + &cli_addr, + &timeout) == -1) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) %p\n"), + ACE_TEXT ("accept"))); + Test_Result = 1; + return 0; + } + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) client %s connected from %d\n"), + ACE_TEXT_CHAR_TO_TCHAR(cli_addr.get_host_name ()), + cli_addr.get_port_number ())); + + //******************* TEST 1 ****************************** + // + // Do a iovec recvv - the client should send 255 bytes, which we + // will be detected and read into a ACE-allocated buffer. Use a 5 + // second timeout to give the client a chance to send it all. + + ACE_OS::sleep (5); + + u_char buffer[255]; + ssize_t len; + int i; + + len = sock_str.recv (buffer, 255); + if (len == -1) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) %p\n"), + ACE_TEXT ("Test 1, recvv failed"))); + Test_Result = 1; + } + + ACE_ASSERT (len == 255); + for (i = 0; i < 255; i++) + if (buffer[i] != i) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) Test 1, rcvd byte %d is %d, not %d\n"), + i, + buffer[i], + i)); + Test_Result = 1; + } + + //******************* TEST 2 ****************************** + // + // Send the buffer back, using send (size_t n, ...) in 3 pieces. + + len = sock_str.send (6, + buffer, + 42, + &buffer[42], + 189, + &buffer[231], + 24); + ACE_ASSERT (len == 255); + + + sock_str.close(); + + return 0; +} + +#endif /* !ACE_LACKS_FORK || ACE_HAS_THREADS */ + +static void +spawn (void) +{ + // Acceptor + ACE_SOCK_Acceptor peer_acceptor; + + // Create a server address. + ACE_INET_Addr server_addr; + + // Bind listener to any port and then find out what the port was. + if (peer_acceptor.open (ACE_Addr::sap_any) == -1 + || peer_acceptor.get_local_addr (server_addr) == -1) + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) %p\n"), + ACE_TEXT ("open"))); + else + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) starting server at port %d\n"), + server_addr.get_port_number ())); + +#if !defined (ACE_LACKS_FORK) + switch (ACE_OS::fork (ACE_TEXT ("child"))) + { + case -1: + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) %p\n%a"), + ACE_TEXT ("fork failed"), + 1)); + /* NOTREACHED */ + case 0: + client (&server_addr); + ACE_OS::exit (0); + /* NOTREACHED */ + default: + server (reinterpret_cast<void *> (&peer_acceptor)); + ACE_OS::wait (); + } +#elif defined (ACE_HAS_THREADS) + if (ACE_Thread_Manager::instance ()->spawn + (ACE_THR_FUNC (server), + reinterpret_cast<void *> (&peer_acceptor), + THR_NEW_LWP | THR_DETACHED) == -1) + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) %p\n%a"), + ACE_TEXT ("thread create failed"), + 1)); + + if (ACE_Thread_Manager::instance ()->spawn + (ACE_THR_FUNC (client), + reinterpret_cast<void *> (&server_addr), + THR_NEW_LWP | THR_DETACHED) == -1) + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) %p\n%a"), + ACE_TEXT ("thread create failed"), + 1)); + + // Wait for the threads to exit. + ACE_Thread_Manager::instance ()->wait (); +#else + ACE_ERROR ((LM_INFO, + ACE_TEXT ("(%P|%t) ") + ACE_TEXT ("only one thread may be run ") + ACE_TEXT ("in a process on this platform\n"))); +#endif /* ACE_HAS_THREADS */ + + peer_acceptor.close (); + } +} + +int +run_main (int, ACE_TCHAR *[]) +{ + ACE_START_TEST (ACE_TEXT ("Sendfile_Test")); + + spawn (); + + ACE_END_TEST; + return Test_Result; +} |